[281/906] Make cube example work on x11. Finish TODO task 9.
authorJulien Isorce <julien.isorce@gmail.com>
Sun, 23 Nov 2008 15:04:27 +0000 (16:04 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:20 +0000 (19:31 +0000)
gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/gstglwindow_win32.c
gst-libs/gst/gl/gstglwindow_x11.c

index dd408d2..5007326 100644 (file)
@@ -1363,8 +1363,8 @@ void gst_gl_display_on_draw(GstGLDisplay* display)
       display->clientDrawCallback (display->redisplay_texture,
                                  display->redisplay_texture_width, display->redisplay_texture_height);
 
-    if (doRedisplay)
-      gst_gl_window_draw (display->gl_window);
+    if (doRedisplay && display->gl_window)
+      gst_gl_window_draw_unlocked (display->gl_window);
   }
   //default opengl scene
   else
index 15e9142..9dd1d92 100644 (file)
@@ -71,6 +71,7 @@ void gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callbac
 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);
 
+void gst_gl_window_draw_unlocked (GstGLWindow *window);
 void gst_gl_window_draw (GstGLWindow *window);
 void gst_gl_window_run_loop (GstGLWindow *window);
 void gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data);
index c4cb968..33c623d 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * GStreamer
  * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
  *
@@ -190,7 +190,7 @@ gst_gl_window_new (gint width, gint height)
 
   g_debug ("gl window created: %d\n", priv->internal_win_id);
 
-  //device is set in the window_proc 
+  //device is set in the window_proc
   g_assert (priv->device);
 
   ShowCursor (TRUE);
@@ -204,7 +204,7 @@ gst_gl_window_error_quark (void)
   return g_quark_from_static_string ("gst-gl-window-error");
 }
 
-void 
+void
 gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
 {
   GstGLWindowPrivate *priv = window->priv;
@@ -215,9 +215,9 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
   SetProp ((HWND)id, "gl_window_id", priv->internal_win_id);
   SetProp ((HWND)id, "gl_window_parent_proc", (WNDPROC) window_parent_proc);
   SetWindowLongPtr ((HWND)id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc);
-  
+
   SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE);
-  SetParent (priv->internal_win_id, (HWND)id);  
+  SetParent (priv->internal_win_id, (HWND)id);
 
   //take changes into account: SWP_FRAMECHANGED
   GetClientRect ((HWND)id, &rect);
@@ -226,7 +226,7 @@ gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id)
   MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right, rect.bottom, FALSE);
 }
 
-void 
+void
 gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context)
 {
   g_warning ("gst_gl_window_set_external_gl_context: not implemented\n");
@@ -237,7 +237,7 @@ void
 gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data)
 {
   GstGLWindowPrivate *priv = window->priv;
-  
+
   priv->draw_cb = callback;
   priv->draw_data = data;
 }
@@ -262,6 +262,12 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
   priv->close_data = data;
 }
 
+void
+gst_gl_window_draw_unlocked (GstGLWindow *window)
+{
+  gst_gl_window_draw (window);
+}
+
 /* Thread safe */
 void
 gst_gl_window_draw (GstGLWindow *window)
@@ -289,7 +295,7 @@ gst_gl_window_run_loop (GstGLWindow *window)
   g_debug ("begin loop\n");
 
   while (running && (bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
-  { 
+  {
       if (bRet == -1)
       {
           g_error ("Failed to get message %x\r\n", GetLastError());
@@ -297,8 +303,8 @@ gst_gl_window_run_loop (GstGLWindow *window)
       }
       else
       {
-          TranslateMessage (&msg); 
-          DispatchMessage (&msg); 
+          TranslateMessage (&msg);
+          DispatchMessage (&msg);
       }
   }
 
@@ -370,7 +376,7 @@ gst_gl_window_set_pixel_format (GstGLWindow *window)
     pfd.cColorBits = (BYTE) GetDeviceCaps (priv->device, BITSPIXEL);
 
     pixelformat = ChoosePixelFormat (priv->device, &pfd );
-    
+
     g_assert (pixelformat);
 
     res = SetPixelFormat (priv->device, pixelformat, &pfd);
@@ -432,7 +438,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
       }
 
       case WM_PAINT:
-      { 
+      {
         if (priv->draw_cb)
         {
           PAINTSTRUCT ps;
@@ -447,7 +453,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
       case WM_CLOSE:
       {
         ShowWindowAsync (priv->internal_win_id, SW_HIDE);
-        
+
         if (priv->close_cb)
             priv->close_cb (priv->close_data);
 
@@ -473,7 +479,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
         if (parent_id)
         {
           WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc");
-          
+
           g_assert (parent_proc);
 
           SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) (guint64) parent_proc);
@@ -502,7 +508,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
             g_debug ("failed to destroy window %d, %x\r\n", hWnd, GetLastError());
           g_debug ("AFTER\n");
         }
-          
+
         PostQuitMessage (0);
         break;
       }
@@ -541,7 +547,7 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
 LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   WNDPROC window_parent_proc = GetProp (hWnd, "gl_window_parent_proc");
-  
+
   if (uMsg == WM_SIZE)
   {
     HWND gl_window_id = GetProp (hWnd, "gl_window_id");
index d4defb0..3d512b9 100644 (file)
@@ -41,6 +41,7 @@ struct _GstGLWindowPrivate
   GCond *cond_send_message;
   gboolean running;
   gboolean visible;
+  gboolean allow_extra_expose_events;
 
   gchar *display_name;
   Display *device;
@@ -116,14 +117,20 @@ gst_gl_window_finalize (GObject * object)
 
   XSetCloseDownMode (priv->device, DestroyAll);
 
-  XCloseDisplay (priv->device);
-
-  XCloseDisplay (priv->disp_send);
-
   /*XAddToSaveSet (display, w)
   Display *display;
   Window w;*/
 
+  //FIXME: it seems it causes destroy all created windows, even by other display connection:
+  //This is case in: gst-launch-0.10 videotestsrc ! tee name=t t. ! queue ! glimagesink t. ! queue ! glimagesink
+  //When the first window is closed and so its display is closed by the following line, then the other Window managed by the
+  //other glimagesink, is not useable and so each opengl call causes a segmentation fault.
+  //Maybe the solution is to use: XAddToSaveSet
+  //The following line is commented to avoid the disagreement explained before.
+  //XCloseDisplay (priv->device);
+
+  XCloseDisplay (priv->disp_send);
+
   g_debug ("display closed\n");
 
   if (priv->cond_send_message)
@@ -269,6 +276,7 @@ gst_gl_window_new (gint width, gint height)
   priv->running = TRUE;
   priv->visible = FALSE;
   priv->parent = 0;
+  priv->allow_extra_expose_events = TRUE;
 
   g_mutex_lock (priv->x_lock);
 
@@ -472,6 +480,33 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
   g_mutex_unlock (priv->x_lock);
 }
 
+void
+gst_gl_window_draw_unlocked (GstGLWindow *window)
+{
+  GstGLWindowPrivate *priv = window->priv;
+
+  if (priv->running && priv->allow_extra_expose_events)
+  {
+    XEvent event;
+    XWindowAttributes attr;
+
+    XGetWindowAttributes (priv->device, priv->internal_win_id, &attr);
+
+    event.xexpose.type = Expose;
+    event.xexpose.send_event = TRUE;
+    event.xexpose.display = priv->device;
+    event.xexpose.window = priv->internal_win_id;
+    event.xexpose.x = attr.x;
+    event.xexpose.y = attr.y;
+    event.xexpose.width = attr.width;
+    event.xexpose.height = attr.height;
+    event.xexpose.count = 0;
+
+    XSendEvent (priv->device, priv->internal_win_id, FALSE, ExposureMask, &event);
+    XSync (priv->disp_send, FALSE);
+  }
+}
+
 /* Thread safe */
 void
 gst_gl_window_draw (GstGLWindow *window)
@@ -535,7 +570,6 @@ gst_gl_window_run_loop (GstGLWindow *window)
 {
   GstGLWindowPrivate *priv = window->priv;
 
-
   g_debug ("begin loop\n");
 
   g_mutex_lock (priv->x_lock);
@@ -543,6 +577,7 @@ gst_gl_window_run_loop (GstGLWindow *window)
   while (priv->running)
   {
     XEvent event;
+    XEvent pending_event;
 
     g_mutex_unlock (priv->x_lock);
 
@@ -609,7 +644,6 @@ gst_gl_window_run_loop (GstGLWindow *window)
 
         else if (wm_quit_loop != None && event.xclient.message_type == wm_quit_loop)
         {
-          XEvent pending_event;
           GstGLWindowCB destroy_cb = (GstGLWindowCB) event.xclient.data.l[0];
           gpointer destroy_data = (gpointer) event.xclient.data.l[1];
 
@@ -702,6 +736,25 @@ gst_gl_window_run_loop (GstGLWindow *window)
 
     }// switch
 
+    // use in cube example
+    if (XPending (priv->device) > 10)
+    {
+        XEvent extra_expose_event;
+        priv->allow_extra_expose_events = FALSE;
+        while (XCheckTypedWindowEvent (priv->device, priv->internal_win_id, Expose, &extra_expose_event))
+        {
+          if (priv->draw_cb)
+          {
+            if (glXGetCurrentContext () != priv->gl_context)
+              g_warning ("current gl context has changed\n");
+            priv->draw_cb (priv->draw_data);
+            glFlush();
+            glXSwapBuffers (priv->device, priv->internal_win_id);
+          }
+        }
+        priv->allow_extra_expose_events = TRUE;
+    }
+
   }// while running
 
   g_mutex_unlock (priv->x_lock);