[818/906] window: add send_message_async vmethod

- provide a default synchronous send_message
- make context creation threadsafe again
This commit is contained in:
Matthew Waters 2013-09-25 12:26:57 +10:00
parent 225d372847
commit db1c7a242b
11 changed files with 308 additions and 248 deletions

View 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_run (GstGLWindow * window);
static void gst_gl_window_android_egl_quit (GstGLWindow * window, static void gst_gl_window_android_egl_quit (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data);
static void gst_gl_window_android_egl_send_message (GstGLWindow * window, static void gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static gboolean gst_gl_window_android_egl_open (GstGLWindow * window, static gboolean gst_gl_window_android_egl_open (GstGLWindow * window,
GError ** error); GError ** error);
static void gst_gl_window_android_egl_close (GstGLWindow * window); 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_run); 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->quit = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message); 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->open = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_open);
window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_close); 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 typedef struct _GstGLMessage
{ {
GMutex lock;
GCond cond;
gboolean fired;
GstGLWindowCB callback; GstGLWindowCB callback;
gpointer data; gpointer data;
GDestroyNotify destroy;
} GstGLMessage; } GstGLMessage;
static gboolean static gboolean
_run_message (GstGLMessage * message) _run_message (GstGLMessage * message)
{ {
g_mutex_lock (&message->lock);
if (message->callback) if (message->callback)
message->callback (message->data); message->callback (message->data);
message->fired = TRUE; if (message->destroy)
g_cond_signal (&message->cond); message->destroy (message->data);
g_mutex_unlock (&message->lock);
g_slice_free (GstGLMessage, message);
return FALSE; return FALSE;
} }
static void static void
gst_gl_window_android_egl_send_message (GstGLWindow * window, gst_gl_window_android_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowAndroidEGL *window_egl; GstGLWindowAndroidEGL *window_egl;
GstGLMessage message; GstGLMessage *message;
window_egl = GST_GL_WINDOW_ANDROID_EGL (window); window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
message.callback = callback; message = g_slice_new (GstGLMessage);
message.data = data;
message.fired = FALSE; message->callback = callback;
g_mutex_init (&message.lock); message->data = data;
g_cond_init (&message.cond); message->destroy = destroy;
g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
&message); message);
g_mutex_lock (&message.lock);
while (!message.fired)
g_cond_wait (&message.cond, &message.lock);
g_mutex_unlock (&message.lock);
} }
static void static void

View file

@ -54,6 +54,7 @@ struct _GstGLContextCocoaPrivate
NSOpenGLContext *gl_context; NSOpenGLContext *gl_context;
NSOpenGLContext *external_gl_context; NSOpenGLContext *external_gl_context;
NSRect rect; NSRect rect;
gint source_id;
}; };

View file

@ -29,6 +29,7 @@
static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
GstGLContext * other_context, GError **error); 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 guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window);
static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate); static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate);
static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context); 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); 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 static void
gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) 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)); 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 = context_class->create_context =
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_create_context); GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_create_context);
context_class->get_gl_context = context_class->get_gl_context =
@ -193,6 +220,11 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
return TRUE; return TRUE;
} }
static void
gst_gl_context_cocoa_destroy_context (GstGLContext *context)
{
}
static guintptr static guintptr
gst_gl_context_cocoa_get_gl_context (GstGLContext * context) gst_gl_context_cocoa_get_gl_context (GstGLContext * context)
{ {

View 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_draw (GstGLWindow * window, guint width, guint height);
static void gst_gl_window_cocoa_run (GstGLWindow * window); static void gst_gl_window_cocoa_run (GstGLWindow * window);
static void gst_gl_window_cocoa_quit (GstGLWindow * window); static void gst_gl_window_cocoa_quit (GstGLWindow * window);
static void gst_gl_window_cocoa_send_message (GstGLWindow * window, static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
struct _GstGLWindowCocoaPrivate struct _GstGLWindowCocoaPrivate
{ {
@ -85,31 +85,8 @@ struct _GstGLWindowCocoaPrivate
NSWindow *parent; NSWindow *parent;
NSThread *thread; NSThread *thread;
gboolean running; 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 static void
gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_run); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_run);
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message); GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async);
#ifndef GNUSTEP #ifndef GNUSTEP
pool = [[NSAutoreleasePool alloc] init]; pool = [[NSAutoreleasePool alloc] init];
@ -201,21 +178,22 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
priv->parent = (NSWindow*) handle; priv->parent = (NSWindow*) handle;
if (priv->internal_win_id) { if (priv->internal_win_id) {
g_source_remove (priv->source_id); GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
if (GSRegisterCurrentThread()) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; GSRegisterCurrentThread();
[app_thread_performer performSelectorOnMainThread:@selector(setWindow)
withObject:0 waitUntilDone:YES];
[pool release]; if (context) {
g_source_remove (context->priv->source_id);
GSUnregisterCurrentThread(); gst_object_unref (context);
} else {
GST_DEBUG ("failed to register current thread, cannot set external window id\n");
} }
[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; GstGLWindowCocoa *window_cocoa;
GstGLWindowCocoaPrivate *priv; GstGLWindowCocoaPrivate *priv;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppThreadPerformer* app_thread_performer;
window_cocoa = GST_GL_WINDOW_COCOA (window); window_cocoa = GST_GL_WINDOW_COCOA (window);
priv = window_cocoa->priv; priv = window_cocoa->priv;
if (GSRegisterCurrentThread()) { GSRegisterCurrentThread();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa];
[app_thread_performer performSelector:@selector(updateWindow) [app_thread_performer performSelector:@selector(updateWindow)
onThread:priv->thread withObject:nil waitUntilDone:YES]; 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]; if (!priv->parent && !priv->visible) {
NSRect windowRect = [priv->internal_win_id frame]; static gint x = 0;
static gint y = 0;
GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x, (int) mainRect.origin.y, NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
(int) mainRect.size.width, (int) mainRect.size.height); NSRect windowRect = [priv->internal_win_id frame];
windowRect.origin.x += x; GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x,
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y; (int) mainRect.origin.y, (int) mainRect.size.width,
windowRect.size.width = width; (int) mainRect.size.height);
windowRect.size.height = height;
GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x, (int) windowRect.origin.y, windowRect.origin.x += x;
(int) windowRect.size.width, (int) windowRect.size.height); windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
windowRect.size.width = width;
windowRect.size.height = height;
x += 20; GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x,
y += 20; (int) windowRect.origin.y, (int) windowRect.size.width,
(int) windowRect.size.height);
x += 20;
y += 20;
#ifndef GNUSTEP #ifndef GNUSTEP
[priv->internal_win_id setFrame:windowRect display:NO]; [priv->internal_win_id setFrame:windowRect display:NO];
GST_DEBUG ("make the window available\n"); GST_DEBUG ("make the window available\n");
[priv->internal_win_id makeMainWindow]; [priv->internal_win_id makeMainWindow];
#endif #endif
[app_thread_performer performSelector:@selector(orderFront) [app_thread_performer performSelector:@selector(orderFront)
onThread:priv->thread withObject:nil waitUntilDone:YES]; onThread:priv->thread withObject:nil waitUntilDone:YES];
/*[priv->internal_win_id setViewsNeedDisplay:YES]; */ /*[priv->internal_win_id setViewsNeedDisplay:YES]; */
priv->visible = TRUE; priv->visible = TRUE;
}
[pool release];
GSUnregisterCurrentThread();
} }
else
GST_DEBUG ("failed to register current thread, cannot draw\n"); [pool release];
} }
static void static void
@ -283,23 +259,19 @@ gst_gl_window_cocoa_run (GstGLWindow * window)
GstGLWindowCocoa *window_cocoa; GstGLWindowCocoa *window_cocoa;
GstGLWindowCocoaPrivate *priv; GstGLWindowCocoaPrivate *priv;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#ifndef GNUSTEP
NSRunLoop *run_loop = [NSRunLoop currentRunLoop]; NSRunLoop *run_loop = [NSRunLoop currentRunLoop];
#endif
window_cocoa = GST_GL_WINDOW_COCOA (window); window_cocoa = GST_GL_WINDOW_COCOA (window);
priv = window_cocoa->priv; priv = window_cocoa->priv;
[run_loop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
GST_DEBUG ("begin loop\n"); GST_DEBUG ("begin loop\n");
if (priv->internal_win_id != nil) { if (priv->internal_win_id != nil) {
priv->running = TRUE; priv->running = TRUE;
#ifndef GNUSTEP
while (priv->running) while (priv->running)
[run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
#else
[NSApp run];
#endif
[priv->internal_win_id release]; [priv->internal_win_id release];
priv->internal_win_id = nil; priv->internal_win_id = nil;
@ -340,8 +312,8 @@ gst_gl_window_cocoa_quit (GstGLWindow * window)
/* Thread safe */ /* Thread safe */
static void static void
gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowCocoa *window_cocoa; GstGLWindowCocoa *window_cocoa;
GstGLWindowCocoaPrivate *priv; GstGLWindowCocoaPrivate *priv;
@ -349,22 +321,18 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
window_cocoa = GST_GL_WINDOW_COCOA (window); window_cocoa = GST_GL_WINDOW_COCOA (window);
priv = window_cocoa->priv; priv = window_cocoa->priv;
GSRegisterCurrentThread ();
if (window) { if (window) {
if (GSRegisterCurrentThread()) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc]
initWithAll:window_cocoa callback:callback userData:data]; initWithAll:window_cocoa callback:callback userData:data];
[app_thread_performer performSelector:@selector(sendToApp) onThread:priv->thread
withObject:nil waitUntilDone:YES];
[pool release]; [app_thread_performer performSelector:@selector(sendToApp) onThread:priv->thread
withObject:nil waitUntilDone:NO];
GSUnregisterCurrentThread(); [pool release];
}
else
GST_DEBUG ("failed to register current thread, cannot send message\n");
} }
} }
@ -394,9 +362,9 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
GST_DEBUG ("initializing GstGLNSWindow\n"); GST_DEBUG ("initializing GstGLNSWindow\n");
[self setTitle:@"OpenGL renderer"]; [self setTitle:@"OpenGL renderer"];
[self setBackgroundColor:[NSColor clearColor]]; [self setBackgroundColor:[NSColor clearColor]];
[self orderOut:m_cocoa->priv->internal_win_id]; [self orderOut:m_cocoa->priv->internal_win_id];
if (m_cocoa->priv->parent) { if (m_cocoa->priv->parent) {
@ -596,7 +564,7 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback,
} }
- (void) sendToApp { - (void) sendToApp {
if (m_cocoa->priv->running && ![m_cocoa->priv->internal_win_id isClosed]) if (m_callback)
m_callback (m_data); m_callback (m_data);
} }

View file

@ -43,8 +43,8 @@ static void gst_gl_window_dispmanx_egl_draw (GstGLWindow * window, guint width,
guint height); guint height);
static void gst_gl_window_dispmanx_egl_run (GstGLWindow * window); 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_quit (GstGLWindow * window);
static void gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, static void gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static void gst_gl_window_dispmanx_egl_close (GstGLWindow * window); static void gst_gl_window_dispmanx_egl_close (GstGLWindow * window);
static gboolean gst_gl_window_dispmanx_egl_open (GstGLWindow * window, static gboolean gst_gl_window_dispmanx_egl_open (GstGLWindow * window,
GError ** error); 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_run); 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->quit = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message); 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->close = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_close);
window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_open); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_open);
window_class->get_display = window_class->get_display =
@ -180,51 +180,41 @@ gst_gl_window_dispmanx_egl_quit (GstGLWindow * window)
typedef struct _GstGLMessage typedef struct _GstGLMessage
{ {
GMutex lock;
GCond cond;
gboolean fired;
GstGLWindowCB callback; GstGLWindowCB callback;
gpointer data; gpointer data;
GDestroyNotify destroy;
} GstGLMessage; } GstGLMessage;
static gboolean static gboolean
_run_message (GstGLMessage * message) _run_message (GstGLMessage * message)
{ {
g_mutex_lock (&message->lock);
if (message->callback) if (message->callback)
message->callback (message->data); message->callback (message->data);
message->fired = TRUE; if (message->destroy)
g_cond_signal (&message->cond); message->destroy (message->data);
g_mutex_unlock (&message->lock);
g_slice_free (GstGLMessage, message);
return FALSE; return FALSE;
} }
static void static void
gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowDispmanxEGL *window_egl; GstGLWindowDispmanxEGL *window_egl;
GstGLMessage message; GstGLMessage *message;
window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); window_egl = GST_GL_WINDOW_DISPMANX_EGL (window);
message.callback = callback; message = g_slice_new (GstGLMessage);
message.data = data;
message.fired = FALSE; message->callback = callback;
g_mutex_init (&message.lock); message->data = data;
g_cond_init (&message.cond); message->destroy = destroy;
g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
&message); message);
g_mutex_lock (&message.lock);
while (!message.fired)
g_cond_wait (&message.cond, &message.lock);
g_mutex_unlock (&message.lock);
} }
static guintptr static guintptr
@ -283,8 +273,8 @@ window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height)
vc_dispmanx_update_submit_sync (dispman_update); vc_dispmanx_update_submit_sync (dispman_update);
if (GST_GL_WINDOW (window_egl)->resize) if (GST_GL_WINDOW (window_egl)->resize)
GST_GL_WINDOW (window_egl)-> GST_GL_WINDOW (window_egl)->resize (GST_GL_WINDOW (window_egl)->
resize (GST_GL_WINDOW (window_egl)->resize_data, width, height); resize_data, width, height);
} }
window_egl->native.width = width; window_egl->native.width = width;

View file

@ -513,6 +513,12 @@ _parse_gl_api (const gchar * apis_s)
return ret; return ret;
} }
static void
_unlock_create_thread (GstGLContext * context)
{
g_mutex_unlock (&context->priv->render_lock);
}
//gboolean //gboolean
//gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error) //gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
static gpointer static gpointer
@ -637,7 +643,10 @@ gst_gl_context_create_thread (GstGLContext * context)
context->priv->alive = TRUE; context->priv->alive = TRUE;
g_cond_signal (&context->priv->create_cond); 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); gst_gl_window_run (context->window);

View file

@ -64,6 +64,9 @@ G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT);
#define GST_GL_WINDOW_GET_PRIVATE(o) \ #define GST_GL_WINDOW_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate)) (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 struct _GstGLWindowPrivate
{ {
GstGLDisplay *display; GstGLDisplay *display;
@ -112,6 +115,8 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
{ {
g_type_class_add_private (klass, sizeof (GstGLWindowPrivate)); 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; 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"); 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 void
gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback, gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback,
gpointer data) 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 (GST_GL_IS_WINDOW (window));
g_return_if_fail (callback != NULL); g_return_if_fail (callback != NULL);
window_class = GST_GL_WINDOW_GET_CLASS (window); 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); GST_GL_WINDOW_LOCK (window);
window_class->send_message (window, callback, data); window_class->send_message (window, callback, data);
GST_GL_WINDOW_UNLOCK (window); 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: * gst_gl_window_set_need_lock:
* *

View file

@ -104,6 +104,7 @@ struct _GstGLWindowClass {
void (*run) (GstGLWindow *window); void (*run) (GstGLWindow *window);
void (*quit) (GstGLWindow *window); void (*quit) (GstGLWindow *window);
void (*send_message) (GstGLWindow *window, GstGLWindowCB callback, gpointer data); 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); gboolean (*open) (GstGLWindow *window, GError **error);
void (*close) (GstGLWindow *window); 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_run (GstGLWindow *window);
void gst_gl_window_quit (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 (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); guintptr gst_gl_window_get_display (GstGLWindow *window);
GstGLContext * gst_gl_window_get_context (GstGLWindow *window); GstGLContext * gst_gl_window_get_context (GstGLWindow *window);

View file

@ -48,8 +48,8 @@ static void gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width,
guint height); guint height);
static void gst_gl_window_wayland_egl_run (GstGLWindow * window); 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_quit (GstGLWindow * window);
static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window, static void gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static void gst_gl_window_wayland_egl_close (GstGLWindow * window); static void gst_gl_window_wayland_egl_close (GstGLWindow * window);
static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window, static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window,
GError ** error); 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_run); 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->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message); 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->close = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_close);
window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open);
window_class->get_display = window_class->get_display =
@ -379,51 +379,41 @@ gst_gl_window_wayland_egl_quit (GstGLWindow * window)
typedef struct _GstGLMessage typedef struct _GstGLMessage
{ {
GMutex lock;
GCond cond;
gboolean fired;
GstGLWindowCB callback; GstGLWindowCB callback;
gpointer data; gpointer data;
GDestroyNotify destroy;
} GstGLMessage; } GstGLMessage;
static gboolean static gboolean
_run_message (GstGLMessage * message) _run_message (GstGLMessage * message)
{ {
g_mutex_lock (&message->lock);
if (message->callback) if (message->callback)
message->callback (message->data); message->callback (message->data);
message->fired = TRUE; if (message->destroy)
g_cond_signal (&message->cond); message->destroy (message->data);
g_mutex_unlock (&message->lock);
g_slice_free (GstGLMessage, message);
return FALSE; return FALSE;
} }
static void static void
gst_gl_window_wayland_egl_send_message (GstGLWindow * window, gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowWaylandEGL *window_egl; GstGLWindowWaylandEGL *window_egl;
GstGLMessage message; GstGLMessage *message;
window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
message.callback = callback; message = g_slice_new (GstGLMessage);
message.data = data;
message.fired = FALSE; message->callback = callback;
g_mutex_init (&message.lock); message->data = data;
g_cond_init (&message.cond); message->destroy = destroy;
g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message,
&message); message);
g_mutex_lock (&message.lock);
while (!message.fired)
g_cond_wait (&message.cond, &message.lock);
g_mutex_unlock (&message.lock);
} }
static guintptr static guintptr

View file

@ -62,8 +62,8 @@ static void gst_gl_window_win32_draw (GstGLWindow * window, guint width,
guint height); guint height);
static void gst_gl_window_win32_run (GstGLWindow * window); static void gst_gl_window_win32_run (GstGLWindow * window);
static void gst_gl_window_win32_quit (GstGLWindow * window); static void gst_gl_window_win32_quit (GstGLWindow * window);
static void gst_gl_window_win32_send_message (GstGLWindow * window, static void gst_gl_window_win32_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static void static void
gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_win32_run); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_win32_run);
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_win32_quit); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_win32_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message); GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message_async);
window_class->get_display = window_class->get_display =
GST_DEBUG_FUNCPTR (gst_gl_window_win32_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 */ /* Thread safe */
static void static void
gst_gl_window_win32_send_message (GstGLWindow * window, GstGLWindowCB callback, gst_gl_window_win32_send_message_async (GstGLWindow * window,
gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowWin32 *window_win32; GstGLWindowWin32 *window_win32;
GstGLMessage *message;
window_win32 = GST_GL_WINDOW_WIN32 (window); window_win32 = GST_GL_WINDOW_WIN32 (window);
message = g_slice_new (GstGLMessage);
if (window_win32) { if (window_win32) {
LRESULT res = LRESULT res;
SendMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM,
(WPARAM) data, (LPARAM) callback); 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)); 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: case WM_GST_GL_WINDOW_CUSTOM:
{ {
if (!window_win32->is_closed) { if (!window_win32->is_closed) {
GstGLWindowCB custom_cb = (GstGLWindowCB) lParam; GstGLMessage *message = (GstGLMessage *) wParam;
custom_cb ((gpointer) wParam); _run_message (message);
} }
break; break;
} }

View 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_draw (GstGLWindow * window, guint width, guint height);
void gst_gl_window_x11_run (GstGLWindow * window); void gst_gl_window_x11_run (GstGLWindow * window);
void gst_gl_window_x11_quit (GstGLWindow * window); void gst_gl_window_x11_quit (GstGLWindow * window);
void gst_gl_window_x11_send_message (GstGLWindow * window, void gst_gl_window_x11_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data); GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
gboolean gst_gl_window_x11_create_context (GstGLWindow * window, gboolean gst_gl_window_x11_create_context (GstGLWindow * window,
GstGLAPI gl_api, guintptr external_gl_context, GError ** error); GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
gboolean gst_gl_window_x11_open (GstGLWindow * window, 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->draw = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw);
window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_x11_run); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_x11_run);
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_x11_quit); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_x11_quit);
window_class->send_message = window_class->send_message_async =
GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message); GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message_async);
window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_x11_open); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_x11_open);
window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_x11_close); 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 = window_x11->priv;
priv->activate = activate; 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); window_x11);
return priv->activate_result; 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 void
gst_gl_window_x11_run (GstGLWindow * window) gst_gl_window_x11_run (GstGLWindow * window)
{ {
@ -726,35 +700,43 @@ gst_gl_window_x11_quit (GstGLWindow * window)
GST_LOG ("quit sent"); GST_LOG ("quit sent");
} }
/* Not called by the gl thread */ 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;
}
void void
gst_gl_window_x11_send_message (GstGLWindow * window, GstGLWindowCB callback, gst_gl_window_x11_send_message_async (GstGLWindow * window,
gpointer data) GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
{ {
GstGLWindowX11 *window_x11; GstGLWindowX11 *window_x11;
GstGLMessage *message;
window_x11 = GST_GL_WINDOW_X11 (window); window_x11 = GST_GL_WINDOW_X11 (window);
message = g_slice_new (GstGLMessage);
if (g_main_loop_is_running (window_x11->loop)) { message->callback = callback;
GstGLMessage message; message->data = data;
message->destroy = destroy;
message.window = window; g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message,
message.callback = callback; message);
message.data = data;
message.fired = FALSE;
g_mutex_init (&message.lock);
g_cond_init (&message.cond);
g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message,
&message);
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);
}
} }
static int static int