mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
[891/906] context: add support for wrapping external contexts
This commit is contained in:
parent
303b77eeff
commit
97f6bc0bfc
7 changed files with 326 additions and 60 deletions
|
@ -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 guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window);
|
||||||
static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate);
|
static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate);
|
||||||
static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context);
|
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) \
|
#define GST_GL_CONTEXT_COCOA_GET_PRIVATE(o) \
|
||||||
(G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoaPrivate))
|
(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->activate = GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_activate);
|
||||||
context_class->get_gl_api =
|
context_class->get_gl_api =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_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
|
#ifndef GNUSTEP
|
||||||
pool = [[NSAutoreleasePool alloc] init];
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
@ -255,3 +258,9 @@ gst_gl_context_cocoa_get_gl_api (GstGLContext * context)
|
||||||
{
|
{
|
||||||
return GST_GL_API_OPENGL;
|
return GST_GL_API_OPENGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstGLPlatform
|
||||||
|
gst_gl_context_cocoa_get_gl_platform (GstGLContext * context)
|
||||||
|
{
|
||||||
|
return GST_GL_API_COCOA;
|
||||||
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ static gboolean gst_gl_context_egl_activate (GstGLContext * context,
|
||||||
static void gst_gl_context_egl_swap_buffers (GstGLContext * context);
|
static void gst_gl_context_egl_swap_buffers (GstGLContext * context);
|
||||||
static guintptr gst_gl_context_egl_get_gl_context (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 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,
|
static gpointer gst_gl_context_egl_get_proc_address (GstGLContext * context,
|
||||||
const gchar * name);
|
const gchar * name);
|
||||||
|
|
||||||
|
@ -71,6 +73,8 @@ gst_gl_context_egl_class_init (GstGLContextEGLClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_egl_swap_buffers);
|
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_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 =
|
context_class->get_proc_address =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_egl_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;
|
const gchar *egl_exts;
|
||||||
gboolean need_surface = TRUE;
|
gboolean need_surface = TRUE;
|
||||||
guintptr external_gl_context = 0;
|
guintptr external_gl_context = 0;
|
||||||
|
guintptr native_display;
|
||||||
|
GstGLDisplay *display;
|
||||||
|
|
||||||
egl = GST_GL_CONTEXT_EGL (context);
|
egl = GST_GL_CONTEXT_EGL (context);
|
||||||
window = gst_gl_context_get_window (context);
|
window = gst_gl_context_get_window (context);
|
||||||
|
|
||||||
if (other_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,
|
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
||||||
GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
|
GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
|
||||||
"Cannot share context with non-EGL context");
|
"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;
|
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
|
static gpointer
|
||||||
gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name)
|
gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -95,6 +95,31 @@ struct _GstGLContextPrivate
|
||||||
GError **error;
|
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
|
GQuark
|
||||||
gst_gl_context_error_quark (void)
|
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;
|
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:
|
* gst_gl_context_new:
|
||||||
* @display: a #GstGLDisplay
|
* @display: a #GstGLDisplay
|
||||||
|
@ -155,13 +192,8 @@ gst_gl_context_new (GstGLDisplay * display)
|
||||||
{
|
{
|
||||||
GstGLContext *context = NULL;
|
GstGLContext *context = NULL;
|
||||||
const gchar *user_choice;
|
const gchar *user_choice;
|
||||||
static volatile gsize _init = 0;
|
|
||||||
|
|
||||||
if (g_once_init_enter (&_init)) {
|
_init_debug ();
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_gl_context_debug, "glcontext", 0,
|
|
||||||
"glcontext element");
|
|
||||||
g_once_init_leave (&_init, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
user_choice = g_getenv ("GST_GL_PLATFORM");
|
user_choice = g_getenv ("GST_GL_PLATFORM");
|
||||||
GST_INFO ("creating a context, user choice:%s", user_choice);
|
GST_INFO ("creating a context, user choice:%s", user_choice);
|
||||||
|
@ -196,35 +228,77 @@ gst_gl_context_new (GstGLDisplay * display)
|
||||||
return context;
|
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
|
static void
|
||||||
gst_gl_context_finalize (GObject * object)
|
gst_gl_context_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
GstGLContext *context = GST_GL_CONTEXT (object);
|
GstGLContext *context = GST_GL_CONTEXT (object);
|
||||||
|
|
||||||
gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL);
|
if (context->window) {
|
||||||
gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL);
|
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) {
|
if (context->priv->alive) {
|
||||||
g_mutex_lock (&context->priv->render_lock);
|
g_mutex_lock (&context->priv->render_lock);
|
||||||
GST_INFO ("send quit gl window loop");
|
GST_INFO ("send quit gl window loop");
|
||||||
gst_gl_window_quit (context->window);
|
gst_gl_window_quit (context->window);
|
||||||
while (context->priv->alive) {
|
while (context->priv->alive) {
|
||||||
g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock);
|
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);
|
gst_object_unref (context->priv->display);
|
||||||
|
|
||||||
if (context->gl_vtable) {
|
if (context->gl_vtable) {
|
||||||
|
@ -310,6 +384,7 @@ gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name)
|
||||||
GstGLContextClass *context_class;
|
GstGLContextClass *context_class;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
|
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);
|
context_class = GST_GL_CONTEXT_GET_CLASS (context);
|
||||||
g_return_val_if_fail (context_class->get_proc_address != NULL, NULL);
|
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
|
gboolean
|
||||||
gst_gl_context_set_window (GstGLContext * context, GstGLWindow * window)
|
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 */
|
/* we can't change the window while we are running */
|
||||||
if (context->priv->alive)
|
if (context->priv->alive)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -413,6 +490,9 @@ gst_gl_context_get_window (GstGLContext * context)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
|
g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
|
||||||
|
|
||||||
|
if (GST_GL_IS_WRAPPED_CONTEXT (context))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
_ensure_window (context);
|
_ensure_window (context);
|
||||||
|
|
||||||
return gst_object_ref (context->window);
|
return gst_object_ref (context->window);
|
||||||
|
@ -442,7 +522,7 @@ gst_gl_context_create (GstGLContext * context,
|
||||||
gboolean alive = FALSE;
|
gboolean alive = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_GL_IS_CONTEXT (context), 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);
|
_ensure_window (context);
|
||||||
|
|
||||||
g_mutex_lock (&context->priv->render_lock);
|
g_mutex_lock (&context->priv->render_lock);
|
||||||
|
@ -497,9 +577,6 @@ _create_context_gles2 (GstGLContext * context, gint * gl_major, gint * gl_minor,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_gst_gl_feature_check_ext_functions (context, 0, 0,
|
|
||||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
|
||||||
|
|
||||||
if (gl_major)
|
if (gl_major)
|
||||||
*gl_major = 2;
|
*gl_major = 2;
|
||||||
if (gl_minor)
|
if (gl_minor)
|
||||||
|
@ -546,9 +623,6 @@ _create_context_opengl (GstGLContext * context, gint * gl_major,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_gst_gl_feature_check_ext_functions (context, maj, min,
|
|
||||||
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
|
||||||
|
|
||||||
if (gl_major)
|
if (gl_major)
|
||||||
*gl_major = maj;
|
*gl_major = maj;
|
||||||
if (gl_minor)
|
if (gl_minor)
|
||||||
|
@ -587,7 +661,7 @@ gst_gl_context_create_thread (GstGLContext * context)
|
||||||
GstGLWindowClass *window_class;
|
GstGLWindowClass *window_class;
|
||||||
GstGLDisplay *display;
|
GstGLDisplay *display;
|
||||||
GstGLFuncs *gl;
|
GstGLFuncs *gl;
|
||||||
gint gl_major = 0;
|
gint gl_major = 0, gl_minor = 0;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
GstGLAPI compiled_api, user_api;
|
GstGLAPI compiled_api, user_api;
|
||||||
gchar *api_string;
|
gchar *api_string;
|
||||||
|
@ -692,13 +766,16 @@ gst_gl_context_create_thread (GstGLContext * context)
|
||||||
|
|
||||||
/* gl api specific code */
|
/* gl api specific code */
|
||||||
if (!ret && USING_OPENGL (display))
|
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))
|
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)
|
if (!ret)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
|
_gst_gl_feature_check_ext_functions (context, gl_major, gl_minor,
|
||||||
|
(const gchar *) gl->GetString (GL_EXTENSIONS));
|
||||||
|
|
||||||
context->priv->alive = TRUE;
|
context->priv->alive = TRUE;
|
||||||
|
|
||||||
g_cond_signal (&context->priv->create_cond);
|
g_cond_signal (&context->priv->create_cond);
|
||||||
|
@ -763,6 +840,26 @@ gst_gl_context_get_gl_context (GstGLContext * context)
|
||||||
return result;
|
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:
|
* gst_gl_context_get_display:
|
||||||
* @context: a #GstGLContext:
|
* @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 (GST_GL_IS_CONTEXT (context));
|
||||||
g_return_if_fail (func != NULL);
|
g_return_if_fail (func != NULL);
|
||||||
|
g_return_if_fail (!GST_GL_IS_WRAPPED_CONTEXT (context));
|
||||||
|
|
||||||
rdata.context = context;
|
rdata.context = context;
|
||||||
rdata.data = data;
|
rdata.data = data;
|
||||||
|
@ -823,3 +921,65 @@ gst_gl_context_thread_add (GstGLContext * context,
|
||||||
|
|
||||||
gst_object_unref (window);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -47,6 +47,10 @@ GQuark gst_gl_context_error_quark (void);
|
||||||
*/
|
*/
|
||||||
typedef void (*GstGLContextThreadFunc) (GstGLContext * context, gpointer data);
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
GST_GL_CONTEXT_ERROR_FAILED,
|
GST_GL_CONTEXT_ERROR_FAILED,
|
||||||
|
@ -89,15 +93,16 @@ struct _GstGLContext {
|
||||||
struct _GstGLContextClass {
|
struct _GstGLContextClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
guintptr (*get_gl_context) (GstGLContext *context);
|
guintptr (*get_gl_context) (GstGLContext *context);
|
||||||
GstGLAPI (*get_gl_api) (GstGLContext *context);
|
GstGLAPI (*get_gl_api) (GstGLContext *context);
|
||||||
gpointer (*get_proc_address) (GstGLContext *context, const gchar *name);
|
GstGLPlatform (*get_gl_platform) (GstGLContext *context);
|
||||||
gboolean (*activate) (GstGLContext *context, gboolean activate);
|
gpointer (*get_proc_address) (GstGLContext *context, const gchar *name);
|
||||||
gboolean (*choose_format) (GstGLContext *context, GError **error);
|
gboolean (*activate) (GstGLContext *context, gboolean activate);
|
||||||
gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api,
|
gboolean (*choose_format) (GstGLContext *context, GError **error);
|
||||||
GstGLContext *other_context, GError ** error);
|
gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api,
|
||||||
void (*destroy_context) (GstGLContext *context);
|
GstGLContext *other_context, GError ** error);
|
||||||
void (*swap_buffers) (GstGLContext *context);
|
void (*destroy_context) (GstGLContext *context);
|
||||||
|
void (*swap_buffers) (GstGLContext *context);
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _reserved[GST_PADDING];
|
gpointer _reserved[GST_PADDING];
|
||||||
|
@ -106,12 +111,16 @@ struct _GstGLContextClass {
|
||||||
/* methods */
|
/* methods */
|
||||||
|
|
||||||
GstGLContext * gst_gl_context_new (GstGLDisplay *display);
|
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);
|
gboolean gst_gl_context_activate (GstGLContext *context, gboolean activate);
|
||||||
|
|
||||||
GstGLDisplay * gst_gl_context_get_display (GstGLContext *context);
|
GstGLDisplay * gst_gl_context_get_display (GstGLContext *context);
|
||||||
gpointer gst_gl_context_get_proc_address (GstGLContext *context, const gchar *name);
|
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);
|
GstGLAPI gst_gl_context_get_gl_api (GstGLContext *context);
|
||||||
guintptr gst_gl_context_get_gl_context (GstGLContext *context);
|
guintptr gst_gl_context_get_gl_context (GstGLContext *context);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ static gboolean gst_gl_context_wgl_create_context (GstGLContext * context,
|
||||||
GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
|
GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
|
||||||
static void gst_gl_context_wgl_destroy_context (GstGLContext * context);
|
static void gst_gl_context_wgl_destroy_context (GstGLContext * context);
|
||||||
GstGLAPI gst_gl_context_wgl_get_gl_api (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,
|
static gpointer gst_gl_context_wgl_get_proc_address (GstGLContext * context,
|
||||||
const gchar * name);
|
const gchar * name);
|
||||||
|
|
||||||
|
@ -66,6 +68,8 @@ gst_gl_context_wgl_class_init (GstGLContextWGLClass * klass)
|
||||||
context_class->get_proc_address =
|
context_class->get_proc_address =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_wgl_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_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
|
static void
|
||||||
|
@ -88,7 +92,7 @@ gst_gl_context_wgl_create_context (GstGLContext * context,
|
||||||
{
|
{
|
||||||
GstGLWindow *window;
|
GstGLWindow *window;
|
||||||
GstGLContextWGL *context_wgl;
|
GstGLContextWGL *context_wgl;
|
||||||
GstGLContextWGL *other_wgl = NULL;
|
HGLRC external_gl_context = NULL;
|
||||||
HDC device;
|
HDC device;
|
||||||
|
|
||||||
context_wgl = GST_GL_CONTEXT_WGL (context);
|
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");
|
"Cannot share context with a non-WGL context");
|
||||||
goto failure;
|
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);
|
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,
|
GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT,
|
||||||
(guintptr) context_wgl->wgl_context);
|
(guintptr) context_wgl->wgl_context);
|
||||||
|
|
||||||
if (other_wgl) {
|
if (external_gl_context) {
|
||||||
if (!wglShareLists (other_wgl->wgl_context, context_wgl->wgl_context)) {
|
if (!wglShareLists (external_gl_context, context_wgl->wgl_context)) {
|
||||||
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
||||||
GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to share contexts 0x%x",
|
GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "failed to share contexts 0x%x",
|
||||||
(unsigned int) GetLastError ());
|
(unsigned int) GetLastError ());
|
||||||
|
@ -253,6 +257,12 @@ gst_gl_context_wgl_get_gl_api (GstGLContext * context)
|
||||||
return GST_GL_API_OPENGL;
|
return GST_GL_API_OPENGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstGLPlatform
|
||||||
|
gst_gl_context_wgl_get_gl_platform (GstGLContext * context)
|
||||||
|
{
|
||||||
|
return GST_GL_PLATFORM_WGL;
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name)
|
gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,8 @@ static void gst_gl_context_glx_destroy_context (GstGLContext * context);
|
||||||
static gboolean gst_gl_context_glx_choose_format (GstGLContext *
|
static gboolean gst_gl_context_glx_choose_format (GstGLContext *
|
||||||
context, GError ** error);
|
context, GError ** error);
|
||||||
GstGLAPI gst_gl_context_glx_get_gl_api (GstGLContext * context);
|
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,
|
static gpointer gst_gl_context_glx_get_proc_address (GstGLContext * context,
|
||||||
const gchar * name);
|
const gchar * name);
|
||||||
|
|
||||||
|
@ -90,6 +92,8 @@ gst_gl_context_glx_class_init (GstGLContextGLXClass * klass)
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_glx_swap_buffers);
|
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_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 =
|
context_class->get_proc_address =
|
||||||
GST_DEBUG_FUNCPTR (gst_gl_context_glx_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);
|
window_x11 = GST_GL_WINDOW_X11 (window);
|
||||||
|
|
||||||
if (other_context) {
|
if (other_context) {
|
||||||
GstGLWindow *other_window;
|
if (gst_gl_context_get_gl_platform (other_context) != GST_GL_PLATFORM_GLX) {
|
||||||
|
|
||||||
if (!GST_GL_IS_CONTEXT_GLX (other_context)) {
|
|
||||||
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
g_set_error (error, GST_GL_CONTEXT_ERROR,
|
||||||
GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
|
GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
|
||||||
"Cannot share context with non-GLX context");
|
"Cannot share context with non-GLX context");
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
other_window = gst_gl_context_get_window (other_context);
|
|
||||||
external_gl_context = gst_gl_context_get_gl_context (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));
|
glx_exts = glXQueryExtensionsString (device, DefaultScreen (device));
|
||||||
|
|
||||||
create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts);
|
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;
|
return context_glx->priv->context_api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstGLPlatform
|
||||||
|
gst_gl_context_glx_get_gl_platform (GstGLContext * context)
|
||||||
|
{
|
||||||
|
return GST_GL_PLATFORM_GLX;
|
||||||
|
}
|
||||||
|
|
||||||
static gpointer
|
static gpointer
|
||||||
gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name)
|
gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -117,7 +117,8 @@ deinit (gpointer data)
|
||||||
gl->DeleteTextures (1, &tex);;
|
gl->DeleteTextures (1, &tex);;
|
||||||
gst_object_unref (fbo);
|
gst_object_unref (fbo);
|
||||||
#if GST_GL_HAVE_GLES2
|
#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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,6 +282,66 @@ GST_START_TEST (test_share)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
Suite *
|
||||||
gst_gl_memory_suite (void)
|
gst_gl_memory_suite (void)
|
||||||
|
@ -291,6 +352,7 @@ gst_gl_memory_suite (void)
|
||||||
suite_add_tcase (s, tc_chain);
|
suite_add_tcase (s, tc_chain);
|
||||||
tcase_add_checked_fixture (tc_chain, setup, teardown);
|
tcase_add_checked_fixture (tc_chain, setup, teardown);
|
||||||
tcase_add_test (tc_chain, test_share);
|
tcase_add_test (tc_chain, test_share);
|
||||||
|
tcase_add_test (tc_chain, test_wrapped_context);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue