[330/906] Can now share textures with an external gl context
authorJulien Isorce <julien.isorce@gmail.com>
Sat, 18 Apr 2009 11:57:44 +0000 (13:57 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:21 +0000 (19:31 +0000)
The external opengl context must be specify when creating
our OpenGL context (glx) or just after (wgl).
When calling glXCreateContext or wglShareLists, the
external opengl context must not be current.
Then our gl context can be current in the gl thread while
the external gl context is current in an other thread.
See tests/examples/clutter/cluttershare.c

gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/gstglwindow_cocoa.m
gst-libs/gst/gl/gstglwindow_win32.c
gst-libs/gst/gl/gstglwindow_winCE.c
gst-libs/gst/gl/gstglwindow_x11.c
gst-libs/gst/gl/gstglwindow_x11ES2.c

index 903afc5..f339f0c 100644 (file)
@@ -158,6 +158,9 @@ gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass)
   display->upload_data_height = 0;
   display->upload_data = NULL;
 
+  //foreign gl context
+  display->external_gl_context = 0;
+
   //filter gen fbo
   display->gen_fbo_width = 0;
   display->gen_fbo_height = 0;
@@ -527,7 +530,8 @@ gst_gl_display_thread_create_context (GstGLDisplay * display)
   GLenum err = 0;
 
   display->gl_window =
-      gst_gl_window_new (display->upload_width, display->upload_height);
+      gst_gl_window_new (display->upload_width, display->upload_height,
+          display->external_gl_context);
 
   if (!display->gl_window) {
     display->isAlive = FALSE;
@@ -2065,12 +2069,13 @@ gst_gl_display_new (void)
  * Called by the first gl element of a video/x-raw-gl flow */
 void
 gst_gl_display_create_context (GstGLDisplay * display,
-    GLint width, GLint height)
+    GLint width, GLint height, guint64 external_gl_context)
 {
   gst_gl_display_lock (display);
 
   display->upload_width = width;
   display->upload_height = height;
+  display->external_gl_context = external_gl_context;
 
   display->gl_thread = g_thread_create (
       (GThreadFunc) gst_gl_display_thread_create_context, display, TRUE, NULL);
index 983b035..25370b5 100644 (file)
@@ -135,6 +135,9 @@ struct _GstGLDisplay
   gint upload_data_height;
   gpointer upload_data;
 
+  //foreign gl context
+  guint64 external_gl_context;
+
   //filter gen fbo
   GLuint gen_fbo_width;
   GLuint gen_fbo_height;
@@ -236,7 +239,7 @@ GType gst_gl_display_get_type (void);
 GstGLDisplay *gst_gl_display_new (void);
 
 void gst_gl_display_create_context (GstGLDisplay * display,
-    GLint width, GLint height);
+    GLint width, GLint height, guint64 external_gl_context);
 gboolean gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture,
     gint width, gint height);
 
index dc7da44..928b028 100644 (file)
@@ -79,10 +79,9 @@ struct _GstGLWindowClass {
 GQuark gst_gl_window_error_quark (void);
 GType gst_gl_window_get_type (void);
 
-GstGLWindow * gst_gl_window_new (gint width, gint height);
+GstGLWindow * gst_gl_window_new (gint width, gint height, guint64 external_gl_context);
 
 void gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id);
-void gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context);
 void gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
 void gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback, gpointer data);
 void gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
index 7e04bba..07086ba 100644 (file)
@@ -146,7 +146,7 @@ gst_gl_window_init (GstGLWindow * window)
 
 /* Must be called in the gl thread */
 GstGLWindow *
-gst_gl_window_new (gint width, gint height)
+gst_gl_window_new (gint width, gint height, guint64 external_gl_context)
 {
   GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
   GstGLWindowPrivate *priv = window->priv;
@@ -229,12 +229,6 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
     g_debug ("failed to register current thread, cannot set external window id");
 }
 
-void
-gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
-{
-  g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
-}
-
 /* Must be called in the gl thread */
 void
 gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
index 61dda5a..dd45a8a 100644 (file)
@@ -51,6 +51,7 @@ struct _GstGLWindowPrivate
   HWND internal_win_id;
   HDC device;
   HGLRC gl_context;
+  HGLRC external_gl_context;
   GstGLWindowCB draw_cb;
   gpointer draw_data;
   GstGLWindowCB2 resize_cb;
@@ -143,7 +144,7 @@ gst_gl_window_init (GstGLWindow * window)
 
 /* Must be called in the gl thread */
 GstGLWindow *
-gst_gl_window_new (gint width, gint height)
+gst_gl_window_new (gint width, gint height, guint64 external_gl_context)
 {
   GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
   GstGLWindowPrivate *priv = window->priv;
@@ -160,6 +161,7 @@ gst_gl_window_new (gint width, gint height)
   priv->internal_win_id = 0;
   priv->device = 0;
   priv->gl_context = 0;
+  priv->external_gl_context = (HGLRC) external_gl_context;
   priv->draw_cb = NULL;
   priv->draw_data = NULL;
   priv->resize_cb = NULL;
@@ -226,12 +228,6 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
       rect.bottom, FALSE);
 }
 
