[gtk+] GdkGLContext: Change the way we track the current context



commit fb50015519bee516f7a83c64034d11cd9a606246
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Oct 30 11:46:09 2014 +0100

    GdkGLContext: Change the way we track the current context
    
    To properly support multithreaded use we use a global GPrivate
    to track the current context. Since we also don't need to track
    the current context on the display we move gdk_display_destroy_gl_context
    to GdkGLContext::discard.

 gdk/gdkdisplay.c                   |   52 +------------------------------
 gdk/gdkdisplayprivate.h            |   11 ++-----
 gdk/gdkglcontext.c                 |   37 +++++++++++++++++-----
 gdk/gdkglcontextprivate.h          |    2 +-
 gdk/wayland/gdkdisplay-wayland.c   |    1 -
 gdk/wayland/gdkglcontext-wayland.c |   33 ++++++++++++++------
 gdk/wayland/gdkglcontext-wayland.h |    4 +--
 gdk/x11/gdkdisplay-x11.c           |    1 -
 gdk/x11/gdkglcontext-x11.c         |   59 ++++++++++++++++++++++-------------
 gdk/x11/gdkglcontext-x11.h         |    4 +--
 10 files changed, 97 insertions(+), 107 deletions(-)
---
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index acbf66f..d48491b 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -2245,28 +2245,6 @@ gdk_error_trap_pop (void)
 }
 
 /*< private >
- * gdk_display_destroy_gl_context:
- * @display: a #GdkDisplay
- * @context: a #GdkGLContext
- *
- * Destroys the platform-specific parts of the @context.
- *
- * The @context instance is still valid, though inert, after
- * this functionr returns.
- */
-void
-gdk_display_destroy_gl_context (GdkDisplay   *display,
-                                GdkGLContext *context)
-{
-  GdkGLContext *current = gdk_display_get_current_gl_context (display);
-
-  if  (current == context)
-    g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
-
-  GDK_DISPLAY_GET_CLASS (display)->destroy_gl_context (display, context);
-}
-
-/*< private >
  * gdk_display_make_gl_context_current:
  * @display: a #GdkDisplay
  * @context: (optional): a #GdkGLContext, or %NULL
@@ -2274,35 +2252,9 @@ gdk_display_destroy_gl_context (GdkDisplay   *display,
  * Makes the given @context the current GL context, or unsets
  * the current GL context if @context is %NULL.
  */
-void
+gboolean
 gdk_display_make_gl_context_current (GdkDisplay   *display,
                                      GdkGLContext *context)
 {
-  GdkGLContext *current = gdk_display_get_current_gl_context (display);
-
-  if (current == context)
-    return;
-
-  if (context == NULL)
-    g_object_set_data (G_OBJECT (display), "-gdk-gl-current-context", NULL);
-  else
-    g_object_set_data_full (G_OBJECT (display), "-gdk-gl-current-context",
-                            g_object_ref (context),
-                            (GDestroyNotify) g_object_unref);
-
-  GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
-}
-
-/*< private >
- * gdk_display_get_current_gl_context:
- * @display: a #GdkDisplay
- *
- * Retrieves the current #GdkGLContext associated with @display.
- *
- * Returns: (transfer none): the current #GdkGLContext or %NULL
- */
-GdkGLContext *
-gdk_display_get_current_gl_context (GdkDisplay *display)
-{
-  return g_object_get_data (G_OBJECT (display), "-gdk-gl-current-context");
+  return GDK_DISPLAY_GET_CLASS (display)->make_gl_context_current (display, context);
 }
diff --git a/gdk/gdkdisplayprivate.h b/gdk/gdkdisplayprivate.h
index 6bd87d1..4c6f4a0 100644
--- a/gdk/gdkdisplayprivate.h
+++ b/gdk/gdkdisplayprivate.h
@@ -228,10 +228,8 @@ struct _GdkDisplayClass
   gchar *                (*utf8_to_string_target)      (GdkDisplay     *display,
                                                         const gchar    *text);
 
-  void                  (*make_gl_context_current)  (GdkDisplay        *display,
-                                                     GdkGLContext      *context);
-  void                  (*destroy_gl_context)       (GdkDisplay        *display,
-                                                     GdkGLContext      *context);
+  gboolean               (*make_gl_context_current)    (GdkDisplay        *display,
+                                                        GdkGLContext      *context);
 
   /* Signals */
   void                   (*opened)                     (GdkDisplay     *display);
