diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c index b01987f6f1c..6be0f7e314f 100644 --- a/dlls/wined3d/cubetexture.c +++ b/dlls/wined3d/cubetexture.c @@ -105,6 +105,8 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { BOOL setGlTextureDesc = FALSE; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + BOOL srgb_mode = This->baseTexture.is_srgb; + BOOL srgb_was_toggled = FALSE; TRACE("(%p) : About to load texture: dirtified(%d)\n", This, This->baseTexture.dirty); @@ -120,23 +122,46 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { ENTER_GL(); ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); LEAVE_GL(); + } else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { + srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; + srgb_was_toggled = (This->baseTexture.is_srgb != srgb_mode); + This->baseTexture.is_srgb = srgb_mode; } IWineD3DCubeTexture_BindTexture(iface); ENTER_GL(); - /* If were dirty then reload the surfaces */ + /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */ if (This->baseTexture.dirty) { for (i = 0; i < This->baseTexture.levels; i++) { for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { if(setGlTextureDesc) IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], This->baseTexture.textureName, cube_targets[j]); - IWineD3DSurface_LoadTexture(This->surfaces[j][i], FALSE); + IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); } } - /* No longer dirty */ - This->baseTexture.dirty = FALSE; + } else if (srgb_was_toggled) { + /* Loop is repeated in the else block with the extra AddDirtyRect line to avoid the alternative of + * checking srgb_was_toggled in every iteration, even when the texture is just dirty + */ + if (This->baseTexture.srgb_mode_change_count < 20) + ++This->baseTexture.srgb_mode_change_count; + else + FIXME("Cubetexture (%p) has been reloaded at least 20 times due to WINED3DSAMP_SRGBTEXTURE changes on it\'s sampler\n", This); + + for (i = 0; i < This->baseTexture.levels; i++) { + for (j = WINED3DCUBEMAP_FACE_POSITIVE_X; j <= WINED3DCUBEMAP_FACE_NEGATIVE_Z ; j++) { + IWineD3DSurfaceImpl_AddDirtyRect(This->surfaces[j][i], NULL); + IWineD3DSurface_SetGlTextureDesc(This->surfaces[j][i], This->baseTexture.textureName, cube_targets[j]); + IWineD3DSurface_LoadTexture(This->surfaces[j][i], srgb_mode); + } + } + } else { + TRACE("(%p) Texture not dirty, nothing to do\n" , iface); } LEAVE_GL(); + + /* No longer dirty */ + This->baseTexture.dirty = FALSE; return ; } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 528f6bd6be5..1904e9ae7a2 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -138,6 +138,10 @@ static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3 _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \ _basetexture.LOD = 0; \ _basetexture.dirty = TRUE; \ + _basetexture.is_srgb = FALSE; \ + _basetexture.srgb_mode_change_count = 0; \ + _basetexture.is_srgb = FALSE; \ + _basetexture.srgb_mode_change_count = 0; \ } /********************************************************** diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c index 39051f115ec..28c9a604740 100644 --- a/dlls/wined3d/stateblock.c +++ b/dlls/wined3d/stateblock.c @@ -1052,7 +1052,7 @@ static HRESULT WINAPI IWineD3DStateBlockImpl_InitStartupStateBlock(IWineD3DStat This->samplerState[i][WINED3DSAMP_MIPMAPLODBIAS ] = 0; This->samplerState[i][WINED3DSAMP_MAXMIPLEVEL ] = 0; This->samplerState[i][WINED3DSAMP_MAXANISOTROPY ] = 1; - This->samplerState[i][WINED3DSAMP_SRGBTEXTURE ] = 0; /* TODO: Gamma correction value*/ + This->samplerState[i][WINED3DSAMP_SRGBTEXTURE ] = 0; This->samplerState[i][WINED3DSAMP_ELEMENTINDEX ] = 0; /* TODO: Indicates which element of a multielement texture to use */ This->samplerState[i][WINED3DSAMP_DMAPOFFSET ] = 0; /* TODO: Vertex offset in the presampled displacement map */ } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index ffa9a40c01b..794cd0a7606 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -98,6 +98,8 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { BOOL setGlTextureDesc = FALSE; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + BOOL srgb_mode = This->baseTexture.is_srgb; + BOOL srgb_was_toggled = FALSE; TRACE("(%p) : About to load texture\n", This); @@ -110,26 +112,40 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { ENTER_GL(); ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); LEAVE_GL(); + } else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { + srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; + srgb_was_toggled = This->baseTexture.is_srgb != srgb_mode; + This->baseTexture.is_srgb = srgb_mode; } IWineD3DTexture_BindTexture(iface); ENTER_GL(); - /* If were dirty then reload the surfaces */ - if(This->baseTexture.dirty) { - + /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */ + if (This->baseTexture.dirty) { for (i = 0; i < This->baseTexture.levels; i++) { if(setGlTextureDesc) IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], This->baseTexture.textureName, IWineD3DTexture_GetTextureDimensions(iface)); - IWineD3DSurface_LoadTexture(This->surfaces[i], FALSE); + IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); } + } else if (srgb_was_toggled) { + if (This->baseTexture.srgb_mode_change_count < 20) + ++This->baseTexture.srgb_mode_change_count; + else + FIXME("Texture (%p) has been reloaded at least 20 times due to WINED3DSAMP_SRGBTEXTURE changes on it\'s sampler\n", This); - /* No longer dirty */ - This->baseTexture.dirty = FALSE; + for (i = 0; i < This->baseTexture.levels; i++) { + IWineD3DSurfaceImpl_AddDirtyRect(This->surfaces[i], NULL); + IWineD3DSurface_SetGlTextureDesc(This->surfaces[i], This->baseTexture.textureName, IWineD3DTexture_GetTextureDimensions(iface)); + IWineD3DSurface_LoadTexture(This->surfaces[i], srgb_mode); + } } else { TRACE("(%p) Texture not dirty, nothing to do\n" , iface); } LEAVE_GL(); + /* No longer dirty */ + This->baseTexture.dirty = FALSE; + return ; } diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 6f748df6a98..33e6234f6c2 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -95,6 +95,8 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac int i; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; + BOOL srgb_mode = This->baseTexture.is_srgb; + BOOL srgb_was_toggled = FALSE; TRACE("(%p) : About to load texture\n", This); @@ -103,18 +105,33 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac ENTER_GL(); if(!device->isInDraw) { ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD); + } else if (GL_SUPPORT(EXT_TEXTURE_SRGB) && This->baseTexture.bindCount > 0) { + srgb_mode = device->stateBlock->samplerState[This->baseTexture.sampler][WINED3DSAMP_SRGBTEXTURE]; + srgb_was_toggled = This->baseTexture.is_srgb != srgb_mode; + This->baseTexture.is_srgb = srgb_mode; } - /* If were dirty then reload the volumes */ - if(This->baseTexture.dirty) { - for (i = 0; i < This->baseTexture.levels; i++) { - IWineD3DVolume_LoadTexture(This->volumes[i], i, FALSE); - } + /* If the texture is marked dirty or the srgb sampler setting has changed since the last load then reload the surfaces */ + if (This->baseTexture.dirty) { + for (i = 0; i < This->baseTexture.levels; i++) + IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + } else if (srgb_was_toggled) { + if (This->baseTexture.srgb_mode_change_count < 20) + ++This->baseTexture.srgb_mode_change_count; + else + FIXME("Volumetexture (%p) has been reloaded at least 20 times due to WINED3DSAMP_SRGBTEXTURE changes on it\'s sampler\n", This); - /* No longer dirty */ - This->baseTexture.dirty = FALSE; + for (i = 0; i < This->baseTexture.levels; i++) { + IWineD3DVolume_AddDirtyBox(This->volumes[i], NULL); + IWineD3DVolume_LoadTexture(This->volumes[i], i, srgb_mode); + } + } else { + TRACE("(%p) Texture not dirty, nothing to do\n" , iface); } LEAVE_GL(); + /* No longer dirty */ + This->baseTexture.dirty = FALSE; + return ; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a76faddd131..facdebec229 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -883,6 +883,8 @@ typedef struct IWineD3DBaseTextureClass DWORD states[MAX_WINETEXTURESTATES]; LONG bindCount; DWORD sampler; + BOOL is_srgb; + UINT srgb_mode_change_count; } IWineD3DBaseTextureClass; typedef struct IWineD3DBaseTextureImpl