From ad4f17075bf4ff32933eb83a8ab33e275bcff34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 26 Sep 2014 14:21:46 +0300 Subject: gl/cocoa: Call UI related API from the application main thread --- gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 113 +++++++++++++++-------------- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 113 ++++++++++++----------------- 2 files changed, 108 insertions(+), 118 deletions(-) diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index e83b33de2..131e06e72 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -85,7 +85,7 @@ gst_gl_window_cocoa_nsapp_iteration (gpointer data) if ([NSThread isMainThread]) { while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5] + untilDate:[NSDate dateWithTimeIntervalSinceNow:0.05] inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) { [NSApp sendEvent:event]; @@ -135,7 +135,7 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) if ([NSThread isMainThread]) { /* In the main thread so just do the call now */ - + /* The sharedApplication class method initializes * the display environment and connects your program * to the window server and the display server @@ -201,17 +201,11 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, GstGLContextCocoaPrivate *priv = context_cocoa->priv; GstGLWindow *window = gst_gl_context_get_window (context); GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window); - GstGLNSView *glView = nil; - NSWindow *window_handle; - NSRect rect; - NSAutoreleasePool *pool; - NSOpenGLPixelFormat *fmt = nil; - NSOpenGLContext *glContext = nil; - NSOpenGLPixelFormatAttribute attribs[] = { - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAccumSize, 32, - 0 - }; + __block NSOpenGLContext *glContext = nil; + +#ifndef GNUSTEP + priv->source_id = g_timeout_add (200, gst_gl_window_cocoa_nsapp_iteration, NULL); +#endif priv->gl_context = nil; if (other_context) @@ -219,52 +213,64 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, else priv->external_gl_context = NULL; -#ifdef GNUSTEP - GSRegisterCurrentThread(); -#endif + dispatch_sync (dispatch_get_main_queue (), ^{ + NSAutoreleasePool *pool; + NSOpenGLPixelFormat *fmt = nil; + GstGLNSView *glView = nil; + NSOpenGLPixelFormatAttribute attribs[] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccumSize, 32, + 0 + }; + NSRect rect; + NSWindow *window_handle; - pool = [[NSAutoreleasePool alloc] init]; + pool = [[NSAutoreleasePool alloc] init]; #ifdef GNUSTEP - [NSApplication sharedApplication]; + [NSApplication sharedApplication]; #endif + rect.origin.x = 0; + rect.origin.y = 0; + rect.size.width = 320; + rect.size.height = 240; + + gst_gl_window_cocoa_create_window (window_cocoa, rect); + window_handle = (NSWindow *) gst_gl_window_get_window_handle (window); + + fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + if (!fmt) { + gst_object_unref (window); + GST_WARNING ("cannot create NSOpenGLPixelFormat"); + return; + } - rect.origin.x = 0; - rect.origin.y = 0; - rect.size.width = 320; - rect.size.height = 240; - - gst_gl_window_cocoa_create_window (window_cocoa, rect); - window_handle = (NSWindow *) gst_gl_window_get_window_handle (window); - - glView = [GstGLNSView alloc]; - - fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - - if (!fmt) { - gst_object_unref (window); - GST_WARNING ("cannot create NSOpenGLPixelFormat"); - return FALSE; - } - - glView = [glView initWithFrame:window_cocoa rect:rect]; + glView = [[GstGLNSView alloc] initWithFrame:window_cocoa rect:rect]; - [window_handle setContentView:glView]; + [window_handle setContentView:glView]; #ifndef GNUSTEP - glContext = [[NSOpenGLContext alloc] initWithFormat:fmt - shareContext:context_cocoa->priv->external_gl_context]; + glContext = [[NSOpenGLContext alloc] initWithFormat:fmt + shareContext:context_cocoa->priv->external_gl_context]; - GST_DEBUG ("NSOpenGL context created: %"G_GUINTPTR_FORMAT, (guintptr) glContext); + GST_DEBUG ("NSOpenGL context created: %"G_GUINTPTR_FORMAT, (guintptr) glContext); - context_cocoa->priv->gl_context = glContext; + context_cocoa->priv->gl_context = glContext; - [glContext setView:glView]; + [glContext setView:glView]; #else - /* FIXME try to make context sharing work in GNUstep */ - context_cocoa->priv->gl_context = glContext; + /* FIXME try to make context sharing work in GNUstep */ + context_cocoa->priv->gl_context = glContext; #endif + [pool release]; + }); + + if (!glContext) { + g_source_remove (priv->source_id); + priv->source_id = 0; + return FALSE; + } /* OpenGL context is made current only one time threre. * Indeed, all OpenGL calls are made in only one thread, @@ -290,14 +296,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, } NS_ENDHANDLER - GST_DEBUG ("opengl GstGLNSWindow initialized: %d x %d\n", - (gint) rect.size.width, (gint) rect.size.height); - - [pool release]; - -#ifndef GNUSTEP - priv->source_id = g_timeout_add_seconds (1, gst_gl_window_cocoa_nsapp_iteration, NULL); -#endif + GST_DEBUG ("opengl GstGLNSWindow initialized"); gst_object_unref (window); @@ -307,6 +306,14 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, static void gst_gl_context_cocoa_destroy_context (GstGLContext *context) { + GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context); + GstGLContextCocoaPrivate *priv = context_cocoa->priv; + + /* FIXME: Need to release context and other things? */ + if (priv->source_id) { + g_source_remove (priv->source_id); + priv->source_id = 0; + } } static guintptr diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 706983562..4f6687179 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -123,20 +123,20 @@ gst_gl_window_cocoa_new (void) return window; } +/* Must be called from the main thread */ gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa, NSRect rect) { GstGLWindowCocoaPrivate *priv = window_cocoa->priv; - /* FIXME: This should probably be done in the application main thread */ priv->internal_win_id = [[GstGLNSWindow alloc] initWithContentRect:rect styleMask: - (NSTitledWindowMask | NSClosableWindowMask | - NSResizableWindowMask | NSMiniaturizableWindowMask) - backing: NSBackingStoreBuffered defer: NO screen: nil gstWin: window_cocoa]; + (NSTitledWindowMask | NSClosableWindowMask | + NSResizableWindowMask | NSMiniaturizableWindowMask) + backing: NSBackingStoreBuffered defer: NO screen: nil gstWin: window_cocoa]; - GST_DEBUG ("NSWindow id: %"G_GUINTPTR_FORMAT, (guintptr) priv->internal_win_id); + GST_DEBUG ("NSWindow id: %"G_GUINTPTR_FORMAT, (guintptr) priv->internal_win_id); - [NSApp setDelegate: priv->internal_win_id]; + [NSApp setDelegate: priv->internal_win_id]; return TRUE; } @@ -175,21 +175,6 @@ gst_gl_window_cocoa_get_window_handle (GstGLWindow *window) return (guintptr) GST_GL_WINDOW_COCOA (window)->priv->internal_win_id; } -static void -set_window_handle_cb (gpointer data) -{ - GstGLWindowCocoa * window_cocoa = data; - NSView *view = [window_cocoa->priv->internal_win_id contentView]; - - /* FIXME: This should probably be in the application main thread! */ - [window_cocoa->priv->internal_win_id orderOut:window_cocoa->priv->internal_win_id]; - - [window_cocoa->priv->external_view addSubview: view]; - - [view setFrame: [window_cocoa->priv->external_view bounds]]; - [view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; -} - static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) { @@ -200,16 +185,6 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) priv = window_cocoa->priv; if (priv->internal_win_id) { - GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window); - - if (context) { - if (context->priv->source_id) { - g_source_remove (context->priv->source_id); - context->priv->source_id = 0; - } - gst_object_unref (context); - } - if (handle) { priv->external_view = (NSView *) handle; priv->visible = TRUE; @@ -220,7 +195,15 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) } - gst_gl_window_send_message (window, (GstGLWindowCB) set_window_handle_cb, window_cocoa); + dispatch_async (dispatch_get_main_queue (), ^{ + NSView *view = [window_cocoa->priv->internal_win_id contentView]; + [window_cocoa->priv->internal_win_id orderOut:window_cocoa->priv->internal_win_id]; + + [window_cocoa->priv->external_view addSubview: view]; + + [view setFrame: [window_cocoa->priv->external_view bounds]]; + [view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; + }); } else { /* no internal window yet so delay it to the next drawing */ priv->external_view = (NSView*) handle; @@ -250,39 +233,38 @@ draw_cb (gpointer data) } if (!priv->external_view && !priv->visible) { - gint x = 0; - gint y = 0; + dispatch_sync (dispatch_get_main_queue (), ^{ + NSRect mainRect = [[NSScreen mainScreen] visibleFrame]; + NSRect windowRect = [priv->internal_win_id frame]; + gint x = 0; + gint y = 0; - /* FIXME: This should probably be done from the application main thread */ + GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x, + (int) mainRect.origin.y, (int) mainRect.size.width, + (int) mainRect.size.height); - NSRect mainRect = [[NSScreen mainScreen] visibleFrame]; - NSRect windowRect = [priv->internal_win_id frame]; + windowRect.origin.x += x; + windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y; + windowRect.size.width = draw_data->width; + windowRect.size.height = draw_data->height; - GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x, - (int) mainRect.origin.y, (int) mainRect.size.width, - (int) mainRect.size.height); + GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x, + (int) windowRect.origin.y, (int) windowRect.size.width, + (int) windowRect.size.height); - windowRect.origin.x += x; - windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y; - windowRect.size.width = draw_data->width; - windowRect.size.height = draw_data->height; - - GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x, - (int) windowRect.origin.y, (int) windowRect.size.width, - (int) windowRect.size.height); - - x += 20; - y += 20; + x += 20; + y += 20; #ifndef GNUSTEP - [priv->internal_win_id setFrame:windowRect display:NO]; - GST_DEBUG ("make the window available\n"); - [priv->internal_win_id makeMainWindow]; + [priv->internal_win_id setFrame:windowRect display:NO]; + GST_DEBUG ("make the window available\n"); + [priv->internal_win_id makeMainWindow]; #endif - [priv->internal_win_id orderFrontRegardless]; + [priv->internal_win_id orderFrontRegardless]; - /*[priv->internal_win_id setViewsNeedDisplay:YES]; */ + [priv->internal_win_id setViewsNeedDisplay:YES]; + }); priv->visible = TRUE; } @@ -383,6 +365,7 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window, /* */ /* =============================================================*/ +/* Must be called from the main thread */ @implementation GstGLNSWindow - (id) initWithContentRect: (NSRect) contentRect @@ -446,7 +429,6 @@ close_window_cb (gpointer data) window = GST_GL_WINDOW (window_cocoa); - [window_cocoa->priv->internal_win_id setClosed]; if (window->close) { window->close (window->close_data); } @@ -456,7 +438,8 @@ close_window_cb (gpointer data) - (BOOL) windowShouldClose:(id)sender { GST_DEBUG ("user clicked the close button\n"); - gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) close_window_cb, window_cocoa); + [window_cocoa->priv->internal_win_id setClosed]; + gst_gl_window_send_message_async (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) close_window_cb, gst_object_ref (window_cocoa), (GDestroyNotify) gst_object_unref); return YES; } @@ -496,9 +479,9 @@ close_window_cb (gpointer data) @implementation GstGLNSView +/* Must be called from the application main thread */ - (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect { - /* FIXME: This should probably be done from the application main thread */ self = [super initWithFrame: contentRect]; window_cocoa = window; @@ -556,7 +539,7 @@ resize_cb (gpointer data) NSRect bounds = [self bounds]; NSRect visibleRect = [self visibleRect]; NSSize frameSize = [self frame].size; - struct resize resize_data; + struct resize *resize_data = g_new (struct resize, 1); GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf, " "visibleRect %lf %lf %lf %lf, frame size %lf %lf", @@ -566,12 +549,12 @@ resize_cb (gpointer data) visibleRect.size.width, visibleRect.size.height, frameSize.width, frameSize.height); - resize_data.window = window_cocoa; - resize_data.bounds = bounds; - resize_data.visibleRect = visibleRect; - resize_data.frameSize = frameSize; + resize_data->window = window_cocoa; + resize_data->bounds = bounds; + resize_data->visibleRect = visibleRect; + resize_data->frameSize = frameSize; - gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) resize_cb, &resize_data); + gst_gl_window_send_message_async (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) resize_cb, resize_data, (GDestroyNotify) g_free); } } -- cgit v1.2.1