From: Józef Kucia Subject: [PATCH v2 2/7] wined3d: Add support for separate sRGB formats. Message-Id: <1454681293-4405-2-git-send-email-jkucia@codeweavers.com> Date: Fri, 5 Feb 2016 15:08:08 +0100 In-Reply-To: <1454681293-4405-1-git-send-email-jkucia@codeweavers.com> References: <1454681293-4405-1-git-send-email-jkucia@codeweavers.com> Signed-off-by: Józef Kucia --- Version 2: * Remove the redundant "!!". * Store wined3d creation flags in struct d3d_info. * Pass wined3d creation flags instead of struct wined3d to wined3d_adpater_init(). * Rename should_use_separate_srgb_gl_texture() to needs_separate_srgb_gl_texture(). * Introduce a flag enabling sRGB read/write control instead of a flag enabling separate sRGB formats. * Remove the 'glGammaInternal' field from struct wined3d_format_srgb_info. * Reorganize sRGB formats initialization code. --- dlls/d3d8/directx.c | 3 +- dlls/d3d9/directx.c | 3 +- dlls/ddraw/ddraw_private.h | 3 +- dlls/wined3d/context.c | 5 ++- dlls/wined3d/device.c | 46 ++++++++++------------ dlls/wined3d/directx.c | 9 +++-- dlls/wined3d/shader.c | 16 +++----- dlls/wined3d/state.c | 12 +++--- dlls/wined3d/texture.c | 5 +-- dlls/wined3d/utils.c | 87 +++++++++++++++++++++++++++++++++--------- dlls/wined3d/wined3d_private.h | 23 +++++++++-- include/wine/wined3d.h | 1 + 12 files changed, 137 insertions(+), 76 deletions(-) diff --git a/dlls/d3d8/directx.c b/dlls/d3d8/directx.c index 0ca0dd3..5d0f6a8 100644 --- a/dlls/d3d8/directx.c +++ b/dlls/d3d8/directx.c @@ -432,7 +432,8 @@ static const struct IDirect3D8Vtbl d3d8_vtbl = BOOL d3d8_init(struct d3d8 *d3d8) { DWORD flags = WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING - | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER; + | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER + | WINED3D_SRGB_READ_WRITE_CONTROL; d3d8->IDirect3D8_iface.lpVtbl = &d3d8_vtbl; d3d8->refcount = 1; diff --git a/dlls/d3d9/directx.c b/dlls/d3d9/directx.c index fb096c4..b09809c 100644 --- a/dlls/d3d9/directx.c +++ b/dlls/d3d9/directx.c @@ -667,7 +667,8 @@ static const struct IDirect3D9ExVtbl d3d9_vtbl = BOOL d3d9_init(struct d3d9 *d3d9, BOOL extended) { - DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER; + DWORD flags = WINED3D_PRESENT_CONVERSION | WINED3D_HANDLE_RESTORE | WINED3D_PIXEL_CENTER_INTEGER + | WINED3D_SRGB_READ_WRITE_CONTROL; if (!extended) flags |= WINED3D_VIDMEM_ACCOUNTING; diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 704d6db..f2399e4 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -60,7 +60,8 @@ struct FvfToDecl #define DDRAW_STRIDE_ALIGNMENT 8 #define DDRAW_WINED3D_FLAGS (WINED3D_LEGACY_DEPTH_BIAS | WINED3D_VIDMEM_ACCOUNTING \ - | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER) + | WINED3D_RESTORE_MODE_ON_ACTIVATE | WINED3D_FOCUS_MESSAGES | WINED3D_PIXEL_CENTER_INTEGER \ + | WINED3D_SRGB_READ_WRITE_CONTROL) enum ddraw_device_state { diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 490c20f..664ef73 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -214,7 +214,7 @@ static void context_attach_surface_fbo(struct wined3d_context *context, case WINED3D_LOCATION_TEXTURE_SRGB: srgb = location == WINED3D_LOCATION_TEXTURE_SRGB; gl_info->fbo_ops.glFramebufferTexture2D(fbo_target, GL_COLOR_ATTACHMENT0 + idx, - surface->texture_target, surface_get_texture_name(surface, gl_info, srgb), + surface->texture_target, surface_get_texture_name(surface, context, srgb), surface->texture_level); checkGLcall("glFramebufferTexture2D()"); break; @@ -2470,7 +2470,8 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST); if (gl_info->supported[ARB_FRAMEBUFFER_SRGB]) { - if (device->state.render_states[WINED3D_RS_SRGBWRITEENABLE]) + if (!(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + || device->state.render_states[WINED3D_RS_SRGBWRITEENABLE]) gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB); else gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 8f39c3b..93624f8 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -403,32 +403,28 @@ void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, c } } - if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] - && device->state.render_states[WINED3D_RS_SRGBWRITEENABLE]) + if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, &device->state, fb)) { - if (fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE) - { - if (rt_count > 1) - WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB " - "support, this might cause graphical issues.\n"); - - corrected_color.r = color->r < wined3d_srgb_const1[0] - ? color->r * wined3d_srgb_const0[3] - : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] - - wined3d_srgb_const0[2]; - corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f); - corrected_color.g = color->g < wined3d_srgb_const1[0] - ? color->g * wined3d_srgb_const0[3] - : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] - - wined3d_srgb_const0[2]; - corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f); - corrected_color.b = color->b < wined3d_srgb_const1[0] - ? color->b * wined3d_srgb_const0[3] - : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] - - wined3d_srgb_const0[2]; - corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f); - color = &corrected_color; - } + if (rt_count > 1) + WARN("Clearing multiple sRGB render targets with no GL_ARB_framebuffer_sRGB " + "support, this might cause graphical issues.\n"); + + corrected_color.r = color->r < wined3d_srgb_const1[0] + ? color->r * wined3d_srgb_const0[3] + : pow(color->r, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] + - wined3d_srgb_const0[2]; + corrected_color.r = min(max(corrected_color.r, 0.0f), 1.0f); + corrected_color.g = color->g < wined3d_srgb_const1[0] + ? color->g * wined3d_srgb_const0[3] + : pow(color->g, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] + - wined3d_srgb_const0[2]; + corrected_color.g = min(max(corrected_color.g, 0.0f), 1.0f); + corrected_color.b = color->b < wined3d_srgb_const1[0] + ? color->b * wined3d_srgb_const0[3] + : pow(color->b, wined3d_srgb_const0[0]) * wined3d_srgb_const0[1] + - wined3d_srgb_const0[2]; + corrected_color.b = min(max(corrected_color.b, 0.0f), 1.0f); + color = &corrected_color; } gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index c7b63f1..afcac3b 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -3365,7 +3365,7 @@ static void wined3d_adapter_init_limits(struct wined3d_gl_info *gl_info) } /* Context activation is done by the caller. */ -static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) +static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter, DWORD wined3d_creation_flags) { static const struct { @@ -3739,6 +3739,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) adapter->d3d_info.limits.ffp_blend_stages = fragment_caps.MaxTextureBlendStages; adapter->d3d_info.limits.ffp_textures = fragment_caps.MaxSimultaneousTextures; adapter->d3d_info.shader_color_key = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_COLOR_KEY; + adapter->d3d_info.wined3d_creation_flags = wined3d_creation_flags; TRACE("Max texture stages: %u.\n", adapter->d3d_info.limits.ffp_blend_stages); if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]) @@ -5822,7 +5823,7 @@ static void wined3d_adapter_init_fb_cfgs(struct wined3d_adapter *adapter, HDC dc } } -static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) +static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal, DWORD wined3d_creation_flags) { static const DWORD supported_gl_versions[] = { @@ -5899,7 +5900,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) supported_gl_versions[i] >> 16, supported_gl_versions[i] & 0xffff); } - if (!wined3d_adapter_init_gl_caps(adapter)) + if (!wined3d_adapter_init_gl_caps(adapter, wined3d_creation_flags)) { ERR("Failed to initialize GL caps for adapter %p.\n", adapter); wined3d_caps_gl_ctx_destroy(&caps_gl_ctx); @@ -5993,7 +5994,7 @@ HRESULT wined3d_init(struct wined3d *wined3d, DWORD flags) return WINED3D_OK; } - if (!wined3d_adapter_init(&wined3d->adapters[0], 0)) + if (!wined3d_adapter_init(&wined3d->adapters[0], 0, flags)) { WARN("Failed to initialize adapter.\n"); return E_FAIL; diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index e81fc4e..8ec8a8e 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -2615,18 +2615,14 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3 UINT i; memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */ - if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE]) + if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, state->fb)) { - unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; - if (rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE) - { - static unsigned int warned = 0; + static unsigned int warned = 0; - args->srgb_correction = 1; - if (state->render_states[WINED3D_RS_ALPHABLENDENABLE] && !warned++) - WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB " - "support, expect rendering artifacts.\n"); - } + args->srgb_correction = 1; + if (state->render_states[WINED3D_RS_ALPHABLENDENABLE] && !warned++) + WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB " + "support, expect rendering artifacts.\n"); } if (shader->reg_maps.shader_version.major == 1 diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 1d80fa0..903f0d4 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3477,7 +3477,7 @@ static enum wined3d_texture_address wined3d_texture_address_mode(const struct wi } static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc *desc, - const struct wined3d_gl_info *gl_info, const DWORD *sampler_states, const struct wined3d_texture *texture) + const struct wined3d_context *context, const DWORD *sampler_states, const struct wined3d_texture *texture) { union { @@ -3513,7 +3513,8 @@ static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc desc->max_anisotropy = 1; desc->compare = texture->resource.format_flags & WINED3DFMT_FLAG_SHADOW; desc->comparison_func = WINED3D_CMP_LESSEQUAL; - desc->srgb_decode = sampler_states[WINED3D_SAMP_SRGB_TEXTURE]; + desc->srgb_decode = !(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + || sampler_states[WINED3D_SAMP_SRGB_TEXTURE]; if (!(texture->resource.format_flags & WINED3DFMT_FLAG_FILTERING)) { @@ -3525,7 +3526,7 @@ static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc if (texture->flags & WINED3D_TEXTURE_COND_NP2) { desc->mip_filter = WINED3D_TEXF_NONE; - if (gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]) + if (context->gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT]) desc->min_filter = WINED3D_TEXF_POINT; } } @@ -3563,7 +3564,7 @@ static void sampler(struct wined3d_context *context, const struct wined3d_state struct gl_texture *gl_tex; unsigned int base_level; - wined3d_sampler_desc_from_sampler_states(&desc, gl_info, sampler_states, texture); + wined3d_sampler_desc_from_sampler_states(&desc, context, sampler_states, texture); wined3d_texture_bind(texture, context, srgb); if (!gl_info->supported[ARB_SAMPLER_OBJECTS]) @@ -4785,12 +4786,11 @@ static void psorigin(struct wined3d_context *context, const struct wined3d_state void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; const struct wined3d_gl_info *gl_info = context->gl_info; TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); - if (state->render_states[WINED3D_RS_SRGBWRITEENABLE] && rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE) + if (needs_srgb_write(context, state, state->fb)) gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB); else gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB); diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 88507fa..09c4ff8 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -153,7 +153,7 @@ void wined3d_texture_bind(struct wined3d_texture *texture, TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb); - if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + if (!needs_separate_srgb_gl_texture(context)) srgb = FALSE; /* sRGB mode cache for preload() calls outside drawprim. */ @@ -439,14 +439,13 @@ void wined3d_texture_load(struct wined3d_texture *texture, struct wined3d_context *context, BOOL srgb) { UINT sub_count = texture->level_count * texture->layer_count; - const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_d3d_info *d3d_info = context->d3d_info; DWORD flag; UINT i; TRACE("texture %p, context %p, srgb %#x.\n", texture, context, srgb); - if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + if (!needs_separate_srgb_gl_texture(context)) srgb = FALSE; if (srgb) diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 3100967..b8a065d 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -58,8 +58,11 @@ static const struct wined3d_format_channels formats[] = {WINED3DFMT_DXT4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_DXT5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_BC1_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {WINED3DFMT_BC1_UNORM_SRGB, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_BC2_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {WINED3DFMT_BC2_UNORM_SRGB, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_BC3_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + {WINED3DFMT_BC3_UNORM_SRGB, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_MULTI2_ARGB8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {WINED3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, @@ -961,17 +964,17 @@ static const struct wined3d_format_texture_info format_texture_info[] = WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED, EXT_TEXTURE_COMPRESSION_S3TC, NULL}, - {WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0, + {WINED3DFMT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED, EXT_TEXTURE_COMPRESSION_S3TC, NULL}, - {WINED3DFMT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0, + {WINED3DFMT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED, EXT_TEXTURE_COMPRESSION_S3TC, NULL}, - {WINED3DFMT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0, + {WINED3DFMT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED, @@ -1344,6 +1347,20 @@ static const struct wined3d_format_texture_info format_texture_info[] = ARB_FRAMEBUFFER_OBJECT, NULL}, }; +struct wined3d_format_srgb_info +{ + enum wined3d_format_id srgb_format_id; + enum wined3d_format_id base_format_id; +}; + +static const struct wined3d_format_srgb_info format_srgb_info[] = +{ + {WINED3DFMT_BC1_UNORM_SRGB, WINED3DFMT_BC1_UNORM}, + {WINED3DFMT_BC2_UNORM_SRGB, WINED3DFMT_BC2_UNORM}, + {WINED3DFMT_BC3_UNORM_SRGB, WINED3DFMT_BC3_UNORM}, + {WINED3DFMT_R8G8B8A8_UNORM_SRGB, WINED3DFMT_R8G8B8A8_UNORM}, +}; + static inline int getFmtIdx(enum wined3d_format_id format_id) { /* First check if the format is at the position of its value. @@ -2172,7 +2189,7 @@ static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx) static void query_internal_format(struct wined3d_adapter *adapter, struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info, - struct wined3d_gl_info *gl_info) + struct wined3d_gl_info *gl_info, BOOL srgb_format) { GLint count, multisample_types[MAX_MULTISAMPLE_TYPES]; struct fragment_caps fragment_caps; @@ -2192,7 +2209,7 @@ static void query_internal_format(struct wined3d_adapter *adapter, query_format_flag(gl_info, format, format->glInternal, GL_FILTER, WINED3DFMT_FLAG_FILTERING, "filtering"); - if (format->glGammaInternal != format->glInternal) + if (srgb_format || format->glGammaInternal != format->glInternal) { query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ, WINED3DFMT_FLAG_SRGB_READ, "sRGB read"); @@ -2219,7 +2236,7 @@ static void query_internal_format(struct wined3d_adapter *adapter, else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT) format_clear_flag(format, WINED3DFMT_FLAG_VTF); - if (format->glGammaInternal != format->glInternal) + if (srgb_format || format->glGammaInternal != format->glInternal) { /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */ if (!gl_info->supported[EXT_TEXTURE_SRGB]) @@ -2278,12 +2295,12 @@ static void query_internal_format(struct wined3d_adapter *adapter, static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info) { - unsigned int i; + unsigned int i, j; for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i) { - int fmt_idx = getFmtIdx(format_texture_info[i].id); - struct wined3d_format *format; + int srgb_fmt_idx = -1, fmt_idx = getFmtIdx(format_texture_info[i].id); + struct wined3d_format *format, *srgb_format; if (fmt_idx == -1) { @@ -2330,11 +2347,51 @@ static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct win format->flags[WINED3D_GL_RES_TYPE_RB] |= format_texture_info[i].flags; format->flags[WINED3D_GL_RES_TYPE_RB] &= ~WINED3DFMT_FLAG_TEXTURE; - query_internal_format(adapter, format, &format_texture_info[i], gl_info); + if (format->glGammaInternal != format->glInternal + && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)) + { + format->glGammaInternal = format->glInternal; + format_clear_flag(format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE); + } + + query_internal_format(adapter, format, &format_texture_info[i], gl_info, FALSE); /* Texture conversion stuff */ format->convert = format_texture_info[i].convert; format->conv_byte_count = format_texture_info[i].conv_byte_count; + + for (j = 0; j < sizeof(format_srgb_info) / sizeof(*format_srgb_info); ++j) + { + if (format_srgb_info[j].base_format_id == format->id) + { + srgb_fmt_idx = getFmtIdx(format_srgb_info[j].srgb_format_id); + if (srgb_fmt_idx == -1) + { + ERR("Format %s (%#x) not found.\n", + debug_d3dformat(format_srgb_info[j].srgb_format_id), + format_srgb_info[j].srgb_format_id); + return FALSE; + } + break; + } + } + + if (srgb_fmt_idx == -1) + continue; + + srgb_format = &gl_info->formats[srgb_fmt_idx]; + + *srgb_format = *format; + srgb_format->id = format_srgb_info[j].srgb_format_id; + + if (gl_info->supported[EXT_TEXTURE_SRGB] + && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)) + { + srgb_format->glInternal = format_texture_info[i].gl_srgb_internal; + srgb_format->glGammaInternal = format_texture_info[i].gl_srgb_internal; + format_set_flag(srgb_format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE); + query_internal_format(adapter, srgb_format, &format_texture_info[i], gl_info, TRUE); + } } return TRUE; @@ -4414,7 +4471,6 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d unsigned int i; DWORD ttff; DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2; - unsigned int rt_fmt_flags = state->fb->render_targets[0]->format_flags; const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_d3d_info *d3d_info = context->d3d_info; @@ -4628,14 +4684,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d break; } } - if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] - && state->render_states[WINED3D_RS_SRGBWRITEENABLE] - && rt_fmt_flags & WINED3DFMT_FLAG_SRGB_WRITE) - { - settings->sRGB_write = 1; - } else { - settings->sRGB_write = 0; - } + settings->sRGB_write = !gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, state->fb); if (d3d_info->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING] || !state->render_states[WINED3D_RS_CLIPPLANEENABLE]) { diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6f4dc36..5cab5bb 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1875,6 +1875,7 @@ struct wined3d_d3d_info BOOL vs_clipping; BOOL shader_color_key; DWORD valid_rt_mask; + DWORD wined3d_creation_flags; }; /* The adapter structure */ @@ -1884,10 +1885,10 @@ struct wined3d_adapter POINT monitor_position; enum wined3d_format_id screen_format; - struct wined3d_gl_info gl_info; + struct wined3d_gl_info gl_info; struct wined3d_d3d_info d3d_info; struct wined3d_driver_info driver_info; - WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ + WCHAR DeviceName[CCHDEVICENAME]; /* DeviceName for use with e.g. ChangeDisplaySettings */ unsigned int cfg_count; struct wined3d_pixel_format *cfgs; UINT64 vram_bytes; @@ -2526,10 +2527,16 @@ static inline struct wined3d_surface *surface_from_resource(struct wined3d_resou return CONTAINING_RECORD(resource, struct wined3d_surface, resource); } +static inline BOOL needs_separate_srgb_gl_texture(const struct wined3d_context *context) +{ + return !context->gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + && context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL; +} + static inline GLuint surface_get_texture_name(const struct wined3d_surface *surface, - const struct wined3d_gl_info *gl_info, BOOL srgb) + const struct wined3d_context *context, BOOL srgb) { - return srgb && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE] + return srgb && needs_separate_srgb_gl_texture(context) ? surface->container->texture_srgb.name : surface->container->texture_rgb.name; } @@ -3371,6 +3378,14 @@ static inline void context_apply_state(struct wined3d_context *context, state_table[rep].apply(context, state, rep); } +static inline BOOL needs_srgb_write(const struct wined3d_context *context, + const struct wined3d_state *state, const struct wined3d_fb_state *fb) +{ + return (!(context->d3d_info->wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL) + || state->render_states[WINED3D_RS_SRGBWRITEENABLE]) + && fb->render_targets[0]->format_flags & WINED3DFMT_FLAG_SRGB_WRITE; +} + /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL" diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 1e91397..73dd05c 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1230,6 +1230,7 @@ enum wined3d_display_rotation #define WINED3D_HANDLE_RESTORE 0x00000040 #define WINED3D_PIXEL_CENTER_INTEGER 0x00000080 #define WINED3D_LEGACY_FFP_LIGHTING 0x00000100 +#define WINED3D_SRGB_READ_WRITE_CONTROL 0x00000200 #define WINED3D_RESZ_CODE 0x7fa05000 -- 2.4.10