[793/906] add a GstGLContext object that will be the basis of OpenGL contexts
authorMatthew Waters <ystreet00@gmail.com>
Wed, 14 Aug 2013 00:44:19 +0000 (10:44 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:30 +0000 (19:31 +0000)
At the moment it just sits in between GstGLDisplay and GstGLWindow
performing some of the stuff that GstGLWindow used to do.

19 files changed:
gst-libs/gst/gl/Makefile.am
gst-libs/gst/gl/android/gstglwindow_android_egl.c
gst-libs/gst/gl/gl.h
gst-libs/gst/gl/gstgl_fwd.h
gst-libs/gst/gl/gstglcontext.c [new file with mode: 0644]
gst-libs/gst/gl/gstglcontext.h [new file with mode: 0644]
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstglfeature.c
gst-libs/gst/gl/gstglfilter.c
gst-libs/gst/gl/gstglmixer.c
gst-libs/gst/gl/gstglutils.c
gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c
gst-libs/gst/gl/win32/gstglwindow_win32_egl.c
gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c
gst-libs/gst/gl/x11/gstglwindow_x11_egl.c
gst-libs/gst/gl/x11/gstglwindow_x11_glx.c

index 9f47797..e9d60b8 100644 (file)
@@ -8,6 +8,7 @@ noinst_HEADERS =
 
 libgstgl_@GST_API_VERSION@_la_SOURCES = \
        gstgldisplay.c \
+       gstglcontext.c \
        gstglmemory.c \
        gstglbufferpool.c \
        gstglfilter.c \
@@ -64,6 +65,7 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \
        gstglconfig.h \
        gstglwindow.h \
        gstgldisplay.h \
+       gstglcontext.h \
        gstglmemory.h \
        gstglbufferpool.h \
        gstgles2.h \
index 1726068..78ab730 100644 (file)
@@ -28,6 +28,9 @@
 #include "config.h"
 #endif
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include "gstglwindow_android_egl.h"
 
 #define GST_CAT_DEFAULT gst_gl_window_debug
@@ -307,13 +310,14 @@ static gpointer
 gst_gl_window_android_egl_get_proc_address (GstGLWindow * window,
     const gchar * name)
 {
+  GstGLContext *context = NULL;
   GstGLWindowAndroidEGL *window_egl;
   gpointer result;
 
   window_egl = GST_GL_WINDOW_ANDROID_EGL (window);
 
   if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) {
-    result = gst_gl_window_default_get_proc_address (window, name);
+    result = gst_gl_context_default_get_proc_address (context, name);
   }
 
   return result;
index 3f3a277..07d9478 100644 (file)
@@ -25,6 +25,7 @@
 #include <gst/gl/gstglconfig.h>
 #include <gst/gl/gstglapi.h>
 #include <gst/gl/gstgldisplay.h>
+#include <gst/gl/gstglcontext.h>
 #include <gst/gl/gstglfeature.h>
 #include <gst/gl/gstglutils.h>
 #include <gst/gl/gstglwindow.h>
index b130504..8de50c2 100644 (file)
@@ -31,6 +31,10 @@ typedef struct _GstGLDisplay GstGLDisplay;
 typedef struct _GstGLDisplayClass GstGLDisplayClass;
 typedef struct _GstGLDisplayPrivate GstGLDisplayPrivate;
 
+typedef struct _GstGLContext GstGLContext;
+typedef struct _GstGLContextClass GstGLContextClass;
+typedef struct _GstGLContextPrivate GstGLContextPrivate;
+
 typedef struct _GstGLWindow        GstGLWindow;
 typedef struct _GstGLWindowPrivate GstGLWindowPrivate;
 typedef struct _GstGLWindowClass   GstGLWindowClass;
diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c
new file mode 100644 (file)
index 0000000..7bd8754
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 Matthew Waters <ystreet00@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gmodule.h>
+
+#include "gl.h"
+#include "gstglcontext.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_context_debug
+GST_DEBUG_CATEGORY (GST_CAT_DEFAULT);
+
+#define gst_gl_context_parent_class parent_class
+G_DEFINE_TYPE (GstGLContext, gst_gl_context, G_TYPE_OBJECT);
+
+#define GST_GL_CONTEXT_GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT, GstGLContextPrivate))
+
+static gpointer gst_gl_context_create_thread (GstGLContext * context);
+static void gst_gl_context_finalize (GObject * object);
+
+struct _GstGLContextPrivate
+{
+  GstGLDisplay *display;
+
+  GThread *gl_thread;
+
+  /* conditions */
+  GMutex render_lock;
+  GCond create_cond;
+  GCond destroy_cond;
+
+  gboolean created;
+  gboolean alive;
+
+  guintptr external_gl_context;
+  GstGLAPI gl_api;
+  GError **error;
+};
+
+GQuark
+gst_gl_context_error_quark (void)
+{
+  return g_quark_from_static_string ("gst-gl-context-error-quark");
+}
+
+static void
+_ensure_window (GstGLContext * context)
+{
+  GstGLWindow *window;
+
+  if (context->window)
+    return;
+
+  window = gst_gl_window_new (context->priv->display);
+
+  gst_gl_context_set_window (context, window);
+}
+
+static void
+gst_gl_context_init (GstGLContext * context)
+{
+  context->priv = GST_GL_CONTEXT_GET_PRIVATE (context);
+
+  g_mutex_init (&context->priv->render_lock);
+
+  g_cond_init (&context->priv->create_cond);
+  g_cond_init (&context->priv->destroy_cond);
+  context->priv->created = FALSE;
+}
+
+static void
+gst_gl_context_class_init (GstGLContextClass * klass)
+{
+  g_type_class_add_private (klass, sizeof (GstGLContextPrivate));
+
+  klass->get_proc_address =
+      GST_DEBUG_FUNCPTR (gst_gl_context_default_get_proc_address);
+
+  G_OBJECT_CLASS (klass)->finalize = gst_gl_context_finalize;
+}
+
+GstGLContext *
+gst_gl_context_new (GstGLDisplay * display)
+{
+  GstGLContext *context = NULL;
+  const gchar *user_choice;
+  static volatile gsize _init = 0;
+
+  if (g_once_init_enter (&_init)) {
+    GST_DEBUG_CATEGORY_INIT (gst_gl_context_debug, "glcontext", 0,
+        "glcontext element");
+    g_once_init_leave (&_init, 1);
+  }
+
+  user_choice = g_getenv ("GST_GL_PLATFORM");
+  GST_INFO ("creating a context, user choice:%s", user_choice);
+#if 0
+#if GST_GL_HAVE_PLATFORM_EGL
+  if (!context && (!user_choice || g_strstr_len (user_choice, 7, "egl")))
+    context = GST_GL_CONTEXT (gst_gl_context_egl_new ());
+#endif
+#if GST_GL_HAVE_PLATFORM_GLX
+  if (!context && (!user_choice || g_strstr_len (user_choice, 3, "glx")))
+    context = GST_GL_CONTEXT (gst_gl_context_glx_new ());
+#endif
+#if GST_GL_HAVE_PLATFORM_WIN32
+  if (!context && (!user_choice || g_strstr_len (user_choice, 5, "win32")))
+    context = GST_GL_CONTEXT (gst_gl_context_win32_new ());
+#endif
+#if GST_GL_HAVE_PLATFORM_COCOA
+  if (!context && (!user_choice || g_strstr_len (user_choice, 5, "cocoa"))) {
+    context = GST_GL_CONTEXT (gst_gl_context_cocoa_new ());
+  }
+#endif
+  if (!context) {
+    /* subclass returned a NULL context */
+    GST_WARNING ("Could not create context. user specified %s",
+        user_choice ? user_choice : "(null)");
+
+    return NULL;
+  }
+#endif
+
+  context = g_object_new (GST_GL_TYPE_CONTEXT, NULL);
+
+  context->priv->display = display;
+
+  return context;
+}
+
+static void
+gst_gl_context_finalize (GObject * object)
+{
+  GstGLContext *context = GST_GL_CONTEXT (object);
+
+  gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL);
+  gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL);
+
+  if (context->priv->alive) {
+    GST_INFO ("send quit gl window loop");
+    gst_gl_window_quit (context->window);
+    g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock);
+  }
+
+  gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL);
+
+  if (context->priv->gl_thread) {
+    gpointer ret = g_thread_join (context->priv->gl_thread);
+    GST_INFO ("gl thread joined");
+    if (ret != NULL)
+      GST_ERROR ("gl thread returned a non-null pointer");
+    context->priv->gl_thread = NULL;
+  }
+
+  gst_object_unref (context->window);
+
+  g_mutex_clear (&context->priv->render_lock);
+
+  g_cond_clear (&context->priv->destroy_cond);
+  g_cond_clear (&context->priv->create_cond);
+
+  G_OBJECT_CLASS (gst_gl_context_parent_class)->finalize (object);
+}
+
+/* FIXME move the relevant window vfuncs into GstGLContext */
+gboolean
+gst_gl_context_activate (GstGLContext * context, gboolean activate)
+{
+  GstGLWindowClass *window_class;
+  gboolean result;
+
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
+  window_class = GST_GL_WINDOW_GET_CLASS (context->window);
+  g_return_val_if_fail (window_class->activate != NULL, FALSE);
+
+  result = window_class->activate (context->window, activate);
+
+  return result;
+}
+
+GstGLAPI
+gst_gl_context_get_gl_api (GstGLContext * context)
+{
+  GstGLWindowClass *window_class;
+
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), GST_GL_API_NONE);
+  window_class = GST_GL_WINDOW_GET_CLASS (context->window);
+  g_return_val_if_fail (window_class->get_gl_api != NULL, GST_GL_API_NONE);
+
+  return window_class->get_gl_api (context->window);
+}
+
+gpointer
+gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name)
+{
+  gpointer ret;
+  GstGLWindowClass *window_class;
+
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
+  window_class = GST_GL_WINDOW_GET_CLASS (context->window);
+  g_return_val_if_fail (window_class->get_proc_address != NULL, NULL);
+
+  ret = window_class->get_proc_address (context->window, name);
+
+  return ret;
+}
+
+gpointer
+gst_gl_context_default_get_proc_address (GstGLContext * context,
+    const gchar * name)
+{
+  static GModule *module = NULL;
+  gpointer ret = NULL;
+
+  if (!module)
+    module = g_module_open (NULL, G_MODULE_BIND_LAZY);
+
+  if (module) {
+    if (!g_module_symbol (module, name, &ret))
+      return NULL;
+  }
+
+  return ret;
+}
+
+gboolean
+gst_gl_context_set_window (GstGLContext * context, GstGLWindow * window)
+{
+  /* we can't change the window while we are running */
+  if (context->priv->alive)
+    return FALSE;
+
+  if (window) {
+    if (gst_gl_window_is_running (window))
+      return FALSE;
+
+    g_weak_ref_set (&window->context_ref, context);
+  }
+
+  if (context->window)
+    gst_object_unref (context->window);
+
+  context->window = window ? gst_object_ref (window) : NULL;
+
+  return TRUE;
+}
+
+GstGLWindow *
+gst_gl_context_get_window (GstGLContext * context)
+{
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL);
+
+  _ensure_window (context);
+
+  return gst_object_ref (context->window);
+}
+
+/* Create an opengl context (one context for one GstGLDisplay) */
+gboolean
+gst_gl_context_create (GstGLContext * context,
+    guintptr external_gl_context, GError ** error)
+{
+  gboolean alive = FALSE;
+  GstGLWindowClass *window_class;
+
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
+  window_class = GST_GL_WINDOW_GET_CLASS (context->window);
+  g_return_val_if_fail (window_class->create_context != NULL, FALSE);
+
+  _ensure_window (context);
+
+  g_mutex_lock (&context->priv->render_lock);
+
+  if (window_class->open) {
+    if (!(alive = window_class->open (context->window, error)))
+      goto out;
+  }
+
+  if (!context->priv->created) {
+    context->priv->external_gl_context = external_gl_context;
+    context->priv->error = error;
+
+    context->priv->gl_thread = g_thread_new ("gstglcontext",
+        (GThreadFunc) gst_gl_context_create_thread, context);
+
+    g_cond_wait (&context->priv->create_cond, &context->priv->render_lock);
+
+    context->priv->created = TRUE;
+
+    GST_INFO ("gl thread created");
+  }
+
+  alive = context->priv->alive;
+
+  g_mutex_unlock (&context->priv->render_lock);
+
+out:
+  return alive;
+}
+
+static gboolean
+_create_context_gles2 (GstGLContext * context, gint * gl_major, gint * gl_minor,
+    GError ** error)
+{
+  GstGLDisplay *display;
+  const GstGLFuncs *gl;
+  GLenum gl_err = GL_NO_ERROR;
+
+  display = context->priv->display;
+  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) {
+    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_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_CONTEXT_ERROR, GST_GL_CONTEXT_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 (GstGLContext * context, gint * gl_major,
+    gint * gl_minor, GError ** error)
+{
+  GstGLDisplay *display;
+  const GstGLFuncs *gl;
+  guint maj, min;
+  GLenum gl_err = GL_NO_ERROR;
+  GString *opengl_version = NULL;
+
+  display = context->priv->display;
+  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) {
+    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_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_CONTEXT_ERROR, GST_GL_CONTEXT_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 | GST_GL_API_OPENGL3;
+#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;
+}
+
+//gboolean
+//gst_gl_context_create (GstGLContext * context, guintptr external_gl_context, GError ** error)
+static gpointer
+gst_gl_context_create_thread (GstGLContext * context)
+{
+  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;
+  guintptr external_gl_context;
+
+  error = context->priv->error;
+  external_gl_context = context->priv->external_gl_context;
+
+  window_class = GST_GL_WINDOW_GET_CLASS (context->window);
+
+  if (window_class->open) {
+    if (!window_class->open (context->window, error))
+      goto failure;
+  }
+
+  display = context->priv->display;
+  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);
+
+  if ((user_api & compiled_api) == GST_GL_API_NONE) {
+    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
+        "Cannot create context with the user requested api (%s).  "
+        "We have support for (%s)", user_api_string, compiled_api_s);
+    g_free (user_api_string);
+    g_free (compiled_api_s);
+    goto failure;
+  }
+
+  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 (context->window, compiled_api & user_api,
+          external_gl_context, error)) {
+    g_assert (error == NULL || *error != NULL);
+    g_free (compiled_api_s);
+    g_free (user_api_string);
+    goto failure;
+  }
+  GST_INFO ("context created context");
+
+  display->gl_api = gst_gl_context_get_gl_api (context);
+  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_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API,
+        "failed to create context, context "
+        "could not provide correct api. user (%s), compiled (%s), context (%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_context_get_proc_address (context, "glGetError");
+  gl->GetString = gst_gl_context_get_proc_address (context, "glGetString");
+
+  if (!gl->GetError || !gl->GetString) {
+    g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED,
+        "could not GetProcAddress core opengl functions");
+    goto failure;
+  }
+
+  /* gl api specific code */
+  if (!ret && USING_OPENGL (display))
+    ret = _create_context_opengl (context, &gl_major, NULL, error);
+  if (!ret && USING_GLES2 (display))
+    ret = _create_context_gles2 (context, &gl_major, NULL, error);
+
+  if (!ret)
+    goto failure;
+
+  context->priv->alive = TRUE;
+
+  g_cond_signal (&context->priv->create_cond);
+  g_mutex_unlock (&context->priv->render_lock);
+
+  gst_gl_window_run (context->window);
+
+  GST_INFO ("loop exited\n");
+
+  g_mutex_lock (&context->priv->render_lock);
+
+  context->priv->alive = FALSE;
+
+  if (window_class->close) {
+    window_class->close (context->window);
+  }
+
+  context_class->activate (context, FALSE);
+
+  context_class->destroy_context (context);
+
+  if (context->window->close)
+    context->window->close (context->window->close_data);
+
+  g_cond_signal (&context->priv->destroy_cond);
+
+  g_mutex_unlock (&context->priv->render_lock);
+
+  return NULL;
+
+failure:
+  {
+    g_cond_signal (&context->priv->create_cond);
+    g_mutex_unlock (&context->priv->render_lock);
+    return NULL;
+  }
+}
+
+guintptr
+gst_gl_context_get_gl_context (GstGLContext * context)
+{
+  GstGLContextClass *context_class;
+  guintptr result;
+
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (context), 0);
+  context_class = GST_GL_CONTEXT_GET_CLASS (context);
+  g_return_val_if_fail (context_class->get_gl_context != NULL, 0);
+
+  result = context_class->get_gl_context (context);
+
+  return result;
+}
diff --git a/gst-libs/gst/gl/gstglcontext.h b/gst-libs/gst/gl/gstglcontext.h
new file mode 100644 (file)
index 0000000..10c30a7
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_GL_CONTEXT_H__
+#define __GST_GL_CONTEXT_H__
+
+#include <gst/gst.h>
+
+#include <gst/gl/gstgl_fwd.h>
+
+G_BEGIN_DECLS
+
+#define GST_GL_TYPE_CONTEXT         (gst_gl_context_get_type())
+#define GST_GL_CONTEXT(o)           (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_CONTEXT, GstGLContext))
+#define GST_GL_CONTEXT_CLASS(k)     (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT, GstGLContextClass))
+#define GST_GL_IS_CONTEXT(o)        (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_CONTEXT))
+#define GST_GL_IS_CONTEXT_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_CONTEXT))
+#define GST_GL_CONTEXT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_CONTEXT, GstGLContextClass))
+GType gst_gl_context_get_type     (void);
+
+#define GST_GL_CONTEXT_ERROR (gst_gl_context_error_quark ())
+GQuark gst_gl_window_error_quark (void);
+
+typedef enum
+{
+  GST_GL_CONTEXT_ERROR_FAILED,
+  GST_GL_CONTEXT_ERROR_WRONG_CONFIG,
+  GST_GL_CONTEXT_ERROR_WRONG_API,
+  GST_GL_CONTEXT_ERROR_OLD_LIBS,
+  GST_GL_CONTEXT_ERROR_CREATE_CONTEXT,
+  GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE,
+} GstGLContextError;
+
+struct _GstGLContext {
+  /*< private >*/
+  GObject parent;
+
+  /*< public >*/
+  GstGLWindow  *window;
+
+  /*< private >*/
+  gpointer _reserved[GST_PADDING];
+
+  GstGLContextPrivate *priv;
+};
+
+struct _GstGLContextClass {
+  /*< private >*/
+  GObjectClass parent_class;
+
+  guintptr (*get_gl_context)     (GstGLContext *context);
+  GstGLAPI (*get_gl_api)         (GstGLContext *context);
+  gpointer (*get_proc_address)   (GstGLContext *context, const gchar *name);
+  gboolean (*activate)           (GstGLContext *context, gboolean activate);
+  gboolean (*create_context)     (GstGLContext *context, GstGLAPI gl_api,
+                                  guintptr external_gl_context, GError ** error);
+
+  /*< private >*/
+  gpointer _reserved[GST_PADDING];
+};
+
+/* methods */
+
+GstGLContext * gst_gl_context_new  (GstGLDisplay *display);
+
+gboolean      gst_gl_context_activate         (GstGLContext *context, gboolean activate);
+
+gpointer      gst_gl_context_get_proc_address (GstGLContext *context, const gchar *name);
+GstGLPlatform gst_gl_context_get_platform     (GstGLContext *context);
+GstGLAPI      gst_gl_context_get_gl_api       (GstGLContext *context);
+
+gboolean      gst_gl_context_create           (GstGLContext *context, guintptr external_gl_context, GError ** error);
+
+gpointer      gst_gl_context_default_get_proc_address (GstGLContext *context, const gchar *name);
+
+gboolean      gst_gl_context_set_window (GstGLContext *context, GstGLWindow *window);
+GstGLWindow * gst_gl_context_get_window (GstGLContext *context);
+
+G_END_DECLS
+
+#endif /* __GST_GL_CONTEXT_H__ */
index 2dd1540..ed0e886 100644 (file)
@@ -81,14 +81,21 @@ gst_gl_display_finalize (GObject * object)
     display->gl_vtable = NULL;
   }
 
