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 ) {