-void
-gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
-{
-  g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
-}
-
 /* Must be called in the gl thread */
 void
 gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
@@ -411,6 +407,14 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
       if (!wglMakeCurrent (priv->device, priv->gl_context))
         g_debug ("failed to make opengl context current %d, %x\r\n", hWnd,
             GetLastError ());
+
+      if (priv->external_gl_context) {
+        if (!wglShareLists (priv->gl_context, priv->external_gl_context))
+          g_debug ("failed to share opengl context %lud with %lud\n",
+              priv->gl_context, priv->external_gl_context);
+        else
+          g_debug ("share opengl context succeed\n");
+      }
     }
 
     SetProp (hWnd, "gl_window", window);
index 1acf63e..b075a35 100644 (file)
@@ -48,6 +48,7 @@ struct _GstGLWindowPrivate
   EGLDisplay display;
   EGLSurface surface;
   EGLContext gl_context;
+  EGLContext external_gl_context;
   GstGLWindowCB draw_cb;
   gpointer draw_data;
   GstGLWindowCB2 resize_cb;
@@ -140,7 +141,7 @@ gst_gl_window_init (GstGLWindow * window)
 
 /* Must be called in the gl thread */
 GstGLWindow *
-gst_gl_window_new (gint width, gint height)
+gst_gl_window_new (gint width, gint height, guint64 external_gl_context)
 {
   GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
   GstGLWindowPrivate *priv = window->priv;
@@ -158,6 +159,7 @@ gst_gl_window_new (gint width, gint height)
   priv->display = 0;
   priv->surface = 0;
   priv->gl_context = 0;
+  priv->external_gl_context = (EGLContext) external_gl_context;
   priv->draw_cb = NULL;
   priv->draw_data = NULL;
   priv->resize_cb = NULL;
@@ -224,12 +226,6 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
       rect.bottom, FALSE);
 }
 
-void
-gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
-{
-  g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
-}
-
 /* Must be called in the gl thread */
 void
 gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
@@ -402,7 +398,7 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
             priv->surface, hWnd, EGLErrorString ());
 
       priv->gl_context =
-          eglCreateContext (priv->display, config, EGL_NO_CONTEXT,
+          eglCreateContext (priv->display, config, priv->external_gl_context,
           contextAttribs);
       if (priv->gl_context != EGL_NO_CONTEXT)
         g_debug ("gl context created: %d\n", priv->gl_context);
index 14dc124..7d69f10 100644 (file)
@@ -242,7 +242,7 @@ gst_gl_window_init (GstGLWindow * window)
 
 /* Must be called in the gl thread */
 GstGLWindow *
-gst_gl_window_new (gint width, gint height)
+gst_gl_window_new (gint width, gint height, guint64 external_gl_context)
 {
   GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
   GstGLWindowPrivate *priv = window->priv;
@@ -379,7 +379,8 @@ gst_gl_window_new (gint width, gint height)
   XSetWMProtocols (priv->device, priv->internal_win_id, wm_atoms, 2);
 
   priv->gl_context =
-      glXCreateContext (priv->device, priv->visual_info, NULL, TRUE);
+      glXCreateContext (priv->device, priv->visual_info, 
+          (GLXContext) external_gl_context, TRUE);
 
   g_debug ("gl context id: %ld\n", (gulong) priv->gl_context);
 
@@ -447,12 +448,6 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
 }
 
 void
-gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
-{
-  g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
-}
-
-void
 gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
     gpointer data)
 {
index e885013..2f74b0d 100644 (file)
@@ -247,7 +247,7 @@ gst_gl_window_init (GstGLWindow * window)
 
 /* Must be called in the gl thread */
 GstGLWindow *
-gst_gl_window_new (gint width, gint height)
+gst_gl_window_new (gint width, gint height, guint64 external_gl_context)
 {
   GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL);
   GstGLWindowPrivate *priv = window->priv;
@@ -395,7 +395,7 @@ gst_gl_window_new (gint width, gint height)
         (gulong) priv->gl_display, EGLErrorString ());
 
   priv->gl_context =
-      eglCreateContext (priv->gl_display, config, EGL_NO_CONTEXT,
+      eglCreateContext (priv->gl_display, config, (EGLContext) external_gl_context,
       context_attrib);
   if (priv->gl_context != EGL_NO_CONTEXT)
     g_debug ("gl context created: %ld\n", (gulong) priv->gl_context);
@@ -449,12 +449,6 @@ gst_gl_window_set_external_window_id (GstGLWindow * window, guint64 id)
 }
 
 void
-gst_gl_window_set_external_gl_context (GstGLWindow * window, guint64 context)
-{
-  g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
-}
-
-void
 gst_gl_window_set_draw_callback (GstGLWindow * window, GstGLWindowCB callback,
     gpointer data)
 {