[PATCH 1/2] winex11: fix destroying of top-level windows v4

Miklós Máté mtmkls at gmail.com
Sat Oct 15 18:21:36 CDT 2016


Fixes https://bugs.winehq.org/show_bug.cgi?id=40767

v2: move glXDestroyWindow before XDestroyWindow
v3: fix critical section, fix command serialization with xsync
    now it passes the ddraw and d3d9 tests (both vanilla and csmt)
v4: fix uninitialized variable, more xsync fixes (being paranoid now)

Signed-off-by: Miklós Máté <mtmkls at gmail.com>
---
 dlls/winex11.drv/opengl.c | 39 +++++++++++++++++++++++++++++++++------
 dlls/winex11.drv/window.c |  1 -
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index d89a193..7b0a0cf 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -1314,6 +1314,9 @@ static void free_gl_drawable( struct gl_drawable *gl )
 {
     switch (gl->type)
     {
+    case DC_GL_WINDOW:
+        pglXDestroyWindow( gdi_display, gl->drawable );
+        break;
     case DC_GL_CHILD_WIN:
         pglXDestroyWindow( gdi_display, gl->drawable );
         XDestroyWindow( gdi_display, gl->window );
@@ -1334,21 +1337,21 @@ static void free_gl_drawable( struct gl_drawable *gl )
 /***********************************************************************
  *              create_gl_drawable
  */
-static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl )
+static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl, struct x11drv_win_data *data )
 {
     gl->drawable = 0;
 
     if (GetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow())  /* top-level window */
     {
-        struct x11drv_win_data *data = get_win_data( hwnd );
-
         if (data)
         {
             gl->type = DC_GL_WINDOW;
             gl->window = create_client_window( data, gl->visual );
             if (gl->window)
+            {
                 gl->drawable = pglXCreateWindow( gdi_display, gl->format->fbconfig, gl->window, NULL );
-            release_win_data( data );
+                XSync( gdi_display, False );
+            }
         }
     }
 #ifdef SONAME_LIBXCOMPOSITE
@@ -1416,6 +1419,8 @@ static BOOL create_gl_drawable( HWND hwnd, struct gl_drawable *gl )
 static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format )
 {
     struct gl_drawable *gl, *prev;
+    Window old_client_window = None;
+    struct x11drv_win_data *data;
 
     gl = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*gl) );
     /* Default GLX and WGL swap interval is 1, but in case of glXSwapIntervalSGI
@@ -1435,12 +1440,19 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format )
     gl->rect.right  = min( max( 1, gl->rect.right ), 65535 );
     gl->rect.bottom = min( max( 1, gl->rect.bottom ), 65535 );
 
-    if (!create_gl_drawable( hwnd, gl ))
+    data = get_win_data( hwnd );
+    if (data) {
+        old_client_window = data->client_window;
+    }
+
+    if (!create_gl_drawable( hwnd, gl, data ))
     {
+        release_win_data( data );
         XFree( gl->visual );
         HeapFree( GetProcessHeap(), 0, gl );
         return FALSE;
     }
+    release_win_data( data );
 
     TRACE( "created GL drawable %lx for win %p %s\n",
            gl->drawable, hwnd, debugstr_fbconfig( format->fbconfig ));
@@ -1452,6 +1464,10 @@ static BOOL set_win_format( HWND hwnd, const struct wgl_pixel_format *format )
     {
         gl->swap_interval = prev->swap_interval;
         free_gl_drawable( prev );
+        XSync( gdi_display, False );
+        if (old_client_window) {
+            XDestroyWindow( data->display, old_client_window );
+        }
     }
     XSaveContext( gdi_display, (XID)hwnd, gl_hwnd_context, (char *)gl );
     LeaveCriticalSection( &context_section );
@@ -1566,6 +1582,7 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent )
 {
     struct gl_drawable *gl;
     GLXDrawable old_drawable;
+    struct x11drv_win_data *data;
 
     if (!(gl = get_gl_drawable( hwnd, 0 ))) return;
 
@@ -1575,6 +1592,7 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent )
     switch (gl->type)
     {
     case DC_GL_WINDOW:
+        pglXDestroyWindow( gdi_display, gl->drawable );
         break;
     case DC_GL_CHILD_WIN:
         if (parent != GetDesktopWindow()) goto done;
@@ -1590,16 +1608,20 @@ void set_gl_drawable_parent( HWND hwnd, HWND parent )
     default:
         goto done;
     }
+    XSync( gdi_display, False );
 
-    if (!create_gl_drawable( hwnd, gl ))
+    data = get_win_data( hwnd );
+    if (!create_gl_drawable( hwnd, gl, data ))
     {
         XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context );
+        release_win_data( data );
         release_gl_drawable( gl );
         XFree( gl->visual );
         HeapFree( GetProcessHeap(), 0, gl );
         __wine_set_pixel_format( hwnd, 0 );
         return;
     }
+    release_win_data( data );
     mark_drawable_dirty( old_drawable, gl->drawable );
 
 done:
@@ -1620,6 +1642,7 @@ void destroy_gl_drawable( HWND hwnd )
     {
         XDeleteContext( gdi_display, (XID)hwnd, gl_hwnd_context );
         free_gl_drawable( gl );
+        XSync( gdi_display, False );
     }
     LeaveCriticalSection( &context_section );
 }
@@ -2386,7 +2409,10 @@ static HDC X11DRV_wglGetPbufferDCARB( struct wgl_pbuffer *object )
 
     EnterCriticalSection( &context_section );
     if (!XFindContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char **)&prev ))
+    {
         free_gl_drawable( prev );
+        XSync( gdi_display, False );
+    }
     XSaveContext( gdi_display, (XID)hdc, gl_pbuffer_context, (char *)gl );
     LeaveCriticalSection( &context_section );
 
@@ -2506,6 +2532,7 @@ static int X11DRV_wglReleasePbufferDCARB( struct wgl_pbuffer *object, HDC hdc )
     {
         XDeleteContext( gdi_display, (XID)hdc, gl_pbuffer_context );
         free_gl_drawable( gl );
+        XSync( gdi_display, False );
     }
     else hdc = 0;
 
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 0de7955..8768f8b 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1437,7 +1437,6 @@ Window create_client_window( struct x11drv_win_data *data, const XVisualInfo *vi
     if (data->client_window)
     {
         XDeleteContext( data->display, data->client_window, winContext );
-        XDestroyWindow( data->display, data->client_window );
     }
 
     if (data->colormap) XFreeColormap( data->display, data->colormap );
-- 
2.9.3




More information about the wine-patches mailing list