summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2023-02-02 02:49:56 +0100
committerBenjamin Otte <otte@redhat.com>2023-02-02 04:23:51 +0100
commitc6cef6db526930b4cd925c0998da5acc4d4ab35d (patch)
treecd6094b7b2f57a3a9069f4fd765ffc4c47ea0bb1
parentfdea27c04d0a10e8b79bb4fd484788f6853a6f6a (diff)
downloadgtk+-c6cef6db526930b4cd925c0998da5acc4d4ab35d.tar.gz
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
-rw-r--r--gdk/gdkglcontext.c31
-rw-r--r--gdk/gdkglcontextprivate.h1
-rw-r--r--gdk/macos/gdkmacosglcontext.c9
-rw-r--r--gdk/win32/gdkglcontext-win32-wgl.c9
-rw-r--r--gdk/x11/gdkglcontext-glx.c9
5 files changed, 57 insertions, 2 deletions
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 599b946de9..a46ffdb9d9 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -502,6 +502,18 @@ gdk_gl_context_real_is_shared (GdkGLContext *self,
}
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
gdk_gl_context_real_clear_current (GdkGLContext *context)
{
#ifdef HAVE_EGL
@@ -670,6 +682,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
klass->is_shared = gdk_gl_context_real_is_shared;
klass->make_current = gdk_gl_context_real_make_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;
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;
}
+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:
* @context: a `GdkGLContext`
@@ -1569,7 +1588,7 @@ gdk_gl_context_make_current (GdkGLContext *context)
masked_context = mask_context (context, surfaceless);
current = g_private_get (&thread_current_context);
- if (current == masked_context)
+ if (current == masked_context && gdk_gl_context_check_is_current (context))
return;
/* we need to realize the GdkGLContext if it wasn't explicitly realized */
@@ -1740,10 +1759,18 @@ GdkGLContext *
gdk_gl_context_get_current (void)
{
MaskedContext *current;
+ GdkGLContext *context;
current = g_private_get (&thread_current_context);
+ context = unmask_context (current);
+
+ if (context && !gdk_gl_context_check_is_current (context))
+ {
+ g_private_replace (&thread_current_context, NULL);
+ context = NULL;
+ }
- return unmask_context (current);
+ return context;
}
gboolean
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index bd66172eba..2ed799d6f7 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -83,6 +83,7 @@ struct _GdkGLContextClass
gboolean (* make_current) (GdkGLContext *context,
gboolean surfaceless);
gboolean (* clear_current) (GdkGLContext *context);
+ gboolean (* is_current) (GdkGLContext *context);
cairo_region_t * (* get_damage) (GdkGLContext *context);
gboolean (* is_shared) (GdkGLContext *self,
diff --git a/gdk/macos/gdkmacosglcontext.c b/gdk/macos/gdkmacosglcontext.c
index 8b6b928d5f..5dc7c202ef 100644
--- a/gdk/macos/gdkmacosglcontext.c
+++ b/gdk/macos/gdkmacosglcontext.c
@@ -549,6 +549,14 @@ gdk_macos_gl_context_clear_current (GdkGLContext *context)
}
static gboolean
+gdk_macos_gl_context_is_current (GdkGLContext *context)
+{
+ GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
+
+ return self->cgl_context == CGLGetCurrentContext ();
+}
+
+static gboolean
gdk_macos_gl_context_make_current (GdkGLContext *context,
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->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->realize = gdk_macos_gl_context_real_realize;
gl_class->get_default_framebuffer = gdk_macos_gl_context_get_default_framebuffer;
diff --git a/gdk/win32/gdkglcontext-win32-wgl.c b/gdk/win32/gdkglcontext-win32-wgl.c
index f15d64d34b..4c32a74f88 100644
--- a/gdk/win32/gdkglcontext-win32-wgl.c
+++ b/gdk/win32/gdkglcontext-win32-wgl.c
@@ -632,6 +632,14 @@ gdk_win32_gl_context_wgl_clear_current (GdkGLContext *context)
}
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
gdk_win32_gl_context_wgl_make_current (GdkGLContext *context,
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->make_current = gdk_win32_gl_context_wgl_make_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->end_frame = gdk_win32_gl_context_wgl_end_frame;
diff --git a/gdk/x11/gdkglcontext-glx.c b/gdk/x11/gdkglcontext-glx.c
index 6be6eb7e16..db3040442c 100644
--- a/gdk/x11/gdkglcontext-glx.c
+++ b/gdk/x11/gdkglcontext-glx.c
@@ -211,6 +211,14 @@ gdk_x11_gl_context_glx_clear_current (GdkGLContext *context)
}
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
gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
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->make_current = gdk_x11_gl_context_glx_make_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;
draw_context_class->end_frame = gdk_x11_gl_context_glx_end_frame;