diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index da3053a70dc..3258909cf48 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -124,7 +124,7 @@ static void context_apply_attachment_filter_states(IWineD3DDevice *iface, IWineD glGetIntegerv(GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding); } - IWineD3DSurface_PreLoad(surface); + surface_internal_preload(surface, SRGB_RGB); glBindTexture(bind_target, surface_impl->glDescription.textureName); if (update_minfilter) glTexParameteri(bind_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -1399,7 +1399,11 @@ static inline WineD3DContext *FindContext(IWineD3DDeviceImpl *This, IWineD3DSurf /* Do that before switching the context: * Read the back buffer of the old drawable into the destination texture */ - IWineD3DSurface_PreLoad(This->lastActiveRenderTarget); + if(((IWineD3DSurfaceImpl *)This->lastActiveRenderTarget)->glDescription.srgbTextureName) { + surface_internal_preload(This->lastActiveRenderTarget, SRGB_BOTH); + } else { + surface_internal_preload(This->lastActiveRenderTarget, SRGB_RGB); + } /* Assume that the drawable will be modified by some other things now */ IWineD3DSurface_ModifyLocation(This->lastActiveRenderTarget, SFLAG_INDRAWABLE, FALSE); diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c index 30fc5499efe..c1805c85b84 100644 --- a/dlls/wined3d/cubetexture.c +++ b/dlls/wined3d/cubetexture.c @@ -91,13 +91,22 @@ static DWORD WINAPI IWineD3DCubeTextureImpl_GetPriority(IWineD3DCubeTexture *ifa return resource_get_priority((IWineD3DResource *)iface); } -static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { +void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { /* Override the IWineD3DResource Preload method */ unsigned int i,j; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL srgb_mode = This->baseTexture.is_srgb; - BOOL *dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; + BOOL srgb_mode; + BOOL *dirty; + + switch(srgb) { + case SRGB_RGB: srgb_mode = FALSE; break; + case SRGB_BOTH: cubetexture_internal_preload(iface, SRGB_RGB); + case SRGB_SRGB: srgb_mode = TRUE; break; + /* DONTKNOW, and shut up the compiler */ + default: srgb_mode = This->baseTexture.is_srgb; break; + } + dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; TRACE("(%p) : About to load texture: dirtified(%d)\n", This, *dirty); @@ -140,6 +149,10 @@ static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { return; } +static void WINAPI IWineD3DCubeTextureImpl_PreLoad(IWineD3DCubeTexture *iface) { + cubetexture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); +} + static void WINAPI IWineD3DCubeTextureImpl_UnLoad(IWineD3DCubeTexture *iface) { unsigned int i, j; IWineD3DCubeTextureImpl *This = (IWineD3DCubeTextureImpl *)iface; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 1fd37e21e9a..7b0c32af712 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -921,6 +921,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, tmpH = max(1, tmpH >> 1); } object->baseTexture.shader_color_fixup = glDesc->color_fixup; + object->baseTexture.internal_preload = texture_internal_preload; TRACE("(%p) : Created texture %p\n", This, object); return WINED3D_OK; @@ -1043,6 +1044,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *ifa tmpD = max(1, tmpD >> 1); } object->baseTexture.shader_color_fixup = glDesc->color_fixup; + object->baseTexture.internal_preload = volumetexture_internal_preload; *ppVolumeTexture = (IWineD3DVolumeTexture *) object; TRACE("(%p) : Created volume texture %p\n", This, object); @@ -1241,6 +1243,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface tmpW = max(1, tmpW >> 1); } object->baseTexture.shader_color_fixup = glDesc->color_fixup; + object->baseTexture.internal_preload = cubetexture_internal_preload; TRACE("(%p) : Created Cube Texture %p\n", This, object); *ppCubeTexture = (IWineD3DCubeTexture *) object; @@ -5529,9 +5532,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, I } if (WINED3D_OK == hr) { + IWineD3DBaseTextureImpl *pDestImpl = (IWineD3DBaseTextureImpl *) pDestinationTexture; /* Make sure that the destination texture is loaded */ - IWineD3DBaseTexture_PreLoad(pDestinationTexture); + pDestImpl->baseTexture.internal_preload(pDestinationTexture, SRGB_RGB); /* Update every surface level of the texture */ levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture); @@ -5921,7 +5925,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, LEAVE_GL(); /* Make sure the surface is loaded and up to date */ - IWineD3DSurface_PreLoad(pDestinationSurface); + surface_internal_preload(pDestinationSurface, SRGB_RGB); IWineD3DSurface_BindTexture(pDestinationSurface, FALSE); IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription); diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 30c7e127efa..3dc0b475c13 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3345,8 +3345,8 @@ static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCont if(stateblock->textures[sampler]) { BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE]; - basetexture_setsrgbcache(stateblock->textures[sampler], srgb); - IWineD3DBaseTexture_PreLoad(stateblock->textures[sampler]); + IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler]; + tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB); IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb); IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index 66fb86d22cb..eade1f15a83 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -584,7 +584,7 @@ static ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) IWineD3DSurface IWineD3DResource parts follow **************************************************** */ -static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) +void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb) { /* TODO: check for locks */ IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface; @@ -593,8 +593,9 @@ static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) TRACE("(%p)Checking to see if the container is a base texture\n", This); if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) { + IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) baseTexture; TRACE("Passing to container\n"); - IWineD3DBaseTexture_PreLoad(baseTexture); + tex_impl->baseTexture.internal_preload(baseTexture, SRGB_RGB); IWineD3DBaseTexture_Release(baseTexture); } else { TRACE("(%p) : About to load surface\n", This); @@ -613,7 +614,7 @@ static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) } } - IWineD3DSurface_LoadTexture(iface, FALSE); + IWineD3DSurface_LoadTexture(iface, srgb == SRGB_SRGB ? TRUE : FALSE); if (This->resource.pool == WINED3DPOOL_DEFAULT) { /* Tell opengl to try and keep this texture in video ram (well mostly) */ @@ -627,6 +628,10 @@ static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) return; } +static void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) { + surface_internal_preload(iface, SRGB_ANY); +} + static void surface_remove_pbo(IWineD3DSurfaceImpl *This) { This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT); This->resource.allocatedMemory = @@ -1505,7 +1510,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHD if(!This->hDC) { IWineD3DBaseSurfaceImpl_CreateDIBSection(iface); if(This->Flags & SFLAG_CLIENT) { - IWineD3DSurface_PreLoad(iface); + surface_internal_preload(iface, SRGB_RGB); } /* Use the dib section from now on if we are not using a PBO */ @@ -2475,7 +2480,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, c LEAVE_GL(); } else { /* bind the real texture, and make sure it up to date */ - IWineD3DSurface_PreLoad(iface); + surface_internal_preload(iface, SRGB_RGB); surface_bind_and_dirtify(This, FALSE); } allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width * height * 4); @@ -2608,8 +2613,10 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *M /* For client textures opengl has to be notified */ if(This->Flags & SFLAG_CLIENT) { + DWORD oldFlags = This->Flags; This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); - IWineD3DSurface_PreLoad(iface); + if(oldFlags & SFLAG_ALLOCATED) surface_internal_preload(iface, SRGB_RGB); + if(oldFlags & SFLAG_SRGBALLOCATED) surface_internal_preload(iface, SRGB_SRGB); /* And hope that the app behaves correctly and did not free the old surface memory before setting a new pointer */ } @@ -2623,9 +2630,11 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *M This->Flags &= ~SFLAG_USERPTR; if(This->Flags & SFLAG_CLIENT) { + DWORD oldFlags = This->Flags; This->Flags &= ~(SFLAG_ALLOCATED | SFLAG_SRGBALLOCATED); /* This respecifies an empty texture and opengl knows that the old memory is gone */ - IWineD3DSurface_PreLoad(iface); + if(oldFlags & SFLAG_ALLOCATED) surface_internal_preload(iface, SRGB_RGB); + if(oldFlags & SFLAG_SRGBALLOCATED) surface_internal_preload(iface, SRGB_SRGB); } } return WINED3D_OK; @@ -2775,7 +2784,7 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); - IWineD3DSurface_PreLoad((IWineD3DSurface *) This); + surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); ENTER_GL(); /* Bind the target texture */ @@ -2868,12 +2877,12 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine TRACE("Using hwstretch blit\n"); /* Activate the Proper context for reading from the source surface, set it up for blitting */ ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT); - IWineD3DSurface_PreLoad((IWineD3DSurface *) This); + surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB); noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO; if(!noBackBufferBackup && Src->glDescription.textureName == 0) { /* Get it a description */ - IWineD3DSurface_PreLoad(SrcSurface); + surface_internal_preload(SrcSurface, SRGB_RGB); } ENTER_GL(); @@ -3433,7 +3442,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const } /* Now load the surface */ - IWineD3DSurface_PreLoad((IWineD3DSurface *) Src); + surface_internal_preload((IWineD3DSurface *) Src, SRGB_RGB); /* Activate the destination context, set it up for blitting */ ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT); @@ -4572,13 +4581,13 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D if(srgb) { if((This->Flags & (SFLAG_INTEXTURE | SFLAG_INSYSMEM)) == SFLAG_INTEXTURE) { /* Performance warning ... */ - FIXME("Downloading srgb texture to reload it as rgb\n"); + FIXME("%p: Downloading rgb texture to reload it as srgb\n", This); IWineD3DSurfaceImpl_LoadLocation(iface, SFLAG_INSYSMEM, rect); } } else { if((This->Flags & SFLAG_LOCATIONS) == SFLAG_INSRGBTEX) { /* Performance warning ... */ - FIXME("Downloading srgb texture to reload it as srgb\n"); + FIXME("%p: Downloading srgb texture to reload it as rgb\n", This); IWineD3DSurfaceImpl_LoadLocation(iface, SFLAG_INSYSMEM, rect); } } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 2ae6694608a..1aabc86193a 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -92,17 +92,26 @@ static DWORD WINAPI IWineD3DTextureImpl_GetPriority(IWineD3DTexture *iface) { return resource_get_priority((IWineD3DResource *)iface); } -static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { +void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { /* Override the IWineD3DResource PreLoad method */ unsigned int i; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; IWineD3DDeviceImpl *device = This->resource.wineD3DDevice; - BOOL srgb_mode = This->baseTexture.is_srgb; - BOOL *dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; + BOOL srgb_mode; + BOOL *dirty; TRACE("(%p) : About to load texture\n", This); + switch(srgb) { + case SRGB_RGB: srgb_mode = FALSE; break; + case SRGB_BOTH: texture_internal_preload(iface, SRGB_RGB); + case SRGB_SRGB: srgb_mode = TRUE; break; + /* DONTKNOW, and shut up the compiler */ + default: srgb_mode = This->baseTexture.is_srgb; break; + } + dirty = srgb_mode ? &This->baseTexture.srgbDirty : &This->baseTexture.dirty; + if(!device->isInDraw) { /* ActivateContext sets isInDraw to TRUE when loading a pbuffer into a texture, thus no danger of * recursive calls @@ -136,6 +145,10 @@ static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { return ; } +static void WINAPI IWineD3DTextureImpl_PreLoad(IWineD3DTexture *iface) { + texture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); +} + static void WINAPI IWineD3DTextureImpl_UnLoad(IWineD3DTexture *iface) { unsigned int i; IWineD3DTextureImpl *This = (IWineD3DTextureImpl *)iface; diff --git a/dlls/wined3d/volumetexture.c b/dlls/wined3d/volumetexture.c index 29f81f7c7dd..977e883210b 100644 --- a/dlls/wined3d/volumetexture.c +++ b/dlls/wined3d/volumetexture.c @@ -90,7 +90,7 @@ static DWORD WINAPI IWineD3DVolumeTextureImpl_GetPriority(IWineD3DVolumeTexture return resource_get_priority((IWineD3DResource *)iface); } -static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *iface) { +void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb) { /* Overrider the IWineD3DResource Preload method */ int i; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; @@ -127,6 +127,10 @@ static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *ifac return ; } +static void WINAPI IWineD3DVolumeTextureImpl_PreLoad(IWineD3DVolumeTexture *iface) { + volumetexture_internal_preload((IWineD3DBaseTexture *) iface, SRGB_ANY); +} + static void WINAPI IWineD3DVolumeTextureImpl_UnLoad(IWineD3DVolumeTexture *iface) { unsigned int i; IWineD3DVolumeTextureImpl *This = (IWineD3DVolumeTextureImpl *)iface; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d3e6bf1e650..6ccd22aa18d 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1351,6 +1351,14 @@ typedef enum winetexturestates { MAX_WINETEXTURESTATES = 13, } winetexturestates; +enum WINED3DSRGB +{ + SRGB_ANY = 0, /* Uses the cached value(e.g. external calls) */ + SRGB_RGB = 1, /* Loads the rgb texture */ + SRGB_SRGB = 2, /* Loads the srgb texture */ + SRGB_BOTH = 3, /* Loads both textures */ +}; + /***************************************************************************** * IWineD3DBaseTexture implementation structure (extends IWineD3DResourceImpl) */ @@ -1370,8 +1378,14 @@ typedef struct IWineD3DBaseTextureClass const struct min_lookup *minMipLookup; const GLenum *magLookup; struct color_fixup_desc shader_color_fixup; + void (*internal_preload)(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); } IWineD3DBaseTextureClass; +void texture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); +void cubetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); +void volumetexture_internal_preload(IWineD3DBaseTexture *iface, enum WINED3DSRGB srgb); +void surface_internal_preload(IWineD3DSurface *iface, enum WINED3DSRGB srgb); + typedef struct IWineD3DBaseTextureImpl { /* IUnknown & WineD3DResource Information */