3 * Copyright (C) 2013 Matthew Waters <ystreet00@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:gstglcontext
23 * @short_description: OpenGL context abstraction
24 * @title: GstGLContext
25 * @see_also: #GstGLDisplay, #GstGLWindow
27 * #GstGLContext wraps an OpenGL context object in a uniform API. As a result
28 * of the limitation on OpenGL context, this object is not thread safe unless
29 * specified and must only be activated in a single thread.
36 #if defined(ANDROID) || defined(__ANDROID__)
37 /* Avoid a linker error with _isoc99_sscanf() when building a shared library
43 #ifndef GL_NUM_EXTENSIONS
44 #define GL_NUM_EXTENSIONS 0x0000821d
50 #include "gstglcontext.h"
52 #if GST_GL_HAVE_PLATFORM_GLX
53 #include "x11/gstglcontext_glx.h"
55 #if GST_GL_HAVE_PLATFORM_EGL
56 #include "egl/gstglcontext_egl.h"
58 #if GST_GL_HAVE_PLATFORM_CGL
59 #include "cocoa/gstglcontext_cocoa.h"
61 #if GST_GL_HAVE_PLATFORM_WGL
62 #include "win32/gstglcontext_wgl.h"
64 #if GST_GL_HAVE_PLATFORM_EAGL
65 #include "eagl/gstglcontext_eagl.h"
68 static GModule *module_self;
70 #if GST_GL_HAVE_OPENGL
71 static GOnce module_opengl_gonce = G_ONCE_INIT;
72 static GModule *module_opengl;
75 load_opengl_module (gpointer user_data)
77 #ifdef GST_GL_LIBGL_MODULE_NAME
78 module_opengl = g_module_open (GST_GL_LIBGL_MODULE_NAME, G_MODULE_BIND_LAZY);
80 /* This automatically handles the suffix and even .la files */
81 module_opengl = g_module_open ("libGL", G_MODULE_BIND_LAZY);
83 /* On Linux the .so is only in -dev packages, try with a real soname
84 * Proper compilers will optimize away the strcmp */
85 if (!module_opengl && strcmp (G_MODULE_SUFFIX, "so") == 0)
86 module_opengl = g_module_open ("libGL.so.1", G_MODULE_BIND_LAZY);
94 static GOnce module_gles2_gonce = G_ONCE_INIT;
95 static GModule *module_gles2;
98 load_gles2_module (gpointer user_data)
100 #ifdef GST_GL_LIBGLESV2_MODULE_NAME
102 g_module_open (GST_GL_LIBGLESV2_MODULE_NAME, G_MODULE_BIND_LAZY);
104 /* This automatically handles the suffix and even .la files */
105 module_gles2 = g_module_open ("libGLESv2", G_MODULE_BIND_LAZY);
107 /* On Linux the .so is only in -dev packages, try with a real soname
108 * Proper compilers will optimize away the strcmp */
109 if (!module_gles2 && strcmp (G_MODULE_SUFFIX, "so") == 0)
110 module_gles2 = g_module_open ("libGLESv2.so.2", G_MODULE_BIND_LAZY);
117 #if GST_GL_HAVE_GLES3
118 #error "Add module loading support for GLES3"
121 #define GST_CAT_DEFAULT gst_gl_context_debug
122 GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
124 #define gst_gl_context_parent_class parent_class
125 G_DEFINE_ABSTRACT_TYPE (GstGLContext, gst_gl_context, GST_TYPE_OBJECT);
127 #define GST_GL_CONTEXT_GET_PRIVATE(o) \
128 (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT, GstGLContextPrivate))
130 static gpointer gst_gl_context_create_thread (GstGLContext * context);
131 static void gst_gl_context_finalize (GObject * object);
133 struct _GstGLContextPrivate
135 GstGLDisplay *display;
147 GstGLContext *other_context;
161 GstGLPlatform platform;
162 GstGLAPI available_apis;
163 } GstGLWrappedContext;
167 GstGLContextClass parent;
168 } GstGLWrappedContextClass;
170 #define GST_GL_TYPE_WRAPPED_CONTEXT (gst_gl_wrapped_context_get_type())
171 GType gst_gl_wrapped_context_get_type (void);
172 G_DEFINE_TYPE (GstGLWrappedContext, gst_gl_wrapped_context,
173 GST_GL_TYPE_CONTEXT);
175 #define GST_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WRAPPED_CONTEXT, GstGLWrappedContext))
176 #define GST_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT, GstGLContextClass))
177 #define GST_GL_IS_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WRAPPED_CONTEXT))
178 #define GST_GL_IS_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WRAPPED_CONTEXT))
179 #define GST_GL_WRAPPED_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WRAPPED_CONTEXT, GstGLWrappedContextClass))
182 gst_gl_context_error_quark (void)
184 return g_quark_from_static_string ("gst-gl-context-error-quark");
188 _ensure_window (GstGLContext * context)
195 window = gst_gl_window_new (context->priv->display);
197 gst_gl_context_set_window (context, window);
199 gst_object_unref (window);
203 gst_gl_context_init (GstGLContext * context)
205 context->priv = GST_GL_CONTEXT_GET_PRIVATE (context);
207 context->window = NULL;
208 context->gl_vtable = g_slice_alloc0 (sizeof (GstGLFuncs));
210 g_mutex_init (&context->priv->render_lock);
212 g_cond_init (&context->priv->create_cond);
213 g_cond_init (&context->priv->destroy_cond);
214 context->priv->created = FALSE;
218 gst_gl_context_class_init (GstGLContextClass * klass)
220 g_type_class_add_private (klass, sizeof (GstGLContextPrivate));
222 module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
224 klass->get_proc_address =
225 GST_DEBUG_FUNCPTR (gst_gl_context_default_get_proc_address);
227 G_OBJECT_CLASS (klass)->finalize = gst_gl_context_finalize;
233 static volatile gsize _init = 0;
235 if (g_once_init_enter (&_init)) {
236 GST_DEBUG_CATEGORY_INIT (gst_gl_context_debug, "glcontext", 0,
237 "glcontext element");
238 g_once_init_leave (&_init, 1);
243 * gst_gl_context_new:
244 * @display: a #GstGLDisplay
246 * Create a new #GstGLContext with the specified @display
248 * Returns: a new #GstGLContext
251 gst_gl_context_new (GstGLDisplay * display)
253 GstGLContext *context = NULL;
254 const gchar *user_choice;
258 user_choice = g_getenv ("GST_GL_PLATFORM");
259 GST_INFO ("creating a context, user choice:%s", user_choice);
260 #if GST_GL_HAVE_PLATFORM_EGL
261 if (!context && (!user_choice || g_strstr_len (user_choice, 7, "egl")))
262 context = GST_GL_CONTEXT (gst_gl_context_egl_new ());
264 #if GST_GL_HAVE_PLATFORM_CGL
265 if (!context && (!user_choice || g_strstr_len (user_choice, 5, "cgl")))
266 context = GST_GL_CONTEXT (gst_gl_context_cocoa_new ());
268 #if GST_GL_HAVE_PLATFORM_GLX
269 if (!context && (!user_choice || g_strstr_len (user_choice, 3, "glx")))
270 context = GST_GL_CONTEXT (gst_gl_context_glx_new ());
272 #if GST_GL_HAVE_PLATFORM_WGL
273 if (!context && (!user_choice || g_strstr_len (user_choice, 3, "wgl"))) {
274 context = GST_GL_CONTEXT (gst_gl_context_wgl_new ());
277 #if GST_GL_HAVE_PLATFORM_EAGL
278 if (!context && (!user_choice || g_strstr_len (user_choice, 5, "eagl")))
279 context = GST_GL_CONTEXT (gst_gl_context_eagl_new ());
283 /* subclass returned a NULL context */
284 GST_WARNING ("Could not create context. user specified %s",
285 user_choice ? user_choice : "(null)");
290 context->priv->display = gst_object_ref (display);
296 * gst_gl_context_new_wrapped:
297 * @display: a #GstGLDisplay
298 * @handle: the OpenGL context to wrap
299 * @context_type: a #GstGLPlatform specifying the type of context in @handle
300 * @available_apis: a #GstGLAPI containing the available OpenGL apis in @handle
302 * Wraps an existing OpenGL context into a #GstGLContext.
304 * Returns: a #GstGLContext wrapping @handle
307 gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle,
308 GstGLPlatform context_type, GstGLAPI available_apis)
310 GstGLContext *context;
311 GstGLWrappedContext *context_wrap = NULL;
315 context_wrap = g_object_new (GST_GL_TYPE_WRAPPED_CONTEXT, NULL);
318 /* subclass returned a NULL context */
319 GST_ERROR ("Could not wrap existing context");
324 context = (GstGLContext *) context_wrap;
326 context->priv->display = gst_object_ref (display);
327 context_wrap->handle = handle;
328 context_wrap->platform = context_type;
329 context_wrap->available_apis = available_apis;
335 gst_gl_context_finalize (GObject * object)
337 GstGLContext *context = GST_GL_CONTEXT (object);
339 if (context->window) {
340 gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL);
341 gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL);
343 if (context->priv->alive) {
344 g_mutex_lock (&context->priv->render_lock);
345 GST_INFO ("send quit gl window loop");
346 gst_gl_window_quit (context->window);
347 while (context->priv->alive) {
348 g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock);
350 g_mutex_unlock (&context->priv->render_lock);
353 gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL);
355 if (context->priv->gl_thread) {
356 gpointer ret = g_thread_join (context->priv->gl_thread);
357 GST_INFO ("gl thread joined");
359 GST_ERROR ("gl thread returned a non-null pointer");
360 context->priv->gl_thread = NULL;
363 gst_object_unref (context->window);
366 gst_object_unref (context->priv->display);
368 if (context->gl_vtable) {
369 g_slice_free (GstGLFuncs, context->gl_vtable);
370 context->gl_vtable = NULL;
373 g_mutex_clear (&context->priv->render_lock);
375 g_cond_clear (&context->priv->destroy_cond);
376 g_cond_clear (&context->priv->create_cond);
378 g_free (context->priv->gl_exts);
380 G_OBJECT_CLASS (gst_gl_context_parent_class)->finalize (object);
384 * gst_gl_context_activate:
385 * @context: a #GstGLContext
386 * @activate: %TRUE to activate, %FALSE to deactivate
388 * (De)activate the OpenGL context represented by this @context.
390 * In OpenGL terms, calls eglMakeCurrent or similar with this context and the
391 * currently set window. See gst_gl_context_set_window() for details.
393 * Returns: Whether the activation succeeded
396 gst_gl_context_activate (GstGLContext * context, gboolean activate)
398 GstGLContextClass *context_class;
401 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
402 context_class = GST_GL_CONTEXT_GET_CLASS (context);
403 g_return_val_if_fail (context_class->activate != NULL, FALSE);
405 result = context_class->activate (context, activate);
411 * gst_gl_context_get_gl_api:
412 * @context: a #GstGLContext
414 * Get the currently enabled OpenGL api.
416 * The currently available API may be limited by the #GstGLDisplay in use and/or
417 * the #GstGLWindow chosen.
419 * Returns: the currently available OpenGL api
422 gst_gl_context_get_gl_api (GstGLContext * context)
424 GstGLContextClass *context_class;
426 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), GST_GL_API_NONE);
427 context_class = GST_GL_CONTEXT_GET_CLASS (context);
428 g_return_val_if_fail (context_class->get_gl_api != NULL, GST_GL_API_NONE);
430 return context_class->get_gl_api (context);
434 * gst_gl_context_get_proc_address:
435 * @context: a #GstGLContext
436 * @name: an opengl function name
438 * Get a function pointer to a specified opengl function, @name. If the the
439 * specific function does not exist, NULL is returned instead.
441 * Platform specfic functions (names starting 'egl', 'glX', 'wgl', etc) can also
442 * be retreived using this method.
444 * Returns: a function pointer or NULL
447 gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name)
450 GstGLContextClass *context_class;
452 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
453 g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), NULL);
454 context_class = GST_GL_CONTEXT_GET_CLASS (context);
455 g_return_val_if_fail (context_class->get_proc_address != NULL, NULL);
457 ret = context_class->get_proc_address (context, name);
463 gst_gl_context_default_get_proc_address (GstGLContext * context,
467 GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
469 /* First try to load symbol from the selected GL API for this context */
470 #if GST_GL_HAVE_GLES2
471 if (!ret && (gl_api & GST_GL_API_GLES2)) {
472 g_once (&module_gles2_gonce, load_gles2_module, NULL);
474 g_module_symbol (module_gles2, name, &ret);
478 #if GST_GL_HAVE_OPENGL
479 if (!ret && (gl_api & (GST_GL_API_OPENGL | GST_GL_API_OPENGL3))) {
480 g_once (&module_opengl_gonce, load_opengl_module, NULL);
482 g_module_symbol (module_opengl, name, &ret);
486 /* Otherwise fall back to the current module */
488 g_module_symbol (module_self, name, &ret);
494 * gst_gl_context_set_window:
495 * @context: a #GstGLContext
496 * @window: (transfer full): a #GstGLWindow
498 * Set's the current window on @context to @window. The window can only be
499 * changed before gst_gl_context_create() has been called and the @window is not
502 * Returns: Whether the window was successfully updated
505 gst_gl_context_set_window (GstGLContext * context, GstGLWindow * window)
507 g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), FALSE);
509 /* we can't change the window while we are running */
510 if (context->priv->alive)
514 if (gst_gl_window_is_running (window))
517 g_weak_ref_set (&window->context_ref, context);
521 gst_object_unref (context->window);
523 context->window = window ? gst_object_ref (window) : NULL;
529 * gst_gl_context_get_window:
530 * @context: a #GstGLContext
532 * Returns: the currently set window
535 gst_gl_context_get_window (GstGLContext * context)
537 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
539 if (GST_GL_IS_WRAPPED_CONTEXT (context))
542 _ensure_window (context);
544 return gst_object_ref (context->window);
548 * gst_gl_context_create:
549 * @context: a #GstGLContext:
550 * @other_context: (allow-none): a #GstGLContext to share OpenGL objects with
551 * @error: (allow-none): a #GError
553 * Creates an OpenGL context in the current thread with the specified
554 * @other_context as a context to share shareable OpenGL objects with. See the
555 * OpenGL specification for what is shared between contexts.
557 * If an error occurs, and @error is not %NULL, then error will contain details
558 * of the error and %FALSE will be returned.
560 * Should only be called once.
562 * Returns: whether the context could successfully be created
565 gst_gl_context_create (GstGLContext * context,
566 GstGLContext * other_context, GError ** error)
568 gboolean alive = FALSE;
570 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
571 g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), FALSE);
572 _ensure_window (context);
574 g_mutex_lock (&context->priv->render_lock);
576 if (!context->priv->created) {
577 context->priv->other_context = other_context;
578 context->priv->error = error;
580 context->priv->gl_thread = g_thread_new ("gstglcontext",
581 (GThreadFunc) gst_gl_context_create_thread, context);
583 g_cond_wait (&context->priv->create_cond, &context->priv->render_lock);
585 context->priv->created = TRUE;
587 GST_INFO ("gl thread created");
590 alive = context->priv->alive;
592 g_mutex_unlock (&context->priv->render_lock);
598 _create_context_gles2 (GstGLContext * context, gint * gl_major, gint * gl_minor,
601 const GstGLFuncs *gl;
602 GLenum gl_err = GL_NO_ERROR;
604 gl = context->gl_vtable;
606 GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
607 GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
608 gl->GetString (GL_SHADING_LANGUAGE_VERSION));
609 GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
610 GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
612 gl_err = gl->GetError ();
613 if (gl_err != GL_NO_ERROR) {
614 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
615 "glGetString error: 0x%x", gl_err);
618 #if GST_GL_HAVE_GLES2
619 if (!GL_ES_VERSION_2_0) {
620 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS,
621 "OpenGL|ES >= 2.0 is required");
635 _create_context_opengl (GstGLContext * context, gint * gl_major,
636 gint * gl_minor, GError ** error)
638 const GstGLFuncs *gl;
640 GLenum gl_err = GL_NO_ERROR;
641 GString *opengl_version = NULL;
643 gl = context->gl_vtable;
645 GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION));
646 GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s",
647 gl->GetString (GL_SHADING_LANGUAGE_VERSION));
648 GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR));
649 GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER));
651 gl_err = gl->GetError ();
652 if (gl_err != GL_NO_ERROR) {
653 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
654 "glGetString error: 0x%x", gl_err);
658 g_string_truncate (g_string_new ((gchar *) gl->GetString (GL_VERSION)),
661 sscanf (opengl_version->str, "%d.%d", &maj, &min);
663 g_string_free (opengl_version, TRUE);
666 if ((maj < 1) || (maj < 2 && maj >= 1 && min < 2)) {
667 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS,
668 "OpenGL >= 1.2.0 required, found %u.%u", maj, min);
683 GstGLAPI ret = GST_GL_API_NONE;
685 #if GST_GL_HAVE_OPENGL
686 ret |= GST_GL_API_OPENGL | GST_GL_API_OPENGL3;
688 #if GST_GL_HAVE_GLES2
689 ret |= GST_GL_API_GLES2;
696 _unlock_create_thread (GstGLContext * context)
698 g_mutex_unlock (&context->priv->render_lock);
702 _build_extension_string (GstGLContext * context)
704 const GstGLFuncs *gl = context->gl_vtable;
705 GString *ext_g_str = g_string_sized_new (1024);
706 const gchar *ext_const_c_str = NULL;
709 gl->GetIntegerv (GL_NUM_EXTENSIONS, &n);
711 for (i = 0; i < n; i++) {
712 ext_const_c_str = (const gchar *) gl->GetStringi (GL_EXTENSIONS, i);
714 g_string_append_printf (ext_g_str, "%s ", ext_const_c_str);
721 //gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
723 gst_gl_context_create_thread (GstGLContext * context)
725 GstGLContextClass *context_class;
726 GstGLWindowClass *window_class;
728 gboolean ret = FALSE;
729 GstGLAPI compiled_api, user_api, gl_api;
731 gchar *compiled_api_s;
732 gchar *user_api_string;
733 const gchar *user_choice;
735 GstGLContext *other_context;
736 GString *ext_g_str = NULL;
737 const gchar *ext_const_c_str = NULL;
739 g_mutex_lock (&context->priv->render_lock);
741 error = context->priv->error;
742 other_context = context->priv->other_context;
744 context_class = GST_GL_CONTEXT_GET_CLASS (context);
745 window_class = GST_GL_WINDOW_GET_CLASS (context->window);
747 if (window_class->open) {
748 if (!window_class->open (context->window, error)) {
749 g_assert (error == NULL || *error != NULL);
754 gl = context->gl_vtable;
755 compiled_api = _compiled_api ();
757 user_choice = g_getenv ("GST_GL_API");
759 user_api = gst_gl_api_from_string (user_choice);
760 user_api_string = gst_gl_api_to_string (user_api);
762 compiled_api_s = gst_gl_api_to_string (compiled_api);
764 if ((user_api & compiled_api) == GST_GL_API_NONE) {
765 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
766 "Cannot create context with the user requested api (%s). "
767 "We have support for (%s)", user_api_string, compiled_api_s);
768 g_free (user_api_string);
769 g_free (compiled_api_s);
773 if (context_class->choose_format &&
774 !context_class->choose_format (context, error)) {
775 g_assert (error == NULL || *error != NULL);
776 g_free (compiled_api_s);
777 g_free (user_api_string);
781 GST_INFO ("Attempting to create opengl context. user chosen api(s) (%s), "
782 "compiled api support (%s)", user_api_string, compiled_api_s);
784 if (!context_class->create_context (context, compiled_api & user_api,
785 other_context, error)) {
786 g_assert (error == NULL || *error != NULL);
787 g_free (compiled_api_s);
788 g_free (user_api_string);
791 GST_INFO ("created context");
793 if (!context_class->activate (context, TRUE)) {
794 g_set_error (error, GST_GL_CONTEXT_ERROR,
795 GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
796 "Failed to activate the GL Context");
797 g_free (compiled_api_s);
798 g_free (user_api_string);
802 gl_api = gst_gl_context_get_gl_api (context);
803 g_assert (gl_api != GST_GL_API_NONE && gl_api != GST_GL_API_ANY);
805 api_string = gst_gl_api_to_string (gl_api);
806 GST_INFO ("available GL APIs: %s", api_string);
808 if (((compiled_api & gl_api) & user_api) == GST_GL_API_NONE) {
809 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
810 "failed to create context, context "
811 "could not provide correct api. user (%s), compiled (%s), context (%s)",
812 user_api_string, compiled_api_s, api_string);
814 g_free (compiled_api_s);
815 g_free (user_api_string);
820 g_free (compiled_api_s);
821 g_free (user_api_string);
823 gl->GetError = gst_gl_context_get_proc_address (context, "glGetError");
824 gl->GetString = gst_gl_context_get_proc_address (context, "glGetString");
825 gl->GetStringi = gst_gl_context_get_proc_address (context, "glGetStringi");
826 gl->GetIntegerv = gst_gl_context_get_proc_address (context, "glGetIntegerv");
828 if (!gl->GetError || !gl->GetString) {
829 g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
830 "could not GetProcAddress core opengl functions");
834 /* gl api specific code */
835 if (!ret && gl_api & GST_GL_API_OPENGL)
836 ret = _create_context_opengl (context, &context->priv->gl_major,
837 &context->priv->gl_minor, error);
838 if (!ret && gl_api & GST_GL_API_GLES2)
840 _create_context_gles2 (context, &context->priv->gl_major,
841 &context->priv->gl_minor, error);
844 g_assert (error == NULL || *error != NULL);
848 /* GL core contexts and GLES3 */
849 if (gl->GetIntegerv && gl->GetStringi && context->priv->gl_major >= 3)
850 ext_g_str = _build_extension_string (context);
852 if (ext_g_str && ext_g_str->len) {
853 GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_g_str->str);
854 _gst_gl_feature_check_ext_functions (context, context->priv->gl_major,
855 context->priv->gl_minor, ext_g_str->str);
857 context->priv->gl_exts = g_string_free (ext_g_str, FALSE);
859 ext_const_c_str = (const gchar *) gl->GetString (GL_EXTENSIONS);
860 if (!ext_const_c_str)
861 ext_const_c_str = "";
863 GST_DEBUG_OBJECT (context, "GL_EXTENSIONS: %s", ext_const_c_str);
864 _gst_gl_feature_check_ext_functions (context, context->priv->gl_major,
865 context->priv->gl_minor, ext_const_c_str);
867 context->priv->gl_exts = g_strdup (ext_const_c_str);
870 context->priv->alive = TRUE;
872 g_cond_signal (&context->priv->create_cond);
874 // g_mutex_unlock (&context->priv->render_lock);
875 gst_gl_window_send_message_async (context->window,
876 (GstGLWindowCB) _unlock_create_thread, context, NULL);
878 gst_gl_window_run (context->window);
880 GST_INFO ("loop exited\n");
882 g_mutex_lock (&context->priv->render_lock);
884 context->priv->alive = FALSE;
886 context_class->activate (context, FALSE);
888 context_class->destroy_context (context);
890 /* User supplied callback */
891 if (context->window->close)
892 context->window->close (context->window->close_data);
894 /* window specific shutdown */
895 if (window_class->close) {
896 window_class->close (context->window);
899 g_cond_signal (&context->priv->destroy_cond);
901 g_mutex_unlock (&context->priv->render_lock);
907 g_cond_signal (&context->priv->create_cond);
908 g_mutex_unlock (&context->priv->render_lock);
914 * gst_gl_context_get_gl_context:
915 * @context: a #GstGLContext:
917 * Gets the backing OpenGL context used by @context.
919 * Returns: The platform specific backing OpenGL context
922 gst_gl_context_get_gl_context (GstGLContext * context)
924 GstGLContextClass *context_class;
927 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), 0);
928 context_class = GST_GL_CONTEXT_GET_CLASS (context);
929 g_return_val_if_fail (context_class->get_gl_context != NULL, 0);
931 result = context_class->get_gl_context (context);
937 * gst_gl_context_get_gl_platform:
938 * @context: a #GstGLContext:
940 * Gets the OpenGL platform that used by @context.
942 * Returns: The platform specific backing OpenGL context
945 gst_gl_context_get_gl_platform (GstGLContext * context)
947 GstGLContextClass *context_class;
949 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), 0);
950 context_class = GST_GL_CONTEXT_GET_CLASS (context);
951 g_return_val_if_fail (context_class->get_gl_platform != NULL, 0);
953 return context_class->get_gl_platform (context);
957 * gst_gl_context_get_display:
958 * @context: a #GstGLContext:
960 * Returns: the #GstGLDisplay associated with this @context
963 gst_gl_context_get_display (GstGLContext * context)
965 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
967 return gst_object_ref (context->priv->display);
972 GstGLContext *context;
973 GstGLContextThreadFunc func;
978 _gst_gl_context_thread_run_generic (RunGenericData * data)
980 GST_TRACE ("running function:%p data:%p", data->func, data->data);
982 data->func (data->context, data->data);
986 * gst_gl_context_thread_add:
987 * @context: a #GstGLContext
988 * @func: a #GstGLContextThreadFunc
989 * @data: (closure): user data to call @func with
991 * Execute @func in the OpenGL thread of @context with @data
996 gst_gl_context_thread_add (GstGLContext * context,
997 GstGLContextThreadFunc func, gpointer data)
1000 RunGenericData rdata;
1002 g_return_if_fail (GST_GL_IS_CONTEXT (context));
1003 g_return_if_fail (func != NULL);
1004 g_return_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context));
1006 rdata.context = context;
1010 window = gst_gl_context_get_window (context);
1012 gst_gl_window_send_message (window,
1013 GST_GL_WINDOW_CB (_gst_gl_context_thread_run_generic), &rdata);
1015 gst_object_unref (window);
1019 * gst_gl_context_get_gl_version:
1020 * @context: a #GstGLContext
1021 * @maj: (out): resulting major version
1022 * @min: (out): resulting minor version
1024 * Returns the OpenGL version implemented by @context. See
1025 * gst_gl_context_get_gl_api() for retreiving the OpenGL api implemented by
1029 gst_gl_context_get_gl_version (GstGLContext * context, gint * maj, gint * min)
1031 g_return_if_fail (GST_GL_IS_CONTEXT (context));
1032 g_return_if_fail (maj == NULL && min == NULL);
1035 *maj = context->priv->gl_major;
1038 *min = context->priv->gl_minor;
1042 * gst_gl_context_check_feature:
1043 * @context: a #GstGLContext
1044 * @feature: a platform specific feature
1046 * Some features require that the context be created before it is possible to
1047 * determine their existence and so will fail if that is not the case.
1049 * Returns: Whether @feature is supported by @context
1052 gst_gl_context_check_feature (GstGLContext * context, const gchar * feature)
1054 GstGLContextClass *context_class;
1056 g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
1057 g_return_val_if_fail (feature != NULL, FALSE);
1059 context_class = GST_GL_CONTEXT_GET_CLASS (context);
1061 if (g_strstr_len (feature, 3, "GL_"))
1062 return gst_gl_check_extension (feature, context->priv->gl_exts);
1064 if (!context_class->check_feature)
1067 return context_class->check_feature (context, feature);
1071 gst_gl_wrapped_context_get_gl_api (GstGLContext * context)
1073 GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context);
1075 return context_wrap->available_apis;
1079 gst_gl_wrapped_context_get_gl_context (GstGLContext * context)
1081 GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context);
1083 return context_wrap->handle;
1086 static GstGLPlatform
1087 gst_gl_wrapped_context_get_gl_platform (GstGLContext * context)
1089 GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context);
1091 return context_wrap->platform;
1095 gst_gl_wrapped_context_activate (GstGLContext * context, gboolean activate)
1097 g_assert_not_reached ();
1103 gst_gl_wrapped_context_class_init (GstGLWrappedContextClass * klass)
1105 GstGLContextClass *context_class = (GstGLContextClass *) klass;
1107 context_class->get_gl_context =
1108 GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_context);
1109 context_class->get_gl_api =
1110 GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_api);
1111 context_class->get_gl_platform =
1112 GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_platform);
1113 context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_activate);
1117 gst_gl_wrapped_context_init (GstGLWrappedContext * context)