summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Waters <ystreet00@gmail.com>2013-08-29 20:10:42 +1000
committerSebastian Dröge <slomo@circular-chaos.org>2013-08-29 14:36:18 +0200
commit57e497f9e24048f5c3dd4c966d92a680bbccc91d (patch)
treed101edae15ea0d0009673fa4609cc8ca9d9ea2b6
parentdde32ba74fe7aa360c39bd836d9f55ce236ae5e9 (diff)
context: Reimplement GL context sharing
https://bugzilla.gnome.org/show_bug.cgi?id=704806
-rw-r--r--gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m11
-rw-r--r--gst-libs/gst/gl/egl/gstglcontext_egl.c96
-rw-r--r--gst-libs/gst/gl/gstglcontext.c14
-rw-r--r--gst-libs/gst/gl/gstglcontext.h7
-rw-r--r--gst-libs/gst/gl/win32/gstglcontext_wgl.c25
-rw-r--r--gst-libs/gst/gl/x11/gstglcontext_glx.c27
6 files changed, 131 insertions, 49 deletions
diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
index 510b09e..e808f37 100644
--- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
+++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
@@ -28,7 +28,7 @@
#include "gstgl_cocoa_private.h"
static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
- guintptr external_opengl_context, GError **error);
+ GstGLContext * other_context, GError **error);
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);
@@ -84,7 +84,7 @@ gst_gl_context_cocoa_new (void)
static gboolean
gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
- guintptr external_gl_context, GError **error)
+ GstGLContext *other_context, GError **error)
{
GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context);
GstGLContextCocoaPrivate *priv = context_cocoa->priv;
@@ -103,7 +103,10 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
};
priv->gl_context = nil;
- priv->external_gl_context = (NSOpenGLContext *) external_gl_context;
+ if (other_context)
+ priv->external_gl_context = (NSOpenGLContext *) gst_gl_context_get_gl_context (other_context);
+ else
+ priv->external_gl_context = NULL;
GSRegisterCurrentThread();
@@ -146,7 +149,9 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
context_cocoa->priv->gl_context = glContext;
[glView setOpenGLContext:glContext];
+
#else
+ /* FIXME try to make context sharing work in GNUstep */
context_cocoa->priv->gl_context = [glView openGLContext];
#endif
diff --git a/gst-libs/gst/gl/egl/gstglcontext_egl.c b/gst-libs/gst/gl/egl/gstglcontext_egl.c
index 3ef5075..6864dd0 100644
--- a/gst-libs/gst/gl/egl/gstglcontext_egl.c
+++ b/gst-libs/gst/gl/egl/gstglcontext_egl.c
@@ -22,6 +22,10 @@
#include "config.h"
#endif
+/* FIXME: Sharing contexts requires the EGLDisplay & EGLConfig to be the same
+ * may need to box it.
+ */
+
#include "gstglcontext_egl.h"
#include <gst/gl/gl.h>
@@ -33,7 +37,7 @@
#endif
static gboolean gst_gl_context_egl_create_context (GstGLContext * context,
- GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
+ GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
static void gst_gl_context_egl_destroy_context (GstGLContext * context);
static gboolean gst_gl_context_egl_choose_format (GstGLContext * context,
GError ** error);
@@ -150,27 +154,40 @@ gst_gl_context_egl_choose_format (GstGLContext * context, GError ** error)
}
static gboolean
-gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GError ** error)
+gst_gl_context_egl_choose_config (GstGLContextEGL * egl,
+ GstGLContext * other_context, GError ** error)
{
EGLint numConfigs;
gint i = 0;
EGLint config_attrib[20];
- config_attrib[i++] = EGL_SURFACE_TYPE;
- config_attrib[i++] = EGL_WINDOW_BIT;
- config_attrib[i++] = EGL_RENDERABLE_TYPE;
- if (egl->gl_api & GST_GL_API_GLES2)
- config_attrib[i++] = EGL_OPENGL_ES2_BIT;
- else
- config_attrib[i++] = EGL_OPENGL_BIT;
- config_attrib[i++] = EGL_DEPTH_SIZE;
- config_attrib[i++] = 16;
- config_attrib[i++] = EGL_NONE;
+ if (other_context) {
+ GstGLContextEGL *other_context_egl = GST_GL_CONTEXT_EGL (other_context);
+ EGLint config_id;
+
+ eglGetConfigAttrib (egl->egl_display, other_context_egl->egl_config,
+ EGL_CONFIG_ID, &config_id);
+
+ config_attrib[i++] = EGL_CONFIG_ID;
+ config_attrib[i++] = config_id;
+ config_attrib[i++] = EGL_NONE;
+ } else {
+ config_attrib[i++] = EGL_SURFACE_TYPE;
+ config_attrib[i++] = EGL_WINDOW_BIT;
+ config_attrib[i++] = EGL_RENDERABLE_TYPE;
+ if (egl->gl_api & GST_GL_API_GLES2)
+ config_attrib[i++] = EGL_OPENGL_ES2_BIT;
+ else
+ config_attrib[i++] = EGL_OPENGL_BIT;
+ config_attrib[i++] = EGL_DEPTH_SIZE;
+ config_attrib[i++] = 16;
+ config_attrib[i++] = EGL_NONE;
+ }
if (eglChooseConfig (egl->egl_display, config_attrib,
&egl->egl_config, 1, &numConfigs)) {
- GST_INFO ("config set: %ld, %ld", (gulong) egl->egl_config,
- (gulong) numConfigs);
+ GST_INFO ("config set: %" G_GUINTPTR_FORMAT ", %u",
+ (guintptr) egl->egl_config, (unsigned int) numConfigs);
} else {
g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
"Failed to set window configuration: %s",
@@ -186,7 +203,7 @@ failure:
static gboolean
gst_gl_context_egl_create_context (GstGLContext * context,
- GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
+ GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
GstGLContextEGL *egl;
GstGLWindow *window = NULL;
@@ -197,19 +214,33 @@ gst_gl_context_egl_create_context (GstGLContext * context,
EGLint minorVersion;
const gchar *egl_exts;
gboolean need_surface = TRUE;
+ guintptr external_gl_context = 0;
egl = GST_GL_CONTEXT_EGL (context);
window = gst_gl_context_get_window (context);
- if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE &&
- (gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) {
+ if (other_context) {
+ if (!GST_GL_IS_CONTEXT_EGL (other_context)) {
+ g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
+ "Cannot share context with non-EGL context");
+ goto failure;
+ }
+ external_gl_context = gst_gl_context_get_gl_context (other_context);
+ }
+
+ if ((gl_api & (GST_GL_API_OPENGL | GST_GL_API_GLES2)) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
- "xEGL supports opengl or gles2");
+ "EGL supports opengl or gles2");
goto failure;
}
- egl->egl_display =
- eglGetDisplay ((EGLNativeDisplayType) gst_gl_window_get_display (window));
+ if (other_context) {
+ GstGLContextEGL *other_egl = (GstGLContextEGL *) other_context;
+ egl->egl_display = other_egl->egl_display;
+ } else {
+ egl->egl_display = eglGetDisplay ((EGLNativeDisplayType)
+ gst_gl_window_get_display (window));
+ }
if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) {
GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion);
@@ -245,11 +276,12 @@ gst_gl_context_egl_create_context (GstGLContext * context,
if (!eglBindAPI (EGL_OPENGL_API)) {
g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
- "Failed to bind OpenGL|ES API: %s",
+ "Failed to bind OpenGL API: %s",
gst_gl_context_egl_get_error_string ());
goto failure;
}
+ GST_INFO ("Using OpenGL");
egl->gl_api = GST_GL_API_OPENGL;
} else if (gl_api & GST_GL_API_GLES2) {
try_gles2:
@@ -260,10 +292,11 @@ gst_gl_context_egl_create_context (GstGLContext * context,
goto failure;
}
+ GST_INFO ("Using OpenGL|ES 2.0");
egl->gl_api = GST_GL_API_GLES2;
}
- if (!gst_gl_context_egl_choose_config (egl, error)) {
+ if (!gst_gl_context_egl_choose_config (egl, other_context, error)) {
g_assert (error == NULL || *error != NULL);
goto failure;
}
@@ -281,7 +314,8 @@ gst_gl_context_egl_create_context (GstGLContext * context,
(EGLContext) external_gl_context, context_attrib);
if (egl->egl_context != EGL_NO_CONTEXT) {
- GST_INFO ("gl context created: %ld", (gulong) egl->egl_context);
+ GST_INFO ("gl context created: %" G_GUINTPTR_FORMAT,
+ (guintptr) egl->egl_context);
} else {
g_set_error (error, GST_GL_CONTEXT_ERROR,
GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
@@ -292,17 +326,19 @@ gst_gl_context_egl_create_context (GstGLContext * context,
egl_exts = eglQueryString (egl->egl_display, EGL_EXTENSIONS);
- /* FIXME do we want a window vfunc ? */
+ if (other_context == NULL) {
+ /* FIXME do we want a window vfunc ? */
#if GST_GL_HAVE_WINDOW_X11
- if (GST_GL_IS_WINDOW_X11 (context->window)) {
- gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
- }
+ if (GST_GL_IS_WINDOW_X11 (context->window)) {
+ gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window);
+ }
#endif
#if GST_GL_HAVE_WINDOW_WIN32
- if (GST_GL_IS_WINDOW_WIN32 (context->window)) {
- gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window);
- }
+ if (GST_GL_IS_WINDOW_WIN32 (context->window)) {
+ gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window);
+ }
#endif
+ }
window_handle = gst_gl_window_get_window_handle (window);
diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c
index c2d20a7..f459de7 100644
--- a/gst-libs/gst/gl/gstglcontext.c
+++ b/gst-libs/gst/gl/gstglcontext.c
@@ -72,7 +72,7 @@ struct _GstGLContextPrivate
gboolean created;
gboolean alive;
- guintptr external_gl_context;
+ GstGLContext *other_context;
GstGLAPI gl_api;
GError **error;
};
@@ -299,7 +299,7 @@ gst_gl_context_get_window (GstGLContext * context)
/* Create an opengl context (one context for one GstGLDisplay) */
gboolean
gst_gl_context_create (GstGLContext * context,
- guintptr external_gl_context, GError ** error)
+ GstGLContext * other_context, GError ** error)
{
gboolean alive = FALSE;
@@ -310,7 +310,7 @@ gst_gl_context_create (GstGLContext * context,
g_mutex_lock (&context->priv->render_lock);
if (!context->priv->created) {
- context->priv->external_gl_context = external_gl_context;
+ context->priv->other_context = other_context;
context->priv->error = error;
context->priv->gl_thread = g_thread_new ("gstglcontext",
@@ -476,7 +476,7 @@ _parse_gl_api (const gchar * apis_s)
}
//gboolean
-//gst_gl_context_create (GstGLContext * context, guintptr external_gl_context, GError ** error)
+//gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
static gpointer
gst_gl_context_create_thread (GstGLContext * context)
{
@@ -492,12 +492,12 @@ gst_gl_context_create_thread (GstGLContext * context)
gchar *user_api_string;
const gchar *user_choice;
GError **error;
- guintptr external_gl_context;
+ GstGLContext *other_context;
g_mutex_lock (&context->priv->render_lock);
error = context->priv->error;
- external_gl_context = context->priv->external_gl_context;
+ other_context = context->priv->other_context;
context_class = GST_GL_CONTEXT_GET_CLASS (context);
window_class = GST_GL_WINDOW_GET_CLASS (context->window);
@@ -539,7 +539,7 @@ gst_gl_context_create_thread (GstGLContext * context)
"compiled api support (%s)", user_api_string, compiled_api_s);
if (!context_class->create_context (context, compiled_api & user_api,
- external_gl_context, error)) {
+ other_context, error)) {
g_assert (error == NULL || *error != NULL);
g_free (compiled_api_s);
g_free (user_api_string);
diff --git a/gst-libs/gst/gl/gstglcontext.h b/gst-libs/gst/gl/gstglcontext.h
index 68d6f05..21db7e8 100644
--- a/gst-libs/gst/gl/gstglcontext.h
+++ b/gst-libs/gst/gl/gstglcontext.h
@@ -23,7 +23,7 @@
#include <gst/gst.h>
-#include <gst/gl/gstgl_fwd.h>
+#include <gst/gl/gl.h>
G_BEGIN_DECLS
@@ -71,7 +71,7 @@ struct _GstGLContextClass {
gboolean (*activate) (GstGLContext *context, gboolean activate);
gboolean (*choose_format) (GstGLContext *context, GError **error);
gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api,
- guintptr external_gl_context, GError ** error);
+ GstGLContext *other_context, GError ** error);
void (*destroy_context) (GstGLContext *context);
void (*swap_buffers) (GstGLContext *context);
@@ -88,8 +88,9 @@ gboolean gst_gl_context_activate (GstGLContext *context, gboolean a
gpointer gst_gl_context_get_proc_address (GstGLContext *context, const gchar *name);
GstGLPlatform gst_gl_context_get_platform (GstGLContext *context);
GstGLAPI gst_gl_context_get_gl_api (GstGLContext *context);
+guintptr gst_gl_context_get_gl_context (GstGLContext *context);
-gboolean gst_gl_context_create (GstGLContext *context, guintptr external_gl_context, GError ** error);
+gboolean gst_gl_context_create (GstGLContext *context, GstGLContext *other_context, GError ** error);
gpointer gst_gl_context_default_get_proc_address (GstGLContext *context, const gchar *name);
diff --git a/gst-libs/gst/gl/win32/gstglcontext_wgl.c b/gst-libs/gst/gl/win32/gstglcontext_wgl.c
index 826ab44..88e35af 100644
--- a/gst-libs/gst/gl/win32/gstglcontext_wgl.c
+++ b/gst-libs/gst/gl/win32/gstglcontext_wgl.c
@@ -40,7 +40,7 @@ static gboolean gst_gl_context_wgl_choose_format (GstGLContext * context,
static gboolean gst_gl_context_wgl_activate (GstGLContext * context,
gboolean activate);
static gboolean gst_gl_context_wgl_create_context (GstGLContext * context,
- GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
+ 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 gpointer gst_gl_context_wgl_get_proc_address (GstGLContext * context,
@@ -84,23 +84,33 @@ gst_gl_context_wgl_new (void)
static gboolean
gst_gl_context_wgl_create_context (GstGLContext * context,
- GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
+ GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
GstGLWindow *window;
GstGLContextWGL *context_wgl;
+ GstGLContextWGL *other_wgl = NULL;
HDC device;
context_wgl = GST_GL_CONTEXT_WGL (context);
window = gst_gl_context_get_window (context);
device = (HDC) gst_gl_window_get_display (window);
+ if (other_context) {
+ if (!GST_GL_IS_CONTEXT_WGL (other_context)) {
+ g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
+ "Cannot share context with a non-WGL context");
+ goto failure;
+ }
+ other_wgl = (GstGLContextWGL *) other_context;
+ }
+
context_wgl->wgl_context = wglCreateContext (device);
if (context_wgl->wgl_context)
GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT,
(guintptr) context_wgl->wgl_context);
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
- "failed to create glcontext:%lu", GetLastError ());
+ "failed to create glcontext:0x%x", (unsigned int) GetLastError ());
goto failure;
}
g_assert (context_wgl->wgl_context);
@@ -108,6 +118,15 @@ 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)) {
+ g_set_error (error, GST_GL_WINDOW_ERROR,
+ GST_GL_WINDOW_ERROR_CREATE_CONTEXT, "failed to share contexts 0x%x",
+ (unsigned int) GetLastError ());
+ goto failure;
+ }
+ }
+
gst_object_unref (window);
return TRUE;
diff --git a/gst-libs/gst/gl/x11/gstglcontext_glx.c b/gst-libs/gst/gl/x11/gstglcontext_glx.c
index 86c9d8a..abfec94 100644
--- a/gst-libs/gst/gl/x11/gstglcontext_glx.c
+++ b/gst-libs/gst/gl/x11/gstglcontext_glx.c
@@ -25,6 +25,10 @@
#include "config.h"
#endif
+/* FIXME: Sharing contexts requires the Display to be the same.
+ * May need to box it
+ */
+
#include <gst/gst.h>
#include "../gstgl_fwd.h"
@@ -46,7 +50,7 @@ static void gst_gl_context_glx_swap_buffers (GstGLContext * context);
static gboolean gst_gl_context_glx_activate (GstGLContext * context,
gboolean activate);
static gboolean gst_gl_context_glx_create_context (GstGLContext *
- context, GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
+ context, GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
static void gst_gl_context_glx_destroy_context (GstGLContext * context);
static gboolean gst_gl_context_glx_choose_format (GstGLContext *
context, GError ** error);
@@ -129,7 +133,7 @@ _describe_fbconfig (Display * display, GLXFBConfig config)
static gboolean
gst_gl_context_glx_create_context (GstGLContext * context,
- GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
+ GstGLAPI gl_api, GstGLContext * other_context, GError ** error)
{
GstGLContextGLX *context_glx;
GstGLWindow *window;
@@ -138,11 +142,28 @@ gst_gl_context_glx_create_context (GstGLContext * context,
const char *glx_exts;
int x_error;
Display *device;
+ guintptr external_gl_context = 0;
context_glx = GST_GL_CONTEXT_GLX (context);
window = gst_gl_context_get_window (context);
window_x11 = GST_GL_WINDOW_X11 (window);
- device = (Display *) gst_gl_window_get_display (window);
+
+ if (other_context) {
+ GstGLWindow *other_window;
+
+ if (!GST_GL_IS_CONTEXT_GLX (other_context)) {
+ g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_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);
+ }
glx_exts = glXQueryExtensionsString (device, DefaultScreen (device));