[701/906] display: move context creation into window
authorMatthew Waters <ystreet00@gmail.com>
Wed, 12 Jun 2013 13:17:30 +0000 (23:17 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:28 +0000 (19:31 +0000)
12 files changed:
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstgldownload.c
gst-libs/gst/gl/gstglfeature.c
gst-libs/gst/gl/gstglfilter.c
gst-libs/gst/gl/gstglmemory.c
gst-libs/gst/gl/gstglmixer.c
gst-libs/gst/gl/gstglupload.c
gst-libs/gst/gl/gstglutils.c
gst-libs/gst/gl/gstglutils.h
gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h

index 6566b75..ef406ff 100644 (file)
@@ -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;
+}
index 6ea7710..5cdb544 100644 (file)
@@ -28,6 +28,7 @@
 #include <gst/video/video.h>
 
 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__ */
index a9cdec2..cce9ee3 100644 (file)
  * 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);
index 641cc38..72c347c 100644 (file)
@@ -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;
 }
 
index 72d156f..099be08 100644 (file)
@@ -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))
index 424e4bd..aac56c3 100644 (file)
@@ -25,6 +25,7 @@
 #include <gst/video/video.h>
 
 #include "gstglmemory.h"
+#include "gstglutils.h"
 
 /**
  * SECTION:gstglmemory
index 1e4b99c..4104d58 100644 (file)
@@ -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;
       }
     }
index 18cb369..00d5a99 100644 (file)
  * 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);
index 3e29c96..9a92fa8 100644 (file)
@@ -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);
 }
 
index 69a02b7..bdff171 100644 (file)
@@ -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__ */
index 66cfa02..40355fe 100644 (file)
@@ -23,6 +23,7 @@
 #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)
 {
@@ -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;
+  }
+}
index 61fb693..bb89e53 100644 (file)
 #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
 
@@ -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