From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index c28d5e2466e..d43647c8c8a 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -143,6 +143,7 @@ struct context struct hint_state hint; /* GL_HINT_BIT */ GLuint draw_fbo; /* currently bound draw FBO name */ GLuint read_fbo; /* currently bound read FBO name */ + GLboolean has_viewport; /* whether viewport has been initialized */ };
struct wgl_handle @@ -1088,7 +1089,6 @@ BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) DWORD tid = HandleToULong(teb->ClientId.UniqueThread); struct context *ctx, *prev = get_current_context( teb, NULL, NULL ); const struct opengl_funcs *funcs = teb->glTable; - struct opengl_drawable *draw, *read;
if (hglrc) { @@ -1106,11 +1106,7 @@ BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) teb->glReserved1[1] = hdc; teb->glCurrentRC = hglrc; teb->glTable = (void *)funcs; - - if ((draw = ctx->base.draw) && !ctx->draw_fbo && draw->fbo) - funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, draw->fbo ); - if ((read = ctx->base.read) && !ctx->read_fbo && read->fbo) - funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, read->fbo ); + pop_default_fbo( teb ); } else if (prev) { @@ -1310,7 +1306,6 @@ BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC DWORD tid = HandleToULong(teb->ClientId.UniqueThread); struct context *ctx, *prev = get_current_context( teb, NULL, NULL ); const struct opengl_funcs *funcs = teb->glTable; - struct opengl_drawable *draw, *read;
if (hglrc) { @@ -1329,11 +1324,7 @@ BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC teb->glReserved1[1] = read_hdc; teb->glCurrentRC = hglrc; teb->glTable = (void *)funcs; - - if ((draw = ctx->base.draw) && !ctx->draw_fbo && draw->fbo) - funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, draw->fbo ); - if ((read = ctx->base.read) && !ctx->read_fbo && read->fbo) - funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, read->fbo ); + pop_default_fbo( teb ); } else if (prev) { @@ -1488,10 +1479,17 @@ void pop_default_fbo( TEB *teb ) const struct opengl_funcs *funcs = teb->glTable; struct opengl_drawable *draw, *read; struct context *ctx; + RECT rect;
if (!(ctx = get_current_context( teb, &draw, &read ))) return; if (!ctx->draw_fbo && draw->fbo) funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, draw->fbo ); if (!ctx->read_fbo && read->fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, read->fbo ); + if (!ctx->has_viewport && draw->fbo && draw->client) + { + NtUserGetClientRect( draw->client->hwnd, &rect, NtUserGetDpiForWindow( draw->client->hwnd ) ); + funcs->p_glViewport( 0, 0, rect.right, rect.bottom ); + ctx->has_viewport = GL_TRUE; + } }
static GLenum *set_default_fbo_draw_buffers( struct context *ctx, struct opengl_drawable *draw,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/unix_wgl.c | 50 ++++++++++++++++++------------------ dlls/win32u/opengl.c | 33 ++++++++++++++++++------ include/wine/opengl_driver.h | 3 ++- 3 files changed, 52 insertions(+), 34 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index d43647c8c8a..aeddb7e7cb5 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -789,29 +789,29 @@ static BOOL check_extension_support( TEB *teb, const char *extension, const char static BOOL get_default_fbo_integer( struct context *ctx, struct opengl_drawable *draw, struct opengl_drawable *read, GLenum pname, GLint *data ) { - if (pname == GL_READ_BUFFER && !ctx->read_fbo && read->fbo) + if (pname == GL_READ_BUFFER && !ctx->read_fbo && read->read_fbo) { if (ctx->pixel_mode.read_buffer) *data = ctx->pixel_mode.read_buffer; else *data = read->doublebuffer ? GL_BACK : GL_FRONT; return TRUE; } - if ((pname == GL_DRAW_BUFFER || pname == GL_DRAW_BUFFER0) && !ctx->draw_fbo && draw->fbo) + if ((pname == GL_DRAW_BUFFER || pname == GL_DRAW_BUFFER0) && !ctx->draw_fbo && draw->draw_fbo) { if (ctx->color_buffer.draw_buffers[0]) *data = ctx->color_buffer.draw_buffers[0]; else *data = draw->doublebuffer ? GL_BACK : GL_FRONT; return TRUE; } - if (pname >= GL_DRAW_BUFFER1 && pname <= GL_DRAW_BUFFER15 && !ctx->draw_fbo && draw->fbo) + if (pname >= GL_DRAW_BUFFER1 && pname <= GL_DRAW_BUFFER15 && !ctx->draw_fbo && draw->draw_fbo) { *data = ctx->color_buffer.draw_buffers[pname - GL_DRAW_BUFFER0]; return TRUE; } - if (pname == GL_DOUBLEBUFFER && draw->fbo) + if (pname == GL_DOUBLEBUFFER && draw->draw_fbo) { *data = draw->doublebuffer; return TRUE; } - if (pname == GL_STEREO && draw->fbo) + if (pname == GL_STEREO && draw->draw_fbo) { *data = draw->stereo; return TRUE; @@ -857,12 +857,12 @@ static BOOL get_integer( TEB *teb, GLenum pname, GLint *data )
if ((ctx = get_current_context( teb, &draw, &read ))) { - if (pname == GL_DRAW_FRAMEBUFFER_BINDING && draw->fbo) + if (pname == GL_DRAW_FRAMEBUFFER_BINDING && draw->draw_fbo) { *data = ctx->draw_fbo; return TRUE; } - if (pname == GL_READ_FRAMEBUFFER_BINDING && read->fbo) + if (pname == GL_READ_FRAMEBUFFER_BINDING && read->read_fbo) { *data = ctx->read_fbo; return TRUE; @@ -1457,9 +1457,9 @@ GLuint get_default_fbo( TEB *teb, GLenum target ) struct context *ctx;
if (!(ctx = get_current_context( teb, &draw, &read ))) return 0; - if (target == GL_FRAMEBUFFER) return draw->fbo; - if (target == GL_DRAW_FRAMEBUFFER) return draw->fbo; - if (target == GL_READ_FRAMEBUFFER) return read->fbo; + if (target == GL_FRAMEBUFFER) return draw->draw_fbo; + if (target == GL_DRAW_FRAMEBUFFER) return draw->draw_fbo; + if (target == GL_READ_FRAMEBUFFER) return read->read_fbo; return 0; }
@@ -1470,8 +1470,8 @@ void push_default_fbo( TEB *teb ) struct context *ctx;
if (!(ctx = get_current_context( teb, &draw, &read ))) return; - if (!ctx->draw_fbo && draw->fbo) funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); - if (!ctx->read_fbo && read->fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); + if (!ctx->draw_fbo && draw->draw_fbo) funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 ); + if (!ctx->read_fbo && read->read_fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); }
void pop_default_fbo( TEB *teb ) @@ -1482,9 +1482,9 @@ void pop_default_fbo( TEB *teb ) RECT rect;
if (!(ctx = get_current_context( teb, &draw, &read ))) return; - if (!ctx->draw_fbo && draw->fbo) funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, draw->fbo ); - if (!ctx->read_fbo && read->fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, read->fbo ); - if (!ctx->has_viewport && draw->fbo && draw->client) + if (!ctx->draw_fbo && draw->draw_fbo) funcs->p_glBindFramebuffer( GL_DRAW_FRAMEBUFFER, draw->draw_fbo ); + if (!ctx->read_fbo && read->read_fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, read->read_fbo ); + if (!ctx->has_viewport && draw->draw_fbo && draw->client) { NtUserGetClientRect( draw->client->hwnd, &rect, NtUserGetDpiForWindow( draw->client->hwnd ) ); funcs->p_glViewport( 0, 0, rect.right, rect.bottom ); @@ -1529,7 +1529,7 @@ void wrap_glDrawBuffers( TEB *teb, GLsizei n, const GLenum *bufs ) struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !ctx->draw_fbo && draw->fbo) + if ((ctx = get_current_context( teb, &draw, NULL )) && !ctx->draw_fbo && draw->draw_fbo) bufs = set_default_fbo_draw_buffers( ctx, draw, n, bufs, buffer );
funcs->p_glDrawBuffers( n, bufs ); @@ -1542,7 +1542,7 @@ void wrap_glFramebufferDrawBuffersEXT( TEB *teb, GLuint fbo, GLsizei n, const GL struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->fbo)) + if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->draw_fbo)) bufs = set_default_fbo_draw_buffers( ctx, draw, n, bufs, buffer );
funcs->p_glFramebufferDrawBuffersEXT( fbo, n, bufs ); @@ -1555,7 +1555,7 @@ void wrap_glNamedFramebufferDrawBuffers( TEB *teb, GLuint fbo, GLsizei n, const struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->fbo)) + if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->draw_fbo)) bufs = set_default_fbo_draw_buffers( ctx, draw, n, bufs, buffer );
funcs->p_glNamedFramebufferDrawBuffers( fbo, n, bufs ); @@ -1632,7 +1632,7 @@ void wrap_glDrawBuffer( TEB *teb, GLenum buf ) struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !ctx->draw_fbo && draw->fbo) + if ((ctx = get_current_context( teb, &draw, NULL )) && !ctx->draw_fbo && draw->draw_fbo) buf = set_default_fbo_draw_buffer( ctx, draw, buf );
funcs->p_glDrawBuffer( buf ); @@ -1644,7 +1644,7 @@ void wrap_glFramebufferDrawBufferEXT( TEB *teb, GLuint fbo, GLenum mode ) struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->fbo)) + if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->draw_fbo)) mode = set_default_fbo_draw_buffer( ctx, draw, mode );
funcs->p_glFramebufferDrawBufferEXT( fbo, mode ); @@ -1656,7 +1656,7 @@ void wrap_glNamedFramebufferDrawBuffer( TEB *teb, GLuint fbo, GLenum buf ) struct opengl_drawable *draw; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->fbo)) + if ((ctx = get_current_context( teb, &draw, NULL )) && !fbo && (fbo = draw->draw_fbo)) buf = set_default_fbo_draw_buffer( ctx, draw, buf );
funcs->p_glNamedFramebufferDrawBuffer( fbo, buf ); @@ -1701,7 +1701,7 @@ void wrap_glReadBuffer( TEB *teb, GLenum src ) struct opengl_drawable *read; struct context *ctx;
- if ((ctx = get_current_context( teb, NULL, &read )) && !ctx->read_fbo && read->fbo) + if ((ctx = get_current_context( teb, NULL, &read )) && !ctx->read_fbo && read->read_fbo) src = set_default_fbo_read_buffer( ctx, read, src );
funcs->p_glReadBuffer( src ); @@ -1713,7 +1713,7 @@ void wrap_glFramebufferReadBufferEXT( TEB *teb, GLuint fbo, GLenum mode ) struct opengl_drawable *read; struct context *ctx;
- if ((ctx = get_current_context( teb, NULL, &read )) && !fbo && (fbo = read->fbo)) + if ((ctx = get_current_context( teb, NULL, &read )) && !fbo && (fbo = read->read_fbo)) mode = set_default_fbo_read_buffer( ctx, read, mode );
funcs->p_glFramebufferReadBufferEXT( fbo, mode ); @@ -1725,7 +1725,7 @@ void wrap_glNamedFramebufferReadBuffer( TEB *teb, GLuint fbo, GLenum src ) struct opengl_drawable *read; struct context *ctx;
- if ((ctx = get_current_context( teb, NULL, &read )) && !fbo && (fbo = read->fbo)) + if ((ctx = get_current_context( teb, NULL, &read )) && !fbo && (fbo = read->read_fbo)) src = set_default_fbo_read_buffer( ctx, read, src );
funcs->p_glNamedFramebufferReadBuffer( fbo, src ); @@ -1776,7 +1776,7 @@ void wrap_glGetFramebufferParameterivEXT( TEB *teb, GLuint fbo, GLenum pname, GL struct opengl_drawable *draw, *read; struct context *ctx;
- if ((ctx = get_current_context( teb, &draw, &read )) && !fbo && (fbo = draw->fbo)) + if ((ctx = get_current_context( teb, &draw, &read )) && !fbo && (fbo = draw->draw_fbo)) if (get_default_fbo_integer( ctx, draw, read, pname, params )) return;
funcs->p_glGetFramebufferParameterivEXT( fbo, pname, params ); diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index f6aa5a4c190..0cf20475bc7 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -322,7 +322,7 @@ static void framebuffer_surface_destroy( struct opengl_drawable *drawable )
static void framebuffer_surface_flush( struct opengl_drawable *drawable, UINT flags ) { - struct wgl_pixel_format desc = pixel_formats[drawable->format - 1]; + struct wgl_pixel_format draw_desc = pixel_formats[drawable->format - 1], read_desc = draw_desc; RECT rect;
TRACE( "%s, flags %#x\n", debugstr_opengl_drawable( drawable ), flags ); @@ -331,22 +331,39 @@ static void framebuffer_surface_flush( struct opengl_drawable *drawable, UINT fl if (!rect.right) rect.right = 1; if (!rect.bottom) rect.bottom = 1;
+ read_desc.samples = read_desc.sample_buffers = 0; + if (flags & GL_FLUSH_WAS_CURRENT) { - destroy_framebuffer( drawable, &desc, drawable->fbo ); - drawable->fbo = 0; + if (drawable->draw_fbo != drawable->read_fbo) + { + destroy_framebuffer( drawable, &draw_desc, drawable->draw_fbo ); + drawable->draw_fbo = 0; + } + destroy_framebuffer( drawable, &read_desc, drawable->read_fbo ); + drawable->read_fbo = 0; }
if (flags & GL_FLUSH_SET_CURRENT) { - drawable->fbo = create_framebuffer( drawable, &desc ); - if (!drawable->fbo) ERR( "Failed to create framebuffer object\n" ); + drawable->read_fbo = create_framebuffer( drawable, &read_desc ); + if (!drawable->read_fbo) ERR( "Failed to create read framebuffer object\n" ); + + if (!draw_desc.sample_buffers) drawable->draw_fbo = drawable->read_fbo; + else drawable->draw_fbo = create_framebuffer( drawable, &draw_desc ); + if (!drawable->draw_fbo) ERR( "Failed to create draw framebuffer object\n" ); }
- if ((flags & (GL_FLUSH_UPDATED | GL_FLUSH_SET_CURRENT)) && drawable->fbo) + if ((flags & (GL_FLUSH_UPDATED | GL_FLUSH_SET_CURRENT)) && drawable->read_fbo) { - TRACE( "Resizing drawable %p/%u to %ux%u\n", drawable, drawable->fbo, rect.right, rect.bottom ); - resize_framebuffer( drawable, &desc, drawable->fbo, rect.right, rect.bottom ); + TRACE( "Resizing drawable %p/%u to %ux%u\n", drawable, drawable->read_fbo, rect.right, rect.bottom ); + resize_framebuffer( drawable, &read_desc, drawable->read_fbo, rect.right, rect.bottom ); + + if (drawable->draw_fbo != drawable->read_fbo) + { + TRACE( "Resizing drawable %p/%u to %ux%u\n", drawable, drawable->draw_fbo, rect.right, rect.bottom ); + resize_framebuffer( drawable, &draw_desc, drawable->draw_fbo, rect.right, rect.bottom ); + } } }
diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 2a0cdb6859b..56f9c1c6793 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -169,7 +169,8 @@ struct opengl_drawable BOOL doublebuffer; /* pixel format is double buffered */ BOOL stereo; /* pixel format is stereo buffered */ EGLSurface surface; /* surface for EGL based drivers */ - GLuint fbo; /* default FBO name when emulating framebuffer */ + GLuint read_fbo; /* default read FBO name when emulating framebuffer */ + GLuint draw_fbo; /* default draw FBO name when emulating framebuffer */ };
static inline const char *debugstr_opengl_drawable( struct opengl_drawable *drawable )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/make_opengl | 15 ++++++ dlls/opengl32/unix_private.h | 1 + dlls/opengl32/unix_thunks.c | 22 ++++++++ dlls/opengl32/unix_wgl.c | 98 ++++++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index ef6b32dca89..60ba6e2d5b1 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -248,6 +248,20 @@ my %hide_default_fbo_thunks = "glGetFramebufferAttachmentParameteriv" => 1, "glGetFramebufferAttachmentParameterivEXT" => 1, ); +my %resolve_default_fbo_thunks = + ( + "glCopyColorTable" => 1, + "glCopyPixels" => 1, + "glCopyTexImage1D" => 1, + "glCopyTexImage2D" => 1, + "glCopyTexSubImage1D" => 1, + "glCopyTexSubImage2D" => 1, + "glCopyTexSubImage3D" => 1, + "glCopyTextureSubImage1D" => 1, + "glCopyTextureSubImage2D" => 1, + "glCopyTextureSubImage3D" => 1, + "glReadPixels" => 1, + ); my %map_default_fbo_thunks = ( "glBindFramebuffer" => [ "framebuffer" ], @@ -555,6 +569,7 @@ sub generate_unix_thunk($$$$) $target = "params->target" if $call_args =~ "params->target"; $ret .= " if (!params->$arg) params->$arg = get_default_fbo( $teb, $target );\n"; } + $ret .= " resolve_default_fbo( $teb, TRUE );\n" if defined $resolve_default_fbo_thunks{$name}; $ret .= " push_default_fbo( $teb );\n" if defined $hide_default_fbo_thunks{$name}; $ret .= " pthread_mutex_lock( &wgl_lock );\n" if $need_lock; $ret .= " $ret_expr"; diff --git a/dlls/opengl32/unix_private.h b/dlls/opengl32/unix_private.h index 9caad96ebda..4b05a98cccf 100644 --- a/dlls/opengl32/unix_private.h +++ b/dlls/opengl32/unix_private.h @@ -86,5 +86,6 @@ extern void set_current_fbo( TEB *teb, GLenum target, GLuint framebuffer ); extern GLuint get_default_fbo( TEB *teb, GLenum target ); extern void push_default_fbo( TEB *teb ); extern void pop_default_fbo( TEB *teb ); +extern void resolve_default_fbo( TEB *teb, BOOL read );
#endif /* __WINE_OPENGL32_UNIX_PRIVATE_H */ diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 98d2a018e78..820bd47929f 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -574,6 +574,7 @@ static NTSTATUS gl_glCopyPixels( void *args ) { struct glCopyPixels_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyPixels( params->x, params->y, params->width, params->height, params->type ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -583,6 +584,7 @@ static NTSTATUS gl_glCopyTexImage1D( void *args ) { struct glCopyTexImage1D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTexImage1D( params->target, params->level, params->internalformat, params->x, params->y, params->width, params->border ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -592,6 +594,7 @@ static NTSTATUS gl_glCopyTexImage2D( void *args ) { struct glCopyTexImage2D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTexImage2D( params->target, params->level, params->internalformat, params->x, params->y, params->width, params->height, params->border ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -601,6 +604,7 @@ static NTSTATUS gl_glCopyTexSubImage1D( void *args ) { struct glCopyTexSubImage1D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTexSubImage1D( params->target, params->level, params->xoffset, params->x, params->y, params->width ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -610,6 +614,7 @@ static NTSTATUS gl_glCopyTexSubImage2D( void *args ) { struct glCopyTexSubImage2D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTexSubImage2D( params->target, params->level, params->xoffset, params->yoffset, params->x, params->y, params->width, params->height ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -2196,6 +2201,7 @@ static NTSTATUS gl_glReadBuffer( void *args ) static NTSTATUS gl_glReadPixels( void *args ) { struct glReadPixels_params *params = args; + resolve_default_fbo( params->teb, TRUE ); wrap_glReadPixels( params->teb, params->x, params->y, params->width, params->height, params->format, params->type, params->pixels ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -5580,6 +5586,7 @@ static NTSTATUS ext_glCopyColorTable( void *args ) { struct glCopyColorTable_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyColorTable( params->target, params->internalformat, params->x, params->y, params->width ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -5751,6 +5758,7 @@ static NTSTATUS ext_glCopyTexSubImage3D( void *args ) { struct glCopyTexSubImage3D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTexSubImage3D( params->target, params->level, params->xoffset, params->yoffset, params->zoffset, params->x, params->y, params->width, params->height ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -5787,6 +5795,7 @@ static NTSTATUS ext_glCopyTextureSubImage1D( void *args ) { struct glCopyTextureSubImage1D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTextureSubImage1D( params->texture, params->level, params->xoffset, params->x, params->y, params->width ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -5805,6 +5814,7 @@ static NTSTATUS ext_glCopyTextureSubImage2D( void *args ) { struct glCopyTextureSubImage2D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTextureSubImage2D( params->texture, params->level, params->xoffset, params->yoffset, params->x, params->y, params->width, params->height ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -5823,6 +5833,7 @@ static NTSTATUS ext_glCopyTextureSubImage3D( void *args ) { struct glCopyTextureSubImage3D_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; + resolve_default_fbo( params->teb, TRUE ); funcs->p_glCopyTextureSubImage3D( params->texture, params->level, params->xoffset, params->yoffset, params->zoffset, params->x, params->y, params->width, params->height ); set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -30894,6 +30905,7 @@ static NTSTATUS wow64_gl_glCopyPixels( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyPixels( params->x, params->y, params->width, params->height, params->type ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -30914,6 +30926,7 @@ static NTSTATUS wow64_gl_glCopyTexImage1D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTexImage1D( params->target, params->level, params->internalformat, params->x, params->y, params->width, params->border ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -30935,6 +30948,7 @@ static NTSTATUS wow64_gl_glCopyTexImage2D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTexImage2D( params->target, params->level, params->internalformat, params->x, params->y, params->width, params->height, params->border ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -30954,6 +30968,7 @@ static NTSTATUS wow64_gl_glCopyTexSubImage1D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTexSubImage1D( params->target, params->level, params->xoffset, params->x, params->y, params->width ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -30975,6 +30990,7 @@ static NTSTATUS wow64_gl_glCopyTexSubImage2D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTexSubImage2D( params->target, params->level, params->xoffset, params->yoffset, params->x, params->y, params->width, params->height ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -33675,6 +33691,7 @@ static NTSTATUS wow64_gl_glReadPixels( void *args ) PTR32 pixels; } *params = args; TEB *teb = get_teb64( params->teb ); + resolve_default_fbo( teb, TRUE ); wrap_glReadPixels( teb, params->x, params->y, params->width, params->height, params->format, params->type, ULongToPtr(params->pixels) ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -39916,6 +39933,7 @@ static NTSTATUS wow64_ext_glCopyColorTable( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyColorTable( params->target, params->internalformat, params->x, params->y, params->width ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -40308,6 +40326,7 @@ static NTSTATUS wow64_ext_glCopyTexSubImage3D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTexSubImage3D( params->target, params->level, params->xoffset, params->yoffset, params->zoffset, params->x, params->y, params->width, params->height ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -40392,6 +40411,7 @@ static NTSTATUS wow64_ext_glCopyTextureSubImage1D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTextureSubImage1D( params->texture, params->level, params->xoffset, params->x, params->y, params->width ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -40433,6 +40453,7 @@ static NTSTATUS wow64_ext_glCopyTextureSubImage2D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTextureSubImage2D( params->texture, params->level, params->xoffset, params->yoffset, params->x, params->y, params->width, params->height ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; @@ -40477,6 +40498,7 @@ static NTSTATUS wow64_ext_glCopyTextureSubImage3D( void *args ) } *params = args; TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = teb->glTable; + resolve_default_fbo( teb, TRUE ); funcs->p_glCopyTextureSubImage3D( params->texture, params->level, params->xoffset, params->yoffset, params->zoffset, params->x, params->y, params->width, params->height ); set_context_attribute( teb, -1 /* unsupported */, NULL, 0 ); return STATUS_SUCCESS; diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index aeddb7e7cb5..46184fcd7a4 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1164,12 +1164,14 @@ void wrap_glFinish( TEB *teb ) { const struct opengl_funcs *funcs = teb->glTable; flush_context( teb, funcs->p_glFinish ); + resolve_default_fbo( teb, FALSE ); }
void wrap_glFlush( TEB *teb ) { const struct opengl_funcs *funcs = teb->glTable; flush_context( teb, funcs->p_glFlush ); + resolve_default_fbo( teb, FALSE ); }
void wrap_glClear( TEB *teb, GLbitfield mask ) @@ -1177,6 +1179,7 @@ void wrap_glClear( TEB *teb, GLbitfield mask ) const struct opengl_funcs *funcs = teb->glTable; flush_context( teb, NULL ); funcs->p_glClear( mask ); + resolve_default_fbo( teb, FALSE ); }
void wrap_glDrawPixels( TEB *teb, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels ) @@ -1184,6 +1187,7 @@ void wrap_glDrawPixels( TEB *teb, GLsizei width, GLsizei height, GLenum format, const struct opengl_funcs *funcs = teb->glTable; flush_context( teb, NULL ); funcs->p_glDrawPixels( width, height, format, type, pixels ); + resolve_default_fbo( teb, FALSE ); }
void wrap_glReadPixels( TEB *teb, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels ) @@ -1198,6 +1202,7 @@ void wrap_glViewport( TEB *teb, GLint x, GLint y, GLsizei width, GLsizei height const struct opengl_funcs *funcs = teb->glTable; flush_context( teb, NULL ); funcs->p_glViewport( x, y, width, height ); + resolve_default_fbo( teb, FALSE ); }
BOOL wrap_wglSwapBuffers( TEB *teb, HDC hdc ) @@ -1205,6 +1210,8 @@ BOOL wrap_wglSwapBuffers( TEB *teb, HDC hdc ) const struct opengl_funcs *funcs = get_dc_funcs( hdc ); BOOL ret;
+ resolve_default_fbo( teb, FALSE ); + if (!(ret = funcs->p_wglSwapBuffers( hdc ))) { /* default implementation: implicitly flush the context */ @@ -1492,6 +1499,97 @@ void pop_default_fbo( TEB *teb ) } }
+static BOOL context_draws_back( struct context *ctx ) +{ + for (int i = 0; i < ARRAY_SIZE(ctx->color_buffer.draw_buffers); i++) + { + switch (ctx->color_buffer.draw_buffers[i]) + { + case GL_LEFT: + case GL_RIGHT: + case GL_BACK: + case GL_FRONT_AND_BACK: + case GL_BACK_LEFT: + case GL_BACK_RIGHT: + return TRUE; + } + } + + return FALSE; +} + +static BOOL context_draws_front( struct context *ctx ) +{ + for (int i = 0; i < ARRAY_SIZE(ctx->color_buffer.draw_buffers); i++) + { + switch (ctx->color_buffer.draw_buffers[i]) + { + case GL_LEFT: + case GL_RIGHT: + case GL_FRONT: + case GL_FRONT_AND_BACK: + case GL_FRONT_LEFT: + case GL_FRONT_RIGHT: + return TRUE; + } + } + + return FALSE; +} + +void resolve_default_fbo( TEB *teb, BOOL read ) +{ + const struct opengl_funcs *funcs = teb->glTable; + struct opengl_drawable *drawable; + struct context *ctx; + + if (!(ctx = get_current_context( teb, read ? NULL : &drawable, read ? &drawable : NULL )) || !drawable) return; + + if (drawable->draw_fbo && drawable->read_fbo && drawable->draw_fbo != drawable->read_fbo) + { + GLenum mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + RECT rect; + + NtUserGetClientRect( drawable->client->hwnd, &rect, NtUserGetDpiForWindow( drawable->client->hwnd ) ); + + if (context_draws_front( ctx )) + { + funcs->p_glNamedFramebufferReadBuffer( drawable->draw_fbo, GL_COLOR_ATTACHMENT0 ); + funcs->p_glNamedFramebufferDrawBuffer( drawable->read_fbo, GL_COLOR_ATTACHMENT0 ); + funcs->p_glBlitNamedFramebuffer( drawable->draw_fbo, drawable->read_fbo, 0, 0, 0, 0, rect.right, rect.bottom, + rect.right, rect.bottom, mask, GL_NEAREST ); + mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + if ((drawable->doublebuffer && context_draws_back( ctx )) || (!drawable->doublebuffer && drawable->stereo && context_draws_front( ctx ))) + { + funcs->p_glNamedFramebufferReadBuffer( drawable->draw_fbo, GL_COLOR_ATTACHMENT1 ); + funcs->p_glNamedFramebufferDrawBuffer( drawable->read_fbo, GL_COLOR_ATTACHMENT1 ); + funcs->p_glBlitNamedFramebuffer( drawable->draw_fbo, drawable->read_fbo, 0, 0, 0, 0, rect.right, rect.bottom, + rect.right, rect.bottom, mask, GL_NEAREST ); + mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + if (drawable->doublebuffer && drawable->stereo && context_draws_front( ctx )) + { + funcs->p_glNamedFramebufferReadBuffer( drawable->draw_fbo, GL_COLOR_ATTACHMENT2 ); + funcs->p_glNamedFramebufferDrawBuffer( drawable->read_fbo, GL_COLOR_ATTACHMENT2 ); + funcs->p_glBlitNamedFramebuffer( drawable->draw_fbo, drawable->read_fbo, 0, 0, 0, 0, rect.right, rect.bottom, + rect.right, rect.bottom, mask, GL_NEAREST ); + mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + + if (drawable->doublebuffer && drawable->stereo && context_draws_back( ctx )) + { + funcs->p_glNamedFramebufferReadBuffer( drawable->draw_fbo, GL_COLOR_ATTACHMENT3 ); + funcs->p_glNamedFramebufferDrawBuffer( drawable->read_fbo, GL_COLOR_ATTACHMENT3 ); + funcs->p_glBlitNamedFramebuffer( drawable->draw_fbo, drawable->read_fbo, 0, 0, 0, 0, rect.right, rect.bottom, + rect.right, rect.bottom, mask, GL_NEAREST ); + mask &= ~(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + } + } +} + static GLenum *set_default_fbo_draw_buffers( struct context *ctx, struct opengl_drawable *draw, GLsizei count, const GLenum *src, GLenum *dst ) {