gl/window: create the main loop/context on init/finalize
authorMatthew Waters <matthew@centricular.com>
Fri, 6 Mar 2015 04:31:18 +0000 (15:31 +1100)
committerMatthew Waters <matthew@centricular.com>
Wed, 11 Mar 2015 13:52:15 +0000 (13:52 +0000)
Avoids races setting the window handle from the main thread.

https://bugzilla.gnome.org/show_bug.cgi?id=745633

gst-libs/gst/gl/android/gstglwindow_android_egl.c
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
gst-libs/gst/gl/eagl/gstglwindow_eagl.m
gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
gst-libs/gst/gl/x11/gstglwindow_x11.c

index 202aba08e23b374b5831e01293f64ee477f2fb8b..cbc0f7b2edd023b1634447df22f404e49a9daa07 100644 (file)
@@ -38,6 +38,7 @@
 #define gst_gl_window_android_egl_parent_class parent_class
 G_DEFINE_TYPE (GstGLWindowAndroidEGL, gst_gl_window_android_egl,
     GST_GL_TYPE_WINDOW);
+static void gst_gl_window_android_egl_finalize (GObject * object);
 
 static guintptr gst_gl_window_android_egl_get_display (GstGLWindow * window);
 static guintptr gst_gl_window_android_egl_get_window_handle (GstGLWindow *
@@ -57,6 +58,7 @@ static void
 gst_gl_window_android_egl_class_init (GstGLWindowAndroidEGLClass * klass)
 {
   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   window_class->get_display =
       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_get_display);
@@ -73,11 +75,26 @@ gst_gl_window_android_egl_class_init (GstGLWindowAndroidEGLClass * klass)
       GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message_async);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_open);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_close);
+
+  gobject_class->finalize = gst_gl_window_android_egl_finalize;
 }
 
 static void
 gst_gl_window_android_egl_init (GstGLWindowAndroidEGL * window)
 {
+  window->main_context = g_main_context_new ();
+  window->loop = g_main_loop_new (window->main_context, FALSE);
+}
+
+static void
+gst_gl_window_android_egl_finalize (GObject * object)
+{
+  GstGLWindowAndroidEGL *window_egl GST_GL_WINDOW_ANDROID_EGL (object);
+
+  g_main_loop_unref (window_egl->loop);
+  g_main_context_unref (window_egl->main_context);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /* Must be called in the gl thread */
@@ -98,11 +115,6 @@ gst_gl_window_android_egl_open (GstGLWindow * window, GError ** error)
 {
   GstGLWindowAndroidEGL *window_egl;
 
-  window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
-
-  window_egl->main_context = g_main_context_new ();
-  window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE);
-
   return TRUE;
 }
 
@@ -112,9 +124,6 @@ gst_gl_window_android_egl_close (GstGLWindow * window)
   GstGLWindowAndroidEGL *window_egl;
 
   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
-
-  g_main_loop_unref (window_egl->loop);
-  g_main_context_unref (window_egl->main_context);
 }
 
 static void
index 17ded0467ee50d8f11abb212a6153977b29adeba..1da6d63d7eea20e5ae065db42dc5deec26bcd117 100644 (file)
@@ -65,6 +65,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
   GST_DEBUG_CATEGORY_GET (GST_CAT_DEFAULT, "glwindow");
 #define gst_gl_window_cocoa_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLWindowCocoa, gst_gl_window_cocoa, GST_GL_TYPE_WINDOW, DEBUG_INIT);
+static void gst_gl_window_cocoa_finalize (GObject * object);
 
 static gboolean gst_gl_window_cocoa_open (GstGLWindow *window, GError **err);
 static void gst_gl_window_cocoa_close (GstGLWindow *window);
@@ -96,9 +97,8 @@ struct _GstGLWindowCocoaPrivate
 static void
 gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
 {
-  GstGLWindowClass *window_class;
-
-  window_class = (GstGLWindowClass *) klass;
+  GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   g_type_class_add_private (klass, sizeof (GstGLWindowCocoaPrivate));
 
@@ -117,6 +117,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
   window_class->set_preferred_size =
       GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_preferred_size);
   window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_show);
+
+  gobject_class->finalize = gst_gl_window_cocoa_finalize;
 }
 
 static void
@@ -126,6 +128,20 @@ gst_gl_window_cocoa_init (GstGLWindowCocoa * window)
 
   window->priv->preferred_width = 320;
   window->priv->preferred_height = 240;
+
+  window->priv->main_context = g_main_context_new ();
+  window->priv->loop =g_main_loop_new (window->priv->main_context, FALSE);
+}
+
+static void
+gst_gl_window_cocoa_finalize (GObject * object)
+{
+  GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (object);
+
+  g_main_loop_unref (window_cocoa->priv->loop);
+  g_main_context_unref (window_cocoa->priv->main_context);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /* Must be called in the gl thread */
@@ -174,10 +190,6 @@ gst_gl_window_cocoa_open (GstGLWindow *window, GError **err)
 
   window_cocoa = GST_GL_WINDOW_COCOA (window);
 
-  window_cocoa->priv->main_context = g_main_context_new ();
-  window_cocoa->priv->loop =
-      g_main_loop_new (window_cocoa->priv->main_context, FALSE);
-
   return TRUE;
 }
 
index edb0cb4c8b52924d41906b178c8914c0638af8be..5f748d3e37d0da5478a692aebbe11e835cf8d5c5 100644 (file)
@@ -40,6 +40,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
 #define gst_gl_window_eagl_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstGLWindowEagl, gst_gl_window_eagl,
     GST_GL_TYPE_WINDOW, DEBUG_INIT);
+static void gst_gl_window_eagl_finalize (GObject * object);
 
 static guintptr gst_gl_window_eagl_get_display (GstGLWindow * window);
 static guintptr gst_gl_window_eagl_get_window_handle (GstGLWindow * window);
@@ -68,9 +69,8 @@ struct _GstGLWindowEaglPrivate
 static void
 gst_gl_window_eagl_class_init (GstGLWindowEaglClass * klass)
 {
-  GstGLWindowClass *window_class;
-
-  window_class = (GstGLWindowClass *) klass;
+  GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   g_type_class_add_private (klass, sizeof (GstGLWindowEaglPrivate));
 
@@ -90,12 +90,29 @@ gst_gl_window_eagl_class_init (GstGLWindowEaglClass * klass)
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_close);
   window_class->set_preferred_size =
       GST_DEBUG_FUNCPTR (gst_gl_window_eagl_set_preferred_size);
+
+  gobject_class->finalize = gst_gl_window_eagl_finalize;
 }
 
 static void
 gst_gl_window_eagl_init (GstGLWindowEagl * window)
 {
   window->priv = GST_GL_WINDOW_EAGL_GET_PRIVATE (window);
+
+  window_eagl->priv->main_context = g_main_context_new ();
+  window_eagl->priv->loop =
+      g_main_loop_new (window_eagl->priv->main_context, FALSE);
+}
+
+static void
+gst_gl_window_eagl_finalize (GObject * object)
+{
+  GstGLWindowWaylandEagl *window_eagl = GST_GL_WINDOW_EAGL (object);
+
+  g_main_loop_unref (window_eagl->priv->loop);
+  g_main_context_unref (window_egl->priv->main_context);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /* Must be called in the gl thread */
@@ -132,26 +149,12 @@ gst_gl_window_eagl_set_window_handle (GstGLWindow * window, guintptr handle)
 static gboolean
 gst_gl_window_eagl_open (GstGLWindow * window, GError ** error)
 {
-  GstGLWindowEagl *window_eagl;
-
-  window_eagl = GST_GL_WINDOW_EAGL (window);
-
-  window_eagl->priv->main_context = g_main_context_new ();
-  window_eagl->priv->loop =
-      g_main_loop_new (window_eagl->priv->main_context, FALSE);
-
   return TRUE;
 }
 
 static void
 gst_gl_window_eagl_close (GstGLWindow * window)
 {
-  GstGLWindowEagl *window_eagl;
-
-  window_eagl = GST_GL_WINDOW_EAGL (window);
-
-  g_main_loop_unref (window_eagl->priv->loop);
-  g_main_context_unref (window_eagl->priv->main_context);
 }
 
 static void
index a0fa6207a888255b333736427f7f6f0fdfb0fa28..271a677993a612ad0dda79cda3712160f8ba7b2b 100644 (file)
@@ -41,6 +41,7 @@ const gchar *WlEGLErrorString ();
 #define gst_gl_window_wayland_egl_parent_class parent_class
 G_DEFINE_TYPE (GstGLWindowWaylandEGL, gst_gl_window_wayland_egl,
     GST_GL_TYPE_WINDOW);
+static void gst_gl_window_wayland_egl_finalize (GObject * object);
 
 static guintptr gst_gl_window_wayland_egl_get_window_handle (GstGLWindow *
     window);
@@ -268,13 +269,6 @@ destroy_surface (GstGLWindowWaylandEGL * window_egl)
 
   if (window_egl->window.callback)
     wl_callback_destroy (window_egl->window.callback);
-
-  g_source_destroy (window_egl->wl_source);
-  g_source_unref (window_egl->wl_source);
-  window_egl->wl_source = NULL;
-  g_main_loop_unref (window_egl->loop);
-  window_egl->loop = NULL, g_main_context_unref (window_egl->main_context);
-  window_egl->main_context = NULL;
 }
 
 static void
@@ -311,6 +305,7 @@ static void
 gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass)
 {
   GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+  GObjectClass *gobject_class = (GObjectClass *) klass;
 
   window_class->get_window_handle =
       GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_window_handle);
@@ -327,11 +322,26 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass)
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open);
   window_class->get_display =
       GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_display);
+
+  gobject_class->finalize = gst_gl_window_wayland_egl_finalize;
 }
 
 static void
 gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window)
 {
+  window->main_context = g_main_context_new ();
+  window->loop = g_main_loop_new (window->main_context, FALSE);
+}
+
+static void
+gst_gl_window_wayland_egl_finalize (GObject * object)
+{
+  GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (object);
+
+  g_main_loop_unref (window_egl->loop);
+  g_main_context_unref (window_egl->main_context);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 /* Must be called in the gl thread */
@@ -372,6 +382,10 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window)
     wl_display_flush (window_egl->display.display);
     wl_display_disconnect (window_egl->display.display);
   }
+
+  g_source_destroy (window_egl->wl_source);
+  g_source_unref (window_egl->wl_source);
+  window_egl->wl_source = NULL;
 }
 
 static gboolean
@@ -401,8 +415,6 @@ gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error)
 
   window_egl->wl_source =
       wayland_event_source_new (window_egl->display.display);
-  window_egl->main_context = g_main_context_new ();
-  window_egl->loop = g_main_loop_new (window_egl->main_context, FALSE);
 
   g_source_attach (window_egl->wl_source, window_egl->main_context);
 
index c5e7355f2f5b2180970438eedf38d6c8b8a633f6..41a3983d47ba91fe3ba9c23687667802976d2046 100644 (file)
@@ -90,7 +90,17 @@ void gst_gl_window_x11_handle_events (GstGLWindow * window,
 static void
 gst_gl_window_x11_finalize (GObject * object)
 {
-  g_return_if_fail (GST_GL_IS_WINDOW_X11 (object));
+  GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (object);
+
+  if (window_x11->loop) {
+    g_main_loop_unref (window_x11->loop);
+    window_x11->loop = NULL;
+  }
+  if (window_x11->main_context) {
+    g_main_context_unref (window_x11->main_context);
+    window_x11->main_context = NULL;
+  }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -131,6 +141,9 @@ static void
 gst_gl_window_x11_init (GstGLWindowX11 * window)
 {
   window->priv = GST_GL_WINDOW_X11_GET_PRIVATE (window);
+
+  window->main_context = g_main_context_new ();
+  window->loop = g_main_loop_new (window->main_context, FALSE);
 }
 
 /* Must be called in the gl thread */
@@ -186,8 +199,6 @@ gst_gl_window_x11_open (GstGLWindow * window, GError ** error)
       DisplayHeight (window_x11->device, window_x11->screen_num);
 
   window_x11->x11_source = x11_event_source_new (window_x11);
-  window_x11->main_context = g_main_context_new ();
-  window_x11->loop = g_main_loop_new (window_x11->main_context, FALSE);
 
   g_source_attach (window_x11->x11_source, window_x11->main_context);
 
@@ -306,20 +317,21 @@ gst_gl_window_x11_close (GstGLWindow * window)
   g_source_destroy (window_x11->x11_source);
   g_source_unref (window_x11->x11_source);
   window_x11->x11_source = NULL;
-  g_main_loop_unref (window_x11->loop);
-  window_x11->loop = NULL;
-  g_main_context_unref (window_x11->main_context);
-  window_x11->main_context = NULL;
 
   window_x11->running = FALSE;
 }
 
-static void
-set_window_handle_cb (gpointer data)
+/* called by the gl thread */
+void
+gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id)
 {
-  GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (data);
+  GstGLWindowX11 *window_x11;
   XWindowAttributes attr;
 
+  window_x11 = GST_GL_WINDOW_X11 (window);
+
+  window_x11->parent_win = (Window) id;
+
   XGetWindowAttributes (window_x11->device, window_x11->parent_win, &attr);
 
   XResizeWindow (window_x11->device, window_x11->internal_win_id,
@@ -331,28 +343,6 @@ set_window_handle_cb (gpointer data)
   XSync (window_x11->device, FALSE);
 }
 
-/* Not called by the gl thread */
-void
-gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id)
-{
-  GstGLWindowX11 *window_x11;
-
-  window_x11 = GST_GL_WINDOW_X11 (window);
-
-  window_x11->parent_win = (Window) id;
-
-  /* The loop may not exist yet because it's created in GstGLWindow::open
-   * which is only called when going from READY to PAUSED state.
-   * If no loop then the parent is directly set in XCreateWindow
-   */
-  if (window_x11->loop && g_main_loop_is_running (window_x11->loop)) {
-    GST_LOG ("set parent window id: %" G_GUINTPTR_FORMAT, id);
-
-    gst_gl_window_send_message (window, (GstGLWindowCB) set_window_handle_cb,
-        window_x11);
-  }
-}
-
 guintptr
 gst_gl_window_x11_get_window_handle (GstGLWindow * window)
 {