-  if (display->window) {
-    gst_object_unref (display->window);
-    display->window = NULL;
+  if (display->context) {
+    gst_object_unref (display->context);
+    display->context = NULL;
   }
 
   G_OBJECT_CLASS (gst_gl_display_parent_class)->finalize (object);
 }
 
+GstGLDisplay *
+gst_gl_display_new (void)
+{
+  return g_object_new (GST_TYPE_GL_DISPLAY, NULL);
+}
+
+#if 1
 typedef struct
 {
   GstGLDisplay *display;
@@ -104,37 +111,36 @@ _gst_gl_display_thread_run_generic (RunGenericData * data)
   data->func (data->display, data->data);
 }
 
-GstGLDisplay *
-gst_gl_display_new (void)
-{
-  return g_object_new (GST_TYPE_GL_DISPLAY, NULL);
-}
-
 void
 gst_gl_display_thread_add (GstGLDisplay * display,
     GstGLDisplayThreadFunc func, gpointer data)
 {
+  GstGLWindow *window;
   RunGenericData rdata;
 
   g_return_if_fail (GST_IS_GL_DISPLAY (display));
-  g_return_if_fail (GST_GL_IS_WINDOW (display->window));
+  g_return_if_fail (GST_GL_IS_CONTEXT (display->context));
   g_return_if_fail (func != NULL);
 
   rdata.display = display;
   rdata.data = data;
   rdata.func = func;
 
-  gst_gl_window_send_message (display->window,
+  window = gst_gl_context_get_window (display->context);
+
+  gst_gl_window_send_message (window,
       GST_GL_WINDOW_CB (_gst_gl_display_thread_run_generic), &rdata);
+
+  gst_object_unref (window);
 }
 
 GstGLAPI
 gst_gl_display_get_gl_api (GstGLDisplay * display)
 {
   g_return_val_if_fail (GST_IS_GL_DISPLAY (display), GST_GL_API_NONE);
-  g_return_val_if_fail (GST_GL_IS_WINDOW (display->window), GST_GL_API_NONE);
+  g_return_val_if_fail (GST_GL_IS_CONTEXT (display->context), GST_GL_API_NONE);
 
-  return gst_gl_window_get_gl_api (display->window);
+  return gst_gl_context_get_gl_api (display->context);
 }
 
 gpointer
@@ -144,45 +150,46 @@ gst_gl_display_get_gl_vtable (GstGLDisplay * display)
 
   return display->gl_vtable;
 }
