[818/906] window: add send_message_async vmethod
authorMatthew Waters <ystreet00@gmail.com>
Wed, 25 Sep 2013 02:26:57 +0000 (12:26 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:31 +0000 (19:31 +0000)
- provide a default synchronous send_message
- make context creation threadsafe again

gst-libs/gst/gl/android/gstglwindow_android_egl.c
gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h
gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m
gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c
gst-libs/gst/gl/gstglcontext.c
gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
gst-libs/gst/gl/win32/gstglwindow_win32.c
gst-libs/gst/gl/x11/gstglwindow_x11.c

index f1bdf66..a918127 100644 (file)
@@ -48,8 +48,8 @@ static void gst_gl_window_android_egl_draw (GstGLWindow * window, guint width,
 static void gst_gl_window_android_egl_run (GstGLWindow * window);
 static void gst_gl_window_android_egl_quit (GstGLWindow * window,
     GstGLWindowCB callback, gpointer data);
-static void gst_gl_window_android_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+static void gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 static gboolean gst_gl_window_android_egl_open (GstGLWindow * window,
     GError ** error);
 static void gst_gl_window_android_egl_close (GstGLWindow * window);
@@ -68,8 +68,8 @@ gst_gl_window_android_egl_class_init (GstGLWindowAndroidEGLClass * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message_async);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_open);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_close);
 }
@@ -150,51 +150,41 @@ gst_gl_window_android_egl_quit (GstGLWindow * window, GstGLWindowCB callback,
 
 typedef struct _GstGLMessage
 {
-  GMutex lock;
-  GCond cond;
-  gboolean fired;
-
   GstGLWindowCB callback;
   gpointer data;
+  GDestroyNotify destroy;
 } GstGLMessage;
 
 static gboolean
 _run_message (GstGLMessage * message)
 {
-  g_mutex_lock (&message->lock);
-
   if (message->callback)
     message->callback (message->data);
 
-  message->fired = TRUE;
-  g_cond_signal (&message->cond);
-  g_mutex_unlock (&message->lock);
+  if (message->destroy)
+    message->destroy (message->data);
+
+  g_slice_free (GstGLMessage, message);
 
   return FALSE;
 }
 
 static void
-gst_gl_window_android_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data)
+gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
 {
   GstGLWindowAndroidEGL *window_egl;
-  GstGLMessage message;
+  GstGLMessage *message;
 
   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
-  message.callback = callback;
-  message.data = data;
-  message.fired = FALSE;
-  g_mutex_init (&message.lock);
-  g_cond_init (&message.cond);
+  message = g_slice_new (GstGLMessage);
 
-  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
-      &message);
-
-  g_mutex_lock (&message.lock);
+  message->callback = callback;
+  message->data = data;
+  message->destroy = destroy;
 
-  while (!message.fired)
-    g_cond_wait (&message.cond, &message.lock);
-  g_mutex_unlock (&message.lock);
+  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
+      message);
 }
 
 static void
index 07b2b14..13577e3 100644 (file)
@@ -54,6 +54,7 @@ struct _GstGLContextCocoaPrivate
   NSOpenGLContext *gl_context;
   NSOpenGLContext *external_gl_context;
   NSRect rect;
+  gint source_id;
 };
 
 
index e808f37..631d2ab 100644 (file)
@@ -29,6 +29,7 @@
 
 static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
     GstGLContext * other_context, GError **error);
+static void gst_gl_context_cocoa_destroy_context (GstGLContext *context);
 static guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window);
 static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate);
 static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context);
@@ -38,6 +39,30 @@ static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context);
 
 G_DEFINE_TYPE (GstGLContextCocoa, gst_gl_context_cocoa, GST_GL_TYPE_CONTEXT);
 
+#ifndef GNUSTEP
+static gboolean
+gst_gl_window_cocoa_nsapp_iteration (gpointer data)
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+  NSEvent *event = nil;
+
+  if ([NSThread isMainThread]) {
+
+    while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask
+      untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]
+      inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) {
+
+      [NSApp sendEvent:event];
+    }
+  }
+
+  [pool release];
+
+  return TRUE;
+}
+#endif
+
 static void
 gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass)
 {
@@ -51,6 +76,8 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass)
 
   g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate));
 
+  context_class->destroy_context =
+      GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_destroy_context);
   context_class->create_context =
       GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_create_context);
   context_class->get_gl_context =
@@ -193,6 +220,11 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
   return TRUE;
 }
 
+static void
+gst_gl_context_cocoa_destroy_context (GstGLContext *context)
+{
+}
+
 static guintptr
 gst_gl_context_cocoa_get_gl_context (GstGLContext * context)
 {
index 038df34..93357ec 100644 (file)
@@ -75,8 +75,8 @@ static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window,
 static void gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height);
 static void gst_gl_window_cocoa_run (GstGLWindow * window);
 static void gst_gl_window_cocoa_quit (GstGLWindow * window);
-static void gst_gl_window_cocoa_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 
 struct _GstGLWindowCocoaPrivate
 {
@@ -85,31 +85,8 @@ struct _GstGLWindowCocoaPrivate
   NSWindow *parent;
   NSThread *thread;
   gboolean running;
-  guint source_id;
 };
 
-gboolean
-gst_gl_window_cocoa_nsapp_iteration (gpointer data)
-{  
-  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-  
-  NSEvent *event = nil;
-  
-  if ([NSThread isMainThread]) {
-    
-    while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask
-      untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]
-      inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) {
-
-      [NSApp sendEvent:event];
-    }
-  }
-  
-  [pool release];
-  
-  return TRUE;
-}
-
 static void
 gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
 {
@@ -131,8 +108,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async);
 
 #ifndef GNUSTEP
   pool = [[NSAutoreleasePool alloc] init];
@@ -201,21 +178,22 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
 
   priv->parent = (NSWindow*) handle;
   if (priv->internal_win_id) {
-    g_source_remove (priv->source_id);
-
-    if (GSRegisterCurrentThread()) {
-      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window);
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
 
-      AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
-      [app_thread_performer performSelectorOnMainThread:@selector(setWindow) 
-          withObject:0 waitUntilDone:YES];
 
-      [pool release];
+    GSRegisterCurrentThread();
 
-      GSUnregisterCurrentThread();
-    } else {
-      GST_DEBUG ("failed to register current thread, cannot set external window id\n");
+    if (context) {
+      g_source_remove (context->priv->source_id);
+      gst_object_unref (context);
     }
+
+    [app_thread_performer performSelectorOnMainThread:@selector(setWindow) 
+        withObject:0 waitUntilDone:YES];
+
+    [pool release];
   }
 }
 
@@ -225,56 +203,54 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height)
 {
   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;
 
-  if (GSRegisterCurrentThread()) {
-    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  GSRegisterCurrentThread();
 
-    AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
-    [app_thread_performer performSelector:@selector(updateWindow) 
+  app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
+  [app_thread_performer performSelector:@selector(updateWindow) 
       onThread:priv->thread withObject:nil waitUntilDone:YES];
-    
-    if (!priv->parent && !priv->visible) {
-      static gint x = 0;
-      static gint y = 0;
 
-      NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
-      NSRect windowRect = [priv->internal_win_id frame];
+  if (!priv->parent && !priv->visible) {
+    static gint x = 0;
+    static gint y = 0;
+
+    NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
+    NSRect windowRect = [priv->internal_win_id frame];
 
-      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 ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x,
+        (int) mainRect.origin.y, (int) mainRect.size.width,
+        (int) mainRect.size.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.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;
 
-      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);
+    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
-      [app_thread_performer performSelector:@selector(orderFront)
-          onThread:priv->thread withObject:nil waitUntilDone:YES];
+    [app_thread_performer performSelector:@selector(orderFront)
+        onThread:priv->thread withObject:nil waitUntilDone:YES];
 
-      /*[priv->internal_win_id setViewsNeedDisplay:YES]; */
-      priv->visible = TRUE;
-    }
-
-    [pool release];
-
-    GSUnregisterCurrentThread();
+    /*[priv->internal_win_id setViewsNeedDisplay:YES]; */
+    priv->visible = TRUE;
   }
-  else
-    GST_DEBUG ("failed to register current thread, cannot draw\n");
+
+  [pool release];
 }
 
 static void
@@ -283,23 +259,19 @@ gst_gl_window_cocoa_run (GstGLWindow * window)
   GstGLWindowCocoa *window_cocoa;
   GstGLWindowCocoaPrivate *priv;
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-#ifndef GNUSTEP
   NSRunLoop *run_loop = [NSRunLoop currentRunLoop];
-#endif
 
   window_cocoa = GST_GL_WINDOW_COCOA (window);
   priv = window_cocoa->priv;
 
+  [run_loop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
+
   GST_DEBUG ("begin loop\n");
-  
+
   if (priv->internal_win_id != nil) {
     priv->running = TRUE;
-#ifndef GNUSTEP
     while (priv->running)
       [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
-#else
-    [NSApp run];
-#endif
 
     [priv->internal_win_id release];
     priv->internal_win_id = nil;
@@ -340,8 +312,8 @@ gst_gl_window_cocoa_quit (GstGLWindow * window)
 
 /* Thread safe */
 static void
-gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
-    gpointer data)
+gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
 {
   GstGLWindowCocoa *window_cocoa;
   GstGLWindowCocoaPrivate *priv;
@@ -349,22 +321,18 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
   window_cocoa = GST_GL_WINDOW_COCOA (window);
   priv = window_cocoa->priv;
 
+  GSRegisterCurrentThread ();
+
   if (window) {
-    if (GSRegisterCurrentThread()) {
-      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-      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:YES];
+    AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc]
+        initWithAll:window_cocoa callback:callback userData:data];
 
-      [pool release];
+    [app_thread_performer performSelector:@selector(sendToApp) onThread:priv->thread
+        withObject:nil waitUntilDone:NO];
 
-      GSUnregisterCurrentThread();
-    }
-    else
-      GST_DEBUG ("failed to register current thread, cannot send message\n");
+    [pool release];
   }
 }
 
@@ -394,9 +362,9 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
   GST_DEBUG ("initializing GstGLNSWindow\n");
 
   [self setTitle:@"OpenGL renderer"];
-  
+
   [self setBackgroundColor:[NSColor clearColor]];
-  
+
   [self orderOut:m_cocoa->priv->internal_win_id];
 
   if (m_cocoa->priv->parent) {
@@ -596,7 +564,7 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
 }
 
 - (void) sendToApp {
-  if (m_cocoa->priv->running && ![m_cocoa->priv->internal_win_id isClosed])
+  if (m_callback)
     m_callback (m_data);
 }
 
index a3648e8..488c34b 100644 (file)
@@ -43,8 +43,8 @@ static void gst_gl_window_dispmanx_egl_draw (GstGLWindow * window, guint width,
     guint height);
 static void gst_gl_window_dispmanx_egl_run (GstGLWindow * window);
 static void gst_gl_window_dispmanx_egl_quit (GstGLWindow * window);
-static void gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+static void gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 static void gst_gl_window_dispmanx_egl_close (GstGLWindow * window);
 static gboolean gst_gl_window_dispmanx_egl_open (GstGLWindow * window,
     GError ** error);
@@ -68,8 +68,8 @@ gst_gl_window_dispmanx_egl_class_init (GstGLWindowDispmanxEGLClass * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message_async);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_close);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_open);
   window_class->get_display =
@@ -180,51 +180,41 @@ gst_gl_window_dispmanx_egl_quit (GstGLWindow * window)
 
 typedef struct _GstGLMessage
 {
-  GMutex lock;
-  GCond cond;
-  gboolean fired;
-
   GstGLWindowCB callback;
   gpointer data;
+  GDestroyNotify destroy;
 } GstGLMessage;
 
 static gboolean
 _run_message (GstGLMessage * message)
 {
-  g_mutex_lock (&message->lock);
-
   if (message->callback)
     message->callback (message->data);
 
-  message->fired = TRUE;
-  g_cond_signal (&message->cond);
-  g_mutex_unlock (&message->lock);
+  if (message->destroy)
+    message->destroy (message->data);
+
+  g_slice_free (GstGLMessage, message);
 
   return FALSE;
 }
 
 static void
-gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data)
+gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
 {
   GstGLWindowDispmanxEGL *window_egl;
-  GstGLMessage message;
+  GstGLMessage *message;
 
   window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
-  message.callback = callback;
-  message.data = data;
-  message.fired = FALSE;
-  g_mutex_init (&message.lock);
-  g_cond_init (&message.cond);
+  message = g_slice_new (GstGLMessage);
 
-  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
-      &message);
-
-  g_mutex_lock (&message.lock);
+  message->callback = callback;
+  message->data = data;
+  message->destroy = destroy;
 
-  while (!message.fired)
-    g_cond_wait (&message.cond, &message.lock);
-  g_mutex_unlock (&message.lock);
+  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
+      message);
 }
 
 static guintptr
@@ -283,8 +273,8 @@ window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height)
     vc_dispmanx_update_submit_sync (dispman_update);
 
     if (GST_GL_WINDOW (window_egl)->resize)
-      GST_GL_WINDOW (window_egl)->
-          resize (GST_GL_WINDOW (window_egl)->resize_data, width, height);
+      GST_GL_WINDOW (window_egl)->resize (GST_GL_WINDOW (window_egl)->
+          resize_data, width, height);
   }
 
   window_egl->native.width = width;
index ae89168..4b85327 100644 (file)
@@ -513,6 +513,12 @@ _parse_gl_api (const gchar * apis_s)
   return ret;
 }
 
+static void
+_unlock_create_thread (GstGLContext * context)
+{
+  g_mutex_unlock (&context->priv->render_lock);
+}
+
 //gboolean
 //gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
 static gpointer
@@ -637,7 +643,10 @@ gst_gl_context_create_thread (GstGLContext * context)
   context->priv->alive = TRUE;
 
   g_cond_signal (&context->priv->create_cond);
-  g_mutex_unlock (&context->priv->render_lock);
+
+//  g_mutex_unlock (&context->priv->render_lock);
+  gst_gl_window_send_message_async (context->window,
+      (GstGLWindowCB) _unlock_create_thread, context, NULL);
 
   gst_gl_window_run (context->window);
 
index 929745a..d4f57a5 100644 (file)
@@ -64,6 +64,9 @@ G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT);
 #define GST_GL_WINDOW_GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate))
 
+static void gst_gl_window_default_send_message (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data);
+
 struct _GstGLWindowPrivate
 {
   GstGLDisplay *display;
@@ -112,6 +115,8 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
 {
   g_type_class_add_private (klass, sizeof (GstGLWindowPrivate));
 
+  klass->send_message = GST_DEBUG_FUNCPTR (gst_gl_window_default_send_message);
+
   G_OBJECT_CLASS (klass)->finalize = gst_gl_window_finalize;
 }
 
@@ -257,6 +262,55 @@ gst_gl_window_quit (GstGLWindow * window)
   GST_INFO ("quit received from gl window");
 }
 
+typedef struct _GstGLSyncMessage
+{
+  GMutex lock;
+  GCond cond;
+  gboolean fired;
+
+  GstGLWindowCB callback;
+  gpointer data;
+} GstGLSyncMessage;
+
+static void
+_run_message_sync (GstGLSyncMessage * message)
+{
+  g_mutex_lock (&message->lock);
+
+  if (message->callback)
+    message->callback (message->data);
+
+  message->fired = TRUE;
+  g_cond_signal (&message->cond);
+  g_mutex_unlock (&message->lock);
+}
+
+void
+gst_gl_window_default_send_message (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data)
+{
+  GstGLSyncMessage message;
+
+  message.callback = callback;
+  message.data = data;
+  message.fired = FALSE;
+  g_mutex_init (&message.lock);
+  g_cond_init (&message.cond);
+
+  gst_gl_window_send_message_async (window, (GstGLWindowCB) _run_message_sync,
+      &message, NULL);
+
+  g_mutex_lock (&message.lock);
+
+  /* block until opengl calls have been executed in the gl thread */
+  while (!message.fired)
+    g_cond_wait (&message.cond, &message.lock);
+  g_mutex_unlock (&message.lock);
+
+  g_mutex_clear (&message.lock);
+  g_cond_clear (&message.cond);
+}
+
 void
 gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback,
     gpointer data)
@@ -266,13 +320,27 @@ gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback,
   g_return_if_fail (GST_GL_IS_WINDOW (window));
   g_return_if_fail (callback != NULL);
   window_class = GST_GL_WINDOW_GET_CLASS (window);
-  g_return_if_fail (window_class->quit != NULL);
+  g_return_if_fail (window_class->send_message != NULL);
 
   GST_GL_WINDOW_LOCK (window);
   window_class->send_message (window, callback, data);
   GST_GL_WINDOW_UNLOCK (window);
 }
 
+void
+gst_gl_window_send_message_async (GstGLWindow * window, GstGLWindowCB callback,
+    gpointer data, GDestroyNotify destroy)
+{
+  GstGLWindowClass *window_class;
+
+  g_return_if_fail (GST_GL_IS_WINDOW (window));
+  g_return_if_fail (callback != NULL);
+  window_class = GST_GL_WINDOW_GET_CLASS (window);
+  g_return_if_fail (window_class->send_message_async != NULL);
+
+  window_class->send_message_async (window, callback, data, destroy);
+}
+
 /**
  * gst_gl_window_set_need_lock:
  *
index 1d2137d..ba2f103 100644 (file)
@@ -104,6 +104,7 @@ struct _GstGLWindowClass {
   void     (*run)                (GstGLWindow *window);
   void     (*quit)               (GstGLWindow *window);
   void     (*send_message)       (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
+  void     (*send_message_async) (GstGLWindow *window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 
   gboolean (*open)               (GstGLWindow *window, GError **error);
   void     (*close)              (GstGLWindow *window);
@@ -131,6 +132,7 @@ void     gst_gl_window_draw                 (GstGLWindow *window, guint width, g
 void     gst_gl_window_run                  (GstGLWindow *window);
 void     gst_gl_window_quit                 (GstGLWindow *window);
 void     gst_gl_window_send_message         (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
+void     gst_gl_window_send_message_async   (GstGLWindow *window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 guintptr gst_gl_window_get_display          (GstGLWindow *window);
 
 GstGLContext * gst_gl_window_get_context (GstGLWindow *window);
index 32f82f6..1c7e3e6 100644 (file)
@@ -48,8 +48,8 @@ static void gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width,
     guint height);
 static void gst_gl_window_wayland_egl_run (GstGLWindow * window);
 static void gst_gl_window_wayland_egl_quit (GstGLWindow * window);
-static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+static void gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 static void gst_gl_window_wayland_egl_close (GstGLWindow * window);
 static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window,
     GError ** error);
@@ -258,8 +258,8 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message_async);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_close);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open);
   window_class->get_display =
@@ -379,51 +379,41 @@ gst_gl_window_wayland_egl_quit (GstGLWindow * window)
 
 typedef struct _GstGLMessage
 {
-  GMutex lock;
-  GCond cond;
-  gboolean fired;
-
   GstGLWindowCB callback;
   gpointer data;
+  GDestroyNotify destroy;
 } GstGLMessage;
 
 static gboolean
 _run_message (GstGLMessage * message)
 {
-  g_mutex_lock (&message->lock);
-
   if (message->callback)
     message->callback (message->data);
 
-  message->fired = TRUE;
-  g_cond_signal (&message->cond);
-  g_mutex_unlock (&message->lock);
+  if (message->destroy)
+    message->destroy (message->data);
+
+  g_slice_free (GstGLMessage, message);
 
   return FALSE;
 }
 
 static void
-gst_gl_window_wayland_egl_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data)
+gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
 {
   GstGLWindowWaylandEGL *window_egl;
-  GstGLMessage message;
+  GstGLMessage *message;
 
   window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
-  message.callback = callback;
-  message.data = data;
-  message.fired = FALSE;
-  g_mutex_init (&message.lock);
-  g_cond_init (&message.cond);
+  message = g_slice_new (GstGLMessage);
 
-  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
-      &message);
-
-  g_mutex_lock (&message.lock);
+  message->callback = callback;
+  message->data = data;
+  message->destroy = destroy;
 
-  while (!message.fired)
-    g_cond_wait (&message.cond, &message.lock);
-  g_mutex_unlock (&message.lock);
+  g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
+      message);
 }
 
 static guintptr
index 94c32fe..f50bc3d 100644 (file)
@@ -62,8 +62,8 @@ static void gst_gl_window_win32_draw (GstGLWindow * window, guint width,
     guint height);
 static void gst_gl_window_win32_run (GstGLWindow * window);
 static void gst_gl_window_win32_quit (GstGLWindow * window);
-static void gst_gl_window_win32_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+static void gst_gl_window_win32_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 
 static void
 gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
@@ -78,8 +78,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_win32_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_win32_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message_async);
   window_class->get_display =
       GST_DEBUG_FUNCPTR (gst_gl_window_win32_get_display);
 }
@@ -330,19 +330,47 @@ gst_gl_window_win32_quit (GstGLWindow * window)
   }
 }
 
+typedef struct _GstGLMessage
+{
+  GstGLWindowCB callback;
+  gpointer data;
+  GDestroyNotify destroy;
+} GstGLMessage;
+
+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_win32_send_message (GstGLWindow * window, GstGLWindowCB callback,
-    gpointer data)
+gst_gl_window_win32_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
 {
   GstGLWindowWin32 *window_win32;
+  GstGLMessage *message;
 
   window_win32 = GST_GL_WINDOW_WIN32 (window);
+  message = g_slice_new (GstGLMessage);
 
   if (window_win32) {
-    LRESULT res =
-        SendMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM,
-        (WPARAM) data, (LPARAM) callback);
+    LRESULT res;
+
+    message->callback = callback;
+    message->data = data;
+    message->destroy = destroy;
+
+    res = PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM,
+        (WPARAM) message, (LPARAM) NULL);
     g_return_if_fail (SUCCEEDED (res));
   }
 }
@@ -449,8 +477,8 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
       case WM_GST_GL_WINDOW_CUSTOM:
       {
         if (!window_win32->is_closed) {
-          GstGLWindowCB custom_cb = (GstGLWindowCB) lParam;
-          custom_cb ((gpointer) wParam);
+          GstGLMessage *message = (GstGLMessage *) wParam;
+          _run_message (message);
         }
         break;
       }
index d3659a4..3a79aa3 100644 (file)
@@ -66,8 +66,8 @@ void gst_gl_window_x11_draw_unlocked (GstGLWindow * window, guint width,
 void gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height);
 void gst_gl_window_x11_run (GstGLWindow * window);
 void gst_gl_window_x11_quit (GstGLWindow * window);
-void gst_gl_window_x11_send_message (GstGLWindow * window,
-    GstGLWindowCB callback, gpointer data);
+void gst_gl_window_x11_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
 gboolean gst_gl_window_x11_create_context (GstGLWindow * window,
     GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
 gboolean gst_gl_window_x11_open (GstGLWindow * window, GError ** error);
@@ -153,8 +153,8 @@ gst_gl_window_x11_class_init (GstGLWindowX11Class * klass)
   window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw);
   window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_x11_run);
   window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_x11_quit);
-  window_class->send_message =
-      GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message_async);
   window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_x11_open);
   window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_x11_close);
 }
@@ -397,7 +397,7 @@ gst_gl_window_x11_activate (GstGLWindow * window, gboolean activate)
   priv = window_x11->priv;
   priv->activate = activate;
 
-  gst_gl_window_x11_send_message (window, GST_GL_WINDOW_CB (callback_activate),
+  gst_gl_window_send_message (window, GST_GL_WINDOW_CB (callback_activate),
       window_x11);
 
   return priv->activate_result;
@@ -541,32 +541,6 @@ gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height)
   }
 }
 
-typedef struct _GstGLMessage
-{
-  GstGLWindow *window;
-  GMutex lock;
-  GCond cond;
-  gboolean fired;
-
-  GstGLWindowCB callback;
-  gpointer data;
-} GstGLMessage;
-
-static gboolean
-_run_message (GstGLMessage * message)
-{
-  g_mutex_lock (&message->lock);
-
-  if (message->callback)
-    message->callback (message->data);
-
-  message->fired = TRUE;
-  g_cond_signal (&message->cond);
-  g_mutex_unlock (&message->lock);
-
-  return FALSE;
-}
-
 void
 gst_gl_window_x11_run (GstGLWindow * window)
 {
@@ -726,35 +700,43 @@ gst_gl_window_x11_quit (GstGLWindow * window)
   GST_LOG ("quit sent");
 }
 
-/* Not called by the gl thread */
-void
-gst_gl_window_x11_send_message (GstGLWindow * window, GstGLWindowCB callback,
-    gpointer data)
+typedef struct _GstGLMessage
 {
-  GstGLWindowX11 *window_x11;
+  GstGLWindowCB callback;
+  gpointer data;
+  GDestroyNotify destroy;
+} GstGLMessage;
 
-  window_x11 = GST_GL_WINDOW_X11 (window);
+static gboolean
+_run_message (GstGLMessage * message)
+{
+  if (message->callback)
+    message->callback (message->data);
 
-  if (g_main_loop_is_running (window_x11->loop)) {
-    GstGLMessage message;
+  if (message->destroy)
+    message->destroy (message->data);
+
+  g_slice_free (GstGLMessage, message);
+
+  return FALSE;
+}
 
-    message.window = window;
-    message.callback = callback;
-    message.data = data;
-    message.fired = FALSE;
-    g_mutex_init (&message.lock);
-    g_cond_init (&message.cond);
+void
+gst_gl_window_x11_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
+{
+  GstGLWindowX11 *window_x11;
+  GstGLMessage *message;
 
-    g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message,
-        &message);
+  window_x11 = GST_GL_WINDOW_X11 (window);
+  message = g_slice_new (GstGLMessage);
 
-    g_mutex_lock (&message.lock);
+  message->callback = callback;
+  message->data = data;
+  message->destroy = destroy;
 
-    /* block until opengl calls have been executed in the gl thread */
-    while (!message.fired)
-      g_cond_wait (&message.cond, &message.lock);
-    g_mutex_unlock (&message.lock);
-  }
+  g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message,
+      message);
 }
 
 static int