struct _GstGLDisplayPrivate
{
- /* conditions */
- GCond cond_create_context;
- GCond cond_destroy_context;
+ GstGLWindow *window;
/* generic gl code */
GstGLDisplayThreadFunc generic_callback;
/* 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 ();
}
{
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;
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);
}
//------------------------------------------------------------
va_end (args);
GST_WARNING ("%s", display->error_message);
-
- display->isAlive = FALSE;
}
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;
+}
#include <gst/video/video.h>
typedef struct _GstGLShader GstGLShader;
+typedef struct _GstGLWindow GstGLWindow;
#include "gstglwindow.h"
#include "gstglshader.h"
/* 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 */
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);
/* 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__ */
* 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);
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 */
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;
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",
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);
}
}
}
g_free (full_function_name);
+ gst_object_unref (window);
return TRUE;
g_free (full_function_name);
}
+ if (window)
+ gst_object_unref (window);
+
return FALSE;
}
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;
}
}
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))
#include <gst/video/video.h>
#include "gstglmemory.h"
+#include "gstglutils.h"
/**
* SECTION:gstglmemory
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;
}
}
* 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);
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);
}
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;
}
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;
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
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;
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);
}
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;
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;
}
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);
}
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__ */
#endif
#include <gmodule.h>
+#include <stdio.h>
#include "gstglwindow.h"
#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)
{
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;
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)
{
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);
}
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;
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;
+ }
+}
#ifndef __GST_GL_WINDOW_H__
#define __GST_GL_WINDOW_H__
+typedef struct _GstGLDisplay GstGLDisplay;
+
#include <gst/gst.h>
#include "gstglapi.h"
+#include "gstgldisplay.h"
G_BEGIN_DECLS
/*< private >*/
gpointer _reserved[GST_PADDING];
+
+ GstGLWindowPrivate *priv;
};
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);
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
#include <gstgleffects.h>
-#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,
#include <gstgleffects.h>
-#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,
#include <gstgleffects.h>
-#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,
#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);
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);
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);
" 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
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,
#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
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)
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:
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;
}
}
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) {
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 */
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,
/* 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 {
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
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);
}
}
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
CDCB clientDrawCallback;
gpointer client_data;
+ volatile gint to_quit;
gboolean keep_aspect_ratio;
GValue *par;
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
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;
}
}