From dbeb6a911bddfdd5f7833e9ada8bb39a9d9a7913 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Wed, 12 Jun 2013 23:17:30 +1000 Subject: [PATCH] [701/906] display: move context creation into window --- gst-libs/gst/gl/gstgldisplay.c | 419 ++++++----------------------------- gst-libs/gst/gl/gstgldisplay.h | 16 +- gst-libs/gst/gl/gstgldownload.c | 10 +- gst-libs/gst/gl/gstglfeature.c | 14 +- gst-libs/gst/gl/gstglfilter.c | 14 +- gst-libs/gst/gl/gstglmemory.c | 1 + gst-libs/gst/gl/gstglmixer.c | 11 +- gst-libs/gst/gl/gstglupload.c | 10 +- gst-libs/gst/gl/gstglutils.c | 94 +++++--- gst-libs/gst/gl/gstglutils.h | 2 + gst-libs/gst/gl/gstglwindow.c | 396 ++++++++++++++++++++++++++++++++- gst-libs/gst/gl/gstglwindow.h | 12 +- gst/gl/effects/gstgleffectidentity.c | 10 +- gst/gl/effects/gstgleffectmirror.c | 10 +- gst/gl/effects/gstgleffectsqueeze.c | 10 +- gst/gl/gltestsrc.c | 6 +- gst/gl/gstglbumper.c | 2 +- gst/gl/gstgleffects.c | 4 +- gst/gl/gstglfiltercube.c | 3 +- gst/gl/gstglimagesink.c | 86 ++++--- gst/gl/gstglimagesink.h | 1 + gst/gl/gstgloverlay.c | 5 +- gst/gl/gstgltestsrc.c | 11 +- 23 files changed, 671 insertions(+), 476 deletions(-) diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 6566b75..ef406ff 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -62,9 +62,7 @@ void gst_gl_display_thread_run_generic (GstGLDisplay * display); struct _GstGLDisplayPrivate { - /* conditions */ - GCond cond_create_context; - GCond cond_destroy_context; + GstGLWindow *window; /* generic gl code */ GstGLDisplayThreadFunc generic_callback; @@ -91,13 +89,8 @@ gst_gl_display_init (GstGLDisplay * display) /* thread safe */ g_mutex_init (&display->mutex); - g_cond_init (&display->priv->cond_create_context); - g_cond_init (&display->priv->cond_destroy_context); - display->gl_vtable = g_slice_alloc0 (sizeof (GstGLFuncs)); - display->gl_window = gst_gl_window_new (); - gst_gl_memory_init (); } @@ -106,39 +99,8 @@ gst_gl_display_finalize (GObject * object) { GstGLDisplay *display = GST_GL_DISPLAY (object); - if (display->gl_window) { - gst_gl_display_lock (display); - - gst_gl_window_set_resize_callback (display->gl_window, NULL, NULL); - gst_gl_window_set_draw_callback (display->gl_window, NULL, NULL); - gst_gl_window_set_close_callback (display->gl_window, NULL, NULL); - - if (display->context_created) { - GST_INFO ("send quit gl window loop"); - gst_gl_window_quit (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_destroy_context), display); - - GST_INFO ("quit sent to gl window loop"); - - g_cond_wait (&display->priv->cond_destroy_context, &display->mutex); - GST_INFO ("quit received from gl window"); - } - gst_gl_display_unlock (display); - } - - if (display->gl_thread) { - gpointer ret = g_thread_join (display->gl_thread); - GST_INFO ("gl thread joined"); - if (ret != NULL) - GST_ERROR ("gl thread returned a not null pointer"); - display->gl_thread = NULL; - } - g_mutex_clear (&display->mutex); - g_cond_clear (&display->priv->cond_destroy_context); - g_cond_clear (&display->priv->cond_create_context); - if (display->error_message) { g_free (display->error_message); display->error_message = NULL; @@ -148,271 +110,13 @@ gst_gl_display_finalize (GObject * object) g_slice_free (GstGLFuncs, display->gl_vtable); display->gl_vtable = NULL; } -} - -static gboolean -_create_context_gles2 (GstGLDisplay * display, gint * gl_major, gint * gl_minor) -{ - const GstGLFuncs *gl; - GLenum gl_err = GL_NO_ERROR; - - gl = display->gl_vtable; - - GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION)); - GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", - gl->GetString (GL_SHADING_LANGUAGE_VERSION)); - GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR)); - GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER)); - - gl_err = gl->GetError (); - if (gl_err != GL_NO_ERROR) { - gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err); - return FALSE; - } -#if GST_GL_HAVE_GLES2 - if (!GL_ES_VERSION_2_0) { - gst_gl_display_set_error (display, "OpenGL|ES >= 2.0 is required"); - return FALSE; - } -#endif - - _gst_gl_feature_check_ext_functions (display, 0, 0, - (const gchar *) gl->GetString (GL_EXTENSIONS)); - - if (gl_major) - *gl_major = 2; - if (gl_minor) - *gl_minor = 0; - - return TRUE; -} - -gboolean -_create_context_opengl (GstGLDisplay * display, gint * gl_major, - gint * gl_minor) -{ - const GstGLFuncs *gl; - guint maj, min; - GLenum gl_err = GL_NO_ERROR; - GString *opengl_version = NULL; - - gl = display->gl_vtable; - - GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION)); - GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", - gl->GetString (GL_SHADING_LANGUAGE_VERSION)); - GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR)); - GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER)); - - gl_err = gl->GetError (); - if (gl_err != GL_NO_ERROR) { - gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err); - return FALSE; - } - opengl_version = - g_string_truncate (g_string_new ((gchar *) gl->GetString (GL_VERSION)), - 3); - - sscanf (opengl_version->str, "%d.%d", &maj, &min); - - g_string_free (opengl_version, TRUE); - - /* OpenGL > 1.2.0 */ - if ((maj < 1) || (maj < 2 && maj >= 1 && min < 2)) { - gst_gl_display_set_error (display, "OpenGL >= 1.2.0 required, found %u.%u", - maj, min); - return FALSE; - } - - _gst_gl_feature_check_ext_functions (display, maj, min, - (const gchar *) gl->GetString (GL_EXTENSIONS)); - - if (gl_major) - *gl_major = maj; - if (gl_minor) - *gl_minor = min; - - return TRUE; -} - -GstGLAPI -_compiled_api (void) -{ - GstGLAPI ret = GST_GL_API_NONE; - -#if GST_GL_HAVE_OPENGL - ret |= GST_GL_API_OPENGL; -#endif -#if GST_GL_HAVE_GLES2 - ret |= GST_GL_API_GLES2; -#endif - - return ret; -} - -GstGLAPI -_parse_gl_api (const gchar * apis_s) -{ - GstGLAPI ret = GST_GL_API_NONE; - gchar *apis = (gchar *) apis_s; - - while (apis) { - if (apis[0] == '\0') { - break; - } else if (apis[0] == ' ' || apis[0] == ',') { - apis = &apis[1]; - } else if (g_strstr_len (apis, 7, "opengl3")) { - ret |= GST_GL_API_OPENGL3; - apis = &apis[7]; - } else if (g_strstr_len (apis, 6, "opengl")) { - ret |= GST_GL_API_OPENGL; - apis = &apis[6]; - } else if (g_strstr_len (apis, 5, "gles1")) { - ret |= GST_GL_API_GLES; - apis = &apis[5]; - } else if (g_strstr_len (apis, 5, "gles2")) { - ret |= GST_GL_API_GLES2; - apis = &apis[5]; - } else if (g_strstr_len (apis, 5, "gles3")) { - ret |= GST_GL_API_GLES3; - apis = &apis[5]; - } else { - break; - } - } - - if (ret == GST_GL_API_NONE) - ret = GST_GL_API_ANY; - - return ret; -} - -gpointer -gst_gl_display_thread_create_context (GstGLDisplay * display) -{ - GstGLFuncs *gl; - gint gl_major = 0; - gboolean ret = FALSE; - GError *error = NULL; - GstGLAPI compiled_api, user_api; - gchar *api_string; - gchar *compiled_api_s; - gchar *user_api_string; - const gchar *user_choice; - - gst_gl_display_lock (display); - - gl = display->gl_vtable; - compiled_api = _compiled_api (); - - if (!display->gl_window) { - gst_gl_display_set_error (display, "Failed to create opengl window"); - goto failure; - } - - user_choice = g_getenv ("GST_GL_API"); - - user_api = _parse_gl_api (user_choice); - user_api_string = gst_gl_api_string (user_api); - - compiled_api_s = gst_gl_api_string (compiled_api); - - GST_INFO ("Attempting to create opengl context. user chosen api(s):%s, " - "compiled api support:%s", user_api_string, compiled_api_s); - - if (!gst_gl_window_create_context (display->gl_window, - compiled_api & user_api, display->external_gl_context, &error)) { - gst_gl_display_set_error (display, - error ? error->message : "Failed to create gl window"); - g_free (compiled_api_s); - g_free (user_api_string); - goto failure; - } - GST_INFO ("window created context"); - - display->gl_api = gst_gl_window_get_gl_api (display->gl_window); - g_assert (display->gl_api != GST_GL_API_NONE - && display->gl_api != GST_GL_API_ANY); - - api_string = gst_gl_api_string (display->gl_api); - GST_INFO ("available GL APIs: %s", api_string); - - if (((compiled_api & display->gl_api) & user_api) == GST_GL_API_NONE) { - gst_gl_display_set_error (display, "failed to create context, window " - "could not provide correct api. user:%s, compiled:%s, window:%s", - user_api_string, compiled_api_s, api_string); - g_free (api_string); - g_free (compiled_api_s); - g_free (user_api_string); - goto failure; - } - - g_free (api_string); - g_free (compiled_api_s); - g_free (user_api_string); - - gl->GetError = - gst_gl_window_get_proc_address (display->gl_window, "glGetError"); - gl->GetString = - gst_gl_window_get_proc_address (display->gl_window, "glGetString"); - - if (!gl->GetError || !gl->GetString) { - gst_gl_display_set_error (display, - "could not GetProcAddress core opengl functions"); - goto failure; - } - - /* gl api specific code */ - if (!ret && USING_OPENGL (display)) - ret = _create_context_opengl (display, &gl_major, NULL); - if (!ret && USING_GLES2 (display)) - ret = _create_context_gles2 (display, &gl_major, NULL); - - if (!ret || !gl_major) { - GST_WARNING ("GL api specific initialization failed"); - goto failure; - } - - g_cond_signal (&display->priv->cond_create_context); - - display->isAlive = TRUE; - gst_gl_display_unlock (display); - - gst_gl_window_run (display->gl_window); - - GST_INFO ("loop exited\n"); - - gst_gl_display_lock (display); - - display->isAlive = FALSE; - - g_object_unref (G_OBJECT (display->gl_window)); - display->gl_window = NULL; - - g_cond_signal (&display->priv->cond_destroy_context); - - gst_gl_display_unlock (display); - - return NULL; - -failure: - { - if (display->gl_window) { - g_object_unref (display->gl_window); - display->gl_window = NULL; - } - - g_cond_signal (&display->priv->cond_create_context); - gst_gl_display_unlock (display); - return NULL; + if (display->priv->window) { + gst_object_unref (display->priv->window); + display->priv->window = NULL; } -} -void -gst_gl_display_thread_destroy_context (GstGLDisplay * display) -{ - GST_INFO ("Context destroyed"); + G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object); } //------------------------------------------------------------ @@ -434,8 +138,6 @@ gst_gl_display_set_error (GstGLDisplay * display, const char *format, ...) va_end (args); GST_WARNING ("%s", display->error_message); - - display->isAlive = FALSE; } void @@ -470,97 +172,106 @@ gst_gl_display_new (void) return g_object_new (GST_GL_TYPE_DISPLAY, NULL); } -/* Create an opengl context (one context for one GstGLDisplay) */ -gboolean -gst_gl_display_create_context (GstGLDisplay * display, - gulong external_gl_context) -{ - gboolean isAlive = FALSE; - - gst_gl_display_lock (display); - - if (!display->context_created) { - display->external_gl_context = external_gl_context; - - display->gl_thread = g_thread_new ("gstglcontext", - (GThreadFunc) gst_gl_display_thread_create_context, display); - - g_cond_wait (&display->priv->cond_create_context, &display->mutex); - - display->context_created = TRUE; - - GST_INFO ("gl thread created"); - } - - isAlive = display->isAlive; - - gst_gl_display_unlock (display); - - return isAlive; -} - void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data) { + g_return_if_fail (GST_IS_GL_DISPLAY (display)); + g_return_if_fail (GST_GL_IS_WINDOW (display->priv->window)); + g_return_if_fail (func != NULL); + gst_gl_display_lock (display); + display->priv->data = data; display->priv->generic_callback = func; - gst_gl_window_send_message (display->gl_window, + + gst_gl_window_send_message (display->priv->window, GST_GL_WINDOW_CB (gst_gl_display_thread_run_generic), display); + gst_gl_display_unlock (display); } guintptr gst_gl_display_get_internal_gl_context (GstGLDisplay * display) { - gulong external_gl_context = 0; - gst_gl_display_lock (display); - external_gl_context = gst_gl_window_get_gl_context (display->gl_window); - gst_gl_display_unlock (display); - return external_gl_context; + g_return_val_if_fail (GST_IS_GL_DISPLAY (display), 0); + g_return_val_if_fail (GST_GL_IS_WINDOW (display->priv->window), 0); + + return gst_gl_window_get_gl_context (display->priv->window); } void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate) { + g_return_if_fail (GST_IS_GL_DISPLAY (display)); + g_return_if_fail (GST_GL_IS_WINDOW (display->priv->window)); + if (!activate) gst_gl_display_lock (display); - gst_gl_window_activate (display->gl_window, activate); + + gst_gl_window_activate (display->priv->window, activate); + if (activate) gst_gl_display_unlock (display); } GstGLAPI -gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display) +gst_gl_display_get_gl_api (GstGLDisplay * display) { + g_return_val_if_fail (GST_IS_GL_DISPLAY (display), GST_GL_API_NONE); + return display->gl_api; } -GstGLAPI -gst_gl_display_get_gl_api (GstGLDisplay * display) +gpointer +gst_gl_display_get_gl_vtable (GstGLDisplay * display) { - GstGLAPI api; + gpointer gl; + + g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL); + + gl = display->gl_vtable; + + return gl; +} + +void +gst_gl_display_set_window (GstGLDisplay * display, GstGLWindow * window) +{ + g_return_if_fail (GST_IS_GL_DISPLAY (display)); + g_return_if_fail (GST_GL_IS_WINDOW (window)); gst_gl_display_lock (display); - api = gst_gl_display_get_gl_api_unlocked (display); - gst_gl_display_unlock (display); - return api; + if (display->priv->window) + gst_object_unref (display->priv->window); + + display->priv->window = gst_object_ref (window); + + gst_gl_display_unlock (display); } -gpointer -gst_gl_display_get_gl_vtable (GstGLDisplay * display) +GstGLWindow * +gst_gl_display_get_window (GstGLDisplay * display) { - gpointer gl; + GstGLWindow *window; + + g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL); gst_gl_display_lock (display); - gl = display->gl_vtable; + + window = + display->priv->window ? gst_object_ref (display->priv->window) : NULL; + gst_gl_display_unlock (display); - return gl; + return window; } -//------------------------------------------------------------ -//------------------------ END PUBLIC ------------------------ -//------------------------------------------------------------ +GstGLWindow * +gst_gl_display_get_window_unlocked (GstGLDisplay * display) +{ + g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL); + + return display->priv->window ? gst_object_ref (display->priv->window) : NULL; +} diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 6ea7710..5cdb544 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -28,6 +28,7 @@ #include typedef struct _GstGLShader GstGLShader; +typedef struct _GstGLWindow GstGLWindow; #include "gstglwindow.h" #include "gstglshader.h" @@ -89,12 +90,6 @@ struct _GstGLDisplay /* thread safe */ GMutex mutex; - /* gl context */ - GThread *gl_thread; - GstGLWindow *gl_window; - gboolean isAlive; - gboolean context_created; - /* gl API we are using */ GstGLAPI gl_api; /* foreign gl context */ @@ -115,9 +110,6 @@ struct _GstGLDisplayClass GstGLDisplay *gst_gl_display_new (void); -gboolean gst_gl_display_create_context (GstGLDisplay * display, - gulong external_gl_context); - void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data); @@ -126,15 +118,17 @@ void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activa /* Must be called inside a lock/unlock on display, or within the glthread */ void gst_gl_display_set_error (GstGLDisplay * display, const char * format, ...); -gboolean gst_gl_display_check_framebuffer_status (GstGLDisplay * display); void gst_gl_display_lock (GstGLDisplay * display); void gst_gl_display_unlock (GstGLDisplay * display); GstGLAPI gst_gl_display_get_gl_api (GstGLDisplay * display); -GstGLAPI gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display); gpointer gst_gl_display_get_gl_vtable (GstGLDisplay * display); +void gst_gl_display_set_window (GstGLDisplay * display, GstGLWindow * window); +GstGLWindow * gst_gl_display_get_window (GstGLDisplay * display); +GstGLWindow * gst_gl_display_get_window_unlocked (GstGLDisplay * display); + G_END_DECLS #endif /* __GST_GL_H__ */ diff --git a/gst-libs/gst/gl/gstgldownload.c b/gst-libs/gst/gl/gstgldownload.c index a9cdec2..cce9ee3 100644 --- a/gst-libs/gst/gl/gstgldownload.c +++ b/gst-libs/gst/gl/gstgldownload.c @@ -43,11 +43,11 @@ * calling thread. */ -#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) -#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) -#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) -#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) -#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3) static void _do_download (GstGLDisplay * display, GstGLDownload * download); static void _init_download (GstGLDisplay * display, GstGLDownload * download); diff --git a/gst-libs/gst/gl/gstglfeature.c b/gst-libs/gst/gl/gstglfeature.c index 641cc38..72c347c 100644 --- a/gst-libs/gst/gl/gstglfeature.c +++ b/gst-libs/gst/gl/gstglfeature.c @@ -150,6 +150,7 @@ _gst_gl_feature_check (GstGLDisplay * display, const char *suffix = NULL; int func_num; GstGLFuncs *gst_gl = display->gl_vtable; + GstGLWindow *window = NULL; /* First check whether the functions should be directly provided by GL */ @@ -172,6 +173,9 @@ _gst_gl_feature_check (GstGLDisplay * display, if (suffix == NULL) goto error; + window = gst_gl_display_get_window (display); + g_assert (window); + /* Try to get all of the entry points */ for (func_num = 0; data->functions[func_num].name; func_num++) { void *func; @@ -183,8 +187,7 @@ _gst_gl_feature_check (GstGLDisplay * display, suffix, NULL); GST_TRACE ("%s should %sbe in core", full_function_name, in_core ? "" : "not "); - func = - gst_gl_window_get_proc_address (display->gl_window, full_function_name); + func = gst_gl_window_get_proc_address (window, full_function_name); if (func == NULL && in_core) { GST_TRACE ("%s was not found in core, trying the extension version", @@ -196,8 +199,7 @@ _gst_gl_feature_check (GstGLDisplay * display, g_free (full_function_name); full_function_name = g_strconcat ("gl", data->functions[func_num].name, suffix, NULL); - func = gst_gl_window_get_proc_address (display->gl_window, - full_function_name); + func = gst_gl_window_get_proc_address (window, full_function_name); } } @@ -212,6 +214,7 @@ _gst_gl_feature_check (GstGLDisplay * display, } g_free (full_function_name); + gst_object_unref (window); return TRUE; @@ -230,6 +233,9 @@ error: g_free (full_function_name); } + if (window) + gst_object_unref (window); + return FALSE; } diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c index 72d156f..099be08 100644 --- a/gst-libs/gst/gl/gstglfilter.c +++ b/gst-libs/gst/gl/gstglfilter.c @@ -253,11 +253,18 @@ gst_gl_filter_start (GstBaseTransform * bt) filter->display = g_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value))); else { + GstGLWindow *window; + GError *error = NULL; + GST_INFO ("Creating GstGLDisplay"); filter->display = gst_gl_display_new (); - if (!gst_gl_display_create_context (filter->display, 0)) { + window = gst_gl_window_new (filter->display); + gst_gl_display_set_window (filter->display, window); + g_object_unref (window); + + if (!gst_gl_window_create_context (window, 0, &error)) { GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND, - GST_GL_DISPLAY_ERR_MSG (filter->display), (NULL)); + ("%s", error->message), (NULL)); return FALSE; } } @@ -727,9 +734,10 @@ gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps, if (filter_class->display_init_cb != NULL) { gst_gl_display_thread_add (filter->display, gst_gl_filter_start_gl, filter); } - +#if 0 if (!filter->display->isAlive) goto error; +#endif if (filter_class->onInitFBO) { if (!filter_class->onInitFBO (filter)) diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c index 424e4bd..aac56c3 100644 --- a/gst-libs/gst/gl/gstglmemory.c +++ b/gst-libs/gst/gl/gstglmemory.c @@ -25,6 +25,7 @@ #include #include "gstglmemory.h" +#include "gstglutils.h" /** * SECTION:gstglmemory diff --git a/gst-libs/gst/gl/gstglmixer.c b/gst-libs/gst/gl/gstglmixer.c index 1e4b99c..4104d58 100644 --- a/gst-libs/gst/gl/gstglmixer.c +++ b/gst-libs/gst/gl/gstglmixer.c @@ -935,11 +935,18 @@ gst_gl_mixer_activate (GstGLMixer * mix, gboolean activate) mix->display = g_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value))); else { + GstGLWindow *window; + GError *error = NULL; + GST_INFO ("Creating GstGLDisplay"); mix->display = gst_gl_display_new (); - if (!gst_gl_display_create_context (mix->display, 0)) { + window = gst_gl_window_new (mix->display); + gst_gl_display_set_window (mix->display, window); + g_object_unref (window); + + if (!gst_gl_window_create_context (window, 0, &error)) { GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, - GST_GL_DISPLAY_ERR_MSG (mix->display), (NULL)); + ("%s", error->message), (NULL)); return FALSE; } } diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index 18cb369..00d5a99 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -43,11 +43,11 @@ * calling thread. */ -#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) -#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) -#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) -#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) -#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3) static void _do_upload (GstGLDisplay * display, GstGLUpload * upload); static void _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload); diff --git a/gst-libs/gst/gl/gstglutils.c b/gst-libs/gst/gl/gstglutils.c index 3e29c96..9a92fa8 100644 --- a/gst-libs/gst/gl/gstglutils.c +++ b/gst-libs/gst/gl/gstglutils.c @@ -234,18 +234,24 @@ void gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, GstVideoFormat v_format, GLint width, GLint height) { + GstGLWindow *window; + gst_gl_display_lock (display); - if (display->isAlive) { + window = gst_gl_display_get_window_unlocked (display); + + if (gst_gl_window_is_running (window)) { gen_texture_width = width; gen_texture_height = height; gen_texture_video_format = v_format; - gst_gl_window_send_message (display->gl_window, + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (gst_gl_display_gen_texture_window_cb), display); *pTexture = gen_texture; } else *pTexture = 0; + gst_object_unref (window); + gst_gl_display_unlock (display); } @@ -263,21 +269,26 @@ gboolean gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, GLuint * fbo, GLuint * depthbuffer) { - gboolean isAlive = FALSE; + gboolean alive = FALSE; + GstGLWindow *window; gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + + if (gst_gl_window_is_running (window)) { gen_fbo_width = width; gen_fbo_height = height; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_gen_fbo), - display); + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gen_fbo), display); *fbo = generated_fbo; *depthbuffer = generated_depth_buffer; } - isAlive = display->isAlive; + alive = gst_gl_window_is_running (window); + + gst_object_unref (window); gst_gl_display_unlock (display); - return isAlive; + return alive; } @@ -297,10 +308,13 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, GstGLDisplayProjection projection, gpointer * stuff) { - gboolean isAlive; + gboolean alive; + GstGLWindow *window; gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + if (gst_gl_window_is_running (window)) { use_fbo = fbo; use_depth_buffer = depth_buffer; use_fbo_texture = texture_fbo; @@ -316,13 +330,14 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, input_texture_width = input_tex_width; input_texture_height = input_tex_height; input_texture = input_tex; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_use_fbo), - display); + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_use_fbo), display); } - isAlive = display->isAlive; + alive = gst_gl_window_is_running (window); + + gst_object_unref (window); gst_gl_display_unlock (display); - return isAlive; + return alive; } gboolean @@ -330,10 +345,13 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff) { - gboolean isAlive; + gboolean alive; + GstGLWindow *window; gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + if (gst_gl_window_is_running (window)) { use_fbo = fbo; use_depth_buffer = depth_buffer; use_fbo_texture = texture_fbo; @@ -341,26 +359,33 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, use_fbo_height = texture_fbo_height; use_fbo_scene_cb_v2 = cb; use_fbo_stuff = stuff; - gst_gl_window_send_message (display->gl_window, + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_use_fbo_v2), display); } - isAlive = display->isAlive; + alive = gst_gl_window_is_running (window); + + gst_object_unref (window); gst_gl_display_unlock (display); - return isAlive; + return alive; } /* Called by gltestsrc and glfilter */ void gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer) { + GstGLWindow *window; + gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + if (gst_gl_window_is_running (window)) { del_fbo = fbo; del_depth_buffer = depth_buffer; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_del_fbo), - display); + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_del_fbo), display); } + + gst_object_unref (window); gst_gl_display_unlock (display); } @@ -371,13 +396,16 @@ gst_gl_display_gen_shader (GstGLDisplay * display, const gchar * shader_vertex_source, const gchar * shader_fragment_source, GstGLShader ** shader) { - gboolean isAlive; + gboolean alive; + GstGLWindow *window; gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + if (gst_gl_window_is_running (window)) { gen_shader_vertex_source = shader_vertex_source; gen_shader_fragment_source = shader_fragment_source; - gst_gl_window_send_message (display->gl_window, + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_gen_shader), display); if (shader) *shader = gen_shader; @@ -385,10 +413,12 @@ gst_gl_display_gen_shader (GstGLDisplay * display, gen_shader_vertex_source = NULL; gen_shader_fragment_source = NULL; } - isAlive = display->isAlive; + alive = gst_gl_window_is_running (window); + + gst_object_unref (window); gst_gl_display_unlock (display); - return isAlive; + return alive; } @@ -396,12 +426,18 @@ gst_gl_display_gen_shader (GstGLDisplay * display, void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader) { + GstGLWindow *window; + gst_gl_display_lock (display); - if (display->isAlive) { + + window = gst_gl_display_get_window_unlocked (display); + if (gst_gl_window_is_running (window)) { del_shader = shader; - gst_gl_window_send_message (display->gl_window, + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (_del_shader), display); } + + gst_object_unref (window); gst_gl_display_unlock (display); } diff --git a/gst-libs/gst/gl/gstglutils.h b/gst-libs/gst/gl/gstglutils.h index 69a02b7..bdff171 100644 --- a/gst-libs/gst/gl/gstglutils.h +++ b/gst-libs/gst/gl/gstglutils.h @@ -99,4 +99,6 @@ gboolean gst_gl_display_gen_shader (GstGLDisplay * display, const gchar * shader_fragment_source, GstGLShader ** shader); void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader); +gboolean gst_gl_display_check_framebuffer_status (GstGLDisplay * display); + #endif /* __GST_GL_UTILS_H__ */ diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 66cfa02..40355fe 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -23,6 +23,7 @@ #endif #include +#include #include "gstglwindow.h" @@ -39,12 +40,45 @@ #include "wayland/gstglwindow_wayland_egl.h" #endif +#include "gstglfeature.h" + +#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) +#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) +#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2) +#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3) + #define GST_CAT_DEFAULT gst_gl_window_debug GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); #define gst_gl_window_parent_class parent_class G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT); +#define GST_GL_WINDOW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate)) + +struct _GstGLWindowPrivate +{ + GstGLDisplay *display; + + GThread *gl_thread; + + /* conditions */ + GMutex render_lock; + GCond cond_create_context; + GCond cond_destroy_context; + + gboolean context_created; + gboolean alive; + + guintptr external_gl_context; + GstGLAPI gl_api; + GError **error; +}; + +static gpointer _gst_gl_window_thread_create_context (GstGLWindow * window); +static void gst_gl_window_finalize (GObject * object); + GQuark gst_gl_window_error_quark (void) { @@ -54,19 +88,30 @@ gst_gl_window_error_quark (void) static void gst_gl_window_init (GstGLWindow * window) { + window->priv = GST_GL_WINDOW_GET_PRIVATE (window); + g_mutex_init (&window->lock); window->need_lock = TRUE; + + g_mutex_init (&window->priv->render_lock); + g_cond_init (&window->priv->cond_create_context); + g_cond_init (&window->priv->cond_destroy_context); + window->priv->context_created = FALSE; } static void gst_gl_window_class_init (GstGLWindowClass * klass) { + g_type_class_add_private (klass, sizeof (GstGLWindowPrivate)); + klass->get_proc_address = GST_DEBUG_FUNCPTR (gst_gl_window_default_get_proc_address); + + G_OBJECT_CLASS (klass)->finalize = gst_gl_window_finalize; } GstGLWindow * -gst_gl_window_new (void) +gst_gl_window_new (GstGLDisplay * display) { GstGLWindow *window = NULL; const gchar *user_choice; @@ -106,9 +151,43 @@ gst_gl_window_new (void) return NULL; } + window->priv->display = display; + return window; } +static void +gst_gl_window_finalize (GObject * object) +{ + GstGLWindow *window = GST_GL_WINDOW (object); + + if (window) { + gst_gl_window_set_resize_callback (window, NULL, NULL); + gst_gl_window_set_draw_callback (window, NULL, NULL); + gst_gl_window_set_close_callback (window, NULL, NULL); + + if (window->priv->alive) { + GST_INFO ("send quit gl window loop"); + gst_gl_window_quit (window, NULL, NULL); + } + } + + if (window->priv->gl_thread) { + gpointer ret = g_thread_join (window->priv->gl_thread); + GST_INFO ("gl thread joined"); + if (ret != NULL) + GST_ERROR ("gl thread returned a non-null pointer"); + window->priv->gl_thread = NULL; + } + + g_mutex_clear (&window->priv->render_lock); + + g_cond_clear (&window->priv->cond_destroy_context); + g_cond_clear (&window->priv->cond_create_context); + + G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); +} + guintptr gst_gl_window_get_gl_context (GstGLWindow * window) { @@ -209,10 +288,17 @@ gst_gl_window_quit (GstGLWindow * window, GstGLWindowCB callback, gpointer data) GST_GL_WINDOW_LOCK (window); + window->priv->alive = FALSE; + window->close = callback; window->close_data = data; window_class->quit (window, callback, data); + GST_INFO ("quit sent to gl window loop"); + + g_cond_wait (&window->priv->cond_destroy_context, &window->priv->render_lock); + GST_INFO ("quit received from gl window"); + GST_GL_WINDOW_UNLOCK (window); } @@ -331,7 +417,7 @@ gst_gl_window_get_proc_address (GstGLWindow * window, const gchar * name) gboolean -gst_gl_window_create_context (GstGLWindow * window, GstGLAPI gl_api, +_priv_gst_gl_window_create_context (GstGLWindow * window, GstGLAPI gl_api, guintptr external_gl_context, GError ** error) { gboolean ret; @@ -368,3 +454,309 @@ gst_gl_window_default_get_proc_address (GstGLWindow * window, return ret; } + +/* Create an opengl context (one context for one GstGLDisplay) */ +gboolean +gst_gl_window_create_context (GstGLWindow * window, + guintptr external_gl_context, GError ** error) +{ + gboolean alive = FALSE; + GstGLWindowClass *window_class; + + g_return_val_if_fail (GST_GL_IS_WINDOW (window), FALSE); + window_class = GST_GL_WINDOW_GET_CLASS (window); + g_return_val_if_fail (window_class->create_context != NULL, FALSE); + + g_mutex_lock (&window->priv->render_lock); + + if (!window->priv->context_created) { + window->priv->external_gl_context = external_gl_context; + window->priv->error = error; + + window->priv->gl_thread = g_thread_new ("gstglcontext", + (GThreadFunc) _gst_gl_window_thread_create_context, window); + + g_cond_wait (&window->priv->cond_create_context, + &window->priv->render_lock); + + window->priv->context_created = TRUE; + + GST_INFO ("gl thread created"); + } + + alive = window->priv->alive; + + g_mutex_unlock (&window->priv->render_lock); + + return alive; +} + +gboolean +gst_gl_window_is_running (GstGLWindow * window) +{ + return window->priv->alive; +} + +static gboolean +_create_context_gles2 (GstGLWindow * window, gint * gl_major, gint * gl_minor) +{ + GstGLDisplay *display; + const GstGLFuncs *gl; + GLenum gl_err = GL_NO_ERROR; + GError **error; + + display = window->priv->display; + gl = display->gl_vtable; + error = window->priv->error; + + GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION)); + GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", + gl->GetString (GL_SHADING_LANGUAGE_VERSION)); + GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR)); + GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER)); + + gl_err = gl->GetError (); + if (gl_err != GL_NO_ERROR) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, + "glGetString error: 0x%x", gl_err); + return FALSE; + } +#if GST_GL_HAVE_GLES2 + if (!GL_ES_VERSION_2_0) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS, + "OpenGL|ES >= 2.0 is required"); + return FALSE; + } +#endif + + _gst_gl_feature_check_ext_functions (display, 0, 0, + (const gchar *) gl->GetString (GL_EXTENSIONS)); + + if (gl_major) + *gl_major = 2; + if (gl_minor) + *gl_minor = 0; + + return TRUE; +} + +gboolean +_create_context_opengl (GstGLWindow * window, gint * gl_major, gint * gl_minor) +{ + GstGLDisplay *display; + const GstGLFuncs *gl; + guint maj, min; + GLenum gl_err = GL_NO_ERROR; + GString *opengl_version = NULL; + GError **error; + + display = window->priv->display; + gl = display->gl_vtable; + error = window->priv->error; + + GST_INFO ("GL_VERSION: %s", gl->GetString (GL_VERSION)); + GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", + gl->GetString (GL_SHADING_LANGUAGE_VERSION)); + GST_INFO ("GL_VENDOR: %s", gl->GetString (GL_VENDOR)); + GST_INFO ("GL_RENDERER: %s", gl->GetString (GL_RENDERER)); + + gl_err = gl->GetError (); + if (gl_err != GL_NO_ERROR) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, + "glGetString error: 0x%x", gl_err); + return FALSE; + } + opengl_version = + g_string_truncate (g_string_new ((gchar *) gl->GetString (GL_VERSION)), + 3); + + sscanf (opengl_version->str, "%d.%d", &maj, &min); + + g_string_free (opengl_version, TRUE); + + /* OpenGL > 1.2.0 */ + if ((maj < 1) || (maj < 2 && maj >= 1 && min < 2)) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS, + "OpenGL >= 1.2.0 required, found %u.%u", maj, min); + return FALSE; + } + + _gst_gl_feature_check_ext_functions (display, maj, min, + (const gchar *) gl->GetString (GL_EXTENSIONS)); + + if (gl_major) + *gl_major = maj; + if (gl_minor) + *gl_minor = min; + + return TRUE; +} + +GstGLAPI +_compiled_api (void) +{ + GstGLAPI ret = GST_GL_API_NONE; + +#if GST_GL_HAVE_OPENGL + ret |= GST_GL_API_OPENGL; +#endif +#if GST_GL_HAVE_GLES2 + ret |= GST_GL_API_GLES2; +#endif + + return ret; +} + +GstGLAPI +_parse_gl_api (const gchar * apis_s) +{ + GstGLAPI ret = GST_GL_API_NONE; + gchar *apis = (gchar *) apis_s; + + while (apis) { + if (apis[0] == '\0') { + break; + } else if (apis[0] == ' ' || apis[0] == ',') { + apis = &apis[1]; + } else if (g_strstr_len (apis, 7, "opengl3")) { + ret |= GST_GL_API_OPENGL3; + apis = &apis[7]; + } else if (g_strstr_len (apis, 6, "opengl")) { + ret |= GST_GL_API_OPENGL; + apis = &apis[6]; + } else if (g_strstr_len (apis, 5, "gles1")) { + ret |= GST_GL_API_GLES; + apis = &apis[5]; + } else if (g_strstr_len (apis, 5, "gles2")) { + ret |= GST_GL_API_GLES2; + apis = &apis[5]; + } else if (g_strstr_len (apis, 5, "gles3")) { + ret |= GST_GL_API_GLES3; + apis = &apis[5]; + } else { + break; + } + } + + if (ret == GST_GL_API_NONE) + ret = GST_GL_API_ANY; + + return ret; +} + +static gpointer +_gst_gl_window_thread_create_context (GstGLWindow * window) +{ + GstGLWindowClass *window_class; + GstGLDisplay *display; + GstGLFuncs *gl; + gint gl_major = 0; + gboolean ret = FALSE; + GstGLAPI compiled_api, user_api; + gchar *api_string; + gchar *compiled_api_s; + gchar *user_api_string; + const gchar *user_choice; + GError **error; + + window_class = GST_GL_WINDOW_GET_CLASS (window); + error = window->priv->error; + display = window->priv->display; + + g_mutex_lock (&window->priv->render_lock); + + gl = display->gl_vtable; + compiled_api = _compiled_api (); + + user_choice = g_getenv ("GST_GL_API"); + + user_api = _parse_gl_api (user_choice); + user_api_string = gst_gl_api_string (user_api); + + compiled_api_s = gst_gl_api_string (compiled_api); + + GST_INFO ("Attempting to create opengl context. user chosen api(s):%s, " + "compiled api support:%s", user_api_string, compiled_api_s); + + if (!window_class->create_context (window, compiled_api & user_api, + window->priv->external_gl_context, error)) { + g_assert (error == NULL || *error != NULL); + g_free (compiled_api_s); + g_free (user_api_string); + goto failure; + } + GST_INFO ("window created context"); + + display->gl_api = gst_gl_window_get_gl_api (window); + g_assert (display->gl_api != GST_GL_API_NONE + && display->gl_api != GST_GL_API_ANY); + + api_string = gst_gl_api_string (display->gl_api); + GST_INFO ("available GL APIs: %s", api_string); + + if (((compiled_api & display->gl_api) & user_api) == GST_GL_API_NONE) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API, + "failed to create context, window " + "could not provide correct api. user:%s, compiled:%s, window:%s", + user_api_string, compiled_api_s, api_string); + g_free (api_string); + g_free (compiled_api_s); + g_free (user_api_string); + goto failure; + } + + g_free (api_string); + g_free (compiled_api_s); + g_free (user_api_string); + + gl->GetError = gst_gl_window_get_proc_address (window, "glGetError"); + gl->GetString = gst_gl_window_get_proc_address (window, "glGetString"); + + if (!gl->GetError || !gl->GetString) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, + "could not GetProcAddress core opengl functions"); + goto failure; + } + + /* gl api specific code */ + if (!ret && USING_OPENGL (display)) + ret = _create_context_opengl (window, &gl_major, NULL); + if (!ret && USING_GLES2 (display)) + ret = _create_context_gles2 (window, &gl_major, NULL); + + if (!ret || !gl_major) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, + "GL api specific initialization failed"); + goto failure; + } + + g_cond_signal (&window->priv->cond_create_context); + + window->priv->alive = TRUE; + g_mutex_unlock (&window->priv->render_lock); + + gst_gl_window_run (window); + + GST_INFO ("loop exited\n"); + + g_mutex_lock (&window->priv->render_lock); + + window->priv->alive = FALSE; + +// g_object_unref (G_OBJECT (display->gl_window)); + +// display->gl_window = NULL; + + g_cond_signal (&window->priv->cond_destroy_context); + + g_mutex_unlock (&window->priv->render_lock); + + return NULL; + +failure: + { + g_cond_signal (&window->priv->cond_create_context); + g_mutex_unlock (&window->priv->render_lock); + return NULL; + } +} diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index 61fb693..bb89e53 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -22,9 +22,12 @@ #ifndef __GST_GL_WINDOW_H__ #define __GST_GL_WINDOW_H__ +typedef struct _GstGLDisplay GstGLDisplay; + #include #include "gstglapi.h" +#include "gstgldisplay.h" G_BEGIN_DECLS @@ -90,6 +93,8 @@ struct _GstGLWindow { /*< private >*/ gpointer _reserved[GST_PADDING]; + + GstGLWindowPrivate *priv; }; struct _GstGLWindowClass { @@ -119,7 +124,7 @@ struct _GstGLWindowClass { GQuark gst_gl_window_error_quark (void); GType gst_gl_window_get_type (void); -GstGLWindow * gst_gl_window_new (void); +GstGLWindow * gst_gl_window_new (GstGLDisplay *display); void gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data); void gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowResizeCB callback, gpointer data); @@ -140,11 +145,12 @@ gpointer gst_gl_window_get_proc_address (GstGLWindow *window, const gchar * GstGLPlatform gst_gl_window_get_platform (GstGLWindow *window); GstGLAPI gst_gl_window_get_gl_api (GstGLWindow *window); -gboolean gst_gl_window_create_context (GstGLWindow *window, GstGLAPI gl_api, - guintptr external_gl_context, GError ** error); +gboolean gst_gl_window_create_context (GstGLWindow *window, guintptr external_gl_context, GError ** error); gpointer gst_gl_window_default_get_proc_address (GstGLWindow *window, const gchar *name); +gboolean gst_gl_window_is_running (GstGLWindow *window); + GST_DEBUG_CATEGORY_EXTERN (gst_gl_window_debug); G_END_DECLS diff --git a/gst/gl/effects/gstgleffectidentity.c b/gst/gl/effects/gstgleffectidentity.c index 8640f19..636706a 100644 --- a/gst/gl/effects/gstgleffectidentity.c +++ b/gst/gl/effects/gstgleffectidentity.c @@ -20,11 +20,11 @@ #include -#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) -#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) -#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) -#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) -#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3) static void gst_gl_effects_identity_callback (gint width, gint height, guint texture, diff --git a/gst/gl/effects/gstgleffectmirror.c b/gst/gl/effects/gstgleffectmirror.c index 20dda3d..7fd2473 100644 --- a/gst/gl/effects/gstgleffectmirror.c +++ b/gst/gl/effects/gstgleffectmirror.c @@ -20,11 +20,11 @@ #include -#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) -#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) -#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) -#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) -#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3) static void gst_gl_effects_mirror_callback (gint width, gint height, guint texture, diff --git a/gst/gl/effects/gstgleffectsqueeze.c b/gst/gl/effects/gstgleffectsqueeze.c index d55975e..0cdadfc 100644 --- a/gst/gl/effects/gstgleffectsqueeze.c +++ b/gst/gl/effects/gstgleffectsqueeze.c @@ -20,11 +20,11 @@ #include -#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) -#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) -#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) -#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) -#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api (display) & GST_GL_API_GLES3) static void gst_gl_effects_squeeze_callback (gint width, gint height, guint texture, diff --git a/gst/gl/gltestsrc.c b/gst/gl/gltestsrc.c index 996e9d8..2576efe 100644 --- a/gst/gl/gltestsrc.c +++ b/gst/gl/gltestsrc.c @@ -86,7 +86,7 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h) #if GST_GL_HAVE_OPENGL int i; - if (gst_gl_display_get_gl_api_unlocked (v->display) & GST_GL_API_OPENGL) { + if (gst_gl_display_get_gl_api (v->display) & GST_GL_API_OPENGL) { glClearColor (0.0, 0.0, 0.0, 1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -192,7 +192,7 @@ void gst_gl_test_src_snow (GstGLTestSrc * v, GstBuffer * buffer, int w, int h) { #if GST_GL_HAVE_OPENGL - if (gst_gl_display_get_gl_api_unlocked (v->display) & GST_GL_API_OPENGL) { + if (gst_gl_display_get_gl_api (v->display) & GST_GL_API_OPENGL) { glClearColor (0.0, 0.0, 0.0, 1.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -219,7 +219,7 @@ gst_gl_test_src_unicolor (GstGLTestSrc * v, GstBuffer * buffer, int w, int h, const struct vts_color_struct *color) { #if GST_GL_HAVE_OPENGL - if (gst_gl_display_get_gl_api_unlocked (v->display) & GST_GL_API_OPENGL) { + if (gst_gl_display_get_gl_api (v->display) & GST_GL_API_OPENGL) { glClearColor (color->R * (1 / 255.0f), color->G * (1 / 255.0f), color->B * (1 / 255.0f), 1.0f); glClear (GL_COLOR_BUFFER_BIT); diff --git a/gst/gl/gstglbumper.c b/gst/gl/gstglbumper.c index 854d268..25bd26b 100644 --- a/gst/gl/gstglbumper.c +++ b/gst/gl/gstglbumper.c @@ -139,7 +139,7 @@ static const gchar *bumper_f_src = " gl_FragColor = vec4(irradiance * textureColor.rgb, textureColor.w);\n" "}\n"; -#define LOAD_ERROR(display, msg) { gst_gl_display_set_error (display, "unable to load %s: %s", bumper->location, msg); display->isAlive = FALSE; return; } +#define LOAD_ERROR(display, msg) { gst_gl_display_set_error (display, "unable to load %s: %s", bumper->location, msg); return; } //png reading error handler static void diff --git a/gst/gl/gstgleffects.c b/gst/gl/gstgleffects.c index 985692d..8d953b6 100644 --- a/gst/gl/gstgleffects.c +++ b/gst/gl/gstgleffects.c @@ -280,7 +280,7 @@ gst_gl_effects_draw_texture (GstGLEffects * effects, GLuint tex, guint width, GstGLFuncs *gl = display->gl_vtable; #if GST_GL_HAVE_OPENGL - if (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) { + if (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) { gfloat verts[] = { -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, @@ -347,7 +347,7 @@ set_horizontal_swap (GstGLDisplay * display, gpointer data) #if GST_GL_HAVE_OPENGL GstGLFuncs *gl = display->gl_vtable; - if (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) { + if (gst_gl_display_get_gl_api (display) & GST_GL_API_OPENGL) { const gfloat mirrormatrix[16] = { -1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 diff --git a/gst/gl/gstglfiltercube.c b/gst/gl/gstglfiltercube.c index 43f116d..8526b3a 100644 --- a/gst/gl/gstglfiltercube.c +++ b/gst/gl/gstglfiltercube.c @@ -289,8 +289,7 @@ gst_gl_filter_cube_filter_texture (GstGLFilter * filter, guint in_tex, GLCB cb = NULL; GstGLAPI api; - api = - gst_gl_display_get_gl_api_unlocked (GST_GL_FILTER (cube_filter)->display); + api = gst_gl_display_get_gl_api (GST_GL_FILTER (cube_filter)->display); #if GST_GL_HAVE_OPENGL if (api & GST_GL_API_OPENGL) diff --git a/gst/gl/gstglimagesink.c b/gst/gl/gstglimagesink.c index 9012df1..77db45d 100644 --- a/gst/gl/gstglimagesink.c +++ b/gst/gl/gstglimagesink.c @@ -412,33 +412,38 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: + g_atomic_int_set (&glimage_sink->to_quit, 0); if (!glimage_sink->display) { - gboolean ok = FALSE; + GstGLWindow *window; + GError *error = NULL; GST_INFO ("Creating GstGLDisplay"); glimage_sink->display = gst_gl_display_new (); + window = gst_gl_window_new (glimage_sink->display); + gst_gl_display_set_window (glimage_sink->display, window); - /* init opengl context */ - ok = gst_gl_display_create_context (glimage_sink->display, 0); - if (!ok) { + if (!gst_gl_window_create_context (window, 0, &error)) { GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, - GST_GL_DISPLAY_ERR_MSG (glimage_sink->display), (NULL)); + ("%s", error->message), (NULL)); if (glimage_sink->display) { g_object_unref (glimage_sink->display); glimage_sink->display = NULL; } + gst_object_unref (window); return GST_STATE_CHANGE_FAILURE; } /* setup callbacks */ - gst_gl_window_set_resize_callback (glimage_sink->display->gl_window, + gst_gl_window_set_resize_callback (window, GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize), glimage_sink); - gst_gl_window_set_draw_callback (glimage_sink->display->gl_window, + gst_gl_window_set_draw_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_draw), glimage_sink); - gst_gl_window_set_close_callback (glimage_sink->display->gl_window, + gst_gl_window_set_close_callback (window, GST_GL_WINDOW_CB (gst_glimage_sink_on_close), glimage_sink); + + gst_object_unref (window); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -470,14 +475,14 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) GST_VIDEO_SINK_WIDTH (glimage_sink) = 1; GST_VIDEO_SINK_HEIGHT (glimage_sink) = 1; - - gst_gl_window_set_resize_callback (glimage_sink->display->gl_window, - GST_GL_WINDOW_RESIZE_CB (NULL), NULL); - gst_gl_window_set_draw_callback (glimage_sink->display->gl_window, - GST_GL_WINDOW_CB (NULL), NULL); - gst_gl_window_set_close_callback (glimage_sink->display->gl_window, - GST_GL_WINDOW_CB (NULL), NULL); if (glimage_sink->display) { + GstGLWindow *window = gst_gl_display_get_window (glimage_sink->display); + + gst_gl_window_set_resize_callback (window, NULL, NULL); + gst_gl_window_set_draw_callback (window, NULL, NULL); + gst_gl_window_set_close_callback (window, NULL, NULL); + + g_object_unref (window); g_object_unref (glimage_sink->display); glimage_sink->display = NULL; } @@ -641,9 +646,12 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) } if (glimage_sink->window_id != glimage_sink->new_window_id) { + GstGLWindow *window = gst_gl_display_get_window (glimage_sink->display); + glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_window_set_window_handle (glimage_sink->display->gl_window, - glimage_sink->window_id); + gst_gl_window_set_window_handle (window, glimage_sink->window_id); + + gst_object_unref (window); } //the buffer is cleared when an other comes in if (glimage_sink->stored_buffer) { @@ -671,6 +679,12 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) gst_video_frame_unmap (&frame); + if (g_atomic_int_get (&glimage_sink->to_quit) != 0) { + GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND, + GST_GL_DISPLAY_ERR_MSG (glimage_sink->display), (NULL)); + return GST_FLOW_ERROR; + } + return GST_FLOW_OK; /* ERRORS */ @@ -715,9 +729,12 @@ gst_glimage_sink_expose (GstVideoOverlay * overlay) if (glimage_sink->display && glimage_sink->window_id) { if (glimage_sink->window_id != glimage_sink->new_window_id) { + GstGLWindow *window = gst_gl_display_get_window (glimage_sink->display); + glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_window_set_window_handle (glimage_sink->display->gl_window, - glimage_sink->window_id); + gst_gl_window_set_window_handle (window, glimage_sink->window_id); + + gst_object_unref (window); } gst_glimage_sink_redisplay (glimage_sink, 0, 0, 0, 0, 0, @@ -900,15 +917,19 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink) /* check if a client draw callback is registered */ if (gl_sink->clientDrawCallback) { + GstGLWindow *window = gst_gl_display_get_window (gl_sink->display); + gboolean doRedisplay = gl_sink->clientDrawCallback (gl_sink->redisplay_texture, gl_sink->redisplay_texture_width, gl_sink->redisplay_texture_height, gl_sink->client_data); - if (doRedisplay && gl_sink->display->gl_window) - gst_gl_window_draw_unlocked (gl_sink->display->gl_window, + if (doRedisplay && window) + gst_gl_window_draw_unlocked (window, gl_sink->redisplay_texture_width, gl_sink->redisplay_texture_height); + + gst_object_unref (window); } /* default opengl scene */ else { @@ -990,6 +1011,8 @@ static void gst_glimage_sink_on_close (GstGLImageSink * gl_sink) { gst_gl_display_set_error (gl_sink->display, "Output window was closed"); + + g_atomic_int_set (&gl_sink->to_quit, 1); } static gboolean @@ -997,15 +1020,17 @@ gst_glimage_sink_redisplay (GstGLImageSink * gl_sink, GLuint texture, gint gl_width, gint gl_height, gint window_width, gint window_height, gboolean keep_aspect_ratio) { - gboolean isAlive; + GstGLWindow *window; + gboolean alive; + + window = gst_gl_display_get_window (gl_sink->display); - gst_gl_display_lock (gl_sink->display); - if (gl_sink->display->isAlive) { + if (window && gst_gl_window_is_running (window)) { #if GST_GL_HAVE_GLES2 if (USING_GLES2 (gl_sink->display)) { if (!gl_sink->redisplay_shader) { - gst_gl_window_send_message (display->gl_window, + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), display); } } @@ -1017,14 +1042,13 @@ gst_glimage_sink_redisplay (GstGLImageSink * gl_sink, GLuint texture, gl_sink->redisplay_texture_height = gl_height; } gl_sink->keep_aspect_ratio = keep_aspect_ratio; - if (gl_sink->display->gl_window) - gst_gl_window_draw (gl_sink->display->gl_window, window_width, - window_height); + if (window) + gst_gl_window_draw (window, window_width, window_height); } - isAlive = gl_sink->display->isAlive; - gst_gl_display_unlock (gl_sink->display); + alive = gst_gl_window_is_running (window); + gst_object_unref (window); - return isAlive; + return alive; } void diff --git a/gst/gl/gstglimagesink.h b/gst/gl/gstglimagesink.h index 2a97bf6..f75ea93 100644 --- a/gst/gl/gstglimagesink.h +++ b/gst/gl/gstglimagesink.h @@ -70,6 +70,7 @@ struct _GstGLImageSink CDCB clientDrawCallback; gpointer client_data; + volatile gint to_quit; gboolean keep_aspect_ratio; GValue *par; diff --git a/gst/gl/gstgloverlay.c b/gst/gl/gstgloverlay.c index 75b71ae..f228d92 100644 --- a/gst/gl/gstgloverlay.c +++ b/gst/gl/gstgloverlay.c @@ -632,8 +632,9 @@ init_pixbuf_texture (GstGLDisplay * display, gpointer data) gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } - } else - display->isAlive = FALSE; + } + //else + // display->isAlive = FALSE; } static gboolean diff --git a/gst/gl/gstgltestsrc.c b/gst/gl/gstgltestsrc.c index 0c7fee0..afaa70d 100644 --- a/gst/gl/gstgltestsrc.c +++ b/gst/gl/gstgltestsrc.c @@ -554,11 +554,18 @@ gst_gl_test_src_start (GstBaseSrc * basesrc) src->display = g_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value))); else { + GstGLWindow *window; + GError *error = NULL; + GST_INFO ("Creating GstGLDisplay"); src->display = gst_gl_display_new (); - if (!gst_gl_display_create_context (src->display, 0)) { + window = gst_gl_window_new (src->display); + gst_gl_display_set_window (src->display, window); + g_object_unref (window); + + if (!gst_gl_window_create_context (window, 0, &error)) { GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, - GST_GL_DISPLAY_ERR_MSG (src->display), (NULL)); + ("%s", error->message), (NULL)); return FALSE; } } -- 2.7.4