+#endif
 
 void
-gst_gl_display_set_window (GstGLDisplay * display, GstGLWindow * window)
+gst_gl_display_set_context (GstGLDisplay * display, GstGLContext * context)
 {
   g_return_if_fail (GST_IS_GL_DISPLAY (display));
-  g_return_if_fail (GST_GL_IS_WINDOW (window));
+  g_return_if_fail (GST_GL_IS_CONTEXT (context));
 
   gst_gl_display_lock (display);
 
-  if (display->window)
-    gst_object_unref (display->window);
+  if (display->context)
+    gst_object_unref (display->context);
 
-  display->window = gst_object_ref (window);
+  display->context = gst_object_ref (context);
 
   gst_gl_display_unlock (display);
 }
 
-GstGLWindow *
-gst_gl_display_get_window (GstGLDisplay * display)
+GstGLContext *
+gst_gl_display_get_context (GstGLDisplay * display)
 {
-  GstGLWindow *window;
+  GstGLContext *context;
 
   g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
 
   gst_gl_display_lock (display);
 
-  window = display->window ? gst_object_ref (display->window) : NULL;
+  context = display->context ? gst_object_ref (display->context) : NULL;
 
   gst_gl_display_unlock (display);
 
-  return window;
+  return context;
 }
 
-GstGLWindow *
-gst_gl_display_get_window_unlocked (GstGLDisplay * display)
+GstGLContext *
+gst_gl_display_get_context_unlocked (GstGLDisplay * display)
 {
   g_return_val_if_fail (GST_IS_GL_DISPLAY (display), NULL);
 
-  return display->window ? gst_object_ref (display->window) : NULL;
+  return display->context ? gst_object_ref (display->context) : NULL;
 }
 
 void
index 9cbb21a..a430a32 100644 (file)
@@ -57,7 +57,7 @@ struct _GstGLDisplay
   GstObject             object;
 
   /* <private> */
-  GstGLWindow          *window;
+  GstGLContext         *context;
   GstGLAPI              gl_api;
 
   GstGLFuncs           *gl_vtable;
@@ -75,11 +75,11 @@ GstGLDisplay *gst_gl_display_new (void);
 #define gst_gl_display_lock(display)        GST_OBJECT_LOCK (display)
 #define gst_gl_display_unlock(display)      GST_OBJECT_UNLOCK (display)
 
-GstGLAPI      gst_gl_display_get_gl_api             (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);
+GstGLAPI       gst_gl_display_get_gl_api             (GstGLDisplay * display);
+gpointer       gst_gl_display_get_gl_vtable          (GstGLDisplay * display);
+void           gst_gl_display_set_context             (GstGLDisplay * display, GstGLContext * context);
+GstGLContext * gst_gl_display_get_context             (GstGLDisplay * display);
+GstGLContext * gst_gl_display_get_context_unlocked    (GstGLDisplay * display);
 
 void gst_gl_display_thread_add (GstGLDisplay * display,
     GstGLDisplayThreadFunc func, gpointer data);
index f599e48..df6f0fd 100644 (file)
@@ -149,7 +149,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
   const char *suffix = NULL;
   int func_num;
   GstGLFuncs *gst_gl = display->gl_vtable;
