diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c index d2660977e4..b8fd96c4e1 100644 --- a/ext/gl/gstglimagesink.c +++ b/ext/gl/gstglimagesink.c @@ -696,22 +696,37 @@ _ensure_gl_setup (GstGLImageSink * gl_sink) if (!gl_sink->context) { GST_OBJECT_LOCK (gl_sink->display); do { - GstGLContext *other_context; - GstGLWindow *window; + GstGLContext *other_context = NULL; + GstGLWindow *window = NULL; - if (gl_sink->context) + if (gl_sink->context) { gst_object_unref (gl_sink->context); + gl_sink->context = NULL; + } GST_DEBUG_OBJECT (gl_sink, "No current context, creating one for %" GST_PTR_FORMAT, gl_sink->display); - gl_sink->context = gst_gl_context_new (gl_sink->display); - if (!gl_sink->context) { - GST_OBJECT_UNLOCK (gl_sink->display); - goto context_creation_error; + if (gl_sink->other_context) { + other_context = gst_object_ref (gl_sink->other_context); + } else { + other_context = + gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL); } + if (!gst_gl_display_create_context (gl_sink->display, + other_context, &gl_sink->context, &error)) { + if (other_context) + gst_object_unref (other_context); + GST_OBJECT_UNLOCK (gl_sink->display); + goto context_error; + } + + GST_DEBUG_OBJECT (gl_sink, + "created context %" GST_PTR_FORMAT " from other context %" + GST_PTR_FORMAT, gl_sink->context, gl_sink->other_context); + window = gst_gl_context_get_window (gl_sink->context); GST_DEBUG_OBJECT (gl_sink, "got window %" GST_PTR_FORMAT, window); @@ -729,25 +744,6 @@ _ensure_gl_setup (GstGLImageSink * gl_sink) gst_gl_window_set_window_handle (window, gl_sink->window_id); } - if (gl_sink->other_context) { - other_context = gst_object_ref (gl_sink->other_context); - } else { - other_context = - gst_gl_display_get_gl_context_for_thread (gl_sink->display, NULL); - } - - GST_DEBUG_OBJECT (gl_sink, - "creating context %" GST_PTR_FORMAT " from other context %" - GST_PTR_FORMAT, gl_sink->context, other_context); - - if (!gst_gl_context_create (gl_sink->context, other_context, &error)) { - if (other_context) - gst_object_unref (other_context); - gst_object_unref (window); - GST_OBJECT_UNLOCK (gl_sink->display); - goto context_error; - } - gst_gl_window_handle_events (window, gl_sink->handle_events); /* setup callbacks */ @@ -782,19 +778,21 @@ _ensure_gl_setup (GstGLImageSink * gl_sink) return TRUE; -context_creation_error: - { - GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, - ("Failed to create GL context"), (NULL)); - return FALSE; - } - context_error: { GST_ELEMENT_ERROR (gl_sink, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL)); - gst_object_unref (gl_sink->context); - gl_sink->context = NULL; + + if (gl_sink->context) { + gst_object_unref (gl_sink->context); + gl_sink->context = NULL; + } + + if (error) { + g_error_free (error); + error = NULL; + } + return FALSE; } } diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index b1264a9c54..51c1df5323 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -84,6 +84,15 @@ G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, GST_TYPE_OBJECT, #define GST_GL_DISPLAY_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_TYPE_GL_DISPLAY, GstGLDisplayPrivate)) +enum +{ + SIGNAL_0, + CREATE_CONTEXT, + LAST_SIGNAL +}; + +static guint gst_gl_display_signals[LAST_SIGNAL] = { 0 }; + static void gst_gl_display_finalize (GObject * object); static guintptr gst_gl_display_default_get_handle (GstGLDisplay * display); @@ -99,6 +108,22 @@ gst_gl_display_class_init (GstGLDisplayClass * klass) { g_type_class_add_private (klass, sizeof (GstGLDisplayPrivate)); + /** + * GstGLDisplay::create-context: + * @object: the #GstGLDisplay + * @context: other context to share resources with. + * + * Overrides the @GstGLContext creation mechanism. + * It can be called in any thread and it is emitted with + * display's object lock held. + * + * Returns: the new context. + */ + gst_gl_display_signals[CREATE_CONTEXT] = + g_signal_new ("create-context", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, + GST_GL_TYPE_CONTEXT, 1, GST_GL_TYPE_CONTEXT); + klass->get_handle = gst_gl_display_default_get_handle; G_OBJECT_CLASS (klass)->finalize = gst_gl_display_finalize; @@ -341,6 +366,58 @@ gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display) return ret; } +/** + * gst_gl_display_create_context: + * @display: a #GstGLDisplay + * @other_context: other #GstGLContext to share resources with. + * @p_context: resulting #GstGLContext + * @error: resulting #GError + * + * It requires the display's object lock to be held. + * + * Returns: whether a new context could be created. + * + * Since: 1.6 + */ +gboolean +gst_gl_display_create_context (GstGLDisplay * display, + GstGLContext * other_context, GstGLContext ** p_context, GError ** error) +{ + GstGLContext *context = NULL; + gboolean ret = FALSE; + + g_return_val_if_fail (display != NULL, FALSE); + g_return_val_if_fail (p_context != NULL, FALSE); + g_return_val_if_fail (error != NULL, FALSE); + g_return_val_if_fail (*error == NULL, FALSE); + + g_signal_emit (display, gst_gl_display_signals[CREATE_CONTEXT], 0, + other_context, &context); + + if (context) { + *p_context = context; + return TRUE; + } + + context = gst_gl_context_new (display); + if (!context) { + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "Failed to create GL context"); + return FALSE; + } + + GST_DEBUG_OBJECT (display, + "creating context %" GST_PTR_FORMAT " from other context %" + GST_PTR_FORMAT, context, other_context); + + ret = gst_gl_context_create (context, other_context, error); + + if (ret) + *p_context = context; + + return ret; +} + static GstGLContext * _get_gl_context_for_thread_unlocked (GstGLDisplay * display, GThread * thread) { diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index a9c1433930..9341884e10 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -92,6 +92,8 @@ GstGLAPI gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display); void gst_context_set_gl_display (GstContext * context, GstGLDisplay * display); gboolean gst_context_get_gl_display (GstContext * context, GstGLDisplay ** display); +gboolean gst_gl_display_create_context (GstGLDisplay * display, + GstGLContext * other_context, GstGLContext ** p_context, GError **error); GstGLContext * gst_gl_display_get_gl_context_for_thread (GstGLDisplay * display, GThread * thread); gboolean gst_gl_display_add_context (GstGLDisplay * display,