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.
This commit is contained in:
Matthew Waters 2015-02-17 18:17:59 +11:00
parent 96398e5bac
commit 0fd6872f7d
3 changed files with 70 additions and 51 deletions

View file

@ -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__ */

View file

@ -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;
if (priv->external_gl_context) {
fmt = CGLGetPixelFormat (priv->external_gl_context);
}
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);
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;
}
}
context_cocoa->priv->pixel_format = fmt;
context_cocoa->priv->gl_context = glContext;
gst_gl_context_cocoa_dump_pixel_format (fmt);
gst_gl_window_cocoa_create_window (window_cocoa);
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;
}
[pool release];
});
context_cocoa->priv->pixel_format = fmt;
context_cocoa->priv->gl_context = glContext;
_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

View file

@ -237,6 +237,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)
{
@ -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);
});
}
}