[PATCH] winex11.drv: Recreate gl_drawable for top-level windows as non-top level when clipping for child windows is required

Micah N Gorrell mgorrell at crossover.com
Tue Apr 9 14:15:00 CDT 2019


Prevent creating a gl_drawable for a window as type DC_GL_WINDOW if the
window has children since DC_GL_WINDOW does not support clipping.

If a parent window is encountered of type DC_GL_WINDOW then recreate the
gl_drawable.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=15232
Signed-off-by: Micah N Gorrell <mgorrell at crossover.com>
---
 dlls/winex11.drv/opengl.c | 23 +++++++++++++++--------
 dlls/winex11.drv/window.c | 13 ++++++++++++-
 dlls/winex11.drv/x11drv.h |  2 +-
 3 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index 13a1da32ea..0d4fb521c4 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -1328,7 +1328,7 @@ static GLXContext create_glxcontext(Display *display, struct wgl_context *contex
 /***********************************************************************
  *              create_gl_drawable
  */
-static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel_format *format )
+static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel_format *format, BOOL have_child )
 {
     struct gl_drawable *gl, *prev;
     XVisualInfo *visual = format->visual;
@@ -1349,7 +1349,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, const struct wgl_pixel
     gl->format = format;
     gl->ref = 1;
 
-    if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())  /* top-level window */
+    if (!have_child && !GetWindow( hwnd, GW_CHILD ) && GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())  /* childless top-level window */
     {
         gl->type = DC_GL_WINDOW;
         gl->window = create_client_window( hwnd, visual );
@@ -1412,7 +1412,7 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format )
 
     if (!format->visual) return FALSE;
 
-    if (!(gl = create_gl_drawable( hwnd, format ))) return FALSE;
+    if (!(gl = create_gl_drawable( hwnd, format, FALSE ))) return FALSE;
 
     TRACE( "created GL drawable %lx for win %p %s\n",
            gl->drawable, hwnd, debugstr_fbconfig( format->fbconfig ));
@@ -1471,7 +1471,7 @@ static BOOL set_pixel_format(HDC hdc, int format, BOOL allow_change)
 /***********************************************************************
  *              sync_gl_drawable
  */
-void sync_gl_drawable( HWND hwnd )
+void sync_gl_drawable( HWND hwnd, BOOL have_child )
 {
     struct gl_drawable *old, *new;
 
@@ -1479,8 +1479,11 @@ void sync_gl_drawable( HWND hwnd )
 
     switch (old->type)
     {
+    case DC_GL_WINDOW:
+        if (!have_child) break; /* Still a childless top-level window */
+        /* fall through */
     case DC_GL_PIXMAP_WIN:
-        if (!(new = create_gl_drawable( hwnd, old->format ))) break;
+        if (!(new = create_gl_drawable( hwnd, old->format, have_child ))) break;
         mark_drawable_dirty( old, new );
         XFlush( gdi_display );
         TRACE( "Recreated GL drawable %lx to replace %lx\n", new->drawable, old->drawable );
@@ -1517,7 +1520,7 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent )
         return;
     }
 
-    if ((new = create_gl_drawable( hwnd, old->format )))
+    if ((new = create_gl_drawable( hwnd, old->format, FALSE )))
     {
         mark_drawable_dirty( old, new );
         release_gl_drawable( new );
@@ -3304,9 +3307,13 @@ static BOOL glxdrv_wglSwapBuffers( HDC hdc )
         }
         pglXSwapBuffers(gdi_display, gl->drawable);
         break;
+    case DC_GL_WINDOW:
     case DC_GL_CHILD_WIN:
         if (ctx) sync_context( ctx );
-        escape.gl_drawable = gl->window;
+        if (gl->type == DC_GL_CHILD_WIN)
+        {
+            escape.gl_drawable = gl->window;
+        }
         /* fall through */
     default:
         if (escape.gl_drawable && pglXSwapBuffersMscOML)
@@ -3362,7 +3369,7 @@ struct opengl_funcs *get_glx_driver( UINT version )
     return NULL;
 }
 
-void sync_gl_drawable( HWND hwnd )
+void sync_gl_drawable( HWND hwnd, HWND child )
 {
 }
 
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 7a3b340e19..97dee523c9 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1874,6 +1874,11 @@ static struct x11drv_win_data *X11DRV_create_win_data( HWND hwnd, const RECT *wi
 
     if (GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId()) return NULL;
 
+    /* Recreate the parent gl_drawable now that we know there are child windows
+     * that will need clipping support.
+     */
+    sync_gl_drawable( parent, TRUE );
+
     display = thread_init_display();
     init_clip_window();  /* make sure the clip window is initialized in this thread */
 
@@ -2206,6 +2211,12 @@ void CDECL X11DRV_SetParent( HWND hwnd, HWND parent, HWND old_parent )
 done:
     release_win_data( data );
     set_gl_drawable_parent( hwnd, parent );
+
+    /* Recreate the parent gl_drawable now that we know there are child windows
+     * that will need clipping support.
+     */
+    sync_gl_drawable( parent, TRUE );
+
     fetch_icon_data( hwnd, 0, 0 );
 }
 
@@ -2369,7 +2380,7 @@ void CDECL X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags
                               data->client_rect.bottom - data->client_rect.top !=
                               old_client_rect.bottom - old_client_rect.top));
         release_win_data( data );
-        if (needs_resize) sync_gl_drawable( hwnd );
+        if (needs_resize) sync_gl_drawable( hwnd, FALSE );
         return;
     }
 
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index a0308b0675..71c1f3877d 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -583,7 +583,7 @@ extern void release_win_data( struct x11drv_win_data *data ) DECLSPEC_HIDDEN;
 extern Window X11DRV_get_whole_window( HWND hwnd ) DECLSPEC_HIDDEN;
 extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
 
-extern void sync_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
+extern void sync_gl_drawable( HWND hwnd, BOOL have_child ) DECLSPEC_HIDDEN;
 extern void set_gl_drawable_parent( HWND hwnd, HWND parent ) DECLSPEC_HIDDEN;
 extern void destroy_gl_drawable( HWND hwnd ) DECLSPEC_HIDDEN;
 extern void wine_vk_surface_destroy( HWND hwnd ) DECLSPEC_HIDDEN;
-- 
2.21.0




More information about the wine-devel mailing list