mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
glcontext: allow wrapped contexts to be utilised like non-wrapped contexts
Fill in the missing pieces like get_proc_address, the gl function vtable
This commit is contained in:
parent
50a11e4a77
commit
bef3f020a6
3 changed files with 185 additions and 91 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue