[251/906] Properly clean OpenGL contexts
authorJulien Isorce <julien.isorce@gmail.com>
Sat, 25 Oct 2008 00:03:16 +0000 (02:03 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:19 +0000 (19:31 +0000)
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstglwindow_win32.c

index 794eafb..a68d043 100644 (file)
@@ -108,8 +108,6 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
   display->gl_thread = NULL;
   display->gl_window = NULL;
   display->winId = 0;
-  display->win_xpos = 0;
-  display->win_ypos = 0;
   display->visible = FALSE;
   display->isAlive = TRUE;
   display->texture_pool = g_hash_table_new (g_direct_hash, g_direct_equal);
@@ -355,8 +353,9 @@ gst_gl_display_finalize (GObject* object)
 
   if (display->gl_thread)
   {
-    g_thread_join (display->gl_thread);
+    gpointer ret = g_thread_join (display->gl_thread);
     GST_INFO ("gl thread joined");
+    g_assert (ret == NULL);
     display->gl_thread = NULL;
   }
 
@@ -389,10 +388,6 @@ gst_gl_display_finalize (GObject* object)
 //------------------ BEGIN GL THREAD ACTIONS -----------------
 //------------------------------------------------------------
 
-//The following functions are thread safe because
-//called by the "gst_gl_display_thread_dispatch_action"
-//in a lock/unlock scope.
-
 /* Called in the gl thread */
 gpointer
 gst_gl_display_thread_create_context (GstGLDisplay *display)
@@ -401,9 +396,15 @@ gst_gl_display_thread_create_context (GstGLDisplay *display)
 
   display->gl_window = gst_gl_window_new (display->upload_width, display->upload_height);
 
-  GST_INFO ("gl window created");
+  if (!display->gl_window)
+  {
+    display->isAlive = FALSE;
+    GST_ERROR_OBJECT (display, "Failed to create gl window");
+    g_cond_signal (display->cond_create_context);
+    return NULL;
+  }
 
-  gst_gl_window_visible (display->gl_window, display->visible);
+  GST_INFO ("gl window created");
 
   //Init glew
   err = glewInit();
@@ -1580,19 +1581,14 @@ 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 x, GLint y,
                                GLint width, GLint height,
-                               gulong winId,
-                               gboolean visible)
+                               gulong winId)
 {
   gst_gl_display_lock (display);
 
   display->winId = winId;
-  display->win_xpos = x;
-  display->win_ypos = y;
   display->upload_width = width;
   display->upload_height = height;
-  display->visible = visible;
 
   display->gl_thread = g_thread_create (
     (GThreadFunc) gst_gl_display_thread_create_context, display, TRUE, NULL);
index ee81188..377b418 100644 (file)
@@ -56,39 +56,6 @@ typedef enum {
   GST_GL_DISPLAY_PROJECTION_PERSPECIVE
 } GstGLDisplayProjection;
 
-
-//Message type
-typedef enum {
-  GST_GL_DISPLAY_ACTION_CREATE_CONTEXT,
-  GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT,
-  GST_GL_DISPLAY_ACTION_CHANGE_CONTEXT,
-  GST_GL_DISPLAY_ACTION_VISIBLE_CONTEXT,
-  GST_GL_DISPLAY_ACTION_RESIZE_CONTEXT,
-  GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT,
-  GST_GL_DISPLAY_ACTION_GENERIC,
-  GST_GL_DISPLAY_ACTION_GEN_TEXTURE,
-  GST_GL_DISPLAY_ACTION_DEL_TEXTURE,
-  GST_GL_DISPLAY_ACTION_INIT_UPLOAD,
-  GST_GL_DISPLAY_ACTION_DO_UPLOAD,
-  GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD,
-  GST_GL_DISPLAY_ACTION_DO_DOWNLOAD,
-  GST_GL_DISPLAY_ACTION_GEN_FBO,
-  GST_GL_DISPLAY_ACTION_USE_FBO,
-  GST_GL_DISPLAY_ACTION_DEL_FBO,
-  GST_GL_DISPLAY_ACTION_GEN_SHADER,
-  GST_GL_DISPLAY_ACTION_DEL_SHADER
-
-} GstGLDisplayAction;
-
-
-//Message to communicate with the gl thread
-typedef struct _GstGLDisplayMsg {
-  GstGLDisplayAction action;
-  gint glutWinId;
-  GstGLDisplay* display;
-} GstGLDisplayMsg;
-
-
 //Texture pool elements
 typedef struct _GstGLDisplayTex {
   GLuint texture;
@@ -114,8 +81,6 @@ struct _GstGLDisplay {
   GThread* gl_thread;
   GstGLWindow* gl_window;
   gulong winId;
-  gint win_xpos;
-  gint win_ypos;
   gboolean visible;
   gboolean isAlive;
   GHashTable* texture_pool;
@@ -248,10 +213,8 @@ GType gst_gl_display_get_type (void);
 GstGLDisplay* gst_gl_display_new (void);
 
 void gst_gl_display_create_context (GstGLDisplay* display,
-                                    GLint x, GLint y,
                                     GLint width, GLint height,
-                                    gulong winId,
-                                    gboolean visible);
+                                    gulong winId);
 void gst_gl_display_set_visible_context (GstGLDisplay* display, gboolean visible);
 void gst_gl_display_resize_context (GstGLDisplay* display, gint width, gint height);
 gboolean gst_gl_display_redisplay (GstGLDisplay* display, GLuint texture, gint width, gint height);
index 2711934..cc0a082 100644 (file)
@@ -96,7 +96,7 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
 
   obj_class->finalize = gst_gl_window_finalize;
 
-  GetClassInfo ((HINSTANCE)klass->instance, "GSTGL", &wc);
+  atom = GetClassInfo ((HINSTANCE)klass->instance, "GSTGL", &wc);
 
   ZeroMemory (&wc, sizeof(WNDCLASS));
 
@@ -107,15 +107,11 @@ gst_gl_window_class_init (GstGLWindowClass * klass)
   wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
   wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
   wc.hCursor = LoadCursor( NULL, IDC_ARROW );
-  wc.hbrBackground = NULL;
+  wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
   wc.lpszMenuName = NULL;
   wc.lpszClassName = "GSTGL";
 
   atom = RegisterClass (&wc);
-
-  g_assert (atom);
-
-  g_debug ("GSTGL window class registered\n");
 }
 
 static void
@@ -138,9 +134,10 @@ gst_gl_window_new (gint width, gint height)
   GstGLWindowPrivate *priv = window->priv;
   GstGLWindowClass* klass = GST_GL_WINDOW_GET_CLASS (window);
   
-  static gint x = 50;
+  static gint x = 0;
   static gint y = 0;
-  y = 50 + height * y++;
+  x += 20;
+  y += 20;
 
   priv->internal_win_id = 0;
   priv->external_win_id = 0;
@@ -180,9 +177,13 @@ gst_gl_window_new (gint width, gint height)
   UpdateWindow (priv->internal_win_id);
   ShowCursor (TRUE);
 
-  wglMakeCurrent (priv->device, priv->gl_context);
-
-  return window;
+  if (wglMakeCurrent (priv->device, priv->gl_context))
+    return window;
+  else
+  {
+    g_debug ("Failed to make opengl context current");
+    return NULL;
+  }
 }
 
 GQuark
@@ -324,7 +325,7 @@ gst_gl_window_draw (GstGLWindow *window)
 
     BeginPaint (priv->external_win_id, &ps);
     priv->draw_cb (priv->draw_data);  //FIXME: wrong thread caller
-    //glFlush();
+    glFlush();
     SwapBuffers (priv->device);
     EndPaint (priv->external_win_id, &ps);
   }
@@ -386,6 +387,7 @@ gst_gl_window_quit_loop (GstGLWindow *window)
     GstGLWindowPrivate *priv = window->priv;
     LRESULT res = PostMessage(priv->internal_win_id, WM_CLOSE, 0, 0);
     g_assert (SUCCEEDED (res));
+    g_debug ("end loop requested\n");
   }
 }
 
@@ -451,8 +453,6 @@ gst_gl_window_set_pixel_format (GstGLWindow *window)
 
 LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-  static gboolean created = FALSE;
-
   if (uMsg == WM_CREATE) {
 
     GstGLWindow *window = (GstGLWindow *) (((LPCREATESTRUCT) lParam)->lpCreateParams);
@@ -468,14 +468,17 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
       priv->device = GetDC (hWnd);
       gst_gl_window_set_pixel_format (window);
       priv->gl_context = wglCreateContext (priv->device);
+      if (priv->gl_context)
+        g_debug ("gl context created: %d\n", priv->gl_context);
+      else
+        g_debug ("failed to create glcontext %d\n", hWnd);
+      g_assert (priv->gl_context);
       ReleaseDC (hWnd, priv->device);
     }
 
-    created = TRUE;
-
     return 0;
   }
-  else if (created) {
+  else if (GetWindowLongPtr(hWnd, GWLP_USERDATA)) {
 
     GstGLWindow *window = (GstGLWindow *) (guint64) GetWindowLongPtr(hWnd, GWLP_USERDATA);
     GstGLWindowPrivate *priv = NULL;
@@ -486,6 +489,8 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
 
     g_assert (priv);
 
+    g_assert (priv->internal_win_id == hWnd);
+
     switch ( uMsg ) {
 
       case WM_SIZE:
@@ -513,14 +518,16 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         g_debug ("WM_CLOSE\n");
         if (priv->close_cb)
           priv->close_cb (priv->close_data);
-        DestroyWindow(hWnd);
-        break;
-      }
+        wglMakeCurrent (NULL, NULL);
 
-      case WM_DESTROY:
-      {
-        g_debug ("WM_DESTROY\n");
-        created = FALSE;
+        if (priv->gl_context)
+          wglDeleteContext (priv->gl_context);
+
+        if (priv->internal_win_id)
+          DestroyWindow(priv->internal_win_id);
+
+        SetWindowLongPtr (hWnd, GWLP_USERDATA, 0);
+        DestroyWindow(hWnd);
         PostQuitMessage (0);
         break;
       }
@@ -540,6 +547,9 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         break;
       }
 
+      case WM_ERASEBKGND:
+        return TRUE;
+
       default:
         return DefWindowProc( hWnd, uMsg, wParam, lParam );
     }