-  GstGLWindow *window = NULL;
+  GstGLContext *context = NULL;
 
   /* First check whether the functions should be directly provided by
      GL */
@@ -172,8 +172,8 @@ _gst_gl_feature_check (GstGLDisplay * display,
   if (suffix == NULL)
     goto error;
 
-  window = gst_gl_display_get_window (display);
-  g_assert (window);
+  context = gst_gl_display_get_context (display);
+  g_assert (context);
 
   /* Try to get all of the entry points */
   for (func_num = 0; data->functions[func_num].name; func_num++) {
@@ -186,7 +186,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 (window, full_function_name);
+    func = gst_gl_context_get_proc_address (context, full_function_name);
 
     if (func == NULL && in_core) {
       GST_TRACE ("%s was not found in core, trying the extension version",
@@ -198,7 +198,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 (window, full_function_name);
+        func = gst_gl_context_get_proc_address (context, full_function_name);
       }
     }
 
@@ -213,7 +213,7 @@ _gst_gl_feature_check (GstGLDisplay * display,
   }
 
   g_free (full_function_name);
-  gst_object_unref (window);
+  gst_object_unref (context);
 
   return TRUE;
 
@@ -232,8 +232,8 @@ error:
     g_free (full_function_name);
   }
 
-  if (window)
-    gst_object_unref (window);
+  if (context)
+    gst_object_unref (context);
 
   return FALSE;
 }
