summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Waters <ystreet00@gmail.com>2014-02-11 08:57:29 +1100
committerMatthew Waters <ystreet00@gmail.com>2014-02-23 11:34:35 +1100
commit83fb4064238fc1ba5f90a390792910d52f2b0424 (patch)
tree9c8a9e4138d6517044ead4cf3f23650e0b0f93a8
parent9d74e9267e5643777f91aba34bbb58b45c84b5b8 (diff)
context: add support for wrapping external contexts
-rw-r--r--gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m9
-rw-r--r--gst-libs/gst/gl/egl/gstglcontext_egl.c14
-rw-r--r--gst-libs/gst/gl/gstglcontext.c230
-rw-r--r--gst-libs/gst/gl/gstglcontext.h29
-rw-r--r--gst-libs/gst/gl/win32/gstglcontext_wgl.c18
-rw-r--r--gst-libs/gst/gl/x11/gstglcontext_glx.c20
-rw-r--r--tests/check/libs/gstglcontext.c64
7 files changed, 325 insertions, 59 deletions
diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
index c5ae84f..486763e 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 9aafd74..b181984 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 c385682..d190502 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->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->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);
+ }
+ 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);
+ 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;
+ }
- 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->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);
@@ -764,6 +841,26 @@ gst_gl_context_get_gl_context (GstGLContext * context)
}
/**
+ * 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 c4ee0bd..55db6cc 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 2dba16d..bc3ea26 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 2be004c..aeff736 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 2139b4b..3425e03 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;
}