diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 744b6af60eb..c8799df333d 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -6495,6 +6495,20 @@ static void textransform(struct wined3d_context *context, const struct wined3d_s fragment_prog_arbfp(context, state, state_id); } +static void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + const struct wined3d_surface *rt = state->fb->render_targets[0]; + + TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id); + + if (state->render_states[WINED3D_RS_SRGBWRITEENABLE] + && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE) + gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB); + else + gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB); +} + static const struct StateEntryTemplate arbfp_fragmentstate_template[] = { {STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR), state_texfactor_arbfp }, WINED3D_GL_EXT_NONE }, @@ -6624,6 +6638,7 @@ static const struct StateEntryTemplate arbfp_fragmentstate_template[] = {STATE_RENDER(WINED3D_RS_FOGVERTEXMODE), { STATE_RENDER(WINED3D_RS_FOGENABLE), NULL }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3D_RS_FOGSTART), { STATE_RENDER(WINED3D_RS_FOGSTART), state_fogstartend }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3D_RS_FOGEND), { STATE_RENDER(WINED3D_RS_FOGSTART), NULL }, WINED3D_GL_EXT_NONE }, + {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), state_srgbwrite }, ARB_FRAMEBUFFER_SRGB }, {STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE), { STATE_PIXELSHADER, NULL }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3D_RS_FOGCOLOR), { STATE_RENDER(WINED3D_RS_FOGCOLOR), state_fogcolor }, WINED3D_GL_EXT_NONE }, {STATE_RENDER(WINED3D_RS_FOGDENSITY), { STATE_RENDER(WINED3D_RS_FOGDENSITY), state_fogdensity }, WINED3D_GL_EXT_NONE }, diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index e47b4e1b1e5..58397e98bc0 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -100,6 +100,7 @@ static const struct wined3d_extension_map gl_extension_map[] = {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM }, {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER }, {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT }, + {"GL_ARB_framebuffer_sRGB", ARB_FRAMEBUFFER_SRGB }, {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4 }, {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL }, {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX }, @@ -2731,6 +2732,13 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */ gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE; } + if (gl_info->supported[ARB_FRAMEBUFFER_SRGB] && !gl_info->supported[EXT_TEXTURE_SRGB_DECODE]) + { + /* Current wined3d sRGB infrastructure requires EXT_texture_sRGB_decode + * for GL_ARB_framebuffer_sRGB support (without EXT_texture_sRGB_decode + * we never render to sRGB surfaces). */ + gl_info->supported[ARB_FRAMEBUFFER_SRGB] = FALSE; + } ENTER_GL(); @@ -4608,6 +4616,8 @@ HRESULT CDECL wined3d_get_device_caps(const struct wined3d *wined3d, UINT adapte caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND; if (gl_info->supported[EXT_DRAW_BUFFERS2]) caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS; + if (gl_info->supported[ARB_FRAMEBUFFER_SRGB]) + caps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT; caps->RasterCaps = WINED3DPRASTERCAPS_DITHER | WINED3DPRASTERCAPS_PAT | diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c index 1abafbbbd52..2244ccd3ee1 100644 --- a/dlls/wined3d/shader.c +++ b/dlls/wined3d/shader.c @@ -1901,14 +1901,23 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3d_shader *shader, struct ps_compile_args *args) { struct wined3d_device *device = shader->device; + const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; const struct wined3d_texture *texture; UINT i; memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */ - if (state->render_states[WINED3D_RS_SRGBWRITEENABLE]) + if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && state->render_states[WINED3D_RS_SRGBWRITEENABLE]) { const struct wined3d_surface *rt = state->fb->render_targets[0]; - if (rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE) args->srgb_correction = 1; + if (rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE) + { + 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"); + } } if (shader->reg_maps.shader_version.major == 1 diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 0be3972b7db..0dcb4318ed0 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -3138,7 +3138,8 @@ void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_s break; } } - if (state->render_states[WINED3D_RS_SRGBWRITEENABLE] + if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] + && state->render_states[WINED3D_RS_SRGBWRITEENABLE] && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE) { settings->sRGB_write = 1; diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h index b87bc6356bc..128937a5cde 100644 --- a/dlls/wined3d/wined3d_gl.h +++ b/dlls/wined3d/wined3d_gl.h @@ -933,6 +933,7 @@ enum wined3d_gl_extension ARB_FRAGMENT_PROGRAM, ARB_FRAGMENT_SHADER, ARB_FRAMEBUFFER_OBJECT, + ARB_FRAMEBUFFER_SRGB, ARB_GEOMETRY_SHADER4, ARB_HALF_FLOAT_PIXEL, ARB_HALF_FLOAT_VERTEX, @@ -1255,6 +1256,12 @@ enum wined3d_gl_extension #define GL_TEXTURE_STENCIL_SIZE 0x88f1 #endif +/* GL_ARB_framebuffer_sRGB */ +#ifndef GL_ARB_framebuffer_sRGB +#define GL_ARB_framebuffer_sRGB 1 +#define GL_FRAMEBUFFER_SRGB 0x8db9 +#endif + /* GL_ARB_geometry_shader4 */ #ifndef GL_ARB_geometry_shader4 #define GL_ARB_geometry_shader4 1 diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 5208a799406..4a11ff2fc32 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1015,6 +1015,7 @@ enum wined3d_display_rotation #define WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS 0x00040000 #define WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING 0x00080000 #define WINED3DPMISCCAPS_FOGVERTEXCLAMPED 0x00100000 +#define WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT 0x00200000 #define WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH 24 #define WINED3DPS20_MIN_DYNAMICFLOWCONTROLDEPTH 0