index b6743dc..d93903f 100644 (file)
@@ -256,16 +256,16 @@ gst_gl_filter_start (GstBaseTransform * bt)
     filter->display =
         gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
   else {
-    GstGLWindow *window;
+    GstGLContext *context;
     GError *error = NULL;
 
     GST_INFO ("Creating GstGLDisplay");
     filter->display = gst_gl_display_new ();
-    window = gst_gl_window_new (filter->display);
-    gst_gl_display_set_window (filter->display, window);
-    gst_object_unref (window);
+    context = gst_gl_context_new (filter->display);
+    gst_gl_display_set_context (filter->display, context);
+    gst_object_unref (context);
 
-    if (!gst_gl_window_create_context (window, 0, &error)) {
+    if (!gst_gl_context_create (context, 0, &error)) {
       GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND,
           ("%s", error->message), (NULL));
       return FALSE;
index 748e5a8..53a3c2c 100644 (file)
@@ -935,16 +935,16 @@ gst_gl_mixer_activate (GstGLMixer * mix, gboolean activate)
       mix->display =
           gst_object_ref (GST_GL_DISPLAY (g_value_get_pointer (id_value)));
     else {
-      GstGLWindow *window;
+      GstGLContext *context;
       GError *error = NULL;
 
       GST_INFO ("Creating GstGLDisplay");
       mix->display = gst_gl_display_new ();
-      window = gst_gl_window_new (mix->display);
-      gst_gl_display_set_window (mix->display, window);
-      gst_object_unref (window);
+      context = gst_gl_context_new (mix->display);
+      gst_gl_display_set_context (mix->display, context);
+      gst_object_unref (context);
 
-      if (!gst_gl_window_create_context (window, 0, &error)) {
+      if (!gst_gl_context_create (context, 0, &error)) {
         GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND,
             ("%s", error->message), (NULL));
         return FALSE;
index 02bfb7d..4039682 100644 (file)
@@ -141,32 +141,34 @@ gst_gl_display_check_framebuffer_status (GstGLDisplay * display)
 void
 gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate)
 {
-  GstGLWindow *window;
+  GstGLContext *context;
 
   g_return_if_fail (GST_IS_GL_DISPLAY (display));
 
   if (!activate)
     gst_gl_display_lock (display);
 
-  window = gst_gl_display_get_window_unlocked (display);
+  context = gst_gl_display_get_context_unlocked (display);
 
-  gst_gl_window_activate (window, activate);
+  gst_gl_context_activate (context, activate);
 
   if (activate)
     gst_gl_display_unlock (display);
 
-  gst_object_unref (window);
+  gst_object_unref (context);
 }
 
 void
 gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture,
     GstVideoFormat v_format, GLint width, GLint height)
 {
+  GstGLContext *context;
   GstGLWindow *window;
 
   gst_gl_display_lock (display);
 
-  window = gst_gl_display_get_window_unlocked (display);
+  context = gst_gl_display_get_context_unlocked (display);
+  window = gst_gl_context_get_window (context);
 
   if (gst_gl_window_is_running (window)) {
     gen_texture_width = width;
@@ -178,6 +180,7 @@ gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture,
   } else
     *pTexture = 0;
 
+  gst_object_unref (context);
   gst_object_unref (window);
 
   gst_gl_display_unlock (display);
@@ -186,17 +189,20 @@ gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture,
 void
 gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture)
 {
+  GstGLContext *context;
   GstGLWindow *window;
 
   gst_gl_display_lock (display);
 
-  window = gst_gl_display_get_window_unlocked (display);
+  context = gst_gl_display_get_context_unlocked (display);
+  window = gst_gl_context_get_window (context);
   if (gst_gl_window_is_running (window) && *pTexture) {
     del_texture = pTexture;
     gst_gl_window_send_message (window,
         GST_GL_WINDOW_CB (gst_gl_display_del_texture_window_cb), display);
   }
 
+  gst_object_unref (context);
   gst_object_unref (window);
 
   gst_gl_display_unlock (display);
index fe28edb..8349c43 100644 (file)
@@ -78,7 +78,6 @@ struct _GstGLWindowPrivate
   GError **error;
 };
 
-static gpointer _gst_gl_window_thread_create_context (GstGLWindow * window);
 static void gst_gl_window_finalize (GObject * object);
 
 GQuark
@@ -99,6 +98,8 @@ gst_gl_window_init (GstGLWindow * window)
   g_cond_init (&window->priv->cond_create_context);
   g_cond_init (&window->priv->cond_destroy_context);
   window->priv->context_created = FALSE;
+
+  g_weak_ref_init (&window->context_ref, NULL);
 }
 
 static void
@@ -106,9 +107,6 @@ 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;
 }
 
