/** * gst_gl_context_can_share: * @context: a #GstGLContext * @other_context: another #GstGLContext * * 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) { GstGLContext *root1, *root2; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); g_return_val_if_fail (GST_GL_IS_CONTEXT (other_context), FALSE); /* check if the contexts are descendants or the root nodes are the same */ return context == other_context || _share_group_descendant (context, other_context, &root1) || _share_group_descendant (other_context, context, &root2) || ((root1 != NULL || root2 != NULL) && root1 == root2); }
/** * 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 */ gboolean gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error) { gboolean alive = FALSE; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), FALSE); _ensure_window (context); g_mutex_lock (&context->priv->render_lock); if (!context->priv->created) { context->priv->other_context = other_context; context->priv->error = error; 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 ("gl thread created"); } alive = context->priv->alive; g_mutex_unlock (&context->priv->render_lock); return alive; }
/** * gst_gl_context_get_display: * @context: a #GstGLContext: * * Returns: the #GstGLDisplay associated with this @context */ GstGLDisplay * gst_gl_context_get_display (GstGLContext * context) { g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL); return gst_object_ref (context->priv->display); }
/** * 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_GL_IS_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; }
/** * 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_GL_IS_CONTEXT (context)); g_return_if_fail (func != NULL); if (GST_GL_IS_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_gl_platform: * @context: a #GstGLContext: * * Gets the OpenGL platform that used by @context. * * Returns: The platform specific backing OpenGL context */ GstGLPlatform gst_gl_context_get_gl_platform (GstGLContext * context) { GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_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_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 currently available OpenGL api */ GstGLAPI gst_gl_context_get_gl_api (GstGLContext * context) { GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_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_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_GL_IS_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_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. */ void gst_gl_context_get_gl_version (GstGLContext * context, gint * maj, gint * min) { g_return_if_fail (GST_GL_IS_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_get_window: * @context: a #GstGLContext * * Returns: the currently set window */ GstGLWindow * gst_gl_context_get_window (GstGLContext * context) { g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL); if (GST_GL_IS_WRAPPED_CONTEXT (context)) 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 retreived 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; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_proc_address != NULL, NULL); ret = context_class->get_proc_address (context, name); return ret; }
/** * 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_GL_IS_CONTEXT (context), NULL); if (GST_GL_IS_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_gl_context: * @context: a #GstGLContext: * * Gets the backing OpenGL context used by @context. * * Returns: The platform specific backing OpenGL context */ guintptr gst_gl_context_get_gl_context (GstGLContext * context) { GstGLContextClass *context_class; guintptr result; g_return_val_if_fail (GST_GL_IS_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_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 */ gboolean gst_gl_context_activate (GstGLContext * context, gboolean activate) { GstGLContextClass *context_class; gboolean result; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->activate != NULL, FALSE); result = context_class->activate (context, activate); return result; }
/** * 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 */ gboolean gst_gl_context_check_feature (GstGLContext * context, const gchar * feature) { GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_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); }
GstGLSyncMeta * gst_buffer_add_gl_sync_meta (GstGLContext * context, GstBuffer * buffer) { GstGLSyncMeta *meta; g_return_val_if_fail (GST_GL_IS_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->glsync = NULL; 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. */ gboolean gst_gl_context_check_gl_version (GstGLContext * context, GstGLAPI api, gint maj, gint min) { g_return_val_if_fail (GST_GL_IS_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; }
/** * 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_GL_IS_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; } return TRUE; failure: return FALSE; }