/** * gst_gl_context_can_share: * @context: a #GstGLContext * @other_context: another #GstGLContext * * Note: This will always fail for two wrapped #GstGLContext's * * Returns: whether @context and @other_context are able to share OpenGL * resources. * * Since: 1.6 */ gboolean gst_gl_context_can_share (GstGLContext * context, GstGLContext * other_context) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); g_return_val_if_fail (GST_IS_GL_CONTEXT (other_context), FALSE); /* check if the contexts are descendants or the root nodes are the same */ return context->priv->sharegroup_id != 0 && context->priv->sharegroup_id == other_context->priv->sharegroup_id; }
/** * gst_gl_allocation_params_init: * @params: the #GstGLAllocationParams to initialize * @struct_size: the struct size of the implementation * @alloc: some alloc flags * @copy: a copy function * @free: a free function * @context: (transfer none): a #GstGLContext * @alloc_size: the number of bytes to allocate. * @alloc_params: (transfer none) (allow-none): a #GstAllocationParams to apply * @wrapped_data: (transfer none) (allow-none): a sysmem data pointer to initialize the allocation with * @gl_handle: (transfer none): a GL handle to initialize the allocation with * @user_data: (transfer none) (allow-none): user data to call @notify with * @notify: (allow-none): a #GDestroyNotify * * @notify will be called once for each allocated memory using these @params * when freeing the memory. * * Returns: whether the paramaters could be initialized */ gboolean gst_gl_allocation_params_init (GstGLAllocationParams * params, gsize struct_size, guint alloc_flags, GstGLAllocationParamsCopyFunc copy, GstGLAllocationParamsFreeFunc free, GstGLContext * context, gsize alloc_size, GstAllocationParams * alloc_params, gpointer wrapped_data, guint gl_handle, gpointer user_data, GDestroyNotify notify) { memset (params, 0, sizeof (*params)); g_return_val_if_fail (struct_size > 0, FALSE); g_return_val_if_fail (copy != NULL, FALSE); g_return_val_if_fail (free != NULL, FALSE); g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); params->struct_size = struct_size; params->alloc_size = alloc_size; params->copy = copy; params->free = free; params->alloc_flags = alloc_flags; params->context = gst_object_ref (context); if (alloc_params) params->alloc_params = gst_allocation_params_copy (alloc_params); params->notify = notify; params->user_data = user_data; params->wrapped_data = wrapped_data; params->gl_handle = gl_handle; return TRUE; }
/** * gst_gl_context_activate: * @context: a #GstGLContext * @activate: %TRUE to activate, %FALSE to deactivate * * (De)activate the OpenGL context represented by this @context. * * In OpenGL terms, calls eglMakeCurrent or similar with this context and the * currently set window. See gst_gl_context_set_window() for details. * * Returns: Whether the activation succeeded * * Since: 1.4 */ gboolean gst_gl_context_activate (GstGLContext * context, gboolean activate) { GstGLContextClass *context_class; gboolean result; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->activate != NULL, FALSE); GST_DEBUG_OBJECT (context, "activate:%d", activate); GST_OBJECT_LOCK (context); result = context_class->activate (context, activate); if (result && activate) { context->priv->active_thread = g_thread_self (); g_private_set (¤t_context_key, context); } else { context->priv->active_thread = NULL; g_private_set (¤t_context_key, NULL); } GST_OBJECT_UNLOCK (context); return result; }
gboolean gst_gl_context_supports_glsl_profile_version (GstGLContext * context, GstGLSLVersion version, GstGLSLProfile profile) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); if (!_is_valid_version_profile (version, profile)) return FALSE; if (profile != GST_GLSL_PROFILE_NONE) { if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) { if ((profile & GST_GLSL_PROFILE_ES) == 0) return FALSE; } else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) != 0) { if ((profile & GST_GLSL_PROFILE_COMPATIBILITY) == 0) return FALSE; } else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL3) != 0) { /* GL_ARB_es2_compatibility is requried for GL3 contexts */ if ((profile & (GST_GLSL_PROFILE_CORE | GST_GLSL_PROFILE_ES)) == 0) return FALSE; } else { g_assert_not_reached (); } } if (version != GST_GLSL_VERSION_NONE) { GstGLAPI gl_api; gint maj, min, glsl_version; if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 1)) { if (version > GST_GLSL_VERSION_310) return FALSE; } else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0)) { if (version > GST_GLSL_VERSION_300) return FALSE; } else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) { if (version > GST_GLSL_VERSION_100) return FALSE; } gl_api = gst_gl_context_get_gl_api (context); gst_gl_context_get_gl_version (context, &maj, &min); glsl_version = gst_gl_version_to_glsl_version (gl_api, maj, min); if (glsl_version > version) return FALSE; if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 1, 0)) /* GL_ARB_es2_compatibility is requried for GL3 contexts */ if (version < GST_GLSL_VERSION_150 && version != GST_GLSL_VERSION_100) return FALSE; if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0) && version < GST_GLSL_VERSION_110) return FALSE; } return TRUE; }
/** * gst_gl_context_thread_add: * @context: a #GstGLContext * @func: a #GstGLContextThreadFunc * @data: (closure): user data to call @func with * * Execute @func in the OpenGL thread of @context with @data * * MT-safe * * Since: 1.4 */ void gst_gl_context_thread_add (GstGLContext * context, GstGLContextThreadFunc func, gpointer data) { GstGLWindow *window; RunGenericData rdata; g_return_if_fail (GST_IS_GL_CONTEXT (context)); g_return_if_fail (func != NULL); if (GST_IS_GL_WRAPPED_CONTEXT (context)) { g_return_if_fail (context->priv->active_thread == g_thread_self ()); func (context, data); return; } rdata.context = context; rdata.data = data; rdata.func = func; window = gst_gl_context_get_window (context); gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gst_gl_context_thread_run_generic), &rdata); gst_object_unref (window); }
/** * gst_gl_context_get_display: * @context: a #GstGLContext: * * Returns: the #GstGLDisplay associated with this @context * * Since: 1.4 */ GstGLDisplay * gst_gl_context_get_display (GstGLContext * context) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); return gst_object_ref (context->display); }
void gst_gl_query_init (GstGLQuery * query, GstGLContext * context, GstGLQueryType query_type) { const GstGLFuncs *gl; g_return_if_fail (query != NULL); g_return_if_fail (GST_IS_GL_CONTEXT (context)); gl = context->gl_vtable; memset (query, 0, sizeof (*query)); _init_debug (); query->context = gst_object_ref (context); query->query_type = _gst_gl_query_type_to_gl (query_type); query->supported = _context_supports_query_type (context, query->query_type); if (query->supported) gl->GenQueries (1, &query->query_id); gst_gl_async_debug_init (&query->debug); query->debug.callback = _log_time; query->debug.user_data = query; }
/** * gst_gl_buffer_allocation_params_new: * @context: a #GstGLContext * @alloc_size: the size in bytes to allocate * @alloc_params: (allow-none): the #GstAllocationParams for @tex_id * @gl_target: the OpenGL target to allocate * @gl_usage: the OpenGL usage hint to allocate with * * Returns: a new #GstGLBufferAllocationParams for allocating OpenGL buffer * objects * * Since: 1.8 */ GstGLBufferAllocationParams * gst_gl_buffer_allocation_params_new (GstGLContext * context, gsize alloc_size, GstAllocationParams * alloc_params, guint gl_target, guint gl_usage) { GstGLBufferAllocationParams *params; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); g_return_val_if_fail (alloc_size > 0, NULL); params = g_new0 (GstGLBufferAllocationParams, 1); if (!gst_gl_allocation_params_init (¶ms->parent, sizeof (*params), GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_BUFFER | GST_GL_ALLOCATION_PARAMS_ALLOC_FLAG_ALLOC, (GstGLAllocationParamsCopyFunc) _gst_gl_buffer_allocation_params_copy_data, (GstGLAllocationParamsFreeFunc) _gst_gl_buffer_allocation_params_free_data, context, alloc_size, alloc_params, NULL, 0, NULL, NULL)) { g_free (params); return NULL; } params->gl_target = gl_target; params->gl_usage = gl_usage; return params; }
gchar * _gst_glsl_mangle_shader (const gchar * str, guint shader_type, GstGLTextureTarget from, GstGLTextureTarget to, GstGLContext * context, GstGLSLVersion * version, GstGLSLProfile * profile) { gchar *tmp, *tmp2; _init_debug (); g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); _mangle_version_profile_from_gl_api (context, from, to, version, profile); tmp2 = _mangle_external_image_extension (str, context, from, to, *version, *profile); tmp = _mangle_texture_access (tmp2, context, from, to, *version, *profile); g_free (tmp2); tmp2 = _mangle_sampler_type (tmp, from, to); g_free (tmp); tmp = _mangle_varying_attribute (tmp2, shader_type, *version, *profile); g_free (tmp2); if (shader_type == GL_FRAGMENT_SHADER) { if ((*profile == GST_GLSL_PROFILE_ES && *version >= GST_GLSL_VERSION_300) || (*profile == GST_GLSL_PROFILE_CORE && *version >= GST_GLSL_VERSION_150)) { tmp2 = _mangle_frag_color_data (tmp); g_free (tmp); tmp = tmp2; } } return tmp; }
Gst3DRenderer * gst_3d_renderer_new (GstGLContext * context) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); Gst3DRenderer *renderer = g_object_new (GST_3D_TYPE_RENDERER, NULL); renderer->context = gst_object_ref (context); return renderer; }
/** * gst_gl_context_get_gl_platform: * @context: a #GstGLContext: * * Gets the OpenGL platform that used by @context. * * Returns: The platform specific backing OpenGL context * * Since: 1.4 */ GstGLPlatform gst_gl_context_get_gl_platform (GstGLContext * context) { GstGLContextClass *context_class; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), 0); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_gl_platform != NULL, 0); return context_class->get_gl_platform (context); }
/** * gst_gl_context_destroy: * @context: a #GstGLContext: * * Destroys an OpenGL context. * * Should only be called after gst_gl_context_create() has been successfully * called for this context. * * Since: 1.6 */ void gst_gl_context_destroy (GstGLContext * context) { GstGLContextClass *context_class; g_return_if_fail (GST_IS_GL_CONTEXT (context)); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_if_fail (context_class->destroy_context != NULL); context_class->destroy_context (context); }
/** * gst_gl_context_get_gl_api: * @context: a #GstGLContext * * Get the currently enabled OpenGL api. * * The currently available API may be limited by the #GstGLDisplay in use and/or * the #GstGLWindow chosen. * * Returns: the available OpenGL api * * Since: 1.4 */ GstGLAPI gst_gl_context_get_gl_api (GstGLContext * context) { GstGLContextClass *context_class; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), GST_GL_API_NONE); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_gl_api != NULL, GST_GL_API_NONE); return context_class->get_gl_api (context); }
/** * gst_gl_context_get_gl_version: * @context: a #GstGLContext * @maj: (out): resulting major version * @min: (out): resulting minor version * * Returns the OpenGL version implemented by @context. See * gst_gl_context_get_gl_api() for retreiving the OpenGL api implemented by * @context. * * Since: 1.4 */ void gst_gl_context_get_gl_version (GstGLContext * context, gint * maj, gint * min) { g_return_if_fail (GST_IS_GL_CONTEXT (context)); g_return_if_fail (maj != NULL && min != NULL); if (maj) *maj = context->priv->gl_major; if (min) *min = context->priv->gl_minor; }
/** * gst_gl_context_clear_shader: * @context: a #GstGLContext * * Clear's the currently set shader from the GL state machine. * * Note: must be called in the GL thread. */ void gst_gl_context_clear_shader (GstGLContext * context) { GstGLFuncs *gl; g_return_if_fail (GST_IS_GL_CONTEXT (context)); gl = context->gl_vtable; if (gl->CreateProgram) gl->UseProgram (0); else if (gl->CreateProgramObject) gl->UseProgramObject (0); }
/** * gst_gl_context_get_gl_context: * @context: a #GstGLContext: * * Gets the backing OpenGL context used by @context. * * Returns: The platform specific backing OpenGL context * * Since: 1.4 */ guintptr gst_gl_context_get_gl_context (GstGLContext * context) { GstGLContextClass *context_class; guintptr result; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), 0); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_gl_context != NULL, 0); result = context_class->get_gl_context (context); return result; }
/** * gst_gl_context_get_window: * @context: a #GstGLContext * * Returns: the currently set window * * Since: 1.4 */ GstGLWindow * gst_gl_context_get_window (GstGLContext * context) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); if (GST_IS_GL_WRAPPED_CONTEXT (context)) { GST_WARNING_OBJECT (context, "context is not toplevel, returning NULL"); return NULL; } _ensure_window (context); return gst_object_ref (context->window); }
/** * gst_gl_context_get_proc_address: * @context: a #GstGLContext * @name: an opengl function name * * Get a function pointer to a specified opengl function, @name. If the the * specific function does not exist, NULL is returned instead. * * Platform specfic functions (names starting 'egl', 'glX', 'wgl', etc) can also * be retrieved using this method. * * Returns: a function pointer or NULL * * Since: 1.4 */ gpointer gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name) { gpointer ret; GstGLContextClass *context_class; GstGLAPI gl_api; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_proc_address != NULL, NULL); gl_api = gst_gl_context_get_gl_api (context); ret = context_class->get_proc_address (gl_api, name); return ret; }
/** * 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; }
/** * gst_gl_context_check_feature: * @context: a #GstGLContext * @feature: a platform specific feature * * Some features require that the context be created before it is possible to * determine their existence and so will fail if that is not the case. * * Returns: Whether @feature is supported by @context * * Since: 1.4 */ gboolean gst_gl_context_check_feature (GstGLContext * context, const gchar * feature) { GstGLContextClass *context_class; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); g_return_val_if_fail (feature != NULL, FALSE); context_class = GST_GL_CONTEXT_GET_CLASS (context); if (g_strstr_len (feature, 3, "GL_")) return gst_gl_check_extension (feature, context->priv->gl_exts); if (!context_class->check_feature) return FALSE; return context_class->check_feature (context, feature); }
/** * gst_buffer_add_gl_sync_meta_full: * @context: a #GstGLContext * @buffer: a #GstBuffer * @data: sync data to hold * * Returns: (transfer none): the #GstGLSyncMeta added to #GstBuffer * * Since: 1.8 */ GstGLSyncMeta * gst_buffer_add_gl_sync_meta_full (GstGLContext * context, GstBuffer * buffer, gpointer data) { GstGLSyncMeta *meta; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); meta = (GstGLSyncMeta *) gst_buffer_add_meta ((buffer), GST_GL_SYNC_META_INFO, NULL); if (!meta) return NULL; meta->context = gst_object_ref (context); meta->data = data; return meta; }
/** * gst_gl_context_check_gl_version: * @context: a #GstGLContext * @api: api type required * @maj: major version required * @min: minor version required * * Returns: whether OpenGL context implements the required api and specified * version. * * Since: 1.4 */ gboolean gst_gl_context_check_gl_version (GstGLContext * context, GstGLAPI api, gint maj, gint min) { g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); if (maj > context->priv->gl_major) return FALSE; if ((gst_gl_context_get_gl_api (context) & api) == GST_GL_API_NONE) return FALSE; if (maj < context->priv->gl_major) return TRUE; if (min > context->priv->gl_minor) return FALSE; return TRUE; }
static GstGLShader * _new_with_stages_va_list (GstGLContext * context, GError ** error, va_list varargs) { GstGLShader *shader; GstGLSLStage *stage; gboolean to_unref_and_out = FALSE; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL); shader = g_object_new (GST_TYPE_GL_SHADER, NULL); gst_object_ref_sink (shader); shader->context = gst_object_ref (context); while ((stage = va_arg (varargs, GstGLSLStage *))) { if (to_unref_and_out) { gst_object_unref (stage); continue; } if (!gst_glsl_stage_compile (stage, error)) { gst_object_unref (stage); to_unref_and_out = TRUE; continue; } if (!gst_gl_shader_attach (shader, stage)) { g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM, "Failed to attach stage to program"); to_unref_and_out = TRUE; continue; } } if (to_unref_and_out) { gst_object_unref (shader); return NULL; } return shader; }
/** * gst_gl_context_create: * @context: a #GstGLContext: * @other_context: (allow-none): a #GstGLContext to share OpenGL objects with * @error: (allow-none): a #GError * * Creates an OpenGL context in the current thread with the specified * @other_context as a context to share shareable OpenGL objects with. See the * OpenGL specification for what is shared between contexts. * * If an error occurs, and @error is not %NULL, then error will contain details * of the error and %FALSE will be returned. * * Should only be called once. * * Returns: whether the context could successfully be created * * Since: 1.4 */ gboolean gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error) { gboolean alive = FALSE; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); g_return_val_if_fail (!GST_IS_GL_WRAPPED_CONTEXT (context), FALSE); GST_DEBUG_OBJECT (context, " other_context:%" GST_PTR_FORMAT, other_context); _ensure_window (context); g_mutex_lock (&context->priv->render_lock); if (!context->priv->created) { g_weak_ref_set (&context->priv->other_context_ref, other_context); context->priv->error = error; if (other_context == NULL) context->priv->sharegroup_id = _new_sharegroup_id (); else context->priv->sharegroup_id = other_context->priv->sharegroup_id; context->priv->gl_thread = g_thread_new ("gstglcontext", (GThreadFunc) gst_gl_context_create_thread, context); g_cond_wait (&context->priv->create_cond, &context->priv->render_lock); context->priv->created = TRUE; GST_INFO_OBJECT (context, "gl thread created"); } alive = context->priv->alive; g_mutex_unlock (&context->priv->render_lock); return alive; }
/** * 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_context_fill_info: * @context: a #GstGLContext: * * Fills @context's info (version, extensions, vtable, etc) from the GL * context in the current thread. Typically used with wrapped contexts to * allow wrapped contexts to be used as regular #GstGLContext's. * * Since: 1.6 */ gboolean gst_gl_context_fill_info (GstGLContext * context, GError ** error) { GstGLFuncs *gl; GString *ext_g_str = NULL; const gchar *ext_const_c_str = NULL; GstGLAPI gl_api; gboolean ret; g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE); g_return_val_if_fail (context->priv->active_thread == g_thread_self (), FALSE); gl = context->gl_vtable; gl_api = gst_gl_context_get_gl_api (context); gl->GetError = gst_gl_context_get_proc_address (context, "glGetError"); gl->GetString = gst_gl_context_get_proc_address (context, "glGetString"); gl->GetStringi = gst_gl_context_get_proc_address (context, "glGetStringi"); gl->GetIntegerv = gst_gl_context_get_proc_address (context, "glGetIntegerv"); if (!gl->GetError || !gl->GetString) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, "could not GetProcAddress core opengl functions"); goto failure; } /* gl api specific code */ ret = _create_context_info (context, gl_api, &context->priv->gl_major, &context->priv->gl_minor, error); if (!ret) { g_assert (error == NULL || *error != NULL); goto failure; } /* GL core contexts and GLES3 */ if (gl->GetIntegerv && gl->GetStringi && context->priv->gl_major >= 3) ext_g_str = _build_extension_string (context); if (ext_g_str && ext_g_str->len) { GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_g_str->str); _gst_gl_feature_check_ext_functions (context, context->priv->gl_major, context->priv->gl_minor, ext_g_str->str); context->priv->gl_exts = g_string_free (ext_g_str, FALSE); } else { ext_const_c_str = (const gchar *) gl->GetString (GL_EXTENSIONS); if (!ext_const_c_str) ext_const_c_str = ""; GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_const_c_str); _gst_gl_feature_check_ext_functions (context, context->priv->gl_major, context->priv->gl_minor, ext_const_c_str); context->priv->gl_exts = g_strdup (ext_const_c_str); } if (gl_api & GST_GL_API_OPENGL3 && !gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 4, 1) && !gst_gl_check_extension ("GL_ARB_ES2_compatibility", context->priv->gl_exts)) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, "An opengl3 context created but the required ES2 compatibility was not found"); goto failure; } /* Does not implement OES_vertex_array_object properly, see * https://bugzilla.gnome.org/show_bug.cgi?id=750185 */ if (g_strcmp0 ((const gchar *) gl->GetString (GL_VENDOR), "Imagination Technologies") == 0 && g_strcmp0 ((const gchar *) gl->GetString (GL_RENDERER), "PowerVR SGX 544MP") == 0) { gl->GenVertexArrays = NULL; gl->DeleteVertexArrays = NULL; gl->BindVertexArray = NULL; gl->IsVertexArray = NULL; } return TRUE; failure: return FALSE; }