@@ -311,11 +309,8 @@ void                _gdk_display_create_window_impl   (GdkDisplay       *display
                                                        gint              attributes_mask);
 GdkWindow *         _gdk_display_create_window        (GdkDisplay       *display);
 
-void                gdk_display_destroy_gl_context       (GdkDisplay        *display,
+gboolean            gdk_display_make_gl_context_current  (GdkDisplay        *display,
                                                           GdkGLContext      *context);
-void                gdk_display_make_gl_context_current  (GdkDisplay        *display,
-                                                          GdkGLContext      *context);
-GdkGLContext *      gdk_display_get_current_gl_context   (GdkDisplay        *display);
 
 G_END_DECLS
 
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index f1e8740..748d932 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -103,13 +103,18 @@ G_DEFINE_QUARK (gdk-gl-error-quark, gdk_gl_error)
 
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GdkGLContext, gdk_gl_context, G_TYPE_OBJECT)
 
+static GPrivate thread_current_context = G_PRIVATE_INIT (g_object_unref);
+
 static void
 gdk_gl_context_dispose (GObject *gobject)
 {
   GdkGLContext *context = GDK_GL_CONTEXT (gobject);
   GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+  GdkGLContext *current;
 
-  gdk_display_destroy_gl_context (gdk_window_get_display (priv->window), context);
+  current = g_private_get (&thread_current_context);
+  if (current == context)
+    g_private_replace (&thread_current_context, NULL);
 
   g_clear_object (&priv->window);
   g_clear_object (&priv->visual);
@@ -310,13 +315,20 @@ void
 gdk_gl_context_make_current (GdkGLContext *context)
 {
   GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (context);
+  GdkGLContext *current;
 
   g_return_if_fail (GDK_IS_GL_CONTEXT (context));
 
-  gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context);
+  current = g_private_get (&thread_current_context);
+  if (current == context)
+    return;
 
-  if (!priv->realized)
-    gdk_gl_context_realize (context);
+  if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), context))
+    {
+      g_private_replace (&thread_current_context, g_object_ref (context));
+      if (!priv->realized)
+        gdk_gl_context_realize (context);
+    }
 }
 
 /**
@@ -352,9 +364,16 @@ gdk_gl_context_get_window (GdkGLContext *context)
 void
 gdk_gl_context_clear_current (void)
 {
-  GdkDisplay *display = gdk_display_get_default ();
+  GdkGLContext *current;
 
-  gdk_display_make_gl_context_current (display, NULL);
+  current = g_private_get (&thread_current_context);
+  if (current != NULL)
+    {
+      GdkGLContextPrivate *priv = gdk_gl_context_get_instance_private (current);
+
+      if (gdk_display_make_gl_context_current (gdk_window_get_display (priv->window), NULL))
+        g_private_replace (&thread_current_context, NULL);
+    }
 }
 
 /**
@@ -369,7 +388,9 @@ gdk_gl_context_clear_current (void)
 GdkGLContext *
 gdk_gl_context_get_current (void)
 {
-  GdkDisplay *display = gdk_display_get_default ();
+  GdkGLContext *current;
+
+  current = g_private_get (&thread_current_context);
 
-  return gdk_display_get_current_gl_context (display);
+  return current;
 }
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index c7b6937..fcb82a8 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -40,7 +40,7 @@ struct _GdkGLContextClass
 {
   GObjectClass parent_class;
 
-  void (* update)          (GdkGLContext *context);
+  void (* update)       (GdkGLContext *context);
   void (* end_frame)    (GdkGLContext *context,
                          cairo_region_t *painted,
                          cairo_region_t *damage);
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 0f367ec..56e7278 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -534,7 +534,6 @@ gdk_wayland_display_class_init (GdkWaylandDisplayClass * class)
   display_class->text_property_to_utf8_list = _gdk_wayland_display_text_property_to_utf8_list;
   display_class->utf8_to_string_target = _gdk_wayland_display_utf8_to_string_target;
 
-  display_class->destroy_gl_context = gdk_wayland_display_destroy_gl_context;
   display_class->make_gl_context_current = gdk_wayland_display_make_gl_context_current;
 }
 
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 5fc320d..5a75c54 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -35,6 +35,8 @@
 
 G_DEFINE_TYPE (GdkWaylandGLContext, gdk_wayland_gl_context, GDK_TYPE_GL_CONTEXT)
 
+static void gdk_x11_gl_context_dispose (GObject *gobject);
+
 static void
 gdk_wayland_gl_context_update (GdkGLContext *context)
 {
@@ -159,9 +161,11 @@ static void
 gdk_wayland_gl_context_class_init (GdkWaylandGLContextClass *klass)
 {
   GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   context_class->update = gdk_wayland_gl_context_update;
   context_class->end_frame = gdk_wayland_gl_context_end_frame;
+  gobject_class->dispose = gdk_x11_gl_context_dispose;
 }
 
 static void
@@ -369,16 +373,18 @@ gdk_wayland_window_create_gl_context (GdkWindow     *window,
   return GDK_GL_CONTEXT (context);
 }
 
-void
-gdk_wayland_display_destroy_gl_context (GdkDisplay   *display,
-                                        GdkGLContext *context)
+static void
+gdk_x11_gl_context_dispose (GObject *gobject)
 {
-  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
-  GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
+  GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (gobject);
 
-  /* TODO: Unset as current if current? */
   if (context_wayland->egl_context != NULL)
     {
+      GdkGLContext *context = GDK_GL_CONTEXT (gobject);
+      GdkWindow *window = gdk_gl_context_get_window (context);
+      GdkDisplay *display = gdk_window_get_display (window);
+      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+
       if (eglGetCurrentContext () == context_wayland->egl_context)
         eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                        EGL_NO_CONTEXT);
@@ -389,9 +395,11 @@ gdk_wayland_display_destroy_gl_context (GdkDisplay   *display,
                          context_wayland->egl_context);
       context_wayland->egl_context = NULL;
     }
+
+  G_OBJECT_CLASS (gdk_wayland_gl_context_parent_class)->dispose (gobject);
 }
 
-void
+gboolean
 gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
                                              GdkGLContext *context)
 {
@@ -404,7 +412,7 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
     {
       eglMakeCurrent(display_wayland->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                      EGL_NO_CONTEXT);
-      return;
+      return TRUE;
     }
 
   context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
@@ -422,6 +430,11 @@ gdk_wayland_display_make_gl_context_current (GdkDisplay   *display,
     }
 
   if (!eglMakeCurrent (display_wayland->egl_display, egl_surface,
-                      egl_surface, context_wayland->egl_context))
-    g_critical ("eglMakeCurrent failed");
+                       egl_surface, context_wayland->egl_context))
+    {
+      g_warning ("eglMakeCurrent failed");
+      return FALSE;
+    }
+
+  return TRUE;
 }
diff --git a/gdk/wayland/gdkglcontext-wayland.h b/gdk/wayland/gdkglcontext-wayland.h
index 6a7d879..a140f5c 100644
--- a/gdk/wayland/gdkglcontext-wayland.h
+++ b/gdk/wayland/gdkglcontext-wayland.h
@@ -55,9 +55,7 @@ GdkGLContext *  gdk_wayland_window_create_gl_context                (GdkWindow
                                                                      GError           **error);
 void            gdk_wayland_window_invalidate_for_new_frame         (GdkWindow         *window,
                                                                      cairo_region_t    *update_area);
