mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-25 01:54:17 +00:00
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:
parent
9938fe7fa9
commit
3f32b45769
3 changed files with 70 additions and 51 deletions
|
@ -59,6 +59,8 @@ struct _GstGLContextCocoaPrivate
|
||||||
|
|
||||||
gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa);
|
gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa);
|
||||||
|
|
||||||
|
void _invoke_on_main (GstGLWindowCB func, gpointer data);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_GL_COCOA_PRIVATE_H__ */
|
#endif /* __GST_GL_COCOA_PRIVATE_H__ */
|
||||||
|
|
|
@ -290,6 +290,18 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
|
||||||
GstGLWindow *window = gst_gl_context_get_window (context);
|
GstGLWindow *window = gst_gl_context_get_window (context);
|
||||||
GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
|
GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
|
||||||
const GLint swapInterval = 1;
|
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
|
#ifndef GSTREAMER_GLIB_COCOA_NSAPPLICATION
|
||||||
priv->source_id = g_timeout_add (200, gst_gl_window_cocoa_nsapp_iteration, NULL);
|
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
|
else
|
||||||
priv->external_gl_context = NULL;
|
priv->external_gl_context = NULL;
|
||||||
|
|
||||||
dispatch_sync (dispatch_get_main_queue (), ^{
|
if (priv->external_gl_context) {
|
||||||
NSAutoreleasePool *pool;
|
fmt = CGLGetPixelFormat (priv->external_gl_context);
|
||||||
CGLPixelFormatObj fmt = NULL;
|
}
|
||||||
CGLContextObj glContext;
|
|
||||||
CGLPixelFormatAttribute attribs[] = {
|
|
||||||
kCGLPFADoubleBuffer,
|
|
||||||
kCGLPFAAccumSize, 32,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
CGLError ret;
|
|
||||||
gint npix;
|
|
||||||
|
|
||||||
pool = [[NSAutoreleasePool alloc] init];
|
if (!fmt) {
|
||||||
|
ret = CGLChoosePixelFormat (attribs, &fmt, &npix);
|
||||||
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 (ret != kCGLNoError) {
|
if (ret != kCGLNoError) {
|
||||||
g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
|
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
||||||
"failed to create context: %s", CGLErrorString (ret));
|
GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "cannot choose a pixel format: %s", CGLErrorString (ret));
|
||||||
gst_object_unref (window);
|
goto error;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context_cocoa->priv->pixel_format = fmt;
|
gst_gl_context_cocoa_dump_pixel_format (fmt);
|
||||||
context_cocoa->priv->gl_context = glContext;
|
|
||||||
|
|
||||||
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) {
|
if (!context_cocoa->priv->gl_context) {
|
||||||
#ifndef GSTREAMER_GLIB_COCOA_NSAPPLICATION
|
#ifndef GSTREAMER_GLIB_COCOA_NSAPPLICATION
|
||||||
g_source_remove (priv->source_id);
|
g_source_remove (priv->source_id);
|
||||||
priv->source_id = 0;
|
priv->source_id = 0;
|
||||||
#endif
|
#endif
|
||||||
return FALSE;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_INFO_OBJECT (context, "GL context created: %p", context_cocoa->priv->gl_context);
|
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);
|
CGLSetParameter (context_cocoa->priv->gl_context, kCGLCPSwapInterval, &swapInterval);
|
||||||
|
|
||||||
gst_object_unref (window);
|
gst_object_unref (window);
|
||||||
|
[pool release];
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
gst_object_unref (window);
|
||||||
|
[pool release];
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -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
|
static void
|
||||||
gst_gl_window_cocoa_show (GstGLWindow * window)
|
gst_gl_window_cocoa_show (GstGLWindow * window)
|
||||||
{
|
{
|
||||||
|
@ -252,17 +266,8 @@ gst_gl_window_cocoa_show (GstGLWindow * window)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_sync (dispatch_get_main_queue(), ^{
|
if (!priv->external_view && !priv->visible)
|
||||||
if (!priv->external_view && !priv->visible) {
|
_invoke_on_main ((GstGLWindowCB) _show_window, window);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,3 +566,15 @@ close_window_cb (gpointer data)
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
void
|
||||||
|
_invoke_on_main (GstGLWindowCB func, gpointer data)
|
||||||
|
{
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
func (data);
|
||||||
|
} else {
|
||||||
|
dispatch_sync (dispatch_get_main_queue (), ^{
|
||||||
|
func (data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue