From 3f32b4576902feb0b0c0f338f16aec159410ce02 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 17 Feb 2015 18:17:59 +1100 Subject: [PATCH] gl/cocoa: don't deadlock if the dispatch_sync is called from the main thread Provide a helper function to check whether we are being called from the main thread and act appropriately. --- gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h | 2 + gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 80 ++++++++++++++--------------- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 39 ++++++++++---- 3 files changed, 70 insertions(+), 51 deletions(-) diff --git a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h index df00a38..ae7abc8 100644 --- a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h +++ b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h @@ -59,6 +59,8 @@ struct _GstGLContextCocoaPrivate gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa); +void _invoke_on_main (GstGLWindowCB func, gpointer data); + G_END_DECLS #endif /* __GST_GL_COCOA_PRIVATE_H__ */ diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index 8298b3d..e7c5722 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -290,6 +290,18 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, GstGLWindow *window = gst_gl_context_get_window (context); GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window); const GLint swapInterval = 1; + NSAutoreleasePool *pool; + CGLPixelFormatObj fmt = NULL; + CGLContextObj glContext; + CGLPixelFormatAttribute attribs[] = { + kCGLPFADoubleBuffer, + kCGLPFAAccumSize, 32, + 0 + }; + CGLError ret; + gint npix; + + pool = [[NSAutoreleasePool alloc] init]; #ifndef GSTREAMER_GLIB_COCOA_NSAPPLICATION priv->source_id = g_timeout_add (200, gst_gl_window_cocoa_nsapp_iteration, NULL); @@ -301,58 +313,40 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, else priv->external_gl_context = NULL; - dispatch_sync (dispatch_get_main_queue (), ^{ - NSAutoreleasePool *pool; - CGLPixelFormatObj fmt = NULL; - CGLContextObj glContext; - CGLPixelFormatAttribute attribs[] = { - kCGLPFADoubleBuffer, - kCGLPFAAccumSize, 32, - 0 - }; - CGLError ret; - gint npix; - - pool = [[NSAutoreleasePool alloc] init]; - - if (priv->external_gl_context) { - fmt = CGLGetPixelFormat (priv->external_gl_context); - } - - if (!fmt) { - ret = CGLChoosePixelFormat (attribs, &fmt, &npix); - if (ret != kCGLNoError) { - gst_object_unref (window); - g_set_error (error, GST_GL_CONTEXT_ERROR, - GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "cannot choose a pixel format: %s", CGLErrorString (ret)); - return; - } - } - - gst_gl_context_cocoa_dump_pixel_format (fmt); + if (priv->external_gl_context) { + fmt = CGLGetPixelFormat (priv->external_gl_context); + } - ret = CGLCreateContext (fmt, priv->external_gl_context, &glContext); + if (!fmt) { + ret = CGLChoosePixelFormat (attribs, &fmt, &npix); if (ret != kCGLNoError) { - g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, - "failed to create context: %s", CGLErrorString (ret)); - gst_object_unref (window); - return; + g_set_error (error, GST_GL_CONTEXT_ERROR, + GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "cannot choose a pixel format: %s", CGLErrorString (ret)); + goto error; } + } + + gst_gl_context_cocoa_dump_pixel_format (fmt); - context_cocoa->priv->pixel_format = fmt; - context_cocoa->priv->gl_context = glContext; + ret = CGLCreateContext (fmt, priv->external_gl_context, &glContext); + if (ret != kCGLNoError) { + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, + "failed to create context: %s", CGLErrorString (ret)); + goto error; + } - gst_gl_window_cocoa_create_window (window_cocoa); + context_cocoa->priv->pixel_format = fmt; + context_cocoa->priv->gl_context = glContext; - [pool release]; - }); + _invoke_on_main ((GstGLWindowCB) gst_gl_window_cocoa_create_window, + window_cocoa); if (!context_cocoa->priv->gl_context) { #ifndef GSTREAMER_GLIB_COCOA_NSAPPLICATION g_source_remove (priv->source_id); priv->source_id = 0; #endif - return FALSE; + goto error; } GST_INFO_OBJECT (context, "GL context created: %p", context_cocoa->priv->gl_context); @@ -365,8 +359,14 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, CGLSetParameter (context_cocoa->priv->gl_context, kCGLCPSwapInterval, &swapInterval); gst_object_unref (window); + [pool release]; return TRUE; + +error: + gst_object_unref (window); + [pool release]; + return FALSE; } static void diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 229948a..17ded04 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -238,6 +238,20 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) } static void +_show_window (gpointer data) +{ + GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (data); + GstGLWindowCocoaPrivate *priv = window_cocoa->priv; + + GST_DEBUG_OBJECT (window_cocoa, "make the window available\n"); + [priv->internal_win_id makeMainWindow]; + [priv->internal_win_id orderFrontRegardless]; + [priv->internal_win_id setViewsNeedDisplay:YES]; + + priv->visible = TRUE; +} + +static void gst_gl_window_cocoa_show (GstGLWindow * window) { GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window); @@ -252,17 +266,8 @@ gst_gl_window_cocoa_show (GstGLWindow * window) return; } - dispatch_sync (dispatch_get_main_queue(), ^{ - if (!priv->external_view && !priv->visible) { - - GST_DEBUG_OBJECT (window_cocoa, "make the window available\n"); - [priv->internal_win_id makeMainWindow]; - [priv->internal_win_id orderFrontRegardless]; - [priv->internal_win_id setViewsNeedDisplay:YES]; - - priv->visible = TRUE; - } - }); + if (!priv->external_view && !priv->visible) + _invoke_on_main ((GstGLWindowCB) _show_window, window); } } @@ -561,3 +566,15 @@ close_window_cb (gpointer data) @end +void +_invoke_on_main (GstGLWindowCB func, gpointer data) +{ + if ([NSThread isMainThread]) { + func (data); + } else { + dispatch_sync (dispatch_get_main_queue (), ^{ + func (data); + }); + } +} + -- 2.7.4