@@ -167,28 +165,7 @@ gst_gl_window_finalize (GObject * object)
 {
   GstGLWindow *window = GST_GL_WINDOW (object);
 
-  gst_gl_window_set_resize_callback (window, NULL, NULL, NULL);
-  gst_gl_window_set_draw_callback (window, NULL, NULL, NULL);
-
-  if (window->priv->alive) {
-    GST_INFO ("send quit gl window loop");
-    gst_gl_window_quit (window);
-  }
-
-  gst_gl_window_set_close_callback (window, NULL, 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_weak_ref_clear (&window->context_ref);
 
   G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
 }
@@ -278,6 +255,7 @@ gst_gl_window_run (GstGLWindow * window)
   g_return_if_fail (window_class->run != NULL);
 
   GST_GL_WINDOW_LOCK (window);
+  window->priv->alive = TRUE;
   window_class->run (window);
   GST_GL_WINDOW_UNLOCK (window);
 }
@@ -301,7 +279,6 @@ gst_gl_window_quit (GstGLWindow * window)
 
   GST_GL_WINDOW_UNLOCK (window);
 
-  g_cond_wait (&window->priv->cond_destroy_context, &window->priv->render_lock);
   GST_INFO ("quit received from gl window");
 }
 
@@ -423,338 +400,16 @@ gst_gl_window_get_proc_address (GstGLWindow * window, const gchar * name)
   return ret;
 }
 
-gpointer
-gst_gl_window_default_get_proc_address (GstGLWindow * window,
-    const gchar * name)
-{
-  static GModule *module = NULL;
-  gpointer ret = NULL;
-
-  if (!module)
-    module = g_module_open (NULL, G_MODULE_BIND_LAZY);
-
-  if (module) {
-    if (!g_module_symbol (module, name, &ret))
-      return NULL;
-  }
-
-  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_class->open) {
-    if (!(alive = window_class->open (window, error)))
-      goto out;
-  }
-
-  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);
-
-out:
-  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,
-    GError ** error)
-{
-  GstGLDisplay *display;
-  const GstGLFuncs *gl;
-  GLenum gl_err = GL_NO_ERROR;
-
-  display = window->priv->display;
-  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) {
-    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,
-    GError ** error)
-{
-  GstGLDisplay *display;
-  const GstGLFuncs *gl;
-  guint maj, min;
-  GLenum gl_err = GL_NO_ERROR;
-  GString *opengl_version = NULL;
-
-  display = window->priv->display;
-  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) {
-    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 | GST_GL_API_OPENGL3;
-#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)
+GstGLContext *
+gst_gl_window_get_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);
-
-  if ((user_api & compiled_api) == GST_GL_API_NONE) {
-    g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API,
-        "Cannot create context with the user requested api (%s).  "
-        "We have support for (%s)", user_api_string, compiled_api_s);
-    g_free (user_api_string);
-    g_free (compiled_api_s);
-    goto failure;
-  }
-
-  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, error);
-  if (!ret && USING_GLES2 (display))
-    ret = _create_context_gles2 (window, &gl_major, NULL, error);
-
-  if (!ret)
-    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;
-
-  if (window_class->close) {
-    window_class->close (window);
-    if (window->close)
-      window->close (window->close_data);
-  }
-
-  g_cond_signal (&window->priv->cond_destroy_context);
-
-  g_mutex_unlock (&window->priv->render_lock);
-
-  return NULL;
+  g_return_val_if_fail (GST_GL_IS_WINDOW (window), NULL);
 
