diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index 35fc9c0df3..3098020816 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -372,6 +372,7 @@ gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle, if (context_type == GST_GL_PLATFORM_CGL) { context_class->get_current_context = gst_gl_context_cocoa_get_current_context; + context_class->get_proc_address = _default_get_proc_address; } #endif #if GST_GL_HAVE_PLATFORM_WGL @@ -384,9 +385,16 @@ gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle, if (context_type == GST_GL_PLATFORM_EAGL) { context_class->get_current_context = gst_gl_context_eagl_get_current_context; + context_class->get_proc_address = _default_get_proc_address; } #endif + if (!context_class->get_current_context) { + /* we don't have API support */ + gst_object_unref (context); + return NULL; + } + return context; } @@ -698,7 +706,6 @@ gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name) GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL); - g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), NULL); context_class = GST_GL_CONTEXT_GET_CLASS (context); g_return_val_if_fail (context_class->get_proc_address != NULL, NULL); @@ -1168,7 +1175,6 @@ gst_gl_context_create_thread (GstGLContext * context) GstGLContextClass *context_class; GstGLWindowClass *window_class; GstGLFuncs *gl; - gboolean ret = FALSE; GstGLAPI compiled_api, user_api, gl_api, display_api; gchar *api_string; gchar *compiled_api_s; @@ -1177,8 +1183,6 @@ gst_gl_context_create_thread (GstGLContext * context) const gchar *user_choice; GError **error; GstGLContext *other_context; - GString *ext_g_str = NULL; - const gchar *ext_const_c_str = NULL; g_mutex_lock (&context->priv->render_lock); @@ -1247,7 +1251,7 @@ gst_gl_context_create_thread (GstGLContext * context) } GST_INFO ("created context"); - if (!context_class->activate (context, TRUE)) { + if (!gst_gl_context_activate (context, TRUE)) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, "Failed to activate the GL Context"); @@ -1280,6 +1284,116 @@ gst_gl_context_create_thread (GstGLContext * context) g_free (user_api_s); g_free (display_api_s); + gst_gl_context_fill_info (context, error); + + context->priv->alive = TRUE; + + if (gl->DebugMessageCallback) { +#if !defined(GST_DISABLE_GST_DEBUG) + GST_INFO ("Enabling GL context debugging"); + /* enable them all */ + gl->DebugMessageControl (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, + GL_TRUE); + gl->DebugMessageCallback (_gst_gl_debug_callback, context); +#endif + } + + if (other_context) + gst_object_unref (other_context); + + g_cond_signal (&context->priv->create_cond); + +// g_mutex_unlock (&context->priv->render_lock); + gst_gl_window_send_message_async (context->window, + (GstGLWindowCB) _unlock_create_thread, context, NULL); + + gst_gl_window_run (context->window); + + GST_INFO ("loop exited\n"); + + g_mutex_lock (&context->priv->render_lock); + + context->priv->alive = FALSE; + + gst_gl_context_activate (context, FALSE); + + context_class->destroy_context (context); + + /* User supplied callback */ + if (context->window->close) + context->window->close (context->window->close_data); + + /* window specific shutdown */ + if (window_class->close) { + window_class->close (context->window); + } + + g_cond_signal (&context->priv->destroy_cond); + + g_mutex_unlock (&context->priv->render_lock); + + return NULL; + +failure: + { + if (other_context) + gst_object_unref (other_context); + + g_cond_signal (&context->priv->create_cond); + g_mutex_unlock (&context->priv->render_lock); + return NULL; + } +} + +/** + * 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_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"); @@ -1331,86 +1445,10 @@ gst_gl_context_create_thread (GstGLContext * context) goto failure; } - context->priv->alive = TRUE; - - if (gl->DebugMessageCallback) { -#if !defined(GST_DISABLE_GST_DEBUG) - GST_INFO ("Enabling GL context debugging"); - /* enable them all */ - gl->DebugMessageControl (GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, 0, - GL_TRUE); - gl->DebugMessageCallback (_gst_gl_debug_callback, context); -#endif - } - - if (other_context) - gst_object_unref (other_context); - - g_cond_signal (&context->priv->create_cond); - -// g_mutex_unlock (&context->priv->render_lock); - gst_gl_window_send_message_async (context->window, - (GstGLWindowCB) _unlock_create_thread, context, NULL); - - gst_gl_window_run (context->window); - - GST_INFO ("loop exited\n"); - - g_mutex_lock (&context->priv->render_lock); - - context->priv->alive = FALSE; - - context_class->activate (context, FALSE); - - context_class->destroy_context (context); - - /* User supplied callback */ - if (context->window->close) - context->window->close (context->window->close_data); - - /* window specific shutdown */ - if (window_class->close) { - window_class->close (context->window); - } - - g_cond_signal (&context->priv->destroy_cond); - - g_mutex_unlock (&context->priv->render_lock); - - return NULL; + return TRUE; failure: - { - if (other_context) - gst_object_unref (other_context); - - g_cond_signal (&context->priv->create_cond); - g_mutex_unlock (&context->priv->render_lock); - return NULL; - } -} - -/** - * 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); + return FALSE; } /** @@ -1512,7 +1550,12 @@ gst_gl_context_thread_add (GstGLContext * context, g_return_if_fail (GST_GL_IS_CONTEXT (context)); g_return_if_fail (func != NULL); - g_return_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context)); + + 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; @@ -1642,9 +1685,12 @@ gst_gl_wrapped_context_get_gl_platform (GstGLContext * context) static gboolean gst_gl_wrapped_context_activate (GstGLContext * context, gboolean activate) { - g_assert_not_reached (); + if (activate) + context->priv->gl_thread = g_thread_self (); + else + context->priv->gl_thread = NULL; - return FALSE; + return TRUE; } static void diff --git a/gst-libs/gst/gl/gstglcontext.h b/gst-libs/gst/gl/gstglcontext.h index 9d243d1c69..e9fe5dcafc 100644 --- a/gst-libs/gst/gl/gstglcontext.h +++ b/gst-libs/gst/gl/gstglcontext.h @@ -145,6 +145,8 @@ gboolean gst_gl_context_check_feature (GstGLContext *context, const gchar * guintptr gst_gl_context_get_current_gl_context (GstGLPlatform platform); GstGLAPI gst_gl_context_get_current_gl_api (guint *major, guint *minor); +gboolean gst_gl_context_fill_info (GstGLContext * context, GError ** error); + /* FIXME: remove */ void gst_gl_context_thread_add (GstGLContext * context, GstGLContextThreadFunc func, gpointer data); diff --git a/tests/check/libs/gstglcontext.c b/tests/check/libs/gstglcontext.c index d9249e921b..ba0b1a98b2 100644 --- a/tests/check/libs/gstglcontext.c +++ b/tests/check/libs/gstglcontext.c @@ -281,15 +281,49 @@ GST_START_TEST (test_share) GST_END_TEST; +static void +accum_true (GstGLContext * context, gpointer data) +{ + gint *i = data; + *i = 1; +} + +static void +check_wrapped (gpointer data) +{ + GstGLContext *wrapped_context = data; + GError *error = NULL; + gint i = 0; + gboolean ret; + + /* check that scheduling on an unactivated wrapped context asserts */ + ASSERT_CRITICAL (gst_gl_context_thread_add (wrapped_context, + (GstGLContextThreadFunc) accum_true, &i)); + fail_if (i != 0); + + /* check that scheduling on an activated context succeeds */ + gst_gl_context_activate (wrapped_context, TRUE); + gst_gl_context_thread_add (wrapped_context, + (GstGLContextThreadFunc) accum_true, &i); + fail_if (i != 1); + + /* check filling out the wrapped context's info */ + fail_if (wrapped_context->gl_vtable->TexImage2D != NULL); + ret = gst_gl_context_fill_info (wrapped_context, &error); + fail_if (!ret, "error received %s\n", + error ? error->message : "Unknown error"); + fail_if (wrapped_context->gl_vtable->TexImage2D == NULL); +} + GST_START_TEST (test_wrapped_context) { GstGLContext *context, *other_context, *wrapped_context; GstGLWindow *window, *other_window; GError *error = NULL; gint i = 0; - guintptr handle; - GstGLPlatform platform; - GstGLAPI apis; + guintptr handle, handle2; + GstGLPlatform platform, platform2; + GstGLAPI apis, apis2; context = gst_gl_context_new (display); @@ -308,6 +342,14 @@ GST_START_TEST (test_wrapped_context) wrapped_context = gst_gl_context_new_wrapped (display, handle, platform, apis); + handle2 = gst_gl_context_get_gl_context (wrapped_context); + platform2 = gst_gl_context_get_gl_platform (wrapped_context); + apis2 = gst_gl_context_get_gl_api (wrapped_context); + + fail_if (handle != handle2); + fail_if (platform != platform2); + fail_if (apis != apis2); + other_context = gst_gl_context_new (display); other_window = gst_gl_window_new (display); gst_gl_context_set_window (other_context, other_window); @@ -330,11 +372,15 @@ GST_START_TEST (test_wrapped_context) i++; } + gst_object_unref (other_context); + + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (check_wrapped), + wrapped_context); + gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (deinit), context); - gst_object_unref (window); gst_object_unref (other_window); - gst_object_unref (other_context); + gst_object_unref (window); gst_object_unref (context); gst_object_unref (wrapped_context); }