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@codeweavers.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, BOOL have_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;
On Apr 9, 2019, at 2:40 PM, Micah N Gorrell mgorrell@codeweavers.com wrote:
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@codeweavers.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 */
The main issue I have is with the name "have_child". It's too… definitive. When it's passed as false (from X11DRV_WindowPosChanged()), that doesn't mean there definitely aren't children, just that we don't know definitively whether there are or aren't. (If it were definitive, then the GetWindow(…, GW_CHILD) check wouldn't be needed.)
Perhaps "known_child"?
Otherwise, looks good to me.
-Ken
On Wed, Apr 10, 2019 at 01:45:21PM -0500, Ken Thomases wrote:
On Apr 9, 2019, at 2:40 PM, Micah N Gorrell mgorrell@codeweavers.com wrote:
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@codeweavers.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 */
The main issue I have is with the name "have_child". It's too… definitive. When it's passed as false (from X11DRV_WindowPosChanged()), that doesn't mean there definitely aren't children, just that we don't know definitively whether there are or aren't. (If it were definitive, then the GetWindow(…, GW_CHILD) check wouldn't be needed.)
Perhaps "known_child"?
Otherwise, looks good to me.
-Ken
Good point. You're absolutely right. When it is TRUE we know there is a child but in many cases we don't know. I'll rename and send a new updated patch in a moment.
-Micah
Prevent creating a gl_drawable for a window as type DC_GL_WINDOW if there are known children of the window, since DC_GL_WINDOW does not support clipping.
Recreate a gl_drawable that was previously create as type DC_GL_WINDOW when a child is encountered.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=15232 Signed-off-by: Micah N Gorrell mgorrell@codeweavers.com --- v2: Renamed have_child argument to known_child
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..d595e534f4 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 known_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 (!known_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 known_child ) { struct gl_drawable *old, *new;
@@ -1479,8 +1479,11 @@ void sync_gl_drawable( HWND hwnd )
switch (old->type) { + case DC_GL_WINDOW: + if (!known_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, known_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, BOOL known_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..c633102a38 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 known_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;