-failure:
-  {
-    g_cond_signal (&window->priv->cond_create_context);
-    g_mutex_unlock (&window->priv->render_lock);
-    return NULL;
-  }
+  return (GstGLContext *) g_weak_ref_get (&window->context_ref);
 }
index e19e75c..f7aae8c 100644 (file)
@@ -75,6 +75,8 @@ struct _GstGLWindow {
   GMutex        lock;
   gboolean      need_lock;
 
+  GWeakRef      context_ref;
+
   guintptr      external_gl_context;
 
   GstGLWindowCB         draw;
@@ -131,7 +133,6 @@ void     gst_gl_window_set_close_callback   (GstGLWindow *window, GstGLWindowCB
 void     gst_gl_window_set_need_lock        (GstGLWindow *window, gboolean need_lock);
 
 guintptr gst_gl_window_get_gl_context       (GstGLWindow *window);
-gboolean gst_gl_window_activate            (GstGLWindow *window, gboolean activate);
 void     gst_gl_window_set_window_handle    (GstGLWindow *window, guintptr handle);
 guintptr gst_gl_window_get_window_handle    (GstGLWindow *window);
 void     gst_gl_window_draw_unlocked        (GstGLWindow *window, guint width, guint height);
@@ -140,13 +141,7 @@ void     gst_gl_window_run                  (GstGLWindow *window);
 void     gst_gl_window_quit                 (GstGLWindow *window);
 void     gst_gl_window_send_message         (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
 
-gpointer      gst_gl_window_get_proc_address (GstGLWindow *window, const gchar *name);
-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, guintptr external_gl_context, GError ** error);
-
-gpointer gst_gl_window_default_get_proc_address (GstGLWindow *window, const gchar *name);
+GstGLContext * gst_gl_window_get_context (GstGLWindow *window);
 
 gboolean gst_gl_window_is_running (GstGLWindow *window);
 
index f8c06ad..16215d5 100644 (file)
@@ -27,6 +27,9 @@
 
 #include "wayland_event_source.h"
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include "gstglwindow_wayland_egl.h"
 
 const gchar *WlEGLErrorString ();
@@ -572,13 +575,14 @@ static gpointer
 gst_gl_window_wayland_egl_get_proc_address (GstGLWindow * window,
     const gchar * name)
 {
+  GstGLContext *context = NULL;
   GstGLWindowWaylandEGL *window_egl;
   gpointer result;
 
   window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
 
   if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) {
-    result = gst_gl_window_default_get_proc_address (window, name);
+    result = gst_gl_context_default_get_proc_address (context, name);
   }
 
   return result;
index 6229c51..6aa4903 100644 (file)
@@ -25,6 +25,9 @@
 
 #include <gst/gst.h>
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include "gstglwindow_win32_egl.h"
 
 static guintptr gst_gl_window_win32_wgl_get_gl_context (GstGLWindowWin32 *
index e85a011..0635967 100644 (file)
@@ -27,6 +27,9 @@
 
 #include <gst/gst.h>
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include "gstglwindow_win32_wgl.h"
 
 #define GST_CAT_DEFAULT gst_gl_window_debug
@@ -215,10 +218,11 @@ static gpointer
 gst_gl_window_win32_wgl_get_proc_address (GstGLWindow * window,
     const gchar * name)
 {
+  GstGLContext *context;
   gpointer result;
 
   if (!(result = wglGetProcAddress ((LPCSTR) name))) {
-    result = gst_gl_window_default_get_proc_address (window, name);
+    result = gst_gl_context_default_get_proc_address (context, name);
   }
 
   return result;
index 7ff1347..45413fb 100644 (file)
@@ -25,6 +25,9 @@
 #include "config.h"
 #endif
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include "gstglwindow_x11_egl.h"
 
 const gchar *X11EGLErrorString ();
@@ -188,11 +191,12 @@ static gpointer
 gst_gl_window_x11_egl_get_proc_address (GstGLWindow * window,
     const gchar * name)
 {
+  GstGLContext *context = NULL;
   GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window);
   gpointer result;
 
   if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) {
-    result = gst_gl_window_default_get_proc_address (window, name);
+    result = gst_gl_context_default_get_proc_address (context, name);
   }
 
   return result;
index d62a990..9325029 100644 (file)
@@ -27,6 +27,9 @@
 
 #include <gst/gst.h>
 
+#include "../gstgl_fwd.h"
+#include <gst/gl/gstglcontext.h>
+
 #include <gst/gl/gl.h>
 #include "gstglwindow_x11_glx.h"
 
@@ -352,10 +355,11 @@ static gpointer
 gst_gl_window_x11_glx_get_proc_address (GstGLWindow * window,
     const gchar * name)
 {
+  GstGLContext *context = NULL;
   gpointer result;
 
   if (!(result = glXGetProcAddressARB ((const GLubyte *) name))) {
-    result = gst_gl_window_default_get_proc_address (window, name);
+    result = gst_gl_context_default_get_proc_address (context, name);
   }
 
   return result;