From: Rémi Bernon rbernon@codeweavers.com
http://bugs.winehq.org/show_bug.cgi?id=58812 --- dlls/opengl32/unix_wgl.c | 98 +++++++++++++++++++++-------------- dlls/win32u/opengl.c | 5 +- dlls/winewayland.drv/opengl.c | 4 ++ dlls/winex11.drv/opengl.c | 4 ++ include/wine/opengl_driver.h | 2 +- 5 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 775836115ce..caeefeea18e 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -1193,16 +1193,72 @@ static GLenum drawable_buffer_from_buffer( struct opengl_drawable *drawable, GLe return drawable->buffer_map[buffer - GL_FRONT_LEFT]; }
+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; +} + static void flush_context( TEB *teb, void (*flush)(void) ) { - struct context *ctx = get_current_context( teb, NULL, NULL ); + struct opengl_drawable *read, *draw; + struct context *ctx = get_current_context( teb, &read, &draw ); const struct opengl_funcs *funcs = teb->glTable; + BOOL force_swap = flush && !ctx->draw_fbo && context_draws_front( ctx ) && + draw->buffer_map[0] == GL_BACK_LEFT && draw->client;
- if (!ctx || !funcs->p_wgl_context_flush( &ctx->base, flush )) + if (!ctx || !funcs->p_wgl_context_flush( &ctx->base, flush, force_swap )) { /* default implementation: call the functions directly */ if (flush) flush(); } + + if (force_swap) + { + GLenum mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + RECT rect; + + WARN( "Front buffer rendering emulation, copying front buffer back\n" ); + + NtUserGetClientRect( draw->client->hwnd, &rect, NtUserGetDpiForWindow( draw->client->hwnd ) ); + if (ctx->read_fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); + funcs->p_glReadBuffer( GL_FRONT_LEFT ); + funcs->p_glBlitFramebuffer( 0, 0, 0, 0, rect.right, rect.bottom, rect.right, rect.bottom, mask, GL_NEAREST ); + if (ctx->read_fbo) funcs->p_glBindFramebuffer( GL_READ_FRAMEBUFFER, ctx->read_fbo ); + else funcs->p_glReadBuffer( drawable_buffer_from_buffer( read, ctx->pixel_mode.read_buffer ) ); + } }
void wrap_glFinish( TEB *teb ) @@ -1567,44 +1623,6 @@ 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; diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 454eb50d0b0..fc0be5795d4 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -2174,7 +2174,7 @@ static BOOL flush_memory_pbuffer( void (*flush)(void) ) return flush_memory_dc( context, draw_hdc, FALSE, flush ); }
-static BOOL win32u_wgl_context_flush( struct wgl_context *context, void (*flush)(void) ) +static BOOL win32u_wgl_context_flush( struct wgl_context *context, void (*flush)(void), BOOL force_swap ) { const struct opengl_funcs *funcs = &display_funcs; struct opengl_drawable *draw = context->draw; @@ -2190,7 +2190,8 @@ static BOOL win32u_wgl_context_flush( struct wgl_context *context, void (*flush)
if (flush) flush(); if (flush == funcs->p_glFinish) flags |= GL_FLUSH_FINISHED; - opengl_drawable_flush( context->draw, interval, flags ); + opengl_drawable_flush( draw, interval, flags ); + if (force_swap) opengl_drawable_swap( draw );
return TRUE; } diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 158ad106fe3..22bd2541581 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -113,6 +113,10 @@ static BOOL wayland_opengl_surface_create(HWND hwnd, int format, struct opengl_d gl = opengl_drawable_create(sizeof(*gl), &wayland_drawable_funcs, format, &client->client); client_surface_release(&client->client); if (!gl) return FALSE; + gl->base.buffer_map[0] = GL_BACK_LEFT; + gl->base.buffer_map[1] = GL_BACK_RIGHT; + gl->base.buffer_map[GL_FRONT - GL_FRONT_LEFT] = GL_BACK; + gl->base.buffer_map[GL_FRONT_AND_BACK - GL_FRONT_LEFT] = GL_BACK;
if (!(gl->wl_egl_window = wl_egl_window_create(client->wl_surface, rect.right, rect.bottom))) goto err; if (!(gl->base.surface = funcs->p_eglCreateWindowSurface(egl->display, config, gl->wl_egl_window, attribs))) goto err; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 3611662f37e..c4cc2b1fe1f 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -521,6 +521,10 @@ static BOOL x11drv_egl_surface_create( HWND hwnd, int format, struct opengl_draw gl = opengl_drawable_create( sizeof(*gl), &x11drv_egl_surface_funcs, format, client ); client_surface_release( client ); if (!gl) return FALSE; + gl->base.buffer_map[0] = GL_BACK_LEFT; + gl->base.buffer_map[1] = GL_BACK_RIGHT; + gl->base.buffer_map[GL_FRONT - GL_FRONT_LEFT] = GL_BACK; + gl->base.buffer_map[GL_FRONT_AND_BACK - GL_FRONT_LEFT] = GL_BACK;
if (!(gl->base.surface = funcs->p_eglCreateWindowSurface( egl->display, egl_config_for_format( format ), (void *)window, NULL ))) diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 67aa27e0ee1..e9052392471 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -83,7 +83,7 @@ struct wgl_context struct opengl_funcs { BOOL (*p_wgl_context_reset)( struct wgl_context *context, HDC hdc, struct wgl_context *share, const int *attribs ); - BOOL (*p_wgl_context_flush)( struct wgl_context *context, void (*flush)(void) ); + BOOL (*p_wgl_context_flush)( struct wgl_context *context, void (*flush)(void), BOOL force_swap ); BOOL (*p_wglCopyContext)( struct wgl_context * hglrcSrc, struct wgl_context * hglrcDst, UINT mask ); struct wgl_context * (*p_wglCreateContext)( HDC hDc ); BOOL (*p_wglDeleteContext)( struct wgl_context * oldContext );