glcontext: add api for retreiving the current context and api
authorMatthew Waters <matthew@centricular.com>
Tue, 28 Oct 2014 06:31:37 +0000 (17:31 +1100)
committerMatthew Waters <matthew@centricular.com>
Tue, 28 Oct 2014 06:33:20 +0000 (17:33 +1100)
that is current in the calling thread.

14 files changed:
docs/libs/gst-plugins-bad-libs-sections.txt
gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h
gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
gst-libs/gst/gl/eagl/gstglcontext_eagl.h
gst-libs/gst/gl/eagl/gstglcontext_eagl.m
gst-libs/gst/gl/egl/gstglcontext_egl.c
gst-libs/gst/gl/egl/gstglcontext_egl.h
gst-libs/gst/gl/gstglcontext.c
gst-libs/gst/gl/gstglcontext.h
gst-libs/gst/gl/win32/gstglcontext_wgl.c
gst-libs/gst/gl/win32/gstglcontext_wgl.h
gst-libs/gst/gl/x11/gstglcontext_glx.c
gst-libs/gst/gl/x11/gstglcontext_glx.h
tests/check/libs/gstglcontext.c

index f9051fa574e75c758a8e627c907974d7e3da8222..939004e00aff33880cc3dfe08a3e69d303a072af 100644 (file)
@@ -804,6 +804,8 @@ gst_gl_context_get_display
 gst_gl_context_get_gl_api
 gst_gl_context_get_gl_context
 gst_gl_context_get_gl_platform
+gst_gl_context_get_current_gl_context
+gst_gl_context_get_current_gl_api
 gst_gl_context_get_thread
 gst_gl_context_can_share
 gst_gl_context_check_feature
index d7f0e044c152a943ea277059b1cb0dabd22e9cec..1c5d66debe8ccc76eda9aa572ecdc75d4626910f 100644 (file)
@@ -61,6 +61,7 @@ struct _GstGLContextCocoaClass {
 GType gst_gl_context_cocoa_get_type (void);
 
 GstGLContextCocoa * gst_gl_context_cocoa_new (void);
+guintptr gst_gl_context_cocoa_get_current_context (void);
 
 G_END_DECLS
 
index 7a12650cc0dcf2fa35d1757fc00f4b38658636ec..94da0bca974561de1cdff6bb2699d2b69098f68e 100644 (file)
@@ -363,3 +363,9 @@ gst_gl_context_cocoa_get_gl_platform (GstGLContext * context)
 {
   return GST_GL_PLATFORM_CGL;
 }
+
+guintptr
+gst_gl_context_cocoa_get_current_context (void)
+{
+  return (guintptr) [NSOpenGLContext currentContext];
+}
index bc4618cf20fffdba9c5e4abfebd12530b9c3217e..fca51772a2b71efdd401a6932f9b0a3b4928980b 100644 (file)
@@ -61,6 +61,7 @@ GstGLContextEagl * gst_gl_context_eagl_new (void);
 
 void gst_gl_context_eagl_prepare_draw (GstGLContextEagl * context);
 void gst_gl_context_eagl_finish_draw (GstGLContextEagl * context);
+guintptr gst_gl_context_eagl_get_current_context (void);
 
 G_END_DECLS
 
index e3b71f355f3eccf39efdb29ce9d373ee8f70fb51..ab8691277343cd38e462c38b5639e3aab44717db 100644 (file)
@@ -341,3 +341,8 @@ gst_gl_context_eagl_get_gl_platform (GstGLContext * context)
   return GST_GL_PLATFORM_EAGL;
 }
 
+guintptr
+gst_gl_context_eagl_get_current_context (void)
+{
+  return (guintptr) [EAGLContext currentContext];
+}
index 16adff9281cc46e91561b30281a59af984d1f5e3..aebbdd57d6867781cd85c72b7315dba00e6a3f94 100644 (file)
@@ -82,6 +82,8 @@ gst_gl_context_egl_class_init (GstGLContextEGLClass * klass)
       GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_proc_address);
   context_class->check_feature =
       GST_DEBUG_FUNCPTR (gst_gl_context_egl_check_feature);
+  context_class->get_current_context =
+      GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_current_context);
 }
 
 static void
@@ -550,8 +552,9 @@ gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result = NULL;
   static GOnce g_once = G_ONCE_INIT;
+  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
 
-  result = gst_gl_context_default_get_proc_address (context, name);
+  result = gst_gl_context_default_get_proc_address (gl_api, name);
 
   g_once (&g_once, load_egl_module, NULL);
 
@@ -583,3 +586,9 @@ gst_gl_context_egl_check_feature (GstGLContext * context, const gchar * feature)
 
   return FALSE;
 }
+
+guintptr
+gst_gl_context_egl_get_current_context (void)
+{
+  return (guintptr) eglGetCurrentContext ();
+}
index 96018655acd7fca0d14a5bd487ba9693056ecf22..2f950f8b03197419d24b01bfb0f0cb477cd07e1f 100644 (file)
@@ -57,6 +57,7 @@ struct _GstGLContextEGLClass {
 
 GType gst_gl_context_egl_get_type     (void);
 GstGLContextEGL * gst_gl_context_egl_new (void);
+guintptr          gst_gl_context_egl_get_current_context (void);
 
 /* TODO:
  * add support for EGL_NO_CONTEXT
index 783fb045092909ce43ea447c6d32f356183bfe6f..2393a532e2993b4f4cd71b400e351c453bac00dc 100644 (file)
@@ -67,6 +67,7 @@
 
 GST_DEBUG_CATEGORY_STATIC (gst_performance);
 static GModule *module_self;
+static GOnce module_self_gonce = G_ONCE_INIT;
 
 #if GST_GL_HAVE_OPENGL
 static GOnce module_opengl_gonce = G_ONCE_INIT;
@@ -118,6 +119,14 @@ load_gles2_module (gpointer user_data)
 }
 #endif
 
+static gpointer
+load_self_module (gpointer user_data)
+{
+  module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
+
+  return NULL;
+}
+
 #if GST_GL_HAVE_GLES3
 #error "Add module loading support for GLES3"
 #endif
@@ -132,6 +141,8 @@ G_DEFINE_ABSTRACT_TYPE (GstGLContext, gst_gl_context, GST_TYPE_OBJECT);
   (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT, GstGLContextPrivate))
 
 static gpointer gst_gl_context_create_thread (GstGLContext * context);
+static gpointer _default_get_proc_address (GstGLContext * context,
+    const gchar * name);
 static void gst_gl_context_finalize (GObject * object);
 
 struct _GstGLContextPrivate
@@ -226,10 +237,7 @@ gst_gl_context_class_init (GstGLContextClass * klass)
 {
   g_type_class_add_private (klass, sizeof (GstGLContextPrivate));
 
-  module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
-
-  klass->get_proc_address =
-      GST_DEBUG_FUNCPTR (gst_gl_context_default_get_proc_address);
+  klass->get_proc_address = GST_DEBUG_FUNCPTR (_default_get_proc_address);
 
   G_OBJECT_CLASS (klass)->finalize = gst_gl_context_finalize;
 }
@@ -339,6 +347,144 @@ gst_gl_context_new_wrapped (GstGLDisplay * display, guintptr handle,
   return context;
 }
 
+/**
+ * gst_gl_context_get_current_gl_context:
+ * @context_type: a #GstGLPlatform specifying the type of context to retreive
+ *
+ * Returns: The OpenGL context handle current in the calling thread or %NULL
+ */
+guintptr
+gst_gl_context_get_current_gl_context (GstGLPlatform context_type)
+{
+  guintptr handle = 0;
+
+  _init_debug ();
+
+#if GST_GL_HAVE_PLATFORM_GLX
+  if (!handle && (context_type & GST_GL_PLATFORM_GLX) != 0)
+    handle = gst_gl_context_glx_get_current_context ();
+#endif
+#if GST_GL_HAVE_PLATFORM_EGL
+  if (!handle && (context_type & GST_GL_PLATFORM_EGL) != 0)
+    handle = gst_gl_context_egl_get_current_context ();
+#endif
+#if GST_GL_HAVE_PLATFORM_CGL
+  if (!handle && (context_type & GST_GL_PLATFORM_CGL) != 0)
+    handle = gst_gl_context_cocoa_get_current_context ();
+#endif
+#if GST_GL_HAVE_PLATFORM_WGL
+  if (!handle && (context_type & GST_GL_PLATFORM_WGL) != 0)
+    handle = gst_gl_context_wgl_get_current_context ();
+#endif
+#if GST_GL_HAVE_PLATFORM_EAGL
+  if (!handle && (context_type & GST_GL_PLATFORM_EAGL) != 0)
+    handle = gst_gl_context_eagl_get_current_context ();
+#endif
+
+  if (!handle)
+    GST_WARNING ("Could not retreive current context");
+
+  return handle;
+}
+
+/**
+ * gst_gl_context_get_current_gl_api:
+ * @context_type: a #GstGLPlatform specifying the type of context to retreive
+ * @major: (out): (allow-none): the major version
+ * @minor: (out): (allow-none): the minor version
+ *
+ * If an error occurs, @major and @minor aren't modified and %GST_GL_API_NONE is
+ * returned.
+ *
+ * Returns: The version supported by the OpenGL context current in the calling
+ *          thread or %GST_GL_API_NONE
+ */
+GstGLAPI
+gst_gl_context_get_current_gl_api (guint * major, guint * minor)
+{
+  const GLubyte *(*GetString) (GLenum name);
+  void (*GetIntegerv) (GLenum name, GLuint * n);
+  const gchar *version;
+  gint maj, min, n;
+  GstGLAPI ret = (1 << 31);
+
+  _init_debug ();
+
+  while (ret != GST_GL_API_NONE) {
+    /* FIXME: attempt to delve into the platform specific GetProcAddress */
+    GetString = gst_gl_context_default_get_proc_address (ret, "glGetString");
+    GetIntegerv =
+        gst_gl_context_default_get_proc_address (ret, "glGetIntegerv");
+    if (!GetString) {
+      goto next;
+    }
+
+    version = (const gchar *) GetString (GL_VERSION);
+    if (!version)
+      goto next;
+
+    /* strlen (x.x) == 3 */
+    n = strlen (version);
+    if (n < 3)
+      goto next;
+
+    if (g_strstr_len (version, 9, "OpenGL ES")) {
+      /* strlen (OpenGL ES x.x) == 13 */
+      if (n < 13)
+        goto next;
+
+      sscanf (&version[10], "%d.%d", &maj, &min);
+
+      if (maj <= 0 || min < 0)
+        goto next;
+
+      if (maj == 1) {
+        ret = GST_GL_API_GLES1;
+        break;
+      } else if (maj == 2 || maj == 3) {
+        ret = GST_GL_API_GLES2;
+        break;
+      }
+
+      goto next;
+    } else {
+      GLuint context_flags = 0;
+      sscanf (version, "%d.%d", &maj, &min);
+
+      if (maj <= 0 || min < 0)
+        goto next;
+
+#if GST_GL_HAVE_OPENGL
+      if (GetIntegerv && (maj > 3 || (maj == 3 && min > 1))) {
+        ret = GST_GL_API_NONE;
+        GetIntegerv (GL_CONTEXT_PROFILE_MASK, &context_flags);
+        if (context_flags & GL_CONTEXT_CORE_PROFILE_BIT)
+          ret |= GST_GL_API_OPENGL3;
+        if (context_flags & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+          ret |= GST_GL_API_OPENGL;
+        break;
+      }
+#endif
+      ret = GST_GL_API_OPENGL;
+      break;
+    }
+
+  next:
+    /* iterate through the apis */
+    ret >>= 1;
+  }
+
+  if (ret == GST_GL_API_NONE)
+    return GST_GL_API_NONE;
+
+  if (major)
+    *major = maj;
+  if (minor)
+    *minor = min;
+
+  return ret;
+}
+
 static void
 gst_gl_context_finalize (GObject * object)
 {
@@ -466,6 +612,14 @@ gst_gl_context_get_gl_api (GstGLContext * context)
   return context_class->get_gl_api (context);
 }
 
+static gpointer
+_default_get_proc_address (GstGLContext * context, const gchar * name)
+{
+  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
+
+  return gst_gl_context_default_get_proc_address (gl_api, name);
+}
+
 /**
  * gst_gl_context_get_proc_address:
  * @context: a #GstGLContext
@@ -496,11 +650,9 @@ gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name)
 }
 
 gpointer
-gst_gl_context_default_get_proc_address (GstGLContext * context,
-    const gchar * name)
+gst_gl_context_default_get_proc_address (GstGLAPI gl_api, const gchar * name)
 {
   gpointer ret = NULL;
-  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
 
   /* First try to load symbol from the selected GL API for this context */
 #if GST_GL_HAVE_GLES2
@@ -520,6 +672,7 @@ gst_gl_context_default_get_proc_address (GstGLContext * context,
 #endif
 
   /* Otherwise fall back to the current module */
+  g_once (&module_self_gonce, load_self_module, NULL);
   if (!ret)
     g_module_symbol (module_self, name, &ret);
 
@@ -1281,7 +1434,7 @@ void
 gst_gl_context_get_gl_version (GstGLContext * context, gint * maj, gint * min)
 {
   g_return_if_fail (GST_GL_IS_CONTEXT (context));
-  g_return_if_fail (maj == NULL && min == NULL);
+  g_return_if_fail (maj != NULL && min != NULL);
 
   if (maj)
     *maj = context->priv->gl_major;
index d2acc0deee8e9a39ca2ef95adb210de1199376dc..9d243d1c699dd11a466c10795335ace4b864bb47 100644 (file)
@@ -95,6 +95,7 @@ struct _GstGLContext {
 struct _GstGLContextClass {
   GstObjectClass parent_class;
 
+  guintptr      (*get_current_context) (void);
   guintptr      (*get_gl_context)     (GstGLContext *context);
   GstGLAPI      (*get_gl_api)         (GstGLContext *context);
   GstGLPlatform (*get_gl_platform)    (GstGLContext *context);
@@ -132,7 +133,7 @@ gboolean      gst_gl_context_can_share        (GstGLContext * context, GstGLCont
 gboolean      gst_gl_context_create           (GstGLContext *context, GstGLContext *other_context, GError ** error);
 void          gst_gl_context_destroy          (GstGLContext *context);
 
-gpointer      gst_gl_context_default_get_proc_address (GstGLContext *context, const gchar *name);
+gpointer      gst_gl_context_default_get_proc_address (GstGLAPI gl_api, const gchar *name);
 
 gboolean      gst_gl_context_set_window (GstGLContext *context, GstGLWindow *window);
 GstGLWindow * gst_gl_context_get_window (GstGLContext *context);
@@ -141,6 +142,9 @@ void          gst_gl_context_get_gl_version (GstGLContext *context, gint *maj, g
 gboolean      gst_gl_context_check_gl_version (GstGLContext * context, GstGLAPI api, gint maj, gint min);
 gboolean      gst_gl_context_check_feature (GstGLContext *context, const gchar *feature);
 
+guintptr      gst_gl_context_get_current_gl_context     (GstGLPlatform platform);
+GstGLAPI      gst_gl_context_get_current_gl_api         (guint *major, guint *minor);
+
 /* FIXME: remove */
 void gst_gl_context_thread_add (GstGLContext * context,
     GstGLContextThreadFunc func, gpointer data);
index 4886e9af52cf0d3a156f27e48b1cc34fbd1dae81..7547b47272773ef28c34896b4f2fa03b0f7ebed7 100644 (file)
@@ -289,10 +289,17 @@ static gpointer
 gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result;
+  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
 
-  if (!(result = gst_gl_context_default_get_proc_address (context, name))) {
+  if (!(result = gst_gl_context_default_get_proc_address (gl_api, name))) {
     result = wglGetProcAddress ((LPCSTR) name);
   }
 
   return result;
 }
+
+guintptr
+gst_gl_context_wgl_get_current_context (void)
+{
+  return (guintptr) wglGetCurrentContext ();
+}
index b996dc7cbcc2d4357b7ec6e31ee21aa0704f5a20..d840175e13d9ba70246e25840926c59e10ee9223 100644 (file)
@@ -56,6 +56,7 @@ struct _GstGLContextWGLClass {
 GType gst_gl_context_wgl_get_type     (void);
 
 GstGLContextWGL * gst_gl_context_wgl_new  (void);
+guintptr gst_gl_context_wgl_get_current_context (void);
 
 G_END_DECLS
 
index 00aa546cef07ede30eb1fc19375efd8d973e9b12..6614dddf73ffe58c089a49ed68253550f802fea4 100644 (file)
@@ -96,6 +96,8 @@ gst_gl_context_glx_class_init (GstGLContextGLXClass * klass)
       GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_platform);
   context_class->get_proc_address =
       GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_proc_address);
+  context_class->get_current_context =
+      GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_current_context);
 }
 
 static void
@@ -197,7 +199,7 @@ gst_gl_context_glx_create_context (GstGLContext * context,
         context_attribs_3);
 
     x_error = gst_gl_window_x11_untrap_x_errors ();
-    context_glx->priv->context_api = GST_GL_API_OPENGL3 | GST_GL_API_OPENGL;
+    context_glx->priv->context_api = GST_GL_API_OPENGL;
 
     if (!context_glx->glx_context || x_error != 0) {
       GST_DEBUG ("Failed to create an Opengl 3 context. trying a legacy one");
@@ -423,10 +425,17 @@ static gpointer
 gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name)
 {
   gpointer result;
+  GstGLAPI gl_api = gst_gl_context_get_gl_api (context);
 
-  if (!(result = gst_gl_context_default_get_proc_address (context, name))) {
+  if (!(result = gst_gl_context_default_get_proc_address (gl_api, name))) {
     result = glXGetProcAddressARB ((const GLubyte *) name);
   }
 
   return result;
 }
+
+guintptr
+gst_gl_context_glx_get_current_context (void)
+{
+  return (guintptr) glXGetCurrentContext ();
+}
index eca8d7f5d6c60c4e384b590f8530f878a593b8fa..0c08f24b84796a2bd31f308301d7e42c60129630 100644 (file)
@@ -60,6 +60,7 @@ struct _GstGLContextGLXClass {
 GType gst_gl_context_glx_get_type     (void);
 
 GstGLContextGLX * gst_gl_context_glx_new (void);
+guintptr          gst_gl_context_glx_get_current_context (void);
 
 G_END_DECLS
 
index bb7e295b08668a126f04df325aebb877d4669cb9..d9249e921b792194a6f6ace2b7873ef91c4b2cd8 100644 (file)
@@ -341,6 +341,60 @@ GST_START_TEST (test_wrapped_context)
 
 GST_END_TEST;
 
+struct context_info
+{
+  GstGLAPI api;
+  guint major;
+  guint minor;
+  GstGLPlatform platform;
+  guintptr handle;
+};
+
+static void
+_fill_context_info (GstGLContext * context, struct context_info *info)
+{
+  info->handle = gst_gl_context_get_current_gl_context (info->platform);
+  info->api = gst_gl_context_get_current_gl_api (&info->major, &info->minor);
+}
+
+GST_START_TEST (test_current_context)
+{
+  GstGLContext *context;
+  GError *error = NULL;
+  guintptr handle;
+  GstGLPlatform platform;
+  GstGLAPI api;
+  gint major, minor;
+  struct context_info info;
+
+  context = gst_gl_context_new (display);
+
+  gst_gl_context_create (context, 0, &error);
+
+  fail_if (error != NULL, "Error creating master context %s\n",
+      error ? error->message : "Unknown Error");
+
+  handle = gst_gl_context_get_gl_context (context);
+  platform = gst_gl_context_get_gl_platform (context);
+  api = gst_gl_context_get_gl_api (context);
+  gst_gl_context_get_gl_version (context, &major, &minor);
+
+  info.platform = platform;
+
+  gst_gl_context_thread_add (context,
+      (GstGLContextThreadFunc) _fill_context_info, &info);
+
+  fail_if (info.platform != platform);
+  fail_if (info.api != api);
+  fail_if (info.major != major);
+  fail_if (info.minor != minor);
+  fail_if (info.handle != handle);
+
+  gst_object_unref (context);
+}
+
+GST_END_TEST;
+
 
 static Suite *
 gst_gl_context_suite (void)
@@ -352,6 +406,7 @@ gst_gl_context_suite (void)
   tcase_add_checked_fixture (tc_chain, setup, teardown);
   tcase_add_test (tc_chain, test_share);
   tcase_add_test (tc_chain, test_wrapped_context);
+  tcase_add_test (tc_chain, test_current_context);
 
   return s;
 }