GstGLContextGLX * gst_gl_context_glx_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_X11) == 0) /* we require an x11 display handle to create GLX contexts */ return NULL; return g_object_new (GST_TYPE_GL_CONTEXT_GLX, NULL); }
/* Must be called in the gl thread */ GstGLContextWGL * gst_gl_context_wgl_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WIN32) == 0) /* we require an win32 display handle to create WGL contexts */ return NULL; return g_object_new (GST_TYPE_GL_CONTEXT_WGL, NULL); }
GstGLWindowWin32 * gst_gl_window_win32_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WIN32) == 0) /* we require an win32 display to create win32 windows */ return NULL; return g_object_new (GST_GL_TYPE_WINDOW_WIN32, NULL); }
/* Must be called in the gl thread */ GstGLWindowDispmanxEGL * gst_gl_window_dispmanx_egl_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_EGL) == 0) /* we require an egl display to create dispmanx windows */ return NULL; GST_DEBUG ("creating Dispmanx EGL window"); return g_object_new (GST_TYPE_GL_WINDOW_DISPMANX_EGL, NULL); }
/* Must be called in the gl thread */ GstGLWindowAndroidEGL * gst_gl_window_android_egl_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_EGL) == 0) /* we require an egl display to create android windows */ return NULL; GST_DEBUG ("creating Android EGL window"); return g_object_new (GST_GL_TYPE_WINDOW_ANDROID_EGL, NULL); }
/* Must be called in the gl thread */ GstGLWindowWaylandEGL * gst_gl_window_wayland_egl_new (GstGLDisplay * display) { if ((gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WAYLAND) == 0) /* we require a wayland display to create wayland surfaces */ return NULL; GST_DEBUG ("creating Wayland EGL window"); return g_object_new (GST_TYPE_GL_WINDOW_WAYLAND_EGL, NULL); }
/** * gst_gl_display_egl_from_gl_display: * @display: an existing #GstGLDisplay * * Creates a EGL display connection from a native Display. * * This function will return the same value for multiple calls with the same * @display. * * Returns: (transfer full): a new #GstGLDisplayEGL * * Since: 1.12 */ GstGLDisplayEGL * gst_gl_display_egl_from_gl_display (GstGLDisplay * display) { GstGLDisplayEGL *ret; GstGLDisplayType display_type; guintptr native_display; g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL); GST_DEBUG_CATEGORY_GET (gst_gl_display_debug, "gldisplay"); if (GST_IS_GL_DISPLAY_EGL (display)) { GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "is already a " "GstGLDisplayEGL", display); return gst_object_ref (display); } /* try to get a previously set GstGLDisplayEGL */ ret = g_object_dup_data (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME, (GDuplicateFunc) _ref_if_set, NULL); if (ret && GST_IS_GL_DISPLAY_EGL (ret)) { GST_LOG_OBJECT (display, "display %" GST_PTR_FORMAT "already has a " "GstGLDisplayEGL %" GST_PTR_FORMAT, display, ret); return ret; } if (ret) gst_object_unref (ret); display_type = gst_gl_display_get_handle_type (display); native_display = gst_gl_display_get_handle (display); g_return_val_if_fail (native_display != 0, NULL); g_return_val_if_fail (display_type != GST_GL_DISPLAY_TYPE_NONE, NULL); ret = g_object_new (GST_TYPE_GL_DISPLAY_EGL, NULL); ret->display = gst_gl_display_egl_get_from_native (display_type, native_display); if (!ret->display) { GST_WARNING_OBJECT (ret, "failed to get EGLDisplay from native display"); gst_object_unref (ret); return NULL; } g_object_set_data_full (G_OBJECT (display), GST_GL_DISPLAY_EGL_NAME, gst_object_ref (ret), (GDestroyNotify) gst_object_unref); return ret; }
static GstVaapiDisplay * gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object) { #if USE_GST_GL_HELPERS GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object); GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context); GstGLDisplayType gl_display_type; GstGLPlatform gl_platform; gpointer native_display; GstVaapiDisplay *display = NULL; GstVaapiDisplayType display_type; /* Get display type and the native hanler */ gl_display_type = gst_gl_display_get_handle_type (gl_display); gl_platform = gst_gl_context_get_gl_platform (gl_context); display_type = gst_vaapi_get_display_type_from_gl (gl_display_type, gl_platform); native_display = GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display)); if (display_type == GST_VAAPI_DISPLAY_TYPE_ANY) { /* derive type and native_display from the active window */ GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context); if (gl_window) native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window)); display_type = gst_vaapi_get_display_type_from_gl_env (); } if (gl_platform == GST_GL_PLATFORM_EGL) { display = gst_vaapi_create_display_from_egl (gl_display, gl_context, display_type, native_display); } /* Non-EGL and fallback */ if (!display) { display = gst_vaapi_create_display_from_handle (display_type, native_display); } gst_object_unref (gl_display); return display; #endif GST_ERROR ("No GstGL support"); return NULL; }
/** * gst_vaapi_plugin_base_create_gl_context: * @plugin: a #GstVaapiPluginBase * * It queries downstream and upstream for a #GstGLDisplay and a other * #GstGLContext. If not found, a new #GstGLDisplay and #GstGLContext * are created, if it is possible. * * Returns: (transfer full) a new created #GstGLContext or %NULL **/ GstObject * gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin) { #if USE_GST_GL_HELPERS GstGLContext *gl_other_context, *gl_context = NULL; GstGLDisplay *gl_display; gst_gl_ensure_element_data (plugin, (GstGLDisplay **) & plugin->gl_display, (GstGLContext **) & plugin->gl_other_context); gl_display = (GstGLDisplay *) plugin->gl_display; if (!gl_display || gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY) { gst_object_replace (&plugin->gl_display, NULL); gst_object_replace (&plugin->gl_other_context, NULL); return NULL; } gl_other_context = (GstGLContext *) plugin->gl_other_context; GST_INFO_OBJECT (plugin, "creating a new GstGL context"); GST_OBJECT_LOCK (gl_display); do { if (gl_context) gst_object_unref (gl_context); gl_context = gst_gl_display_get_gl_context_for_thread (gl_display, NULL); if (!gl_context) { if (!gst_gl_display_create_context (gl_display, gl_other_context, &gl_context, NULL)) break; } } while (!gst_gl_display_add_context (gl_display, gl_context)); GST_OBJECT_UNLOCK (gl_display); return GST_OBJECT_CAST (gl_context); #else return NULL; #endif }
/** * gst_gl_handle_context_query: * @element: a #GstElement * @query: a #GstQuery of type %GST_QUERY_CONTEXT * @display: (transfer none) (nullable): a #GstGLDisplay * @context: (transfer none) (nullable): a #GstGLContext * @other_context: (transfer none) (nullable): application provided #GstGLContext * * Returns: Whether the @query was successfully responded to from the passed * @display, @context, and @other_context. */ gboolean gst_gl_handle_context_query (GstElement * element, GstQuery * query, GstGLDisplay * display, GstGLContext * gl_context, GstGLContext * other_context) { const gchar *context_type; GstContext *context, *old_context; g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); g_return_val_if_fail (GST_IS_QUERY (query), FALSE); g_return_val_if_fail (display == NULL || GST_IS_GL_DISPLAY (display), FALSE); g_return_val_if_fail (gl_context == NULL || GST_IS_GL_CONTEXT (gl_context), FALSE); g_return_val_if_fail (other_context == NULL || GST_IS_GL_CONTEXT (other_context), FALSE); GST_LOG_OBJECT (element, "handle context query %" GST_PTR_FORMAT, query); gst_query_parse_context_type (query, &context_type); if (display && g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) { gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE); gst_context_set_gl_display (context, display); gst_query_set_context (query, context); gst_context_unref (context); GST_DEBUG_OBJECT (element, "successfully set %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, display, query); return TRUE; } #if GST_GL_HAVE_WINDOW_X11 else if (display && g_strcmp0 (context_type, "gst.x11.display.handle") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.x11.display.handle", TRUE); if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_X11) { Display *x11_display = (Display *) gst_gl_display_get_handle (display); if (x11_display) { s = gst_context_writable_structure (context); gst_structure_set (s, "display", G_TYPE_POINTER, x11_display, NULL); gst_query_set_context (query, context); gst_context_unref (context); GST_DEBUG_OBJECT (element, "successfully set x11 display %p (from %" GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, x11_display, display, query); return TRUE; } } } #endif #if GST_GL_HAVE_WINDOW_WAYLAND else if (display && g_strcmp0 (context_type, "GstWaylandDisplayHandleContextType") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("GstWaylandDisplayHandleContextType", TRUE); if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_WAYLAND) { struct wl_display *wayland_display = (struct wl_display *) gst_gl_display_get_handle (display); if (wayland_display) { s = gst_context_writable_structure (context); gst_structure_set (s, "display", G_TYPE_POINTER, wayland_display, NULL); gst_query_set_context (query, context); gst_context_unref (context); GST_DEBUG_OBJECT (element, "successfully set wayland display %p (from %" GST_PTR_FORMAT ") on %" GST_PTR_FORMAT, wayland_display, display, query); return TRUE; } } } #endif else if (other_context && g_strcmp0 (context_type, "gst.gl.app_context") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.gl.app_context", TRUE); s = gst_context_writable_structure (context); gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, other_context, NULL); gst_query_set_context (query, context); gst_context_unref (context); GST_DEBUG_OBJECT (element, "successfully set application GL context %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, other_context, query); return TRUE; } else if (gl_context && g_strcmp0 (context_type, "gst.gl.local_context") == 0) { GstStructure *s; gst_query_parse_context (query, &old_context); if (old_context) context = gst_context_copy (old_context); else context = gst_context_new ("gst.gl.local_context", TRUE); s = gst_context_writable_structure (context); gst_structure_set (s, "context", GST_TYPE_GL_CONTEXT, gl_context, NULL); gst_query_set_context (query, context); gst_context_unref (context); GST_DEBUG_OBJECT (element, "successfully set GL context %" GST_PTR_FORMAT " on %" GST_PTR_FORMAT, gl_context, query); return TRUE; } return FALSE; }
/** * gst_gl_handle_set_context: * @element: a #GstElement * @context: a #GstContext * @display: (inout) (transfer full): location of a #GstGLDisplay * @other_context: (inout) (transfer full): location of a #GstGLContext * * Helper function for implementing GstElement::set_context() in OpenGL capable * elements. * * Retrieve's the #GstGLDisplay or #GstGLContext in @context and places the * result in @display or @other_context respectively. * * Returns: whether the @display or @other_context could be set successfully */ gboolean gst_gl_handle_set_context (GstElement * element, GstContext * context, GstGLDisplay ** display, GstGLContext ** other_context) { GstGLDisplay *display_replacement = NULL; GstGLContext *context_replacement = NULL; const gchar *context_type; g_return_val_if_fail (display != NULL, FALSE); g_return_val_if_fail (other_context != NULL, FALSE); if (!context) return FALSE; context_type = gst_context_get_context_type (context); if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) { if (!gst_context_get_gl_display (context, &display_replacement)) { GST_WARNING_OBJECT (element, "Failed to get display from context"); return FALSE; } } #if GST_GL_HAVE_WINDOW_X11 else if (g_strcmp0 (context_type, "gst.x11.display.handle") == 0) { const GstStructure *s; Display *display; s = gst_context_get_structure (context); if (gst_structure_get (s, "display", G_TYPE_POINTER, &display, NULL)) display_replacement = (GstGLDisplay *) gst_gl_display_x11_new_with_display (display); } #endif #if GST_GL_HAVE_WINDOW_WAYLAND else if (g_strcmp0 (context_type, "GstWaylandDisplayHandleContextType") == 0) { const GstStructure *s; struct wl_display *display; s = gst_context_get_structure (context); if (gst_structure_get (s, "display", G_TYPE_POINTER, &display, NULL)) display_replacement = (GstGLDisplay *) gst_gl_display_wayland_new_with_display (display); } #endif else if (g_strcmp0 (context_type, "gst.gl.app_context") == 0) { const GstStructure *s = gst_context_get_structure (context); GstGLDisplay *context_display; GstGLDisplay *element_display; if (gst_structure_get (s, "context", GST_TYPE_GL_CONTEXT, &context_replacement, NULL)) { context_display = gst_gl_context_get_display (context_replacement); element_display = display_replacement ? display_replacement : *display; if (element_display && (gst_gl_display_get_handle_type (element_display) & gst_gl_display_get_handle_type (context_display)) == 0) { GST_ELEMENT_WARNING (element, LIBRARY, SETTINGS, ("%s", "Cannot set a GL context with a different display type"), ("%s", "Cannot set a GL context with a different display type")); gst_object_unref (context_replacement); context_replacement = NULL; } gst_object_unref (context_display); } } if (display_replacement) { GstGLDisplay *old = *display; *display = display_replacement; if (old) gst_object_unref (old); } if (context_replacement) { GstGLContext *old = *other_context; *other_context = context_replacement; if (old) gst_object_unref (old); } return TRUE; }
static GstVaapiDisplay * gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object) { #if USE_GST_GL_HELPERS GstGLContext *const gl_context = GST_GL_CONTEXT (gl_context_object); GstGLDisplay *const gl_display = gst_gl_context_get_display (gl_context); gpointer native_display = GSIZE_TO_POINTER (gst_gl_display_get_handle (gl_display)); GstVaapiDisplay *display, *out_display; GstVaapiDisplayType display_type; switch (gst_gl_display_get_handle_type (gl_display)) { #if USE_X11 case GST_GL_DISPLAY_TYPE_X11: display_type = GST_VAAPI_DISPLAY_TYPE_X11; break; #endif #if USE_WAYLAND case GST_GL_DISPLAY_TYPE_WAYLAND: display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; break; #endif case GST_GL_DISPLAY_TYPE_ANY:{ /* Derive from the active window */ GstGLWindow *const gl_window = gst_gl_context_get_window (gl_context); const gchar *const gl_window_type = g_getenv ("GST_GL_WINDOW"); display_type = GST_VAAPI_DISPLAY_TYPE_ANY; if (!gl_window) break; native_display = GSIZE_TO_POINTER (gst_gl_window_get_display (gl_window)); if (gl_window_type) { #if USE_X11 if (!display_type && g_strcmp0 (gl_window_type, "x11") == 0) display_type = GST_VAAPI_DISPLAY_TYPE_X11; #endif #if USE_WAYLAND if (!display_type && g_strcmp0 (gl_window_type, "wayland") == 0) display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; #endif } else { #if USE_X11 if (!display_type && GST_GL_HAVE_WINDOW_X11) display_type = GST_VAAPI_DISPLAY_TYPE_X11; #endif #if USE_WAYLAND if (!display_type && GST_GL_HAVE_WINDOW_WAYLAND) display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND; #endif } break; } default: display_type = GST_VAAPI_DISPLAY_TYPE_ANY; break; } if (!display_type) return NULL; display = gst_vaapi_create_display_from_handle (display_type, native_display); if (!display) return NULL; switch (gst_gl_context_get_gl_platform (gl_context)) { #if USE_EGL case GST_GL_PLATFORM_EGL:{ guint gles_version; switch (gst_gl_context_get_gl_api (gl_context)) { case GST_GL_API_GLES1: gles_version = 1; goto create_egl_display; case GST_GL_API_GLES2: gles_version = 2; goto create_egl_display; case GST_GL_API_OPENGL: case GST_GL_API_OPENGL3: gles_version = 0; create_egl_display: out_display = gst_vaapi_display_egl_new (display, gles_version); break; default: out_display = NULL; break; } if (!out_display) return NULL; gst_vaapi_display_egl_set_gl_context (GST_VAAPI_DISPLAY_EGL (out_display), GSIZE_TO_POINTER (gst_gl_context_get_gl_context (gl_context))); break; } #endif default: out_display = gst_vaapi_display_ref (display); break; } gst_vaapi_display_unref (display); return out_display; #endif GST_ERROR ("unsupported GStreamer version %s", GST_API_VERSION_S); return NULL; }