mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
[801/906] context: Reimplement GL context sharing
https://bugzilla.gnome.org/show_bug.cgi?id=704806
This commit is contained in:
parent
40a2c12495
commit
48cd6ac353
6 changed files with 131 additions and 49 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
Loading…
Reference in a new issue