diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 0d027c5a1a..e1996cf063 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -77,6 +77,8 @@ static void gst_gl_window_cocoa_set_preferred_size (GstGLWindow * window, gint width, gint height); static void gst_gl_window_cocoa_show (GstGLWindow * window); static void gst_gl_window_cocoa_queue_resize (GstGLWindow * window); +static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); struct _GstGLWindowCocoaPrivate { @@ -90,6 +92,8 @@ struct _GstGLWindowCocoaPrivate /* atomic set when the internal NSView has been created */ int view_ready; + + dispatch_queue_t gl_queue; }; static void @@ -111,6 +115,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_preferred_size); window_class->show = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_show); window_class->queue_resize = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_queue_resize); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async); gobject_class->finalize = gst_gl_window_cocoa_finalize; } @@ -122,11 +128,15 @@ gst_gl_window_cocoa_init (GstGLWindowCocoa * window) window->priv->preferred_width = 320; window->priv->preferred_height = 240; + window->priv->gl_queue = + dispatch_queue_create ("org.freedesktop.gstreamer.glwindow", NULL); } static void gst_gl_window_cocoa_finalize (GObject * object) { + GstGLWindowCocoa *window = GST_GL_WINDOW_COCOA (object); + dispatch_release (window->priv->gl_queue); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -370,6 +380,30 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height) [pool release]; } +static void +gst_gl_window_cocoa_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) +{ + GstGLWindowCocoa *window_cocoa = (GstGLWindowCocoa *) window; + GstGLContext *context = gst_gl_window_get_context (window); + + if (gst_gl_context_get_thread (context) == g_thread_self()) { + /* this case happens for nested calls happening from inside the GCD queue */ + callback (data); + if (destroy) + destroy (data); + gst_object_unref (context); + } else { + dispatch_async (window_cocoa->priv->gl_queue, ^{ + gst_gl_context_activate (context, TRUE); + gst_object_unref (context); + callback (data); + if (destroy) + destroy (data); + }); + } +} + /* =============================================================*/ /* */ /* GstGLNSWindow implementation */ diff --git a/gst-libs/gst/gl/eagl/gstglwindow_eagl.m b/gst-libs/gst/gl/eagl/gstglwindow_eagl.m index eb9d4f7f4a..f130cc015f 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); @@ -48,21 +49,27 @@ static void gst_gl_window_eagl_set_window_handle (GstGLWindow * window, static void gst_gl_window_eagl_set_preferred_size (GstGLWindow * window, gint width, gint height); static void gst_gl_window_eagl_draw (GstGLWindow * window); +static void gst_gl_window_eagl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); struct _GstGLWindowEaglPrivate { UIView *view; gint window_width, window_height; gint preferred_width, preferred_height; + dispatch_queue_t gl_queue; }; static void gst_gl_window_eagl_class_init (GstGLWindowEaglClass * klass) { + GObjectClass *gobject_class = (GObjectClass *) klass; GstGLWindowClass *window_class = (GstGLWindowClass *) klass; g_type_class_add_private (klass, sizeof (GstGLWindowEaglPrivate)); + gobject_class->finalize = gst_gl_window_eagl_finalize; + window_class->get_display = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_get_display); window_class->get_window_handle = @@ -72,13 +79,24 @@ gst_gl_window_eagl_class_init (GstGLWindowEaglClass * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_draw); window_class->set_preferred_size = GST_DEBUG_FUNCPTR (gst_gl_window_eagl_set_preferred_size); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_eagl_send_message_async); } static void gst_gl_window_eagl_init (GstGLWindowEagl * window) { window->priv = GST_GL_WINDOW_EAGL_GET_PRIVATE (window); + window->priv->gl_queue = + dispatch_queue_create ("org.freedesktop.gstreamer.glwindow", NULL); +} +static void +gst_gl_window_eagl_finalize (GObject * object) +{ + GstGLWindowEagl *window = GST_GL_WINDOW_EAGL (object); + dispatch_release (window->priv->gl_queue); + G_OBJECT_CLASS (parent_class)->finalize (object); } /* Must be called in the gl thread */ @@ -126,6 +144,30 @@ gst_gl_window_eagl_set_preferred_size (GstGLWindow * window, gint width, gint he window_eagl->priv->preferred_height = height; } +static void +gst_gl_window_eagl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) +{ + GstGLWindowEagl *window_eagl = (GstGLWindowEagl *) window; + GstGLContext *context = gst_gl_window_get_context (window); + + if (gst_gl_context_get_thread (context) == g_thread_self()) { + /* this case happens for nested calls happening from inside the GCD queue */ + callback (data); + if (destroy) + destroy (data); + gst_object_unref (context); + } else { + dispatch_async (window_eagl->priv->gl_queue, ^{ + gst_gl_context_activate (context, TRUE); + gst_object_unref (context); + callback (data); + if (destroy) + destroy (data); + }); + } +} + static void draw_cb (gpointer data) {