summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2014-09-25 16:13:19 +0300
committerSebastian Dröge <sebastian@centricular.com>2014-10-14 10:00:28 +0200
commitfdb81f02d7a09ee23ded57a938ad2ff3bc09a08b (patch)
tree2eca733939a18482112623cddd36864468c5e369
parent7a55a58fc4db9bd4f08e9702a963e8553676a520 (diff)
downloadgstreamer-plugins-bad-fdb81f02d7a09ee23ded57a938ad2ff3bc09a08b.tar.gz
gl/cocoa: Switch from our custom main loop to a GMainLoop
Simplifies code a lot and makes it more similar to the other backends.
-rw-r--r--gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h19
-rw-r--r--gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m414
2 files changed, 169 insertions, 264 deletions
diff --git a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h
index 4510cb2a5..726d6071b 100644
--- a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h
+++ b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h
@@ -30,25 +30,6 @@
G_BEGIN_DECLS
-@interface AppThreadPerformer : NSObject {
- GstGLWindowCocoa *m_cocoa;
- GstGLWindowCB m_callback;
- GstGLWindowResizeCB m_callback2;
- gpointer m_data;
- gint m_width;
- gint m_height;
-}
-- (id) init: (GstGLWindowCocoa *)window;
-- (id) initWithCallback:(GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data;
-- (id) initWithSize: (GstGLWindowCocoa *)window callback:(GstGLWindowResizeCB)callback userData:(gpointer)data toSize:(NSSize)size;
-- (id) initWithAll: (GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data;
-- (void) updateWindow;
-- (void) sendToApp;
-- (void) setWindow;
-- (void) stopApp;
-- (void) closeWindow;
-@end
-
struct _GstGLContextCocoaPrivate
{
NSOpenGLContext *gl_context;
diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
index 2de31d7f4..4cb5a3def 100644
--- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
+++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
@@ -53,11 +53,6 @@
/* */
/* =============================================================*/
-#ifndef GNUSTEP
-static BOOL GSRegisterCurrentThread(void) { return TRUE; };
-static void GSUnregisterCurrentThread(void) {};
-#endif
-
#define GST_GL_WINDOW_COCOA_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW_COCOA, GstGLWindowCocoaPrivate))
@@ -69,6 +64,8 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define gst_gl_window_cocoa_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstGLWindowCocoa, gst_gl_window_cocoa, GST_GL_TYPE_WINDOW, DEBUG_INIT);
+static gboolean gst_gl_window_cocoa_open (GstGLWindow *window, GError **err);
+static void gst_gl_window_cocoa_close (GstGLWindow *window);
static guintptr gst_gl_window_cocoa_get_window_handle (GstGLWindow * window);
static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window,
guintptr handle);
@@ -83,8 +80,8 @@ struct _GstGLWindowCocoaPrivate
GstGLNSWindow *internal_win_id;
NSView *external_view;
gboolean visible;
- NSThread *thread;
- gboolean running;
+ GMainContext *main_context;
+ GMainLoop *loop;
};
static void
@@ -96,6 +93,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
g_type_class_add_private (klass, sizeof (GstGLWindowCocoaPrivate));
+ window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_open);
+ window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_close);
window_class->get_window_handle =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_window_handle);
window_class->set_window_handle =
@@ -132,15 +131,15 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa)
GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
NSRect rect = context_cocoa->priv->rect;
- priv->internal_win_id =[[GstGLNSWindow alloc] initWithContentRect:rect styleMask:
+ /* FIXME: This should probably be done in the application main thread */
+ priv->internal_win_id = [GstGLNSWindow alloc];
+ [priv->internal_win_id initWithContentRect:rect styleMask:
(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);
- priv->thread = [NSThread currentThread];
-
[NSApp setDelegate: priv->internal_win_id];
gst_object_unref (context);
@@ -148,6 +147,34 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa)
return TRUE;
}
+static gboolean
+gst_gl_window_cocoa_open (GstGLWindow *window, GError **err)
+{
+ GstGLWindowCocoa *window_cocoa;
+
+ window_cocoa = GST_GL_WINDOW_COCOA (window);
+
+ window_cocoa->priv->main_context = g_main_context_new ();
+ window_cocoa->priv->loop =
+ g_main_loop_new (window_cocoa->priv->main_context, FALSE);
+
+ return TRUE;
+}
+
+static void
+gst_gl_window_cocoa_close (GstGLWindow *window)
+{
+ GstGLWindowCocoa *window_cocoa;
+
+ window_cocoa = GST_GL_WINDOW_COCOA (window);
+
+ g_main_loop_unref (window_cocoa->priv->loop);
+ g_main_context_unref (window_cocoa->priv->main_context);
+
+ [window_cocoa->priv->internal_win_id release];
+ window_cocoa->priv->internal_win_id = nil;
+}
+
static guintptr
gst_gl_window_cocoa_get_window_handle (GstGLWindow *window)
{
@@ -155,6 +182,21 @@ gst_gl_window_cocoa_get_window_handle (GstGLWindow *window)
}
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)
{
GstGLWindowCocoa *window_cocoa;
@@ -162,13 +204,9 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
window_cocoa = GST_GL_WINDOW_COCOA (window);
priv = window_cocoa->priv;
-
+
if (priv->internal_win_id) {
GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window);
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
-
- GSRegisterCurrentThread();
if (context) {
if (context->priv->source_id) {
@@ -186,38 +224,34 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
priv->external_view = 0;
priv->visible = FALSE;
}
-
- [app_thread_performer performSelectorOnMainThread:@selector(setWindow)
- withObject:0 waitUntilDone:YES];
- [pool release];
+
+ gst_gl_window_send_message (window, (GstGLWindowCB) set_window_handle_cb, window_cocoa);
} else {
- /* not internal window yet so delay it to the next drawing */
+ /* no internal window yet so delay it to the next drawing */
priv->external_view = (NSView*) handle;
priv->visible = FALSE;
}
}
/* Thread safe */
-static void
-gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
+struct draw
{
- GstGLWindowCocoa *window_cocoa;
- GstGLWindowCocoaPrivate *priv;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- AppThreadPerformer* app_thread_performer;
-
- window_cocoa = GST_GL_WINDOW_COCOA (window);
- priv = window_cocoa->priv;
-
- GSRegisterCurrentThread();
+ GstGLWindowCocoa *window;
+ guint width, height;
+};
- app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
+static void
+draw_cb (gpointer data)
+{
+ struct draw *draw_data = data;
+ GstGLWindowCocoa *window_cocoa = draw_data->window;
+ GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
/* useful when set_window_handle is called before
* the internal NSWindow */
if (priv->external_view && !priv->visible) {
- gst_gl_window_cocoa_set_window_handle (window, (guintptr) priv->external_view);
+ gst_gl_window_cocoa_set_window_handle (GST_GL_WINDOW (window_cocoa), (guintptr) priv->external_view);
priv->visible = TRUE;
}
@@ -225,6 +259,8 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
static gint x = 0;
static gint y = 0;
+ /* FIXME: This should probably be done from the application main thread */
+
NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
NSRect windowRect = [priv->internal_win_id frame];
@@ -234,8 +270,8 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
windowRect.origin.x += x;
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
- windowRect.size.width = width;
- windowRect.size.height = height;
+ 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,
@@ -249,46 +285,46 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
GST_DEBUG ("make the window available\n");
[priv->internal_win_id makeMainWindow];
#endif
- [app_thread_performer performSelector:@selector(orderFront)
- onThread:priv->thread withObject:nil waitUntilDone:YES];
+
+ [priv->internal_win_id orderFrontRegardless];
/*[priv->internal_win_id setViewsNeedDisplay:YES]; */
priv->visible = TRUE;
}
- [app_thread_performer performSelector:@selector(updateWindow)
- onThread:priv->thread withObject:nil waitUntilDone:YES];
+ if (g_main_loop_is_running (priv->loop)) {
+ if (![priv->internal_win_id isClosed]) {
+ /* draw opengl scene in the back buffer */
+ GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data);
- [pool release];
+ /* Copy the back buffer to the front buffer */
+ [[[priv->internal_win_id contentView] openGLContext] flushBuffer];
+ }
+ }
}
static void
-gst_gl_window_cocoa_run (GstGLWindow * window)
+gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
{
- GstGLWindowCocoa *window_cocoa;
- GstGLWindowCocoaPrivate *priv;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSRunLoop *run_loop = [NSRunLoop currentRunLoop];
-
- window_cocoa = GST_GL_WINDOW_COCOA (window);
- priv = window_cocoa->priv;
-
- [run_loop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
+ struct draw draw_data;
- GST_DEBUG ("begin loop\n");
+ draw_data.window = GST_GL_WINDOW_COCOA (window);
+ draw_data.width = width;
+ draw_data.height = height;
- if (priv->internal_win_id != nil) {
- priv->running = TRUE;
- while (priv->running)
- [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
+ gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, &draw_data);
+}
- [priv->internal_win_id release];
- priv->internal_win_id = nil;
- }
+static void
+gst_gl_window_cocoa_run (GstGLWindow * window)
+{
+ GstGLWindowCocoa *window_cocoa;
- [pool release];
+ window_cocoa = GST_GL_WINDOW_COCOA (window);
- GST_DEBUG ("end loop\n");
+ GST_LOG ("starting main loop");
+ g_main_loop_run (window_cocoa->priv->loop);
+ GST_LOG ("exiting main loop");
}
/* Thread safe */
@@ -296,60 +332,50 @@ static void
gst_gl_window_cocoa_quit (GstGLWindow * window)
{
GstGLWindowCocoa *window_cocoa;
- GstGLWindowCocoaPrivate *priv;
window_cocoa = GST_GL_WINDOW_COCOA (window);
- priv = window_cocoa->priv;
- if (window) {
- if (GSRegisterCurrentThread() || 1) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc]
- initWithAll:window_cocoa callback:NULL userData:NULL];
- [app_thread_performer performSelector:@selector(stopApp)
- onThread:priv->thread withObject:nil waitUntilDone:YES];
+ g_main_loop_quit (window_cocoa->priv->loop);
+}
- [pool release];
+/* Thread safe */
+typedef struct _GstGLMessage
+{
+ GstGLWindowCB callback;
+ gpointer data;
+ GDestroyNotify destroy;
+} GstGLMessage;
- GSUnregisterCurrentThread();
- }
- else
- GST_DEBUG ("failed to register current thread, application thread is lost\n");
- }
+static gboolean
+_run_message (GstGLMessage * message)
+{
+ if (message->callback)
+ message->callback (message->data);
+
+ if (message->destroy)
+ message->destroy (message->data);
+
+ g_slice_free (GstGLMessage, message);
+
+ return FALSE;
}
-/* Thread safe */
static void
gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{
GstGLWindowCocoa *window_cocoa;
- GstGLWindowCocoaPrivate *priv;
+ GstGLMessage *message;
window_cocoa = GST_GL_WINDOW_COCOA (window);
- priv = window_cocoa->priv;
+ message = g_slice_new (GstGLMessage);
- GSRegisterCurrentThread ();
+ message->callback = callback;
+ message->data = data;
+ message->destroy = destroy;
- if (window) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- /* performSelector is not re-entrant so do it manually */
- if (G_UNLIKELY ([NSThread currentThread] == priv->thread)) {
- if (callback)
- callback (data);
- } else {
- AppThreadPerformer* app_thread_performer =
- [[AppThreadPerformer alloc] initWithAll:window_cocoa
- callback:callback userData:data];
-
- [app_thread_performer performSelector:@selector(sendToApp)
- onThread:priv->thread withObject:nil waitUntilDone:NO];
-
- [pool release];
- }
- }
+ g_main_context_invoke (window_cocoa->priv->main_context,
+ (GSourceFunc) _run_message, message);
}
/* =============================================================*/
@@ -413,20 +439,25 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
return YES;
}
+static void
+close_window_cb (gpointer data)
+{
+ GstGLWindowCocoa *window_cocoa = data;
+ GstGLWindow *window;
+
+ window = GST_GL_WINDOW (window_cocoa);
+
+ [window_cocoa->priv->internal_win_id setClosed];
+ if (window->close) {
+ window->close (window->close_data);
+ }
+}
+
/* Called in the main thread which is never the gl thread */
- (BOOL) windowShouldClose:(id)sender {
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc]
- init:m_cocoa];
-
+
GST_DEBUG ("user clicked the close button\n");
-
- [app_thread_performer performSelector:@selector(closeWindow) onThread:m_cocoa->priv->thread
- withObject:nil waitUntilDone:YES];
-
- [pool release];
-
+ gst_gl_window_send_message (GST_GL_WINDOW (m_cocoa), (GstGLWindowCB) close_window_cb, m_cocoa);
return YES;
}
@@ -479,156 +510,49 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
return self;
}
-- (void)reshape {
- GstGLWindow *window;
-
- window = GST_GL_WINDOW (m_cocoa);
-
- if (window->resize) {
-
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSRect bounds = [self bounds];
- AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc]
- initWithSize:m_cocoa callback:window->resize userData:window->resize_data
- toSize:bounds.size];
-
- [app_thread_performer performSelector:@selector(resizeWindow) onThread:m_cocoa->priv->thread
- withObject:nil waitUntilDone:YES];
-
- [pool release];
- }
-}
-
-- (void) update {
-}
-
-@end
-
-/* =============================================================*/
-/* */
-/* AppThreadPerformer implementation */
-/* */
-/* =============================================================*/
-
-@implementation AppThreadPerformer
-
-- (id) init: (GstGLWindowCocoa *) window {
- m_cocoa = window;
- m_callback = NULL;
- m_callback2 = NULL;
- m_data = NULL;
- m_width = 0;
- m_height = 0;
- return self;
-}
-
-- (id) initWithCallback:(GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer)data {
- m_cocoa = window;
- m_callback = callback;
- m_callback2 = NULL;
- m_data = data;
- m_width = 0;
- m_height = 0;
- return self;
-}
-
-- (id) initWithSize: (GstGLWindowCocoa *) window
- callback:(GstGLWindowResizeCB)callback userData:(gpointer)data
- toSize:(NSSize)size {
- m_cocoa = window;
- m_callback = NULL;
- m_callback2 = callback;
- m_data = data;
- m_width = size.width;
- m_height = size.height;
- return self;
-}
-
-- (id) initWithAll: (GstGLWindowCocoa *) window
- callback:(GstGLWindowCB) callback userData: (gpointer) data {
- m_cocoa = window;
- m_callback = callback;
- m_callback2 = NULL;
- m_data = data;
- m_width = 0;
- m_height = 0;
- return self;
-}
-
-- (void) updateWindow {
- if (m_cocoa->priv->running) {
-
- if (![m_cocoa->priv->internal_win_id isClosed]) {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+struct resize
+{
+ GstGLWindowCocoa * window;
+ gint width, height;
+};
- /* draw opengl scene in the back buffer */
- GST_GL_WINDOW (m_cocoa)->draw (GST_GL_WINDOW (m_cocoa)->draw_data);
- /* Copy the back buffer to the front buffer */
- [[[m_cocoa->priv->internal_win_id contentView] openGLContext] flushBuffer];
+static void
+resize_cb (gpointer data)
+{
+ struct resize *resize_data = data;
+ GstGLWindowCocoa *window_cocoa = resize_data->window;
+ GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
- [pool release];
+ if (g_main_loop_is_running (window_cocoa->priv->loop) && ![window_cocoa->priv->internal_win_id isClosed]) {
+ if (window->resize) {
+ window->resize (window->resize_data, resize_data->width, resize_data->height);
}
- }
-}
-- (void) resizeWindow {
- if (m_cocoa->priv->running && ![m_cocoa->priv->internal_win_id isClosed]) {
- m_callback2 (m_data, m_width, m_height);
- [[[m_cocoa->priv->internal_win_id contentView] openGLContext] update];
- GST_GL_WINDOW (m_cocoa)->draw (GST_GL_WINDOW (m_cocoa)->draw_data);
- [[[m_cocoa->priv->internal_win_id contentView] openGLContext] flushBuffer];
+ [[[window_cocoa->priv->internal_win_id contentView] openGLContext] update];
+ GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data);
+ [[[window_cocoa->priv->internal_win_id contentView] openGLContext] flushBuffer];
}
}
-- (void) sendToApp {
- if (m_callback)
- m_callback (m_data);
-}
-
-- (void) setWindow {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- NSView *view = [m_cocoa->priv->internal_win_id contentView];
-
- [m_cocoa->priv->internal_win_id orderOut:m_cocoa->priv->internal_win_id];
-
- [m_cocoa->priv->external_view addSubview: view];
-
- [view setFrame: [m_cocoa->priv->external_view bounds]];
- [view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
-
- [pool release];
-}
-
-- (void) stopApp {
-#ifdef GNUSTEP
- NSAutoreleasePool *pool = nil;
-#endif
-
- m_cocoa->priv->running = FALSE;
- if (m_callback)
- m_callback (m_data);
-
-#ifdef GNUSTEP
- pool = [[NSAutoreleasePool alloc] init];
- if ([NSApp isRunning])
- [NSApp stop:self];
- [pool release];
-#endif
-}
-
-- (void) closeWindow {
+- (void)reshape {
GstGLWindow *window;
window = GST_GL_WINDOW (m_cocoa);
- [m_cocoa->priv->internal_win_id setClosed];
- if (window->close) {
- window->close (window->close_data);
+ if (window->resize) {
+ NSRect bounds = [self bounds];
+ struct resize resize_data;
+
+ resize_data.window = m_cocoa;
+ resize_data.width = bounds.size.width;
+ resize_data.height = bounds.size.height;
+
+ gst_gl_window_send_message (GST_GL_WINDOW (m_cocoa), (GstGLWindowCB) resize_cb, &resize_data);
}
}
-- (void) orderFront {
- [m_cocoa->priv->internal_win_id orderFrontRegardless];
+- (void) update {
}
@end
+