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
This commit is contained in:
Matthew Waters 2015-03-06 15:31:18 +11:00
parent ee637bef1e
commit bc7a7259f3
5 changed files with 99 additions and 73 deletions

View 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

View 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;
}

View 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

View 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);

View 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)
{