gl/cocoa: avoid deadlock when creating context on the main thread.
authorMatthew Waters <matthew@centricular.com>
Tue, 3 Mar 2015 07:05:04 +0000 (18:05 +1100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:57 +0000 (19:31 +0000)
Make window/view creation async so that it is possible to
gst_gl_context_create from the main thread.

ext/gl/caopengllayersink.m
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.h
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m

index fdbcf7b..3a11b8e 100644 (file)
@@ -272,8 +272,6 @@ _ensure_gl_setup (GstCAOpenGLLayerSink * ca_sink)
 {
   GError *error = NULL;
 
-  g_assert (![NSThread isMainThread]);
-
   if (!gst_gl_ensure_element_data (ca_sink, &ca_sink->display,
           &ca_sink->other_context))
     return FALSE;
@@ -400,6 +398,7 @@ gst_ca_opengl_layer_sink_change_state (GstElement * element, GstStateChange tran
 
   switch (transition) {
     case GST_STATE_CHANGE_NULL_TO_READY:
+      _ensure_gl_setup (ca_sink);
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
       g_atomic_int_set (&ca_sink->to_quit, 0);
index 3a794fc..775c291 100644 (file)
@@ -62,7 +62,6 @@ GstGLWindowCocoa * gst_gl_window_cocoa_new (void);
 
 void gst_gl_window_cocoa_draw_thread (GstGLWindowCocoa *window_cocoa);
 
-
 G_END_DECLS
 
 #endif /* __GST_GL_WINDOW_COCOA_H__ */
index 1da6d63..adc63d2 100644 (file)
@@ -92,6 +92,9 @@ struct _GstGLWindowCocoaPrivate
   gint preferred_height;
 
   GLint viewport_dim[4];
+
+  /* atomic set when the internal NSView has been created */
+  int view_ready;
 };
 
 static void
@@ -178,7 +181,9 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa)
 
       GST_DEBUG ("NSWindow id: %"G_GUINTPTR_FORMAT, (guintptr) priv->internal_win_id);
 
- [priv->internal_win_id setContentView:glView];
+  [priv->internal_win_id setContentView:glView];
+
+  g_atomic_int_set (&window_cocoa->priv->view_ready, 1);
 
   return TRUE;
 }
@@ -287,7 +292,14 @@ static void
 gst_gl_window_cocoa_draw (GstGLWindow * window)
 {
   GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
-  GstGLNSView *view = (GstGLNSView *)[window_cocoa->priv->internal_win_id contentView];
+  GstGLNSView *view;
+
+  /* As the view is created asynchronously in the main thread we cannot know
+   * exactly when it will be ready to draw to */
+  if (!g_atomic_int_get (&window_cocoa->priv->view_ready))
+    return;
+
+  view = (GstGLNSView *)[window_cocoa->priv->internal_win_id contentView];
 
   /* this redraws the GstGLCAOpenGLLayer which calls
    * gst_gl_window_cocoa_draw_thread(). Use an explicit CATransaction since we
@@ -584,9 +596,8 @@ _invoke_on_main (GstGLWindowCB func, gpointer data)
   if ([NSThread isMainThread]) {
     func (data);
   } else {
-    dispatch_sync (dispatch_get_main_queue (), ^{
+    dispatch_async (dispatch_get_main_queue (), ^{
       func (data);
     });
   }
 }
-