gdk: Add private GLContext::is_current() check

... and use this check in gdk_gl_context_make_current() and
gdk_gl_context_get_current() to make sure the context really is still
current.

The context no longer being current can happen when external GL
implementations make their own contexts current in the same threads GDK
contexts are used in.
And that can happen for example by WebKit.

Theoretically, this should also allow external EGL code to run in X11
applications when GDK chooses to use GLX, but I didn't try it.

Fixes #5392
This commit is contained in:
Benjamin Otte 2023-02-02 02:49:56 +01:00
parent fdea27c04d
commit c6cef6db52
5 changed files with 57 additions and 2 deletions

View File

@ -501,6 +501,18 @@ gdk_gl_context_real_is_shared (GdkGLContext *self,
return TRUE; return TRUE;
} }
static gboolean
gdk_gl_context_real_is_current (GdkGLContext *self)
{
#ifdef HAVE_EGL
GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (self);
return priv->egl_context == eglGetCurrentContext ();
#else
return TRUE;
#endif
}
static gboolean static gboolean
gdk_gl_context_real_clear_current (GdkGLContext *context) gdk_gl_context_real_clear_current (GdkGLContext *context)
{ {
@ -670,6 +682,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
klass->is_shared = gdk_gl_context_real_is_shared; klass->is_shared = gdk_gl_context_real_is_shared;
klass->make_current = gdk_gl_context_real_make_current; klass->make_current = gdk_gl_context_real_make_current;
klass->clear_current = gdk_gl_context_real_clear_current; klass->clear_current = gdk_gl_context_real_clear_current;
klass->is_current = gdk_gl_context_real_is_current;
klass->get_default_framebuffer = gdk_gl_context_real_get_default_framebuffer; klass->get_default_framebuffer = gdk_gl_context_real_get_default_framebuffer;
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame; draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
@ -1551,6 +1564,12 @@ gdk_gl_context_check_extensions (GdkGLContext *context)
priv->extensions_checked = TRUE; priv->extensions_checked = TRUE;
} }
static gboolean
gdk_gl_context_check_is_current (GdkGLContext *context)
{
return GDK_GL_CONTEXT_GET_CLASS (context)->is_current (context);
}
/** /**
* gdk_gl_context_make_current: * gdk_gl_context_make_current:
* @context: a `GdkGLContext` * @context: a `GdkGLContext`
@ -1569,7 +1588,7 @@ gdk_gl_context_make_current (GdkGLContext *context)
masked_context = mask_context (context, surfaceless); masked_context = mask_context (context, surfaceless);
current = g_private_get (&thread_current_context); current = g_private_get (&thread_current_context);
if (current == masked_context) if (current == masked_context && gdk_gl_context_check_is_current (context))
return; return;
/* we need to realize the GdkGLContext if it wasn't explicitly realized */ /* we need to realize the GdkGLContext if it wasn't explicitly realized */
@ -1740,10 +1759,18 @@ GdkGLContext *
gdk_gl_context_get_current (void) gdk_gl_context_get_current (void)
{ {
MaskedContext *current; MaskedContext *current;
GdkGLContext *context;
current = g_private_get (&thread_current_context); current = g_private_get (&thread_current_context);
context = unmask_context (current);
return unmask_context (current); if (context && !gdk_gl_context_check_is_current (context))
{
g_private_replace (&thread_current_context, NULL);
context = NULL;
}
return context;
} }
gboolean gboolean

View File