-void            gdk_wayland_display_destroy_gl_context              (GdkDisplay        *display,
-                                                                     GdkGLContext      *context);
-void            gdk_wayland_display_make_gl_context_current         (GdkDisplay        *display,
+gboolean        gdk_wayland_display_make_gl_context_current         (GdkDisplay        *display,
                                                                      GdkGLContext      *context);
 
 G_END_DECLS
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 358ae84..220a85b 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -2894,7 +2894,6 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
   display_class->text_property_to_utf8_list = _gdk_x11_display_text_property_to_utf8_list;
   display_class->utf8_to_string_target = _gdk_x11_display_utf8_to_string_target;
 
-  display_class->destroy_gl_context = gdk_x11_display_destroy_gl_context;
   display_class->make_gl_context_current = gdk_x11_display_make_gl_context_current;
 
   _gdk_x11_windowing_init ();
diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c
index 8d1e6cf..b7a90eb 100644
--- a/gdk/x11/gdkglcontext-x11.c
+++ b/gdk/x11/gdkglcontext-x11.c
@@ -496,13 +496,39 @@ gdk_x11_gl_context_texture_from_surface (GdkGLContext *context,
 }
 
 static void
+gdk_x11_gl_context_dispose (GObject *gobject)
+{
+  GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (gobject);
+
+  if (context_x11->glx_context != NULL)
+    {
+      GdkGLContext *context = GDK_GL_CONTEXT (gobject);
+      GdkWindow *window = gdk_gl_context_get_window (context);
+      GdkDisplay *display = gdk_window_get_display (window);
+      Display *dpy = gdk_x11_display_get_xdisplay (display);
+
+      if (glXGetCurrentContext () == context_x11->glx_context)
+        glXMakeContextCurrent (dpy, None, None, NULL);
+
+      GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
+      glXDestroyContext (dpy, context_x11->glx_context);
+      context_x11->glx_context = NULL;
+    }
+
+  G_OBJECT_CLASS (gdk_x11_gl_context_parent_class)->dispose (gobject);
+}
+
+static void
 gdk_x11_gl_context_class_init (GdkX11GLContextClass *klass)
 {
   GdkGLContextClass *context_class = GDK_GL_CONTEXT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   context_class->update = gdk_x11_gl_context_update;
   context_class->end_frame = gdk_x11_gl_context_end_frame;
   context_class->texture_from_surface = gdk_x11_gl_context_texture_from_surface;
+
+  gobject_class->dispose = gdk_x11_gl_context_dispose;
 }
 
 static void
@@ -1110,25 +1136,7 @@ gdk_x11_window_create_gl_context (GdkWindow    *window,
   return GDK_GL_CONTEXT (context);
 }
 
-void
-gdk_x11_display_destroy_gl_context (GdkDisplay   *display,
-                                    GdkGLContext *context)
-{
-  GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
-  Display *dpy = gdk_x11_display_get_xdisplay (display);
-
-  if (context_x11->glx_context != NULL)
-    {
-      if (glXGetCurrentContext () == context_x11->glx_context)
-        glXMakeContextCurrent (dpy, None, None, NULL);
-
-      GDK_NOTE (OPENGL, g_print ("Destroying GLX context\n"));
-      glXDestroyContext (dpy, context_x11->glx_context);
-      context_x11->glx_context = NULL;
-    }
-}
-
-void
+gboolean
 gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
                                          GdkGLContext *context)
 {
@@ -1141,7 +1149,7 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
   if (context == NULL)
     {
       glXMakeContextCurrent (dpy, None, None, NULL);
-      return;
+      return TRUE;
     }
 
   context_x11 = GDK_X11_GL_CONTEXT (context);
@@ -1161,8 +1169,13 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
             g_print ("Making GLX context current to drawable %lu\n",
                      (unsigned long) context_x11->drawable));
 
-  glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
-                         context_x11->glx_context);
+  if (!glXMakeContextCurrent (dpy, context_x11->drawable, context_x11->drawable,
+                              context_x11->glx_context))
+    {
+      GDK_NOTE (OPENGL,
+                g_print ("Making GLX context current failed\n"));
+      return FALSE;
+    }
 
   if (context_x11->is_attached && GDK_X11_DISPLAY (display)->has_glx_swap_interval)
     {
@@ -1171,6 +1184,8 @@ gdk_x11_display_make_gl_context_current (GdkDisplay   *display,
       else
         glXSwapIntervalSGI (0);
     }
+
+  return TRUE;
 }
 
 /**
diff --git a/gdk/x11/gdkglcontext-x11.h b/gdk/x11/gdkglcontext-x11.h
index 683ca41..865a765 100644
--- a/gdk/x11/gdkglcontext-x11.h
+++ b/gdk/x11/gdkglcontext-x11.h
@@ -64,9 +64,7 @@ GdkGLContext *  gdk_x11_window_create_gl_context                (GdkWindow
                                                                  GError           **error);
 void            gdk_x11_window_invalidate_for_new_frame         (GdkWindow         *window,
                                                                  cairo_region_t    *update_area);
-void            gdk_x11_display_destroy_gl_context              (GdkDisplay        *display,
-                                                                 GdkGLContext      *context);
-void            gdk_x11_display_make_gl_context_current         (GdkDisplay        *display,
+gboolean        gdk_x11_display_make_gl_context_current         (GdkDisplay        *display,
                                                                  GdkGLContext      *context);
 
 G_END_DECLS


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]