From 92f1299cd2de68b76be4016115d8571c93e9a2ab Mon Sep 17 00:00:00 2001 From: hybrid Date: Thu, 19 May 2011 20:07:13 +0000 Subject: [PATCH] Add flag to enable sRGB correct color calculations (e.g. blend and lighting). This allows for much better color calculations, but requires to change the explicitly defined colors in the code to be converted to linear color space. Changed many init routines to use SIrrlichtCreationParameters struct instead of many single parameters. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3729 dfc29bdd-3216-0410-991c-e03cc46cb475 --- include/SIrrCreationParameters.h | 17 ++++ source/Irrlicht/CD3D9Driver.cpp | 113 +++++++++++++-------------- source/Irrlicht/CD3D9Driver.h | 16 ++-- source/Irrlicht/CD3D9Texture.cpp | 4 +- source/Irrlicht/CIrrDeviceLinux.cpp | 14 +++- source/Irrlicht/COpenGLDriver.cpp | 117 +++++++++++++++------------- source/Irrlicht/COpenGLDriver.h | 8 +- source/Irrlicht/COpenGLTexture.cpp | 55 +++++++++---- 8 files changed, 198 insertions(+), 146 deletions(-) diff --git a/include/SIrrCreationParameters.h b/include/SIrrCreationParameters.h index a8839488..5afe6def 100644 --- a/include/SIrrCreationParameters.h +++ b/include/SIrrCreationParameters.h @@ -29,6 +29,7 @@ namespace irr Stencilbuffer(false), Vsync(false), AntiAlias(0), + HandleSRGB(false), WithAlphaChannel(false), Doublebuffer(true), IgnoreInput(false), @@ -62,6 +63,7 @@ namespace irr Stencilbuffer = other.Stencilbuffer; Vsync = other.Vsync; AntiAlias = other.AntiAlias; + HandleSRGB = other.HandleSRGB; WithAlphaChannel = other.WithAlphaChannel; Doublebuffer = other.Doublebuffer; IgnoreInput = other.IgnoreInput; @@ -140,6 +142,21 @@ namespace irr Default value: 0 - disabled */ u8 AntiAlias; + //! Flag to enable proper sRGB and linear color handling + /** In most situations, it is desireable to have the color handling in + non-linear sRGB color space, and only do the intermediate color + calculations in linear RGB space. If this flag is enabled, the device and + driver try to assure that all color input and output are color corrected + and only the internal color representation is linear. This means, that + the color output is properly gamma-adjusted to provide the brighter + colors for monitor display. And that blending and lighting give a more + natural look, due to proper conversion from non-linear colors into linear + color space for blend operations. If this flag is enabled, all texture colors + (which are usually in sRGB space) are correctly displayed. However vertex colors + and other explicitly set values have to be manually encoded in linear color space. + Default value: false. */ + bool HandleSRGB; + //! Whether the main framebuffer uses an alpha channel. /** In some situations it might be desireable to get a color buffer with an alpha channel, e.g. when rendering into a diff --git a/source/Irrlicht/CD3D9Driver.cpp b/source/Irrlicht/CD3D9Driver.cpp index 07d61883..19be258d 100644 --- a/source/Irrlicht/CD3D9Driver.cpp +++ b/source/Irrlicht/CD3D9Driver.cpp @@ -29,20 +29,17 @@ namespace } //! constructor -CD3D9Driver::CD3D9Driver(const core::dimension2d& screenSize, HWND window, - bool fullscreen, bool stencilbuffer, - io::IFileSystem* io, bool pureSoftware) -: CNullDriver(io, screenSize), CurrentRenderMode(ERM_NONE), +CD3D9Driver::CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io) + : CNullDriver(io, params.WindowSize), CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(false), - StencilBuffer(stencilbuffer), AntiAliasing(0), D3DLibrary(0), pID3D(0), pID3DDevice(0), PrevRenderTarget(0), WindowId(0), SceneSourceRect(0), LastVertexType((video::E_VERTEX_TYPE)-1), VendorID(0), MaxTextureUnits(0), MaxUserClipPlanes(0), MaxMRTs(1), NumSetMRTs(1), MaxLightDistance(0.f), LastSetLight(-1), Cached2DModeSignature(0), ColorFormat(ECF_A8R8G8B8), DeviceLost(false), - Fullscreen(fullscreen), DriverWasReset(true), OcclusionQuerySupport(false), - AlphaToCoverageSupport(false), DisplayAdapter(0) + DriverWasReset(true), OcclusionQuerySupport(false), + AlphaToCoverageSupport(false), Params(params) { #ifdef _DEBUG setDebugName("CD3D9Driver"); @@ -164,15 +161,8 @@ void CD3D9Driver::createMaterialRenderers() //! initialises the Direct3D API -bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, - HWND hwnd, u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, u8 antiAlias, u32 displayAdapter) +bool CD3D9Driver::initDriver(HWND hwnd, bool pureSoftware) { - HRESULT hr; - Fullscreen = fullScreen; - CurrentDepthBufferSize = screenSize; - DisplayAdapter = displayAdapter; - if (!pID3D) { D3DLibrary = LoadLibrary( __TEXT("d3d9.dll") ); @@ -204,7 +194,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, // print device information D3DADAPTER_IDENTIFIER9 dai; - if (!FAILED(pID3D->GetAdapterIdentifier(DisplayAdapter, 0, &dai))) + if (!FAILED(pID3D->GetAdapterIdentifier(Params.DisplayAdapter, 0, &dai))) { char tmp[512]; @@ -232,8 +222,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, } D3DDISPLAYMODE d3ddm; - hr = pID3D->GetAdapterDisplayMode(DisplayAdapter, &d3ddm); - if (FAILED(hr)) + if (FAILED(pID3D->GetAdapterDisplayMode(Params.DisplayAdapter, &d3ddm))) { os::Printer::log("Error: Could not get Adapter Display mode.", ELL_ERROR); return false; @@ -241,19 +230,19 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, ZeroMemory(&present, sizeof(present)); - present.BackBufferCount = 1; - present.EnableAutoDepthStencil = TRUE; - if (vsync) + present.BackBufferCount = 1; + present.EnableAutoDepthStencil = TRUE; + if (Params.Vsync) present.PresentationInterval = D3DPRESENT_INTERVAL_ONE; else present.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - if (fullScreen) + if (Params.Fullscreen) { - present.BackBufferWidth = screenSize.Width; - present.BackBufferHeight = screenSize.Height; + present.BackBufferWidth = Params.WindowSize.Width; + present.BackBufferHeight = Params.WindowSize.Height; // request 32bit mode if user specified 32 bit, added by Thomas Stuefe - if (bits == 32) + if (Params.Bits == 32) present.BackBufferFormat = D3DFMT_X8R8G8B8; else present.BackBufferFormat = D3DFMT_R5G6B5; @@ -268,7 +257,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, present.Windowed = TRUE; } - UINT adapter = DisplayAdapter; + UINT adapter = Params.DisplayAdapter; D3DDEVTYPE devtype = D3DDEVTYPE_HAL; #ifndef _IRR_D3D_NO_SHADER_DEBUGGING devtype = D3DDEVTYPE_REF; @@ -287,36 +276,35 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, #endif // enable anti alias if possible and desired - if (antiAlias > 0) + if (Params.AntiAlias > 0) { - if(antiAlias > 16) - antiAlias = 16; + if (Params.AntiAlias > 32) + Params.AntiAlias = 32; DWORD qualityLevels = 0; - while(antiAlias > 0) + while(Params.AntiAlias > 0) { if(SUCCEEDED(pID3D->CheckDeviceMultiSampleType(adapter, - devtype, present.BackBufferFormat, !fullScreen, - (D3DMULTISAMPLE_TYPE)antiAlias, &qualityLevels))) + devtype, present.BackBufferFormat, !Params.Fullscreen, + (D3DMULTISAMPLE_TYPE)Params.AntiAlias, &qualityLevels))) { - present.MultiSampleType = (D3DMULTISAMPLE_TYPE)antiAlias; + present.MultiSampleType = (D3DMULTISAMPLE_TYPE)Params.AntiAlias; present.MultiSampleQuality = qualityLevels-1; present.SwapEffect = D3DSWAPEFFECT_DISCARD; break; } - --antiAlias; + --Params.AntiAlias; } - if(antiAlias==0) + if (Params.AntiAlias==0) { os::Printer::log("Anti aliasing disabled because hardware/driver lacks necessary caps.", ELL_WARNING); } } - AntiAliasing = antiAlias; // check stencil buffer compatibility - if (StencilBuffer) + if (Params.Stencilbuffer) { present.AutoDepthStencilFormat = D3DFMT_D24S8; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, @@ -334,7 +322,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, D3DRTYPE_SURFACE, present.AutoDepthStencilFormat))) { os::Printer::log("Device does not support stencilbuffer, disabling stencil buffer.", ELL_WARNING); - StencilBuffer = false; + Params.Stencilbuffer = false; } } } @@ -343,11 +331,11 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, present.BackBufferFormat, present.BackBufferFormat, present.AutoDepthStencilFormat))) { os::Printer::log("Depth-stencil format is not compatible with display format, disabling stencil buffer.", ELL_WARNING); - StencilBuffer = false; + Params.Stencilbuffer = false; } } // do not use else here to cope with flag change in previous block - if (!StencilBuffer) + if (!Params.Stencilbuffer) { present.AutoDepthStencilFormat = D3DFMT_D32; if(FAILED(pID3D->CheckDeviceFormat(adapter, devtype, @@ -373,18 +361,16 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, // create device - DWORD fpuPrecision = highPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; + DWORD fpuPrecision = Params.HighPrecisionFPU ? D3DCREATE_FPU_PRESERVE : 0; if (pureSoftware) { - hr = pID3D->CreateDevice(DisplayAdapter, D3DDEVTYPE_REF, hwnd, - fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice); - - if (FAILED(hr)) + if (FAILED(pID3D->CreateDevice(Params.DisplayAdapter, D3DDEVTYPE_REF, hwnd, + fpuPrecision | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present, &pID3DDevice))) os::Printer::log("Was not able to create Direct3D9 software device.", ELL_ERROR); } else { - hr = pID3D->CreateDevice(adapter, devtype, hwnd, + HRESULT hr = pID3D->CreateDevice(adapter, devtype, hwnd, fpuPrecision | D3DCREATE_HARDWARE_VERTEXPROCESSING, &present, &pID3DDevice); if(FAILED(hr)) @@ -409,13 +395,13 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, pID3DDevice->GetDeviceCaps(&Caps); // disable stencilbuffer if necessary - if (StencilBuffer && + if (Params.Stencilbuffer && (!(Caps.StencilCaps & D3DSTENCILCAPS_DECRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_INCRSAT) || !(Caps.StencilCaps & D3DSTENCILCAPS_KEEP))) { os::Printer::log("Device not able to use stencil buffer, disabling stencil buffer.", ELL_WARNING); - StencilBuffer = false; + Params.Stencilbuffer = false; } // set default vertex shader @@ -440,7 +426,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, OcclusionQuerySupport=(pID3DDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL) == S_OK); if (VendorID==0x10DE)//NVidia - AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(DisplayAdapter, D3DDEVTYPE_HAL, + AlphaToCoverageSupport = (pID3D->CheckDeviceFormat(Params.DisplayAdapter, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,D3DRTYPE_SURFACE, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C')) == S_OK); else if (VendorID==0x1002)//ATI @@ -461,7 +447,7 @@ bool CD3D9Driver::initDriver(const core::dimension2d& screenSize, DriverAttributes->setAttribute("MaxTextureLODBias", 16); DriverAttributes->setAttribute("Version", 901); DriverAttributes->setAttribute("ShaderLanguageVersion", (s32)Caps.VertexShaderVersion*100); - DriverAttributes->setAttribute("AntiAlias", AntiAliasing); + DriverAttributes->setAttribute("AntiAlias", Params.AntiAlias); // set the renderstates setRenderStates3DMode(); @@ -537,7 +523,7 @@ bool CD3D9Driver::beginScene(bool backBuffer, bool zBuffer, SColor color, if (zBuffer) flags |= D3DCLEAR_ZBUFFER; - if (StencilBuffer) + if (Params.Stencilbuffer) flags |= D3DCLEAR_STENCIL; if (flags) @@ -582,7 +568,10 @@ bool CD3D9Driver::endScene() sourceRectData.bottom = SceneSourceRect->LowerRightCorner.Y; } - hr = pID3DDevice->Present(srcRct, NULL, WindowId, NULL); + IDirect3DSwapChain9* swChain; + hr = pID3DDevice->GetSwapChain(0, &swChain); + DWORD flags = (Caps.Caps3&D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION)?D3DPRESENT_LINEAR_CONTENT:0; + hr = swChain->Present(srcRct, NULL, WindowId, NULL, flags); if (SUCCEEDED(hr)) return true; @@ -630,7 +619,7 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const // this but actually don't do this at all. return false; //(Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP) != 0; case EVDF_STENCIL_BUFFER: - return StencilBuffer && Caps.StencilCaps; + return Params.Stencilbuffer && Caps.StencilCaps; case EVDF_VERTEX_SHADER_1_1: return Caps.VertexShaderVersion >= D3DVS_VERSION(1,1); case EVDF_VERTEX_SHADER_2_0: @@ -2096,6 +2085,10 @@ D3DTEXTUREADDRESS CD3D9Driver::getTextureWrapMode(const u8 clamp) void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderstates) { + // This needs only to be updated onresets + if (Params.HandleSRGB && resetAllRenderstates) + pID3DDevice->SetRenderState(D3DRS_SRGBWRITEENABLE, TRUE); + if (resetAllRenderstates || lastmaterial.AmbientColor != material.AmbientColor || lastmaterial.DiffuseColor != material.DiffuseColor || @@ -2334,7 +2327,7 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria } // enable antialiasing - if (AntiAliasing) + if (Params.AntiAlias) { if (material.AntiAliasing & (EAAM_SIMPLE|EAAM_QUALITY)) pID3DDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); @@ -2356,6 +2349,9 @@ void CD3D9Driver::setBasicRenderStates(const SMaterial& material, const SMateria // texture address mode for (u32 st=0; stSetSamplerState(st, D3DSAMP_SRGBTEXTURE, TRUE); + if (resetAllRenderstates || lastmaterial.TextureLayer[st].LODBias != material.TextureLayer[st].LODBias) { const float tmp = material.TextureLayer[st].LODBias * 0.125f; @@ -2767,7 +2763,7 @@ const wchar_t* CD3D9Driver::getName() const //! volume. Then, use IVideoDriver::drawStencilShadow() to visualize the shadow. void CD3D9Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail) { - if (!StencilBuffer || !count) + if (!Params.Stencilbuffer || !count) return; setRenderStatesStencilShadowMode(zfail); @@ -2809,7 +2805,7 @@ void CD3D9Driver::drawStencilShadowVolume(const core::vector3df* triangles, s32 void CD3D9Driver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge, video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge) { - if (!StencilBuffer) + if (!Params.Stencilbuffer) return; S3DVertex vtx[4]; @@ -3503,9 +3499,8 @@ IVideoDriver* createDirectX9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window) { const bool pureSoftware = false; - CD3D9Driver* dx9 = new CD3D9Driver(params.WindowSize, window, params.Fullscreen, params.Stencilbuffer, io, pureSoftware); - if (!dx9->initDriver(params.WindowSize, window, params.Bits, params.Fullscreen, pureSoftware, params.HighPrecisionFPU, - params.Vsync, params.AntiAlias, params.DisplayAdapter)) + CD3D9Driver* dx9 = new CD3D9Driver(params, io); + if (!dx9->initDriver(window, pureSoftware)) { dx9->drop(); dx9 = 0; diff --git a/source/Irrlicht/CD3D9Driver.h b/source/Irrlicht/CD3D9Driver.h index 390db1f4..5c722b54 100644 --- a/source/Irrlicht/CD3D9Driver.h +++ b/source/Irrlicht/CD3D9Driver.h @@ -15,6 +15,7 @@ #endif #include "CNullDriver.h" +#include "SIrrCreationParameters.h" #include "IMaterialRendererServices.h" #if defined(__BORLANDC__) || defined (__BCPLUSPLUS__) #include "irrMath.h" // needed by borland for sqrtf define @@ -50,8 +51,7 @@ namespace video friend class CD3D9Texture; //! constructor - CD3D9Driver(const core::dimension2d& screenSize, HWND window, bool fullscreen, - bool stencibuffer, io::IFileSystem* io, bool pureSoftware=false); + CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io); //! destructor virtual ~CD3D9Driver(); @@ -191,9 +191,7 @@ namespace video const core::vector3df& end, SColor color = SColor(255,255,255,255)); //! initialises the Direct3D API - bool initDriver(const core::dimension2d& screenSize, HWND hwnd, - u32 bits, bool fullScreen, bool pureSoftware, - bool highPrecisionFPU, bool vsync, u8 antiAlias, u32 displayAdapter); + bool initDriver(HWND hwnd, bool pureSoftware); //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 //! driver, it would return "Direct3D8.1". @@ -412,8 +410,6 @@ namespace video SMaterial Material, LastMaterial; bool ResetRenderStates; // bool to make all renderstates be reseted if set. bool Transformation3DChanged; - bool StencilBuffer; - u8 AntiAliasing; const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES]; bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES]; core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode. @@ -424,13 +420,14 @@ namespace video IDirect3DSurface9* PrevRenderTarget; core::dimension2d CurrentRendertargetSize; - core::dimension2d CurrentDepthBufferSize; HWND WindowId; core::rect* SceneSourceRect; D3DCAPS9 Caps; + SIrrlichtCreationParameters Params; + E_VERTEX_TYPE LastVertexType; SColorf AmbientLight; @@ -459,12 +456,9 @@ namespace video ECOLOR_FORMAT ColorFormat; D3DFORMAT D3DColorFormat; bool DeviceLost; - bool Fullscreen; bool DriverWasReset; bool OcclusionQuerySupport; bool AlphaToCoverageSupport; - - u32 DisplayAdapter; }; diff --git a/source/Irrlicht/CD3D9Texture.cpp b/source/Irrlicht/CD3D9Texture.cpp index aff46232..d5d2750e 100644 --- a/source/Irrlicht/CD3D9Texture.cpp +++ b/source/Irrlicht/CD3D9Texture.cpp @@ -312,9 +312,9 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image) { LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9; D3DDISPLAYMODE d3ddm; - intf->GetAdapterDisplayMode(Driver->DisplayAdapter, &d3ddm); + intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm); - if (D3D_OK==intf->CheckDeviceFormat(Driver->DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format)) + if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format)) { usage = D3DUSAGE_AUTOGENMIPMAP; HardwareMipMaps = true; diff --git a/source/Irrlicht/CIrrDeviceLinux.cpp b/source/Irrlicht/CIrrDeviceLinux.cpp index 2247eb43..e92bdb23 100644 --- a/source/Irrlicht/CIrrDeviceLinux.cpp +++ b/source/Irrlicht/CIrrDeviceLinux.cpp @@ -410,6 +410,11 @@ bool CIrrDeviceLinux::createWindow() #elif defined(GLX_SGIS_multisample) GLX_SAMPLE_BUFFERS_SGIS, 1, GLX_SAMPLES_SGIS, CreationParams.AntiAlias, // 18,19 +#endif +#ifdef GL_ARB_framebuffer_sRGB + CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:GLX_USE_GL, +#elif defined(GL_EXT_framebuffer_sRGB) + CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:GLX_USE_GL, #endif GLX_STEREO, CreationParams.Stereobuffer?True:False, None @@ -545,7 +550,7 @@ bool CIrrDeviceLinux::createWindow() // attribute array for the draw buffer int visualAttrBuffer[] = { - GLX_RGBA, GL_TRUE, + GLX_RGBA, GLX_USE_GL, GLX_RED_SIZE, 4, GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, @@ -557,6 +562,11 @@ bool CIrrDeviceLinux::createWindow() // GLX_USE_GL, which is silently ignored by glXChooseVisual CreationParams.Doublebuffer?GLX_DOUBLEBUFFER:GLX_USE_GL, // 14 CreationParams.Stereobuffer?GLX_STEREO:GLX_USE_GL, // 15 +#ifdef GL_ARB_framebuffer_sRGB + CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB:GLX_USE_GL, +#elif defined(GL_EXT_framebuffer_sRGB) + CreationParams.HandleSRGB?GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT:GLX_USE_GL, +#endif None }; @@ -613,7 +623,7 @@ bool CIrrDeviceLinux::createWindow() } #ifdef _DEBUG else - os::Printer::log("Visual chosen: ", core::stringc(static_cast(visual->visualid)).c_str(), ELL_INFORMATION); + os::Printer::log("Visual chosen: ", core::stringc(static_cast(visual->visualid)).c_str(), ELL_DEBUG); #endif // create color map diff --git a/source/Irrlicht/COpenGLDriver.cpp b/source/Irrlicht/COpenGLDriver.cpp index 7dd73e06..bb770d91 100644 --- a/source/Irrlicht/COpenGLDriver.cpp +++ b/source/Irrlicht/COpenGLDriver.cpp @@ -37,7 +37,7 @@ COpenGLDriver::COpenGLDriver(const irr::SIrrlichtCreationParameters& params, CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), - CurrentTarget(ERT_FRAME_BUFFER), + CurrentTarget(ERT_FRAME_BUFFER), Params(params), Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), HDc(0), Window(static_cast(params.WindowId)), Win32Device(device), DeviceType(EIDT_WIN32) @@ -79,7 +79,7 @@ bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrr } //! inits the open gl driver -bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceWin32* device) +bool COpenGLDriver::initDriver(CIrrDeviceWin32* device) { // Create a window to test antialiasing support const fschar_t* ClassName = __TEXT("GLCIrrDeviceWin32"); @@ -105,11 +105,11 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi RECT clientSize; clientSize.top = 0; clientSize.left = 0; - clientSize.right = params.WindowSize.Width; - clientSize.bottom = params.WindowSize.Height; + clientSize.right = Params.WindowSize.Width; + clientSize.bottom = Params.WindowSize.Height; DWORD style = WS_POPUP; - if (!params.Fullscreen) + if (!Params.Fullscreen) style = WS_SYSMENU | WS_BORDER | WS_CAPTION | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; AdjustWindowRect(&clientSize, style, FALSE); @@ -138,17 +138,17 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - (params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering - (params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer + (Params.Doublebuffer?PFD_DOUBLEBUFFER:0) | // Must Support Double Buffering + (Params.Stereobuffer?PFD_STEREO:0), // Must Support Stereo Buffer PFD_TYPE_RGBA, // Request An RGBA Format - params.Bits, // Select Our Color Depth + Params.Bits, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored - params.ZBufferBits, // Z-Buffer (Depth Buffer) - params.Stencilbuffer ? 1 : 0, // Stencil Buffer Depth + Params.ZBufferBits, // Z-Buffer (Depth Buffer) + Params.Stencilbuffer ? 1 : 0, // Stencil Buffer Depth 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved @@ -161,10 +161,10 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi { if (i == 1) { - if (params.Stencilbuffer) + if (Params.Stencilbuffer) { os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); - params.Stencilbuffer = false; + Params.Stencilbuffer = false; pfd.cStencilBits = 0; } else @@ -177,7 +177,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi } if (i == 3) { - if (params.Bits!=16) + if (Params.Bits!=16) pfd.cDepthBits = 16; else continue; @@ -186,7 +186,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi if (i == 4) { // try single buffer - if (params.Doublebuffer) + if (Params.Doublebuffer) pfd.dwFlags &= ~PFD_DOUBLEBUFFER; else continue; @@ -268,15 +268,15 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi f32 fAttributes[] = {0.0, 0.0}; s32 iAttributes[] = { - WGL_DRAW_TO_WINDOW_ARB,GL_TRUE, - WGL_SUPPORT_OPENGL_ARB,GL_TRUE, + WGL_DRAW_TO_WINDOW_ARB,1, + WGL_SUPPORT_OPENGL_ARB,1, WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB,(params.Bits==32) ? 24 : 15, - WGL_ALPHA_BITS_ARB,(params.Bits==32) ? 8 : 1, - WGL_DEPTH_BITS_ARB,params.ZBufferBits, // 10,11 - WGL_STENCIL_BITS_ARB,(params.Stencilbuffer) ? 1 : 0, - WGL_DOUBLE_BUFFER_ARB,(params.Doublebuffer) ? GL_TRUE : GL_FALSE, - WGL_STEREO_ARB,(params.Stereobuffer) ? GL_TRUE : GL_FALSE, + WGL_COLOR_BITS_ARB,(Params.Bits==32) ? 24 : 15, + WGL_ALPHA_BITS_ARB,(Params.Bits==32) ? 8 : 1, + WGL_DEPTH_BITS_ARB,Params.ZBufferBits, // 10,11 + WGL_STENCIL_BITS_ARB,Params.Stencilbuffer ? 1 : 0, + WGL_DOUBLE_BUFFER_ARB,Params.Doublebuffer ? 1 : 0, + WGL_STEREO_ARB,Params.Stereobuffer ? 1 : 0, WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, #ifdef WGL_ARB_multisample WGL_SAMPLES_ARB,AntiAlias, // 20,21 @@ -288,21 +288,26 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi WGL_SAMPLES_3DFX,AntiAlias, // 20,21 WGL_SAMPLE_BUFFERS_3DFX, 1, #endif -#if 0 #ifdef WGL_ARB_framebuffer_sRGB - WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, GL_TRUE, + WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, Params.HandleSRGB ? 1:0, #elif defined(WGL_EXT_framebuffer_sRGB) - WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, GL_TRUE, + WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, Params.HandleSRGB ? 1:0, #endif -#endif - 0,0 +// WGL_DEPTH_FLOAT_EXT, 1, + 0,0,0,0 }; + int iAttrSize = sizeof(iAttributes)/sizeof(int); + const bool framebuffer_srgb_supported = ((wglExtensions.find("WGL_ARB_framebuffer_sRGB") != -1) || + (wglExtensions.find("WGL_EXT_framebuffer_sRGB") != -1)); + if (!framebuffer_srgb_supported) + { + memmove(&iAttributes[24],&iAttributes[26],sizeof(int)*(iAttrSize-26)); + iAttrSize -= 2; + } if (!multi_sample_supported) { - iAttributes[20]=0; - iAttributes[21]=0; - iAttributes[22]=0; - iAttributes[23]=0; + memmove(&iAttributes[20],&iAttributes[24],sizeof(int)*(iAttrSize-24)); + iAttrSize -= 4; } s32 rv=0; @@ -313,7 +318,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi UINT numFormats=0; const BOOL valid = wglChoosePixelFormat_ARB(HDc,iAttributes,fAttributes,1,&pixelFormat,&numFormats); - if (valid && numFormats>0) + if (valid && numFormats) rv = pixelFormat; else iAttributes[21] -= 1; @@ -350,10 +355,10 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi { if (i == 1) { - if (params.Stencilbuffer) + if (Params.Stencilbuffer) { os::Printer::log("Cannot create a GL device with stencil buffer, disabling stencil shadows.", ELL_WARNING); - params.Stencilbuffer = false; + Params.Stencilbuffer = false; pfd.cStencilBits = 0; } else @@ -366,7 +371,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi } if (i == 3) { - if (params.Bits!=16) + if (Params.Bits!=16) pfd.cDepthBits = 16; else continue; @@ -391,6 +396,7 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi os::Printer::log("Cannot set the pixel format.", ELL_ERROR); return false; } + os::Printer::log("Pixel Format", core::stringc(PixelFormat).c_str(), ELL_DEBUG); // create rendering context #ifdef WGL_ARB_create_context @@ -446,9 +452,9 @@ bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDevi ColorFormat = ECF_R5G6B5; } - genericDriverInit(params.WindowSize, params.Stencilbuffer); + genericDriverInit(); - extGlSwapInterval(params.Vsync ? 1 : 0); + extGlSwapInterval(Params.Vsync ? 1 : 0); return true; } @@ -465,14 +471,14 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), - CurrentTarget(ERT_FRAME_BUFFER), + CurrentTarget(ERT_FRAME_BUFFER), Params(params), Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), OSXDevice(device), DeviceType(EIDT_OSX) { #ifdef _DEBUG setDebugName("COpenGLDriver"); #endif - genericDriverInit(params.WindowSize, params.Stencilbuffer); + genericDriverInit(); } #endif @@ -488,7 +494,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), - CurrentTarget(ERT_FRAME_BUFFER), + CurrentTarget(ERT_FRAME_BUFFER), Params(params), Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), X11Device(device), DeviceType(EIDT_X11) { @@ -532,18 +538,18 @@ bool COpenGLDriver::changeRenderContext(const SExposedVideoData& videoData, CIrr //! inits the open gl driver -bool COpenGLDriver::initDriver(irr::SIrrlichtCreationParameters params, CIrrDeviceLinux* device) +bool COpenGLDriver::initDriver(CIrrDeviceLinux* device) { ExposedData.OpenGLLinux.X11Context = glXGetCurrentContext(); ExposedData.OpenGLLinux.X11Display = glXGetCurrentDisplay(); - ExposedData.OpenGLLinux.X11Window = (unsigned long)params.WindowId; + ExposedData.OpenGLLinux.X11Window = (unsigned long)Params.WindowId; Drawable = glXGetCurrentDrawable(); X11Display = (Display*)ExposedData.OpenGLLinux.X11Display; - genericDriverInit(params.WindowSize, params.Stencilbuffer); + genericDriverInit(); // set vsync - extGlSwapInterval(params.Vsync ? 1 : 0); + extGlSwapInterval(Params.Vsync ? 1 : 0); return true; } @@ -561,7 +567,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, CurrentRenderMode(ERM_NONE), ResetRenderStates(true), Transformation3DChanged(true), AntiAlias(params.AntiAlias), RenderTargetTexture(0), CurrentRendertargetSize(0,0), ColorFormat(ECF_R8G8B8), - CurrentTarget(ERT_FRAME_BUFFER), + CurrentTarget(ERT_FRAME_BUFFER), Params(params), Doublebuffer(params.Doublebuffer), Stereo(params.Stereobuffer), SDLDevice(device), DeviceType(EIDT_SDL) { @@ -569,7 +575,7 @@ COpenGLDriver::COpenGLDriver(const SIrrlichtCreationParameters& params, setDebugName("COpenGLDriver"); #endif - genericDriverInit(params.WindowSize, params.Stencilbuffer); + genericDriverInit(); } #endif // _IRR_COMPILE_WITH_SDL_DEVICE_ @@ -612,7 +618,7 @@ COpenGLDriver::~COpenGLDriver() // METHODS // ----------------------------------------------------------------------- -bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer) +bool COpenGLDriver::genericDriverInit() { Name=L"OpenGL "; Name.append(glGetString(GL_VERSION)); @@ -634,7 +640,7 @@ bool COpenGLDriver::genericDriverInit(const core::dimension2d& screenSize, for (i=0; i& screenSize, glPixelStorei(GL_PACK_ALIGNMENT, 1); // Reset The Current Viewport - glViewport(0, 0, screenSize.Width, screenSize.Height); + glViewport(0, 0, Params.WindowSize.Width, Params.WindowSize.Height); UserClipPlanes.reallocate(MaxUserClipPlanes); for (i=0; i& screenSize, #endif glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1); + Params.HandleSRGB &= ((FeatureAvailable[IRR_ARB_framebuffer_sRGB] || FeatureAvailable[IRR_EXT_framebuffer_sRGB]) && + FeatureAvailable[IRR_EXT_texture_sRGB]); +#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) + if (Params.HandleSRGB) + glEnable(GL_FRAMEBUFFER_SRGB); +#endif + // This is a fast replacement for NORMALIZE_NORMALS // if ((Version>101) || FeatureAvailable[IRR_EXT_rescale_normal]) // glEnable(GL_RESCALE_NORMAL_EXT); @@ -4421,7 +4434,7 @@ GLenum COpenGLDriver::primitiveTypeToGL(scene::E_PRIMITIVE_TYPE type) const } -GLenum COpenGLDriver::getGLBlend (E_BLEND_FACTOR factor) const +GLenum COpenGLDriver::getGLBlend(E_BLEND_FACTOR factor) const { GLenum r = 0; switch (factor) @@ -4462,7 +4475,7 @@ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, { #ifdef _IRR_COMPILE_WITH_OPENGL_ COpenGLDriver* ogl = new COpenGLDriver(params, io, device); - if (!ogl->initDriver(params, device)) + if (!ogl->initDriver(device)) { ogl->drop(); ogl = 0; @@ -4498,7 +4511,7 @@ IVideoDriver* createOpenGLDriver(const SIrrlichtCreationParameters& params, { #ifdef _IRR_COMPILE_WITH_OPENGL_ COpenGLDriver* ogl = new COpenGLDriver(params, io, device); - if (!ogl->initDriver(params, device)) + if (!ogl->initDriver(device)) { ogl->drop(); ogl = 0; diff --git a/source/Irrlicht/COpenGLDriver.h b/source/Irrlicht/COpenGLDriver.h index 4f1518bc..e07b6265 100644 --- a/source/Irrlicht/COpenGLDriver.h +++ b/source/Irrlicht/COpenGLDriver.h @@ -33,19 +33,20 @@ namespace video class COpenGLDriver : public CNullDriver, public IMaterialRendererServices, public COpenGLExtensionHandler { + friend class COpenGLTexture; public: #ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceWin32* device); //! inits the windows specific parts of the open gl driver - bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceWin32* device); + bool initDriver(CIrrDeviceWin32* device); bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceWin32* device); #endif #ifdef _IRR_COMPILE_WITH_X11_DEVICE_ COpenGLDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, CIrrDeviceLinux* device); //! inits the GLX specific parts of the open gl driver - bool initDriver(SIrrlichtCreationParameters params, CIrrDeviceLinux* device); + bool initDriver(CIrrDeviceLinux* device); bool changeRenderContext(const SExposedVideoData& videoData, CIrrDeviceLinux* device); #endif @@ -392,7 +393,7 @@ namespace video void uploadClipPlane(u32 index); //! inits the parts of the open gl driver used on all platforms - bool genericDriverInit(const core::dimension2d& screenSize, bool stencilBuffer); + bool genericDriverInit(); //! returns a device dependent texture from a software surface (IImage) virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData); @@ -472,6 +473,7 @@ namespace video //! Render target type for render operations E_RENDER_TARGET CurrentTarget; + SIrrlichtCreationParameters Params; bool Doublebuffer; bool Stereo; diff --git a/source/Irrlicht/COpenGLTexture.cpp b/source/Irrlicht/COpenGLTexture.cpp index f340d514..e50b2895 100644 --- a/source/Irrlicht/COpenGLTexture.cpp +++ b/source/Irrlicht/COpenGLTexture.cpp @@ -135,26 +135,31 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT filtering = GL_LINEAR; colorformat = GL_RGBA; type = GL_UNSIGNED_BYTE; + GLenum internalformat = GL_RGBA; switch(format) { case ECF_A1R5G5B5: colorformat=GL_BGRA_EXT; type=GL_UNSIGNED_SHORT_1_5_5_5_REV; - return GL_RGBA; + internalformat = GL_RGBA; + break; case ECF_R5G6B5: colorformat=GL_BGR; type=GL_UNSIGNED_SHORT_5_6_5_REV; - return GL_RGB; + internalformat = GL_RGB; + break; case ECF_R8G8B8: colorformat=GL_BGR; type=GL_UNSIGNED_BYTE; - return GL_RGB; + internalformat = GL_RGB; + break; case ECF_A8R8G8B8: colorformat=GL_BGRA_EXT; if (Driver->Version > 101) type=GL_UNSIGNED_INT_8_8_8_8_REV; - return GL_RGBA; + internalformat = GL_RGBA; + break; // Floating Point texture formats. Thanks to Patryk "Nadro" Nadrowski. case ECF_R16F: { @@ -163,11 +168,12 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RED; type = GL_FLOAT; - return GL_R16F; + internalformat = GL_R16F; #else - return GL_RGB8; + internalformat = GL_RGB8; #endif } + break; case ECF_G16R16F: { #ifdef GL_ARB_texture_rg @@ -175,11 +181,12 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RG; type = GL_FLOAT; - return GL_RG16F; + internalformat = GL_RG16F; #else - return GL_RGB8; + internalformat = GL_RGB8; #endif } + break; case ECF_A16B16G16R16F: { #ifdef GL_ARB_texture_rg @@ -187,11 +194,12 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RGBA; type = GL_FLOAT; - return GL_RGBA16F_ARB; + internalformat = GL_RGBA16F_ARB; #else - return GL_RGBA8; + internalformat = GL_RGBA8; #endif } + break; case ECF_R32F: { #ifdef GL_ARB_texture_rg @@ -199,11 +207,12 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RED; type = GL_FLOAT; - return GL_R32F; + internalformat = GL_R32F; #else - return GL_RGB8; + internalformat = GL_RGB8; #endif } + break; case ECF_G32R32F: { #ifdef GL_ARB_texture_rg @@ -211,11 +220,12 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RG; type = GL_FLOAT; - return GL_RG32F; + internalformat = GL_RG32F; #else - return GL_RGB8; + internalformat = GL_RGB8; #endif } + break; case ECF_A32B32G32R32F: { #ifdef GL_ARB_texture_float @@ -223,17 +233,28 @@ GLint COpenGLTexture::getOpenGLFormatAndParametersFromColorFormat(ECOLOR_FORMAT colorformat = GL_RGBA; type = GL_FLOAT; - return GL_RGBA32F_ARB; + internalformat = GL_RGBA32F_ARB; #else - return GL_RGBA8; + internalformat = GL_RGBA8; #endif } + break; default: { os::Printer::log("Unsupported texture format", ELL_ERROR); - return GL_RGBA8; + internalformat = GL_RGBA8; } } +#if defined(GL_ARB_framebuffer_sRGB) || defined(GL_EXT_framebuffer_sRGB) + if (Driver->Params.HandleSRGB) + { + if (internalformat==GL_RGBA) + internalformat=GL_SRGB_ALPHA_EXT; + else if (internalformat==GL_RGB) + internalformat=GL_SRGB_EXT; + } +#endif + return internalformat; }