Commit 943fb2fb authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

wined3d: Do RGB <=> sRGB transfers using FBO blits.

Concept based on a patch by Stefan.
parent fd6d9cd8
......@@ -5821,7 +5821,7 @@ void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surfa
} else {
TRACE("Source surface %p is offscreen\n", src_surface);
ENTER_GL();
context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL);
context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, src_surface, NULL, SFLAG_INTEXTURE);
glReadBuffer(GL_COLOR_ATTACHMENT0);
checkGLcall("glReadBuffer()");
}
......@@ -5849,7 +5849,7 @@ void stretch_rect_fbo(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surfa
TRACE("Destination surface %p is offscreen\n", dst_surface);
ENTER_GL();
context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL);
context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, dst_surface, NULL, SFLAG_INTEXTURE);
context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
}
......
......@@ -4206,6 +4206,43 @@ static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT
context_release(context);
}
static void surface_load_srgb_fbo(IWineD3DSurfaceImpl *surface, DWORD location)
{
IWineD3DDeviceImpl *device = surface->resource.device;
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
context = context_acquire(device, NULL);
gl_info = context->gl_info;
ENTER_GL();
context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, surface, NULL,
location == SFLAG_INSRGBTEX ? SFLAG_INTEXTURE : SFLAG_INSRGBTEX);
glReadBuffer(GL_COLOR_ATTACHMENT0);
checkGLcall("glReadBuffer()");
context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, surface, NULL, location);
context_set_draw_buffer(context, GL_COLOR_ATTACHMENT0);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE));
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE1));
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE2));
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_COLORWRITEENABLE3));
glDisable(GL_SCISSOR_TEST);
IWineD3DDeviceImpl_MarkStateDirty(device, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
gl_info->fbo_ops.glBlitFramebuffer(0, 0, surface->currentDesc.Width, surface->currentDesc.Height,
0, 0, surface->currentDesc.Width, surface->currentDesc.Height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
checkGLcall("glBlitFramebuffer()");
LEAVE_GL();
context_release(context);
}
HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RECT *rect)
{
IWineD3DDeviceImpl *device = surface->resource.device;
......@@ -4360,10 +4397,20 @@ HRESULT surface_load_location(IWineD3DSurfaceImpl *surface, DWORD flag, const RE
}
else /* if(flag & (SFLAG_INTEXTURE | SFLAG_INSRGBTEX)) */
{
const DWORD attach_flags = WINED3DFMT_FLAG_FBO_ATTACHABLE | WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
if (drawable_read_ok && (surface->Flags & SFLAG_INDRAWABLE))
{
read_from_framebuffer_texture(surface, flag == SFLAG_INSRGBTEX);
}
else if (surface->Flags & (SFLAG_INSRGBTEX | SFLAG_INTEXTURE)
&& (surface->resource.format_desc->Flags & attach_flags) == attach_flags
&& fbo_blit_supported(gl_info, BLIT_OP_BLIT,
NULL, surface->resource.usage, surface->resource.pool, surface->resource.format_desc,
NULL, surface->resource.usage, surface->resource.pool, surface->resource.format_desc))
{
surface_load_srgb_fbo(surface, flag);
}
else
{
/* Upload from system memory */
......
......@@ -120,7 +120,7 @@ static void swapchain_blit(IWineD3DSwapChainImpl *This, struct wined3d_context *
if (gl_info->fbo_ops.glBlitFramebuffer && is_identity_fixup(backbuffer->resource.format_desc->color_fixup))
{
ENTER_GL();
context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL);
context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, SFLAG_INTEXTURE);
glReadBuffer(GL_COLOR_ATTACHMENT0);
context_bind_fbo(context, GL_DRAW_FRAMEBUFFER, NULL);
......
......@@ -1056,6 +1056,26 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
}
}
if (format_desc->glInternal != format_desc->glGammaInternal)
{
glTexImage2D(GL_TEXTURE_2D, 0, format_desc->glGammaInternal, 16, 16, 0,
format_desc->glFormat, format_desc->glType, NULL);
gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
checkGLcall("Framebuffer format check");
if (status == GL_FRAMEBUFFER_COMPLETE)
{
TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format_desc->format));
format_desc->Flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
}
else
{
WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format_desc->format));
}
}
glDeleteTextures(1, &tex);
LEAVE_GL();
......
......@@ -1164,7 +1164,7 @@ void context_apply_clear_state(struct wined3d_context *context, IWineD3DDeviceIm
UINT rt_count, IWineD3DSurfaceImpl **rts, IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN;
void context_apply_draw_state(struct wined3d_context *context, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN;
void context_apply_fbo_state_blit(struct wined3d_context *context, GLenum target,
IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil) DECLSPEC_HIDDEN;
IWineD3DSurfaceImpl *render_target, IWineD3DSurfaceImpl *depth_stencil, DWORD location) DECLSPEC_HIDDEN;
void context_attach_depth_stencil_fbo(struct wined3d_context *context,
GLenum fbo_target, IWineD3DSurfaceImpl *depth_stencil, BOOL use_render_buffer) DECLSPEC_HIDDEN;
void context_bind_fbo(struct wined3d_context *context, GLenum target, GLuint *fbo) DECLSPEC_HIDDEN;
......@@ -1979,6 +1979,7 @@ struct fbo_entry
struct list entry;
IWineD3DSurfaceImpl **render_targets;
IWineD3DSurfaceImpl *depth_stencil;
DWORD location;
BOOL attached;
GLuint id;
};
......@@ -2929,7 +2930,7 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN;
#define WINED3DFMT_FLAG_RENDERTARGET 0x00000010
#define WINED3DFMT_FLAG_FOURCC 0x00000020
#define WINED3DFMT_FLAG_FBO_ATTACHABLE 0x00000040
#define WINED3DFMT_FLAG_COMPRESSED 0x00000080
#define WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB 0x00000080
#define WINED3DFMT_FLAG_GETDC 0x00000100
#define WINED3DFMT_FLAG_FLOAT 0x00000200
#define WINED3DFMT_FLAG_BUMPMAP 0x00000400
......@@ -2937,6 +2938,7 @@ extern WINED3DFORMAT pixelformat_for_depth(DWORD depth) DECLSPEC_HIDDEN;
#define WINED3DFMT_FLAG_SRGB_WRITE 0x00001000
#define WINED3DFMT_FLAG_VTF 0x00002000
#define WINED3DFMT_FLAG_SHADOW 0x00004000
#define WINED3DFMT_FLAG_COMPRESSED 0x00008000
struct wined3d_format_desc
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment