From bc7a7259f357b0065dd94e0668b5a895d83fa53a Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Fri, 6 Mar 2015 15:31:18 +1100 Subject: [PATCH] gl/window: create the main loop/context on init/finalize Avoids races setting the window handle from the main thread. https://bugzilla.gnome.org/show_bug.cgi?id=745633 --- .../gst/gl/android/gstglwindow_android_egl.c | 25 ++++++--- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 26 ++++++--- gst-libs/gst/gl/eagl/gstglwindow_eagl.m | 37 +++++++------ .../gst/gl/wayland/gstglwindow_wayland_egl.c | 30 +++++++---- gst-libs/gst/gl/x11/gstglwindow_x11.c | 54 ++++++++----------- 5 files changed, 99 insertions(+), 73 deletions(-) diff --git a/gst-libs/gst/gl/android/gstglwindow_android_egl.c b/gst-libs/gst/gl/android/gstglwindow_android_egl.c index 202aba08e2..cbc0f7b2ed 100644 --- a/gst-libs/gst/gl/android/gstglwindow_android_egl.c +++ b/gst-libs/gst/gl/android/gstglwindow_android_egl.c @@ -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 diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 17ded0467e..1da6d63d7e 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -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; } diff --git a/gst-libs/gst/gl/eagl/gstglwindow_eagl.m b/gst-libs/gst/gl/eagl/gstglwindow_eagl.m index edb0cb4c8b..5f748d3e37 100644 --- a/gst-libs/gst/gl/eagl/gstglwindow_eagl.m +++ b/gst-libs/gst/gl/eagl/gstglwindow_eagl.m @@ -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 diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index a0fa6207a8..271a677993 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -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); diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.c b/gst-libs/gst/gl/x11/gstglwindow_x11.c index c5e7355f2f..41a3983d47 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.c +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.c @@ -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) {