wined3d: Use EXT_texture_sRGB_decode to avoid sRGB texture duplication.

This commit is contained in:
Henri Verbeet 2011-03-03 09:24:10 +01:00 committed by Alexandre Julliard
parent a97c1ad15e
commit 75c8e9f7b4
7 changed files with 75 additions and 32 deletions

View File

@ -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])
{

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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 */

View File

@ -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;