@ -83,6 +83,7 @@ struct _GdkGLContextClass
gboolean (* make_current) (GdkGLContext *context, gboolean (* make_current) (GdkGLContext *context,
gboolean surfaceless); gboolean surfaceless);
gboolean (* clear_current) (GdkGLContext *context); gboolean (* clear_current) (GdkGLContext *context);
gboolean (* is_current) (GdkGLContext *context);
cairo_region_t * (* get_damage) (GdkGLContext *context); cairo_region_t * (* get_damage) (GdkGLContext *context);
gboolean (* is_shared) (GdkGLContext *self, gboolean (* is_shared) (GdkGLContext *self,

View File

@ -548,6 +548,14 @@ gdk_macos_gl_context_clear_current (GdkGLContext *context)
return TRUE; return TRUE;
} }
static gboolean
gdk_macos_gl_context_is_current (GdkGLContext *context)
{
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
return self->cgl_context == CGLGetCurrentContext ();
}
static gboolean static gboolean
gdk_macos_gl_context_make_current (GdkGLContext *context, gdk_macos_gl_context_make_current (GdkGLContext *context,
gboolean surfaceless) gboolean surfaceless)
@ -639,6 +647,7 @@ gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
gl_class->get_damage = gdk_macos_gl_context_get_damage; gl_class->get_damage = gdk_macos_gl_context_get_damage;
gl_class->clear_current = gdk_macos_gl_context_clear_current; gl_class->clear_current = gdk_macos_gl_context_clear_current;
gl_class->is_current = gdk_macos_gl_context_is_current;
gl_class->make_current = gdk_macos_gl_context_make_current; gl_class->make_current = gdk_macos_gl_context_make_current;
gl_class->realize = gdk_macos_gl_context_real_realize; gl_class->realize = gdk_macos_gl_context_real_realize;
gl_class->get_default_framebuffer = gdk_macos_gl_context_get_default_framebuffer; gl_class->get_default_framebuffer = gdk_macos_gl_context_get_default_framebuffer;

View File

@ -631,6 +631,14 @@ gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
return wglMakeCurrent (NULL, NULL); return wglMakeCurrent (NULL, NULL);
} }
static gboolean
gdk_win32_gl_context_wgl_is_current (GdkGLContext *context)
{
GdkWin32GLContextWGL *self = GDK_WIN32_GL_CONTEXT_WGL (context);
return self->wgl_context == wglGetCurrentContext ();
}
static gboolean static gboolean
gdk_win32_gl_context_wgl_make_current (GdkGLContext *context, gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
gboolean surfaceless) gboolean surfaceless)
@ -682,6 +690,7 @@ gdk_win32_gl_context_wgl_class_init (GdkWin32GLContextWGLClass *klass)
context_class->realize = gdk_win32_gl_context_wgl_realize; context_class->realize = gdk_win32_gl_context_wgl_realize;
context_class->make_current = gdk_win32_gl_context_wgl_make_current; context_class->make_current = gdk_win32_gl_context_wgl_make_current;
context_class->clear_current = gdk_win32_gl_context_wgl_clear_current; context_class->clear_current = gdk_win32_gl_context_wgl_clear_current;
context_class->is_current = gdk_win32_gl_context_wgl_is_current;
draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame; draw_context_class->begin_frame = gdk_win32_gl_context_wgl_begin_frame;
draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame; draw_context_class->end_frame = gdk_win32_gl_context_wgl_end_frame;

View File

@ -210,6 +210,14 @@ gdk_x11_gl_context_glx_clear_current (GdkGLContext *context)
return TRUE; return TRUE;
} }
static gboolean
gdk_x11_gl_context_glx_is_current (GdkGLContext *context)
{
GdkX11GLContextGLX *self = GDK_X11_GL_CONTEXT_GLX (context);
return self->glx_context == glXGetCurrentContext ();
}
static gboolean static gboolean
gdk_x11_gl_context_glx_make_current (GdkGLContext *context, gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
gboolean surfaceless) gboolean surfaceless)
@ -685,6 +693,7 @@ gdk_x11_gl_context_glx_class_init (GdkX11GLContextGLXClass *klass)
context_class->realize = gdk_x11_gl_context_glx_realize; context_class->realize = gdk_x11_gl_context_glx_realize;
context_class->make_current = gdk_x11_gl_context_glx_make_current; context_class->make_current = gdk_x11_gl_context_glx_make_current;
context_class->clear_current = gdk_x11_gl_context_glx_clear_current; context_class->clear_current = gdk_x11_gl_context_glx_clear_current;
context_class->is_current = gdk_x11_gl_context_glx_is_current;
context_class->get_damage = gdk_x11_gl_context_glx_get_damage; context_class->get_damage = gdk_x11_gl_context_glx_get_damage;
draw_context_class->end_frame = gdk_x11_gl_context_glx_end_frame; draw_context_class->end_frame = gdk_x11_gl_context_glx_end_frame;