From 3ad466945ec523465206763d3336b768518483ed Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Tue, 11 Feb 2014 08:57:29 +1100 Subject: [PATCH] [891/906] context: add support for wrapping external contexts --- gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 9 + gst-libs/gst/gl/egl/gstglcontext_egl.c | 14 +- gst-libs/gst/gl/gstglcontext.c | 232 +++++++++++++++++---- gst-libs/gst/gl/gstglcontext.h | 29 ++- gst-libs/gst/gl/win32/gstglcontext_wgl.c | 18 +- gst-libs/gst/gl/x11/gstglcontext_glx.c | 20 +- tests/check/libs/gstglcontext.c | 64 +++++- 7 files changed, 326 insertions(+), 60 deletions(-) diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index c5ae84f565..486763ea89 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -33,6 +33,7 @@ static void gst_gl_context_cocoa_destroy_context (GstGLContext *context); static guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window); static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate); static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context); +static GstGLPlatform gst_gl_context_cocoa_get_gl_platform (GstGLContext * context); #define GST_GL_CONTEXT_COCOA_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoaPrivate)) @@ -85,6 +86,8 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_activate); context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_api); + context_class->get_gl_platform = + GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_platform); #ifndef GNUSTEP pool = [[NSAutoreleasePool alloc] init]; @@ -255,3 +258,9 @@ gst_gl_context_cocoa_get_gl_api (GstGLContext * context) { return GST_GL_API_OPENGL; } + +static GstGLPlatform +gst_gl_context_cocoa_get_gl_platform (GstGLContext * context) +{ + return GST_GL_API_COCOA; +} diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c index 9aafd743d8..b181984ff3 100644 --- a/gst-libs/gst/gl/egl/gstglcontext_egl.c +++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c @@ -48,6 +48,8 @@ static gboolean gst_gl_context_egl_activate (GstGLContext * context, static void gst_gl_context_egl_swap_buffers (GstGLContext * context); static guintptr gst_gl_context_egl_get_gl_context (GstGLContext * context); static GstGLAPI gst_gl_context_egl_get_gl_api (GstGLContext * context); +static GstGLPlatform gst_gl_context_egl_get_gl_platform (GstGLContext * + context); static gpointer gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name); @@ -71,6 +73,8 @@ gst_gl_context_egl_class_init (GstGLContextEGLClass * klass) GST_DEBUG_FUNCPTR (gst_gl_context_egl_swap_buffers); context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_gl_api); + context_class->get_gl_platform = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_gl_platform); context_class->get_proc_address = GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_proc_address); } @@ -213,12 +217,14 @@ gst_gl_context_egl_create_context (GstGLContext * context, const gchar *egl_exts; gboolean need_surface = TRUE; guintptr external_gl_context = 0; + guintptr native_display; + GstGLDisplay *display; egl = GST_GL_CONTEXT_EGL (context); window = gst_gl_context_get_window (context); if (other_context) { - if (!GST_GL_IS_CONTEXT_EGL (other_context)) { + if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_EGL) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Cannot share context with non-EGL context"); @@ -462,6 +468,12 @@ gst_gl_context_egl_get_gl_api (GstGLContext * context) return GST_GL_CONTEXT_EGL (context)->gl_api; } +static GstGLPlatform +gst_gl_context_egl_get_gl_platform (GstGLContext * context) +{ + return GST_GL_PLATFORM_EGL; +} + static gpointer gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name) { diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index c385682cfe..d190502973 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -95,6 +95,31 @@ struct _GstGLContextPrivate GError **error; }; +typedef struct +{ + GstGLContext parent; + + guintptr handle; + GstGLPlatform platform; + GstGLAPI available_apis; +} GstGLWrappedContext; + +typedef struct +{ + GstGLContextClass parent; +} GstGLWrappedContextClass; + +#define GST_GL_TYPE_WRAPPED_CONTEXT (gst_gl_wrapped_context_get_type()) +GType gst_gl_wrapped_context_get_type (void); +G_DEFINE_TYPE (GstGLWrappedContext, gst_gl_wrapped_context, + GST_GL_TYPE_CONTEXT); + +#define GST_GL_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WRAPPED_CONTEXT, GstGLWrappedContext)) +#define GST_GL_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT, GstGLContextClass)) +#define GST_GL_IS_WRAPPED_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WRAPPED_CONTEXT)) +#define GST_GL_IS_WRAPPED_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WRAPPED_CONTEXT)) +#define GST_GL_WRAPPED_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WRAPPED_CONTEXT, GstGLWrappedContextClass)) + GQuark gst_gl_context_error_quark (void) { @@ -142,6 +167,18 @@ gst_gl_context_class_init (GstGLContextClass * klass) G_OBJECT_CLASS (klass)->finalize = gst_gl_context_finalize; } +static void +_init_debug (void) +{ + static volatile gsize _init = 0; + + if (g_once_init_enter (&_init)) { + GST_DEBUG_CATEGORY_INIT (gst_gl_context_debug, "glcontext", 0, + "glcontext element"); + g_once_init_leave (&_init, 1); + } +} + /** * gst_gl_context_new: * @display: a #GstGLDisplay @@ -155,13 +192,8 @@ gst_gl_context_new (GstGLDisplay * display) { GstGLContext *context = NULL; const gchar *user_choice; - static volatile gsize _init = 0; - if (g_once_init_enter (&_init)) { - GST_DEBUG_CATEGORY_INIT (gst_gl_context_debug, "glcontext", 0, - "glcontext element"); - g_once_init_leave (&_init, 1); - } + _init_debug (); user_choice = g_getenv ("GST_GL_PLATFORM"); GST_INFO ("creating a context, user choice:%s", user_choice); @@ -196,35 +228,77 @@ gst_gl_context_new (GstGLDisplay * display) return context; } +/** + * gst_gl_context_new_wrapped: + * @display: a #GstGLDisplay + * @handle: the OpenGL context to wrap + * @context_type: a #GstGLPlatform specifying the type of context in @handle + * @available_apis: a #GstGLAPI containing the available OpenGL apis in @handle + * + * Wraps an existing OpenGL context into a #GstGLContext. + * + * Returns: a #GstGLContext wrapping @handle + */ +GstGLContext * +gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle, + GstGLPlatform context_type, GstGLAPI available_apis) +{ + GstGLContext *context; + GstGLWrappedContext *context_wrap = NULL; + + _init_debug (); + + context_wrap = g_object_new (GST_GL_TYPE_WRAPPED_CONTEXT, NULL); + + if (!context_wrap) { + /* subclass returned a NULL context */ + GST_ERROR ("Could not wrap existing context"); + + return NULL; + } + + context = (GstGLContext *) context_wrap; + + context->priv->display = gst_object_ref (display); + context_wrap->handle = handle; + context_wrap->platform = context_type; + context_wrap->available_apis = available_apis; + + return context; +} + static void gst_gl_context_finalize (GObject * object) { GstGLContext *context = GST_GL_CONTEXT (object); - gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL); - gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL); + if (context->window) { + gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL); + gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL); - if (context->priv->alive) { - g_mutex_lock (&context->priv->render_lock); - GST_INFO ("send quit gl window loop"); - gst_gl_window_quit (context->window); - while (context->priv->alive) { - g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock); + if (context->priv->alive) { + g_mutex_lock (&context->priv->render_lock); + GST_INFO ("send quit gl window loop"); + gst_gl_window_quit (context->window); + while (context->priv->alive) { + g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock); + } + g_mutex_unlock (&context->priv->render_lock); } - g_mutex_unlock (&context->priv->render_lock); + + gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL); + + if (context->priv->gl_thread) { + gpointer ret = g_thread_join (context->priv->gl_thread); + GST_INFO ("gl thread joined"); + if (ret != NULL) + GST_ERROR ("gl thread returned a non-null pointer"); + context->priv->gl_thread = NULL; + } + + gst_object_unref (context->window); } - gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL); - - if (context->priv->gl_thread) { - gpointer ret = g_thread_join (context->priv->gl_thread); - GST_INFO ("gl thread joined"); - if (ret != NULL) - GST_ERROR ("gl thread returned a non-null pointer"); - context->priv->gl_thread = NULL; - } - - gst_object_unref (context->window); gst_object_unref (context->priv->display); if (context->gl_vtable) { @@ -310,6 +384,7 @@ 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); @@ -383,6 +458,8 @@ gst_gl_context_default_get_proc_address (GstGLContext * context, gboolean gst_gl_context_set_window (GstGLContext * context, GstGLWindow * window) { + g_return_val_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context), NULL); + /* we can't change the window while we are running */ if (context->priv->alive) return FALSE; @@ -413,6 +490,9 @@ 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); @@ -442,7 +522,7 @@ gst_gl_context_create (GstGLContext * context, 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); @@ -497,9 +577,6 @@ _create_context_gles2 (GstGLContext * context, gint * gl_major, gint * gl_minor, } #endif - _gst_gl_feature_check_ext_functions (context, 0, 0, - (const gchar *) gl->GetString (GL_EXTENSIONS)); - if (gl_major) *gl_major = 2; if (gl_minor) @@ -546,9 +623,6 @@ _create_context_opengl (GstGLContext * context, gint * gl_major, return FALSE; } - _gst_gl_feature_check_ext_functions (context, maj, min, - (const gchar *) gl->GetString (GL_EXTENSIONS)); - if (gl_major) *gl_major = maj; if (gl_minor) @@ -587,7 +661,7 @@ gst_gl_context_create_thread (GstGLContext * context) GstGLWindowClass *window_class; GstGLDisplay *display; GstGLFuncs *gl; - gint gl_major = 0; + gint gl_major = 0, gl_minor = 0; gboolean ret = FALSE; GstGLAPI compiled_api, user_api; gchar *api_string; @@ -692,13 +766,16 @@ gst_gl_context_create_thread (GstGLContext * context) /* gl api specific code */ if (!ret && USING_OPENGL (display)) - ret = _create_context_opengl (context, &gl_major, NULL, error); + ret = _create_context_opengl (context, &gl_major, &gl_minor, error); if (!ret && USING_GLES2 (display)) - ret = _create_context_gles2 (context, &gl_major, NULL, error); + ret = _create_context_gles2 (context, &gl_major, &gl_minor, error); if (!ret) goto failure; + _gst_gl_feature_check_ext_functions (context, gl_major, gl_minor, + (const gchar *) gl->GetString (GL_EXTENSIONS)); + context->priv->alive = TRUE; g_cond_signal (&context->priv->create_cond); @@ -763,6 +840,26 @@ gst_gl_context_get_gl_context (GstGLContext * context) return result; } +/** + * 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_display: * @context: a #GstGLContext: @@ -811,6 +908,7 @@ 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)); rdata.context = context; rdata.data = data; @@ -823,3 +921,65 @@ gst_gl_context_thread_add (GstGLContext * context, gst_object_unref (window); } + + +static GstGLAPI +gst_gl_wrapped_context_get_gl_api (GstGLContext * context) +{ + GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context); + + return context_wrap->available_apis; +} + +static guintptr +gst_gl_wrapped_context_get_gl_context (GstGLContext * context) +{ + GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context); + + return context_wrap->handle; +} + +static GstGLPlatform +gst_gl_wrapped_context_get_gl_platform (GstGLContext * context) +{ + GstGLWrappedContext *context_wrap = GST_GL_WRAPPED_CONTEXT (context); + + return context_wrap->platform; +} + +static gboolean +gst_gl_wrapped_context_activate (GstGLContext * context, gboolean activate) +{ + g_assert_not_reached (); + + return FALSE; +} + +static void +gst_gl_wrapped_context_class_init (GstGLWrappedContextClass * klass) +{ + GstGLContextClass *context_class = (GstGLContextClass *) klass; + + context_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_context); + context_class->get_gl_api = + GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_api); + context_class->get_gl_platform = + GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_get_gl_platform); + context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_wrapped_context_activate); +} + +static void +gst_gl_wrapped_context_init (GstGLWrappedContext * context) +{ +} + +/* Must be called in the gl thread */ +GstGLWrappedContext * +gst_gl_wrapped_context_new (void) +{ + GstGLWrappedContext *context = + g_object_new (GST_GL_TYPE_WRAPPED_CONTEXT, NULL); + + return context; +} diff --git a/gst-libs/gst/gl/gstglcontext.h b/gst-libs/gst/gl/gstglcontext.h index c4ee0bde6e..55db6cceca 100644 --- a/gst-libs/gst/gl/gstglcontext.h +++ b/gst-libs/gst/gl/gstglcontext.h @@ -47,6 +47,10 @@ GQuark gst_gl_context_error_quark (void); */ typedef void (*GstGLContextThreadFunc) (GstGLContext * context, gpointer data); +#define GST_GL_CONTEXT_TYPE_GLX "gst.gl.context.GLX" +#define GST_GL_CONTEXT_TYPE_EGL "gst.gl.context.EGL" +#define GST_GL_CONTEXT_TYPE_WGL "gst.gl.context.WGL" + typedef enum { GST_GL_CONTEXT_ERROR_FAILED, @@ -89,15 +93,16 @@ struct _GstGLContext { struct _GstGLContextClass { GObjectClass parent_class; - guintptr (*get_gl_context) (GstGLContext *context); - GstGLAPI (*get_gl_api) (GstGLContext *context); - gpointer (*get_proc_address) (GstGLContext *context, const gchar *name); - gboolean (*activate) (GstGLContext *context, gboolean activate); - gboolean (*choose_format) (GstGLContext *context, GError **error); - gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api, - GstGLContext *other_context, GError ** error); - void (*destroy_context) (GstGLContext *context); - void (*swap_buffers) (GstGLContext *context); + guintptr (*get_gl_context) (GstGLContext *context); + GstGLAPI (*get_gl_api) (GstGLContext *context); + GstGLPlatform (*get_gl_platform) (GstGLContext *context); + gpointer (*get_proc_address) (GstGLContext *context, const gchar *name); + gboolean (*activate) (GstGLContext *context, gboolean activate); + gboolean (*choose_format) (GstGLContext *context, GError **error); + gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api, + GstGLContext *other_context, GError ** error); + void (*destroy_context) (GstGLContext *context); + void (*swap_buffers) (GstGLContext *context); /*< private >*/ gpointer _reserved[GST_PADDING]; @@ -106,12 +111,16 @@ struct _GstGLContextClass { /* methods */ GstGLContext * gst_gl_context_new (GstGLDisplay *display); +GstGLContext * gst_gl_context_new_wrapped (GstGLDisplay *display, + guintptr handle, + GstGLPlatform context_type, + GstGLAPI available_apis); gboolean gst_gl_context_activate (GstGLContext *context, gboolean activate); GstGLDisplay * gst_gl_context_get_display (GstGLContext *context); gpointer gst_gl_context_get_proc_address (GstGLContext *context, const gchar *name); -GstGLPlatform gst_gl_context_get_platform (GstGLContext *context); +GstGLPlatform gst_gl_context_get_gl_platform (GstGLContext *context); GstGLAPI gst_gl_context_get_gl_api (GstGLContext *context); guintptr gst_gl_context_get_gl_context (GstGLContext *context); diff --git a/gst-libs/gst/gl/win32/gstglcontext_wgl.c b/gst-libs/gst/gl/win32/gstglcontext_wgl.c index 2dba16d7aa..bc3ea2637c 100644 --- a/gst-libs/gst/gl/win32/gstglcontext_wgl.c +++ b/gst-libs/gst/gl/win32/gstglcontext_wgl.c @@ -43,6 +43,8 @@ static gboolean gst_gl_context_wgl_create_context (GstGLContext * context, GstGLAPI gl_api, GstGLContext * other_context, GError ** error); static void gst_gl_context_wgl_destroy_context (GstGLContext * context); GstGLAPI gst_gl_context_wgl_get_gl_api (GstGLContext * context); +static GstGLPlatform gst_gl_context_wgl_get_gl_platform (GstGLContext * + context); static gpointer gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name); @@ -66,6 +68,8 @@ gst_gl_context_wgl_class_init (GstGLContextWGLClass * klass) context_class->get_proc_address = GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_proc_address); context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_gl_api); + context_class->get_gl_platform = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_gl_platform); } static void @@ -88,7 +92,7 @@ gst_gl_context_wgl_create_context (GstGLContext * context, { GstGLWindow *window; GstGLContextWGL *context_wgl; - GstGLContextWGL *other_wgl = NULL; + HGLRC external_gl_context = NULL; HDC device; context_wgl = GST_GL_CONTEXT_WGL (context); @@ -102,7 +106,7 @@ gst_gl_context_wgl_create_context (GstGLContext * context, "Cannot share context with a non-WGL context"); goto failure; } - other_wgl = (GstGLContextWGL *) other_context; + external_gl_context = (HGLRC) gst_gl_context_get_gl_context (other_context); } context_wgl->wgl_context = wglCreateContext (device); @@ -120,8 +124,8 @@ gst_gl_context_wgl_create_context (GstGLContext * context, GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT, (guintptr) context_wgl->wgl_context); - if (other_wgl) { - if (!wglShareLists (other_wgl->wgl_context, context_wgl->wgl_context)) { + if (external_gl_context) { + if (!wglShareLists (external_gl_context, context_wgl->wgl_context)) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to share contexts 0x%x", (unsigned int) GetLastError ()); @@ -253,6 +257,12 @@ gst_gl_context_wgl_get_gl_api (GstGLContext * context) return GST_GL_API_OPENGL; } +static GstGLPlatform +gst_gl_context_wgl_get_gl_platform (GstGLContext * context) +{ + return GST_GL_PLATFORM_WGL; +} + static gpointer gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name) { diff --git a/gst-libs/gst/gl/x11/gstglcontext_glx.c b/gst-libs/gst/gl/x11/gstglcontext_glx.c index 2be004c350..aeff7363d0 100644 --- a/gst-libs/gst/gl/x11/gstglcontext_glx.c +++ b/gst-libs/gst/gl/x11/gstglcontext_glx.c @@ -55,6 +55,8 @@ static void gst_gl_context_glx_destroy_context (GstGLContext * context); static gboolean gst_gl_context_glx_choose_format (GstGLContext * context, GError ** error); GstGLAPI gst_gl_context_glx_get_gl_api (GstGLContext * context); +static GstGLPlatform gst_gl_context_glx_get_gl_platform (GstGLContext * + context); static gpointer gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name); @@ -90,6 +92,8 @@ gst_gl_context_glx_class_init (GstGLContextGLXClass * klass) GST_DEBUG_FUNCPTR (gst_gl_context_glx_swap_buffers); context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_api); + context_class->get_gl_platform = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_platform); context_class->get_proc_address = GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_proc_address); } @@ -149,23 +153,17 @@ gst_gl_context_glx_create_context (GstGLContext * context, window_x11 = GST_GL_WINDOW_X11 (window); if (other_context) { - GstGLWindow *other_window; - - if (!GST_GL_IS_CONTEXT_GLX (other_context)) { + if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_GLX) { g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Cannot share context with non-GLX context"); goto failure; } - other_window = gst_gl_context_get_window (other_context); external_gl_context = gst_gl_context_get_gl_context (other_context); - device = (Display *) gst_gl_window_get_display (other_window); - gst_object_unref (other_window); - } else { - device = (Display *) gst_gl_window_get_display (window); } + device = (Display *) gst_gl_window_get_display (window); glx_exts = glXQueryExtensionsString (device, DefaultScreen (device)); create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts); @@ -408,6 +406,12 @@ gst_gl_context_glx_get_gl_api (GstGLContext * context) return context_glx->priv->context_api; } +static GstGLPlatform +gst_gl_context_glx_get_gl_platform (GstGLContext * context) +{ + return GST_GL_PLATFORM_GLX; +} + static gpointer gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name) { diff --git a/tests/check/libs/gstglcontext.c b/tests/check/libs/gstglcontext.c index 2139b4bd1a..3425e033d7 100644 --- a/tests/check/libs/gstglcontext.c +++ b/tests/check/libs/gstglcontext.c @@ -117,7 +117,8 @@ deinit (gpointer data) gl->DeleteTextures (1, &tex);; gst_object_unref (fbo); #if GST_GL_HAVE_GLES2 - gst_object_unref (shader); + if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2) + gst_object_unref (shader); #endif } @@ -281,6 +282,66 @@ GST_START_TEST (test_share) GST_END_TEST; +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; + + display = gst_gl_display_new (); + context = gst_gl_context_new (display); + + window = gst_gl_window_new (display); + gst_gl_context_set_window (context, window); + + gst_gl_context_create (context, 0, &error); + + fail_if (error != NULL, "Error creating master context %s\n", + error ? error->message : "Unknown Error"); + + handle = gst_gl_context_get_gl_context (context); + platform = gst_gl_context_get_gl_platform (context); + apis = gst_gl_context_get_gl_api (context); + + wrapped_context = + gst_gl_context_new_wrapped (display, handle, platform, apis); + + other_context = gst_gl_context_new (display); + other_window = gst_gl_window_new (display); + gst_gl_context_set_window (other_context, other_window); + + gst_gl_context_create (other_context, wrapped_context, &error); + + fail_if (error != NULL, "Error creating secondary context %s\n", + error ? error->message : "Unknown Error"); + + /* make the window visible */ + gst_gl_window_draw (window, 320, 240); + + gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (init), context); + + while (i < 1000) { + gst_gl_window_send_message (other_window, GST_GL_WINDOW_CB (draw_tex), + context); + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (draw_render), + context); + i++; + } + + 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 (context); +} + +GST_END_TEST; + Suite * gst_gl_memory_suite (void) @@ -291,6 +352,7 @@ gst_gl_memory_suite (void) suite_add_tcase (s, tc_chain); tcase_add_checked_fixture (tc_chain, setup, teardown); tcase_add_test (tc_chain, test_share); + tcase_add_test (tc_chain, test_wrapped_context); return s; }