[801/906] context: Reimplement GL context sharing

https://bugzilla.gnome.org/show_bug.cgi?id=704806
This commit is contained in:
Matthew Waters 2013-08-29 20:10:42 +10:00
parent 2d876dfb70
commit b24021b1ac
6 changed files with 131 additions and 49 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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));