glcontext/cocoa: handle sending one message during shutdown

gst_gl_window_quit() will attempt to send a message but will be called
from GstGLContext's finalize handler and so the weak ref that backs
gst_gl_window_get_context will return NULL as it has already been
cleared.  We need that context in send_message_async to decide whether
to run the provided callback immediately or queue in GCD
This commit is contained in:
Matthew Waters 2020-03-26 13:51:24 +11:00 committed by GStreamer Merge Bot
parent 3a9fde7b24
commit 7f59cefafb

View file

@ -69,6 +69,7 @@ static void gst_gl_window_cocoa_finalize (GObject * object);
static gboolean gst_gl_window_cocoa_open (GstGLWindow *window, GError **err); static gboolean gst_gl_window_cocoa_open (GstGLWindow *window, GError **err);
static void gst_gl_window_cocoa_close (GstGLWindow *window); static void gst_gl_window_cocoa_close (GstGLWindow *window);
static void gst_gl_window_cocoa_quit (GstGLWindow *window);
static guintptr gst_gl_window_cocoa_get_window_handle (GstGLWindow * window); static guintptr gst_gl_window_cocoa_get_window_handle (GstGLWindow * window);
static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window,
guintptr handle); guintptr handle);
@ -96,6 +97,9 @@ struct _GstGLWindowCocoaPrivate
int view_ready; int view_ready;
gpointer gl_queue; gpointer gl_queue;
gboolean shutting_down;
GstGLContext *last_context;
}; };
#define DEBUG_INIT \ #define DEBUG_INIT \
@ -114,6 +118,7 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_open); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_open);
window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_close); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_close);
window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit);
window_class->get_window_handle = window_class->get_window_handle =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_window_handle); GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_window_handle);
window_class->set_window_handle = window_class->set_window_handle =
@ -468,7 +473,8 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
{ {
GstGLWindowCocoa *window_cocoa = (GstGLWindowCocoa *) window; GstGLWindowCocoa *window_cocoa = (GstGLWindowCocoa *) window;
GstGLContext *context = gst_gl_window_get_context (window); GstGLContext *context = gst_gl_window_get_context (window);
GThread *thread = gst_gl_context_get_thread (context); GstGLContext *unref_context = NULL;
GThread *thread = NULL;
GstGLWindowCocoaPrivate *priv = window_cocoa->priv; GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
#if OS_OBJECT_USE_OBJC #if OS_OBJECT_USE_OBJC
dispatch_queue_t gl_queue = (__bridge dispatch_queue_t)priv->gl_queue; dispatch_queue_t gl_queue = (__bridge dispatch_queue_t)priv->gl_queue;
@ -476,16 +482,31 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
dispatch_queue_t gl_queue = (dispatch_queue_t)priv->gl_queue; dispatch_queue_t gl_queue = (dispatch_queue_t)priv->gl_queue;
#endif #endif
if (context)
window_cocoa->priv->last_context = unref_context = context;
/* we may not have a context if we are shutting down */
if (!context && window_cocoa->priv->shutting_down) {
context = window_cocoa->priv->last_context;
window_cocoa->priv->shutting_down = FALSE;
}
g_return_if_fail (context != NULL);
thread = gst_gl_context_get_thread (context);
if (thread == g_thread_self()) { if (thread == g_thread_self()) {
/* this case happens for nested calls happening from inside the GCD queue */ /* this case happens for nested calls happening from inside the GCD queue */
callback (data); callback (data);
if (destroy) if (destroy)
destroy (data); destroy (data);
gst_object_unref (context); if (unref_context)
gst_object_unref (unref_context);
} else { } else {
dispatch_async (gl_queue, ^{ dispatch_async (gl_queue, ^{
gst_gl_context_activate (context, TRUE); gst_gl_context_activate (context, TRUE);
gst_object_unref (context); if (unref_context)
gst_object_unref (unref_context);
callback (data); callback (data);
if (destroy) if (destroy)
destroy (data); destroy (data);
@ -495,6 +516,16 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
g_thread_unref (thread); g_thread_unref (thread);
} }
static void
gst_gl_window_cocoa_quit (GstGLWindow * window)
{
GstGLWindowCocoa *window_cocoa = (GstGLWindowCocoa *) window;
window_cocoa->priv->shutting_down = TRUE;
GST_GL_WINDOW_CLASS (parent_class)->quit (window);
}
struct SetRenderRectangle struct SetRenderRectangle
{ {
GstGLWindowCocoa *window_cocoa; GstGLWindowCocoa *window_cocoa;