[PATCH 3/4] wined3d: Use EXT_texture_sRGB_decode to avoid sRGB texture duplication.

Henri Verbeet hverbeet at codeweavers.com
Thu Mar 3 02:24:10 CST 2011


---
 dlls/wined3d/basetexture.c     |   18 +++++++++++++++---
 dlls/wined3d/context.c         |   16 +++++++++-------
 dlls/wined3d/cubetexture.c     |   12 ++++++------
 dlls/wined3d/surface.c         |   18 ++++++++++++++++++
 dlls/wined3d/texture.c         |   14 +++++++-------
 dlls/wined3d/utils.c           |   16 +++++++++++-----
 dlls/wined3d/wined3d_private.h |   13 +++++++++----
 7 files changed, 75 insertions(+), 32 deletions(-)

diff --git a/dlls/wined3d/basetexture.c b/dlls/wined3d/basetexture.c
index 09e9ff3..534847f 100644
--- a/dlls/wined3d/basetexture.c
+++ b/dlls/wined3d/basetexture.c
@@ -240,6 +240,7 @@ void basetexture_set_dirty(IWineD3DBaseTextureImpl *texture, BOOL dirty)
 /* Context activation is done by the caller. */
 HRESULT basetexture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb, BOOL *set_surface_desc)
 {
+    const struct wined3d_gl_info *gl_info = &texture->resource.device->adapter->gl_info;
     HRESULT hr = WINED3D_OK;
     GLenum textureDimensions;
     BOOL isNewTexture = FALSE;
@@ -248,7 +249,7 @@ HRESULT basetexture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb, BOOL *set_
     TRACE("texture %p, srgb %#x, set_surface_desc %p.\n", texture, srgb, set_surface_desc);
 
     texture->baseTexture.is_srgb = srgb; /* SRGB mode cache for PreLoad calls outside drawprim */
-    gl_tex = basetexture_get_gl_texture(texture, srgb);
+    gl_tex = basetexture_get_gl_texture(texture, gl_info, srgb);
 
     textureDimensions = texture->baseTexture.target;
 
@@ -279,7 +280,10 @@ HRESULT basetexture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb, BOOL *set_
         gl_tex->states[WINED3DTEXSTA_MIPFILTER]     = WINED3DTEXF_LINEAR; /* GL_NEAREST_MIPMAP_LINEAR */
         gl_tex->states[WINED3DTEXSTA_MAXMIPLEVEL]   = 0;
         gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = 1;
-        gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE]   = 0;
+        if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+            gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = TRUE;
+        else
+            gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE] = srgb;
         gl_tex->states[WINED3DTEXSTA_SHADOW]        = FALSE;
         basetexture_set_dirty(texture, TRUE);
         isNewTexture = TRUE;
@@ -374,7 +378,7 @@ void basetexture_apply_state_changes(IWineD3DBaseTextureImpl *texture,
 
     TRACE("texture %p, samplerStates %p\n", texture, samplerStates);
 
-    gl_tex = basetexture_get_gl_texture(texture, texture->baseTexture.is_srgb);
+    gl_tex = basetexture_get_gl_texture(texture, gl_info, texture->baseTexture.is_srgb);
 
     /* This function relies on the correct texture being bound and loaded. */
 
@@ -495,6 +499,14 @@ void basetexture_apply_state_changes(IWineD3DBaseTextureImpl *texture,
         gl_tex->states[WINED3DTEXSTA_MAXANISOTROPY] = aniso;
     }
 
+    /* These should always be the same unless EXT_texture_sRGB_decode is supported. */
+    if (samplerStates[WINED3DSAMP_SRGBTEXTURE] != gl_tex->states[WINED3DTEXSTA_SRGBTEXTURE])
+    {
+        glTexParameteri(textureDimensions, GL_TEXTURE_SRGB_DECODE_EXT,
+                samplerStates[WINED3DSAMP_SRGBTEXTURE] ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
+        checkGLcall("glTexParameteri(GL_TEXTURE_SRGB_DECODE_EXT)");
+    }
+
     if (!(texture->resource.format->flags & WINED3DFMT_FLAG_SHADOW)
             != !gl_tex->states[WINED3DTEXSTA_SHADOW])
     {
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 4f3cd67..8852733 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -112,7 +112,8 @@ static void context_destroy_fbo(struct wined3d_context *context, GLuint *fbo)
 }
 
 /* GL locking is done by the caller */
-static void context_apply_attachment_filter_states(IWineD3DSurfaceImpl *surface, DWORD location)
+static void context_apply_attachment_filter_states(const struct wined3d_context *context,
+        IWineD3DSurfaceImpl *surface, DWORD location)
 {
     /* Update base texture states array */
     if (surface->container.type == WINED3D_CONTAINER_TEXTURE)
@@ -127,7 +128,8 @@ static void context_apply_attachment_filter_states(IWineD3DSurfaceImpl *surface,
         {
             case SFLAG_INTEXTURE:
             case SFLAG_INSRGBTEX:
-                gl_tex = basetexture_get_gl_texture(texture, location == SFLAG_INSRGBTEX);
+                gl_tex = basetexture_get_gl_texture(texture,
+                        context->gl_info, location == SFLAG_INSRGBTEX);
                 break;
 
             default:
@@ -219,7 +221,7 @@ void context_attach_depth_stencil_fbo(struct wined3d_context *context,
         else
         {
             surface_prepare_texture(depth_stencil, gl_info, FALSE);
-            context_apply_attachment_filter_states(depth_stencil, SFLAG_INTEXTURE);
+            context_apply_attachment_filter_states(context, depth_stencil, SFLAG_INTEXTURE);
 
             if (format_flags & WINED3DFMT_FLAG_DEPTH)
             {
@@ -278,9 +280,9 @@ static void context_attach_surface_fbo(const struct wined3d_context *context,
             case SFLAG_INSRGBTEX:
                 srgb = location == SFLAG_INSRGBTEX;
                 surface_prepare_texture(surface, gl_info, srgb);
-                context_apply_attachment_filter_states(surface, location);
+                context_apply_attachment_filter_states(context, surface, location);
                 gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx,
-                        surface->texture_target, surface_get_texture_name(surface, srgb),
+                        surface->texture_target, surface_get_texture_name(surface, gl_info, srgb),
                         surface->texture_level);
                 break;
 
@@ -457,10 +459,10 @@ static void context_apply_fbo_entry(struct wined3d_context *context, GLenum targ
         for (i = 0; i < gl_info->limits.buffers; ++i)
         {
             if (entry->render_targets[i])
-                context_apply_attachment_filter_states(entry->render_targets[i], entry->location);
+                context_apply_attachment_filter_states(context, entry->render_targets[i], entry->location);
         }
         if (entry->depth_stencil)
-            context_apply_attachment_filter_states(entry->depth_stencil, SFLAG_INTEXTURE);
+            context_apply_attachment_filter_states(context, entry->depth_stencil, SFLAG_INTEXTURE);
     }
 }
 
diff --git a/dlls/wined3d/cubetexture.c b/dlls/wined3d/cubetexture.c
index 0d6d20e..2500650 100644
--- a/dlls/wined3d/cubetexture.c
+++ b/dlls/wined3d/cubetexture.c
@@ -39,16 +39,15 @@ static HRESULT cubetexture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb)
     if (set_gl_texture_desc && SUCCEEDED(hr))
     {
         UINT sub_count = texture->baseTexture.level_count * texture->baseTexture.layer_count;
+        const struct wined3d_gl_info *gl_info = &texture->resource.device->adapter->gl_info;
+        BOOL srgb_tex = !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] && texture->baseTexture.is_srgb;
+        GLuint name = srgb_tex ? texture->baseTexture.texture_srgb.name : texture->baseTexture.texture_rgb.name;
         UINT i;
 
         for (i = 0; i < sub_count; ++i)
         {
             IWineD3DSurfaceImpl *surface = surface_from_resource(texture->baseTexture.sub_resources[i]);
-
-            if (texture->baseTexture.is_srgb)
-                surface_set_texture_name(surface, texture->baseTexture.texture_srgb.name, TRUE);
-            else
-                surface_set_texture_name(surface, texture->baseTexture.texture_rgb.name, FALSE);
+            surface_set_texture_name(surface, name, srgb_tex);
         }
     }
 
@@ -60,6 +59,7 @@ static void cubetexture_preload(IWineD3DBaseTextureImpl *texture, enum WINED3DSR
 {
     UINT sub_count = texture->baseTexture.level_count * texture->baseTexture.layer_count;
     IWineD3DDeviceImpl *device = texture->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct wined3d_context *context = NULL;
     struct gl_texture *gl_tex;
     BOOL srgb_mode;
@@ -86,7 +86,7 @@ static void cubetexture_preload(IWineD3DBaseTextureImpl *texture, enum WINED3DSR
             break;
     }
 
-    gl_tex = basetexture_get_gl_texture(texture, srgb_mode);
+    gl_tex = basetexture_get_gl_texture(texture, gl_info, srgb_mode);
 
     /* We only have to activate a context for gl when we're not drawing.
      * In most cases PreLoad will be called during draw and a context was
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index 0897467..30e1d64 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -4283,6 +4283,7 @@ void surface_load_ds_location(IWineD3DSurfaceImpl *surface, struct wined3d_conte
 
 void surface_modify_location(IWineD3DSurfaceImpl *surface, DWORD flag, BOOL persistent)
 {
+    const struct wined3d_gl_info *gl_info = &surface->resource.device->adapter->gl_info;
     IWineD3DSurfaceImpl *overlay;
 
     TRACE("surface %p, location %s, persistent %#x.\n",
@@ -4301,6 +4302,12 @@ void surface_modify_location(IWineD3DSurfaceImpl *surface, DWORD flag, BOOL pers
         }
     }
 
+    if (flag & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)
+            && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    {
+        flag |= (SFLAG_INTEXTURE | SFLAG_INSRGBTEX);
+    }
+
     if (persistent)
     {
         if (((surface->flags & SFLAG_INTEXTURE) && !(flag & SFLAG_INTEXTURE))
@@ -4388,6 +4395,11 @@ HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RE
         }
     }
 
+    if (flag == SFLAG_INSRGBTEX && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    {
+        flag = SFLAG_INTEXTURE;
+    }
+
     if (surface->flags & flag)
     {
         TRACE("Location already up to date\n");
@@ -4648,6 +4660,12 @@ HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RE
         surface->flags |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
     }
 
+    if (surface->flags & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)
+            && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+    {
+        surface->flags |= (SFLAG_INTEXTURE | SFLAG_INSRGBTEX);
+    }
+
     return WINED3D_OK;
 }
 
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c
index c575e2b..0491a8e 100644
--- a/dlls/wined3d/texture.c
+++ b/dlls/wined3d/texture.c
@@ -38,18 +38,17 @@ static HRESULT texture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb)
     hr = basetexture_bind(texture, srgb, &set_gl_texture_desc);
     if (set_gl_texture_desc && SUCCEEDED(hr))
     {
-        UINT i;
+        const struct wined3d_gl_info *gl_info = &texture->resource.device->adapter->gl_info;
+        BOOL srgb_tex = !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] && texture->baseTexture.is_srgb;
         struct gl_texture *gl_tex;
+        UINT i;
 
-        if (texture->baseTexture.is_srgb)
-            gl_tex = &texture->baseTexture.texture_srgb;
-        else
-            gl_tex = &texture->baseTexture.texture_rgb;
+        gl_tex = basetexture_get_gl_texture(texture, gl_info, srgb_tex);
 
         for (i = 0; i < texture->baseTexture.level_count; ++i)
         {
             IWineD3DSurfaceImpl *surface = surface_from_resource(texture->baseTexture.sub_resources[i]);
-            surface_set_texture_name(surface, gl_tex->name, texture->baseTexture.is_srgb);
+            surface_set_texture_name(surface, gl_tex->name, srgb_tex);
         }
 
         /* Conditinal non power of two textures use a different clamping
@@ -89,6 +88,7 @@ static HRESULT texture_bind(IWineD3DBaseTextureImpl *texture, BOOL srgb)
 static void texture_preload(IWineD3DBaseTextureImpl *texture, enum WINED3DSRGB srgb)
 {
     IWineD3DDeviceImpl *device = texture->resource.device;
+    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct wined3d_context *context = NULL;
     struct gl_texture *gl_tex;
     unsigned int i;
@@ -115,7 +115,7 @@ static void texture_preload(IWineD3DBaseTextureImpl *texture, enum WINED3DSRGB s
             break;
     }
 
-    gl_tex = basetexture_get_gl_texture(texture, srgb_mode);
+    gl_tex = basetexture_get_gl_texture(texture, gl_info, srgb_mode);
 
     if (!device->isInDraw)
     {
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 07a2a74..7a156ad 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1197,12 +1197,18 @@ static BOOL init_format_texture_info(struct wined3d_gl_info *gl_info)
         format->flags |= format_texture_info[i].flags;
         format->heightscale = 1.0f;
 
-        /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
-        if (!gl_info->supported[EXT_TEXTURE_SRGB]
-                && format->glGammaInternal != format->glInternal)
+        if (format->glGammaInternal != format->glInternal)
         {
-            format->glGammaInternal = format->glInternal;
-            format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+            /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
+            if (!gl_info->supported[EXT_TEXTURE_SRGB])
+            {
+                format->glGammaInternal = format->glInternal;
+                format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
+            }
+            else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
+            {
+                format->glInternal = format->glGammaInternal;
+            }
         }
 
         /* Texture conversion stuff */
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 87d5c48..cb619a5 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1908,9 +1908,12 @@ static inline IWineD3DBaseTextureImpl *basetexture_from_resource(struct wined3d_
     return CONTAINING_RECORD(resource, IWineD3DBaseTextureImpl, resource);
 }
 
-static inline struct gl_texture *basetexture_get_gl_texture(IWineD3DBaseTextureImpl *texture, BOOL srgb)
+static inline struct gl_texture *basetexture_get_gl_texture(IWineD3DBaseTextureImpl *texture,
+        const struct wined3d_gl_info *gl_info, BOOL srgb)
 {
-    return srgb ? &texture->baseTexture.texture_srgb : &texture->baseTexture.texture_rgb;
+    return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+            ? &texture->baseTexture.texture_srgb
+            : &texture->baseTexture.texture_rgb;
 }
 
 void basetexture_apply_state_changes(IWineD3DBaseTextureImpl *texture,
@@ -2160,9 +2163,11 @@ static inline IWineD3DSurfaceImpl *surface_from_resource(struct wined3d_resource
     return CONTAINING_RECORD(resource, IWineD3DSurfaceImpl, resource);
 }
 
-static inline GLuint surface_get_texture_name(IWineD3DSurfaceImpl *surface, BOOL srgb)
+static inline GLuint surface_get_texture_name(IWineD3DSurfaceImpl *surface,
+        const struct wined3d_gl_info *gl_info, BOOL srgb)
 {
-    return srgb ? surface->texture_name_srgb : surface->texture_name;
+    return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]
+            ? surface->texture_name_srgb : surface->texture_name;
 }
 
 void surface_add_dirty_rect(IWineD3DSurfaceImpl *surface, const RECT *dirty_rect) DECLSPEC_HIDDEN;
-- 
1.7.3.4




More information about the wine-patches mailing list