static gboolean _check_collision (GstGLContext * context, GstGLContext * collision) { GThread *thread, *collision_thread; gboolean ret = FALSE; if (!context || !collision) return FALSE; thread = gst_gl_context_get_thread (context); collision_thread = gst_gl_context_get_thread (collision); if (!thread || !collision_thread) { ret = FALSE; goto out; } if (collision == context) { ret = TRUE; goto out; } out: if (thread) g_thread_unref (thread); if (collision_thread) g_thread_unref (collision_thread); return ret; }
static void _set_window_handle_cb (GstSetWindowHandleCb * data) { GstGLContext *context = gst_gl_window_get_context (data->window); GstGLWindowClass *window_class = GST_GL_WINDOW_GET_CLASS (data->window); GThread *thread = NULL; /* deactivate if necessary */ if (context) { thread = gst_gl_context_get_thread (context); if (thread) { /* This is only thread safe iff the context thread == g_thread_self() */ g_assert (thread == g_thread_self ()); gst_gl_context_activate (context, FALSE); } } window_class->set_window_handle (data->window, data->handle); /* reactivate */ if (context && thread) gst_gl_context_activate (context, TRUE); if (context) gst_object_unref (context); if (thread) g_thread_unref (thread); }
static GstGLContext * _get_gl_context_for_thread_unlocked (GstGLDisplay * display, GThread * thread) { GstGLContext *context = NULL; GList *prev = NULL, *l = display->priv->contexts; while (l) { GWeakRef *ref = l->data; GThread *context_thread; context = g_weak_ref_get (ref); if (!context) { /* remove dead contexts */ g_weak_ref_clear (l->data); display->priv->contexts = g_list_delete_link (display->priv->contexts, l); l = prev ? prev->next : display->priv->contexts; continue; } context_thread = gst_gl_context_get_thread (context); if (thread != NULL && thread == context_thread) { g_thread_unref (context_thread); gst_object_unref (context); prev = l; l = l->next; continue; } if (context_thread) g_thread_unref (context_thread); return context; } return NULL; }
/** * gst_gl_display_add_context: * @display: a #GstGLDisplay * @context: (transfer none): a #GstGLContext * * Returns: whether @context was successfully added. %FALSE may be returned * if there already exists another context for @context's active thread. * * Must be called with the object lock held. * * Since: 1.6 */ gboolean gst_gl_display_add_context (GstGLDisplay * display, GstGLContext * context) { GstGLContext *collision = NULL; GstGLDisplay *context_display; gboolean ret = TRUE; GThread *thread; GWeakRef *ref; g_return_val_if_fail (GST_IS_GL_DISPLAY (display), FALSE); g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); context_display = gst_gl_context_get_display (context); g_assert (context_display == display); gst_object_unref (context_display); thread = gst_gl_context_get_thread (context); if (thread) { collision = _get_gl_context_for_thread_unlocked (display, thread); g_thread_unref (thread); /* adding the same context is a no-op */ if (context == collision) { ret = TRUE; goto out; } if (_check_collision (context, collision)) { ret = FALSE; goto out; } } ref = g_new0 (GWeakRef, 1); g_weak_ref_init (ref, context); display->priv->contexts = g_list_prepend (display->priv->contexts, ref); out: if (collision) gst_object_unref (collision); GST_DEBUG_OBJECT (display, "%ssuccessfully inserted context %" GST_PTR_FORMAT, ret ? "" : "un", context); return ret; }