From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/opengl.c | 52 ++++++++++++++++++++++++++++++++++----- dlls/winex11.drv/x11drv.h | 3 +-- 3 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index fa477a4de6b..5b3ff6d379c 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -240,6 +240,7 @@ static INT X11DRV_ExtEscape( PHYSDEV dev, INT escape, INT in_count, LPCVOID in_d { struct x11drv_escape_get_drawable *data = out_data; data->drawable = physDev->drawable; + data->dc_rect = physDev->dc_rect; return TRUE; } break; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index f8e220df1f0..5f40f28de3d 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1822,13 +1822,34 @@ static BOOL glxdrv_wglShareLists(struct wgl_context *org, struct wgl_context *de return TRUE; }
-static void present_gl_drawable( HWND hwnd, HDC hdc, struct gl_drawable *gl, BOOL flush ) +static void set_dc_drawable( HDC hdc, Drawable drawable, const RECT *rect, int mode ) { - struct x11drv_escape_flush_gl_drawable escape = + struct x11drv_escape_set_drawable escape = { - .code = X11DRV_FLUSH_GL_DRAWABLE, - .flush = flush, + .code = X11DRV_SET_DRAWABLE, + .drawable = drawable, + .dc_rect = *rect, + .mode = mode, }; + NtGdiExtEscape( hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); +} + +static Drawable get_dc_drawable( HDC hdc, RECT *rect ) +{ + struct x11drv_escape_get_drawable escape = {.code = X11DRV_GET_DRAWABLE}; + NtGdiExtEscape( hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, sizeof(escape), (LPSTR)&escape ); + *rect = escape.dc_rect; + return escape.drawable; +} + +static void present_gl_drawable( HWND hwnd, HDC hdc, struct gl_drawable *gl, BOOL flush ) +{ + static const WCHAR displayW[] = {'D','I','S','P','L','A','Y'}; + static HDC hdc_src; + + UNICODE_STRING device_str = RTL_CONSTANT_STRING(displayW); + HWND toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); + RECT rect_dst, rect_src, rect; Drawable drawable;
if (!gl) return; @@ -1838,9 +1859,28 @@ static void present_gl_drawable( HWND hwnd, HDC hdc, struct gl_drawable *gl, BOO case DC_GL_CHILD_WIN: drawable = gl->window; break; default: drawable = 0; break; } - if (!(escape.gl_drawable = drawable)) return; + if (!drawable) return;
- NtGdiExtEscape( hdc, NULL, 0, X11DRV_ESCAPE, sizeof(escape), (LPSTR)&escape, 0, NULL ); + if (flush) XFlush( gdi_display ); + + NtUserGetClientRect( hwnd, &rect_src, NtUserGetDpiForWindow( hwnd ) ); + OffsetRect( &rect_src, -rect_src.left, -rect_src.top ); + + NtUserGetClientRect( hwnd, &rect_dst, get_win_monitor_dpi( hwnd ) ); + NtUserMapWindowPoints( hwnd, toplevel, (POINT *)&rect_dst, 2, get_win_monitor_dpi( hwnd ) ); + + pthread_mutex_lock( &context_mutex ); + + if (!hdc_src && !(hdc_src = NtGdiOpenDCW( &device_str, NULL, NULL, 0, TRUE, NULL, NULL, NULL ))) goto done; + + if (get_dc_drawable( hdc_src, &rect ) != drawable || !EqualRect( &rect, &rect_src )) + set_dc_drawable( hdc_src, drawable, &rect_src, IncludeInferiors ); + + NtGdiStretchBlt( hdc, 0, 0, rect_dst.right - rect_dst.left, rect_dst.bottom - rect_dst.top, + hdc_src, 0, 0, rect_src.right, rect_src.bottom, SRCCOPY, 0 ); + +done: + pthread_mutex_unlock( &context_mutex ); }
static void wglFinish(void) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 88560a9c9e0..b966b685ec4 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -351,8 +351,7 @@ struct x11drv_escape_get_drawable { enum x11drv_escape_codes code; /* escape code (X11DRV_GET_DRAWABLE) */ Drawable drawable; /* X drawable */ - Drawable gl_drawable; /* GL drawable */ - int pixel_format; /* internal GL pixel format */ + RECT dc_rect; /* DC rectangle relative to drawable */ };
struct x11drv_escape_flush_gl_drawable