From 0ed39ad13db834525f35462f4c9deec1c61786aa Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Wed, 23 Mar 2016 21:19:10 +0100 Subject: [PATCH] wined3d: Use ARB_texture_swizzle for color fixups when possible. Signed-off-by: Matteo Bruni Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/cs.c | 4 +++- dlls/wined3d/glsl_shader.c | 8 ++++---- dlls/wined3d/shader.c | 5 ++++- dlls/wined3d/texture.c | 27 +++++++++++++++++++++++++++ dlls/wined3d/utils.c | 5 ++++- dlls/wined3d/wined3d_private.h | 6 ++++++ 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 910350d4e60..0e6cc5b3efd 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -634,6 +634,7 @@ void wined3d_cs_emit_set_constant_buffer(struct wined3d_cs *cs, enum wined3d_sha static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) { + const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info; const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info; const struct wined3d_cs_set_texture *op = data; struct wined3d_texture *prev; @@ -653,7 +654,8 @@ static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data) op->texture->sampler = op->stage; if (!prev || op->texture->target != prev->target - || !is_same_fixup(new_format->color_fixup, old_format->color_fixup) + || (!is_same_fixup(new_format->color_fixup, old_format->color_fixup) + && !(can_use_texture_swizzle(gl_info, new_format) && can_use_texture_swizzle(gl_info, old_format))) || (new_fmt_flags & WINED3DFMT_FLAG_SHADOW) != (old_fmt_flags & WINED3DFMT_FLAG_SHADOW)) device_invalidate_state(cs->device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL)); diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 8892d498903..e6ef82a61e7 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -2883,9 +2883,8 @@ static void PRINTF_ATTR(9, 10) shader_glsl_gen_sample_code(const struct wined3d_ shader_glsl_swizzle_to_str(swizzle, FALSE, ins->dst[0].write_mask, dst_swizzle); - /* FIXME: We currently don't support fixups for vertex shaders or anything - * above SM3. Note that for SM4+ the sampler index doesn't have to match - * the resource index. */ + /* If ARB_texture_swizzle is supported we don't need to do anything here. + * We actually rely on it for vertex shaders and SM4+. */ if (version->type == WINED3D_SHADER_TYPE_PIXEL && version->major < 4) { const struct shader_glsl_ctx_priv *priv = ins->ctx->backend_data; @@ -8035,7 +8034,8 @@ static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct s if (gl_info->glsl_version >= MAKEDWORD_VERSION(4, 30) && gl_info->supported[WINED3D_GL_VERSION_4_3]) shader_model = 5; else if (gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50) && gl_info->supported[WINED3D_GL_VERSION_3_2] - && gl_info->supported[ARB_SHADER_BIT_ENCODING] && gl_info->supported[ARB_SAMPLER_OBJECTS]) + && gl_info->supported[ARB_SHADER_BIT_ENCODING] && gl_info->supported[ARB_SAMPLER_OBJECTS] + && gl_info->supported[ARB_TEXTURE_SWIZZLE]) shader_model = 4; /* ARB_shader_texture_lod or EXT_gpu_shader4 is required for the SM3 * texldd and texldl instructions. */ diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 9aa0fa1e167..db30868d97d 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2786,7 +2786,10 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 args->color_fixup[i] = COLOR_FIXUP_IDENTITY; continue; } - args->color_fixup[i] = texture->resource.format->color_fixup; + if (can_use_texture_swizzle(gl_info, texture->resource.format)) + args->color_fixup[i] = COLOR_FIXUP_IDENTITY; + else + args->color_fixup[i] = texture->resource.format->color_fixup; if (texture->resource.format_flags & WINED3DFMT_FLAG_SHADOW) args->shadow |= 1u << i; diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index feb691914c6..e163e83f607 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -219,6 +219,8 @@ void wined3d_texture_bind(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) { const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_format *format = texture->resource.format; + const struct color_fixup_desc fixup = format->color_fixup; struct gl_texture *gl_tex; GLenum target; @@ -330,6 +332,31 @@ void wined3d_texture_bind(struct wined3d_texture *texture, gl_info->gl_ops.gl.p_glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); checkGLcall("glTexParameteri(GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY)"); } + + if (!is_identity_fixup(fixup) && can_use_texture_swizzle(gl_info, format)) + { + static const GLenum swizzle_source[] = + { + GL_ZERO, /* CHANNEL_SOURCE_ZERO */ + GL_ONE, /* CHANNEL_SOURCE_ONE */ + GL_RED, /* CHANNEL_SOURCE_X */ + GL_GREEN, /* CHANNEL_SOURCE_Y */ + GL_BLUE, /* CHANNEL_SOURCE_Z */ + GL_ALPHA, /* CHANNEL_SOURCE_W */ + }; + struct + { + GLint x, y, z, w; + } + swizzle; + + swizzle.x = swizzle_source[fixup.x_source]; + swizzle.y = swizzle_source[fixup.y_source]; + swizzle.z = swizzle_source[fixup.z_source]; + swizzle.w = swizzle_source[fixup.w_source]; + gl_info->gl_ops.gl.p_glTexParameteriv(target, GL_TEXTURE_SWIZZLE_RGBA, &swizzle.x); + checkGLcall("glTexParameteriv(GL_TEXTURE_SWIZZLE_RGBA)"); + } } /* Context activation is done by the caller. */ diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 506bc07284f..df22e80fb69 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -4840,7 +4840,10 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d if ((texture = state->textures[i])) { - settings->op[i].color_fixup = texture->resource.format->color_fixup; + if (can_use_texture_swizzle(gl_info, texture->resource.format)) + settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY; + else + settings->op[i].color_fixup = texture->resource.format->color_fixup; if (ignore_textype) { settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index a9d2a96bc62..7b7b65bcd0c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3435,6 +3435,12 @@ static inline BOOL needs_srgb_write(const struct wined3d_context *context, && fb->render_targets[0] && fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE; } +static inline BOOL can_use_texture_swizzle(const struct wined3d_gl_info *gl_info, const struct wined3d_format *format) +{ + return gl_info->supported[ARB_TEXTURE_SWIZZLE] && !is_complex_fixup(format->color_fixup) + && !is_scaling_fixup(format->color_fixup); +} + /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"