[269/906] Better deal with XNextEvent and XSendEvent
authorJulien Isorce <julien.isorce@gmail.com>
Sat, 15 Nov 2008 17:51:44 +0000 (18:51 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:20 +0000 (19:31 +0000)
gst-libs/gst/gl/gstglwindow_x11.c

index f079eb9..072bccf 100644 (file)
@@ -37,9 +37,7 @@ enum
 
 struct _GstGLWindowPrivate
 {
-  GMutex *glwin_lock;
   GMutex *x_lock;
-  GCond *cond_x_event;
   GCond *cond_send_message;
   gboolean running;
 
@@ -83,7 +81,6 @@ gst_gl_window_finalize (GObject * object)
   GstGLWindowPrivate *priv = window->priv;
   XEvent event;
 
-  g_mutex_lock (priv->glwin_lock);
   g_mutex_lock (priv->x_lock);
 
   g_debug ("gl window finalizing\n");
@@ -120,7 +117,6 @@ gst_gl_window_finalize (GObject * object)
   g_debug ("display closed\n");
 
   g_mutex_unlock (priv->x_lock);
-  g_mutex_unlock (priv->glwin_lock);
 
   if (priv->cond_send_message)
   {
@@ -134,18 +130,6 @@ gst_gl_window_finalize (GObject * object)
     priv->x_lock = NULL;
   }
 
-  if (priv->cond_x_event)
-  {
-    g_cond_free (priv->cond_x_event);
-    priv->cond_x_event = NULL;
-  }
-
-  if (priv->glwin_lock)
-  {
-    g_mutex_free (priv->glwin_lock);
-    priv->glwin_lock = NULL;
-  }
-
   G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
 
   g_debug ("lock deleted\n");
@@ -262,13 +246,12 @@ gst_gl_window_new (gint width, gint height)
   static gint x = 0;
   static gint y = 0;
 
-  priv->glwin_lock = g_mutex_new ();
   priv->x_lock = g_mutex_new ();
-  priv->cond_x_event = g_cond_new ();
   priv->cond_send_message = g_cond_new ();
   priv->running = TRUE;
 
-  g_mutex_lock (priv->glwin_lock);
+  //XInitThreads ();
+
   g_mutex_lock (priv->x_lock);
 
   x += 20;
@@ -318,8 +301,6 @@ gst_gl_window_new (gint width, gint height)
   if (wm_delete_and_gl[0] == None)
     g_debug ("Cannot create WM_DELETE_WINDOW\n");
 
-  //XSetWMProtocols (priv->device, priv->internal_win_id, &wm_delete, 1);
-
   wm_delete_and_gl[1] = XInternAtom (priv->device, "WM_GL_WINDOW", False);
   if (wm_delete_and_gl[1] == None)
     g_debug ("Cannot create WM_GL_WINDOW\n");
@@ -334,8 +315,8 @@ gst_gl_window_new (gint width, gint height)
     g_debug ("direct rendering failed\n");
 
   size_hints.flags = USPosition | USSize;
-  size_hints.x = x;
-  size_hints.y = y;
+  size_hints.x = x; //FIXME: not working
+  size_hints.y = y; //FIXME: not working
   size_hints.width = width;
   size_hints.height= height;
 
@@ -355,7 +336,6 @@ gst_gl_window_new (gint width, gint height)
     g_debug ("failed to make opengl context current\n");
 
   g_mutex_unlock (priv->x_lock);
-  g_mutex_unlock (priv->glwin_lock);
 
   return window;
 }
@@ -400,12 +380,12 @@ gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gp
 {
   GstGLWindowPrivate *priv = window->priv;
 
-  g_mutex_lock (priv->glwin_lock);
+  g_mutex_lock (priv->x_lock);
 
   priv->draw_cb = callback;
   priv->draw_data = data;
 
-  g_mutex_unlock (priv->glwin_lock);
+  g_mutex_unlock (priv->x_lock);
 }
 
 /* Must be called in the gl thread */
@@ -414,12 +394,12 @@ gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback
 {
   GstGLWindowPrivate *priv = window->priv;
 
-  g_mutex_lock (priv->glwin_lock);
+  g_mutex_lock (priv->x_lock);
 
   priv->resize_cb = callback;
   priv->resize_data = data;
 
-  g_mutex_unlock (priv->glwin_lock);
+  g_mutex_unlock (priv->x_lock);
 }
 
 /* Must be called in the gl thread */
@@ -428,12 +408,12 @@ gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, g
 {
   GstGLWindowPrivate *priv = window->priv;
 
-  g_mutex_lock (priv->glwin_lock);
+  g_mutex_lock (priv->x_lock);
 
   priv->close_cb = callback;
   priv->close_data = data;
 
-  g_mutex_unlock (priv->glwin_lock);
+  g_mutex_unlock (priv->x_lock);
 }
 
 /* Thread safe */
@@ -444,12 +424,10 @@ gst_gl_window_visible (GstGLWindow *window, gboolean visible)
   {
     GstGLWindowPrivate *priv = window->priv;
 
-    g_mutex_lock (priv->glwin_lock);
+    g_mutex_lock (priv->x_lock);
 
     if (priv->running)
     {
-      g_mutex_lock (priv->x_lock);
-
       g_debug ("set visible %lld\n", (guint64) priv->internal_win_id);
 
       if (visible)
@@ -458,13 +436,9 @@ gst_gl_window_visible (GstGLWindow *window, gboolean visible)
         XUnmapWindow (priv->device, priv->internal_win_id);
 
       XSync(priv->device, FALSE);
-
-      g_cond_signal (priv->cond_x_event);
-
-      g_mutex_unlock (priv->x_lock);
     }
 
-    g_mutex_unlock (priv->glwin_lock);
+    g_mutex_unlock (priv->x_lock);
   }
 }
 
@@ -477,14 +451,15 @@ gst_gl_window_draw (GstGLWindow *window)
   {
     GstGLWindowPrivate *priv = window->priv;
 
-    g_mutex_lock (priv->glwin_lock);
+    g_mutex_lock (priv->x_lock);
 
     if (priv->running)
     {
+      Display *disp;
       XEvent event;
       XWindowAttributes attr;
 
-      g_mutex_lock (priv->x_lock);
+      disp = XOpenDisplay (priv->display_name);
 
       XGetWindowAttributes (priv->device, priv->internal_win_id, &attr);
 
@@ -502,12 +477,10 @@ gst_gl_window_draw (GstGLWindow *window)
 
       XSync (priv->device, FALSE);
 
-      g_cond_signal (priv->cond_x_event);
-
-      g_mutex_unlock (priv->x_lock);
+      XCloseDisplay (disp);
     }
 
-    g_mutex_unlock (priv->glwin_lock);
+    g_mutex_unlock (priv->x_lock);
   }
   g_debug ("DRAW OUT\n");
 }
@@ -517,147 +490,138 @@ gst_gl_window_run_loop (GstGLWindow *window)
 {
   GstGLWindowPrivate *priv = window->priv;
 
+
   g_debug ("begin loop\n");
 
-  g_mutex_lock (priv->glwin_lock);
+  g_mutex_lock (priv->x_lock);
 
   while (priv->running)
   {
     gboolean running = priv->running;
+    XEvent event;
 
-    g_mutex_unlock (priv->glwin_lock);
+    g_mutex_unlock (priv->x_lock);
 
-    g_mutex_lock (priv->x_lock);
+    g_debug("Before XNextEvent\n");
 
-    while (XPending (priv->device))
-    {
+    /* XSendEvent (which are called in other threads) are done from another display structure */
+    XNextEvent(priv->device, &event);
 
-      XEvent event;
+    g_debug("After XNextEvent\n");
 
-      XNextEvent(priv->device, &event);
+    g_mutex_lock (priv->x_lock);
 
-      switch (event.type)
+    switch (event.type)
+    {
+      case ClientMessage:
       {
-        case ClientMessage:
-        {
 
-          Atom wm_delete = XInternAtom (priv->device, "WM_DELETE_WINDOW", True);
-          Atom wm_gl = XInternAtom (priv->device, "WM_GL_WINDOW", True);
+        Atom wm_delete = XInternAtom (priv->device, "WM_DELETE_WINDOW", True);
+        Atom wm_gl = XInternAtom (priv->device, "WM_GL_WINDOW", True);
 
-          if (wm_delete == None)
-            g_debug ("Cannot create WM_DELETE_WINDOW\n");
-          if (wm_gl == None)
-            g_debug ("Cannot create WM_GL_WINDOW\n");
+        if (wm_delete == None)
+          g_debug ("Cannot create WM_DELETE_WINDOW\n");
+        if (wm_gl == None)
+          g_debug ("Cannot create WM_GL_WINDOW\n");
 
-          if (wm_gl != None && event.xclient.message_type == wm_gl)
+        if (wm_gl != None && event.xclient.message_type == wm_gl)
+        {
+          if (running)
           {
-            if (running)
-            {
-              GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
-              gpointer custom_data = (gpointer) event.xclient.data.l[1];
-
-              if (!custom_cb || !custom_data)
-                g_debug ("custom cb not initialized\n");
+            GstGLWindowCB custom_cb = (GstGLWindowCB) event.xclient.data.l[0];
+            gpointer custom_data = (gpointer) event.xclient.data.l[1];
 
-              custom_cb (custom_data);
-            }
+            if (!custom_cb || !custom_data)
+              g_debug ("custom cb not initialized\n");
 
-            g_cond_signal (priv->cond_send_message);
+            custom_cb (custom_data);
           }
 
-          else if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete)
-          {
-            XEvent event;
+          g_debug("signal\n");
 
-            g_debug ("Close\n");
+          g_cond_signal (priv->cond_send_message);
+        }
 
-            g_mutex_lock (priv->glwin_lock);
-            running = priv->running = FALSE;
-            g_mutex_unlock (priv->glwin_lock);
+        else if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete)
+        {
+          XEvent event;
 
-            if (priv->close_cb)
-              priv->close_cb (priv->close_data);
+          g_debug ("Close\n");
 
-            XFlush (priv->device);
-            while (XCheckTypedEvent (priv->device, ClientMessage, &event))
-            {
-              g_debug ("discared custom x event\n");
-              g_cond_signal (priv->cond_send_message);
-            }
-          }
-          else
+          running = priv->running = FALSE;
+
+          if (priv->close_cb)
+            priv->close_cb (priv->close_data);
+
+          XFlush (priv->device);
+          while (XCheckTypedEvent (priv->device, ClientMessage, &event))
           {
-            g_debug("not reconized client message\n");
+            g_debug ("discared custom x event\n");
+            g_cond_signal (priv->cond_send_message);
           }
-          break;
         }
-
-        case CreateNotify:
-        case ConfigureNotify:
+        else
         {
-          gint width = event.xconfigure.width;
-          gint height = event.xconfigure.height;
-          if (priv->resize_cb)
-            priv->resize_cb (priv->resize_data, width, height);
-          break;
+          g_debug("not reconized client message\n");
         }
+        break;
+      }
 
-        case DestroyNotify:
-          g_debug ("DestroyNotify\n");
-          break;
-
-        case Expose:
-          if (priv->draw_cb)
-          {
-            priv->draw_cb (priv->draw_data);
-            //glFlush();
-            glXSwapBuffers (priv->device, priv->internal_win_id);
-          }
-          break;
-
-        case VisibilityNotify:
+      case CreateNotify:
+      case ConfigureNotify:
+      {
+        gint width = event.xconfigure.width;
+        gint height = event.xconfigure.height;
+        if (priv->resize_cb)
+          priv->resize_cb (priv->resize_data, width, height);
+        break;
+      }
+
+      case DestroyNotify:
+        g_debug ("DestroyNotify\n");
+        break;
+
+      case Expose:
+        if (priv->draw_cb)
         {
-          switch (event.xvisibility.state)
-          {
-            case VisibilityUnobscured:
-              if (priv->draw_cb)
-                priv->draw_cb (priv->draw_data);
-              break;
-
-            case VisibilityPartiallyObscured:
-              if (priv->draw_cb)
-                priv->draw_cb (priv->draw_data);
-              break;
-
-            case VisibilityFullyObscured:
-              break;
-
-            default:
-              g_debug("unknown xvisibility event: %d\n", event.xvisibility.state);
-              break;
-          }
-          break;
+          priv->draw_cb (priv->draw_data);
+          //glFlush();
+          glXSwapBuffers (priv->device, priv->internal_win_id);
         }
+        break;
 
-        default:
-          break;
-
-      }// switch
-
-    }// while XPending
-
-    g_debug ("wait loop\n");
-    if (running && !XPending (priv->device))
-      g_cond_wait (priv->cond_x_event, priv->x_lock);
-    g_debug ("wake loop\n");
+      case VisibilityNotify:
+      {
+        switch (event.xvisibility.state)
+        {
+          case VisibilityUnobscured:
+            if (priv->draw_cb)
+              priv->draw_cb (priv->draw_data);
+            break;
+
+          case VisibilityPartiallyObscured:
+            if (priv->draw_cb)
+              priv->draw_cb (priv->draw_data);
+            break;
+
+          case VisibilityFullyObscured:
+            break;
+
+          default:
+            g_debug("unknown xvisibility event: %d\n", event.xvisibility.state);
+            break;
+        }
+        break;
+      }
 
-    g_mutex_unlock (priv->x_lock);
+      default:
+        break;
 
-    g_mutex_lock (priv->glwin_lock);
+    }// switch
 
   }// while running
 
-  g_mutex_unlock (priv->glwin_lock);
+  g_mutex_unlock (priv->x_lock);
 
   g_debug ("end loop\n");
 }
@@ -671,13 +635,12 @@ gst_gl_window_quit_loop (GstGLWindow *window)
   {
     GstGLWindowPrivate *priv = window->priv;
 
-    g_mutex_lock (priv->glwin_lock);
-
-    priv->running = FALSE;
+    g_mutex_lock (priv->x_lock);
 
-    g_cond_signal (priv->cond_x_event);
+    if (priv->running)
+      priv->running = FALSE;
 
-    g_mutex_unlock (priv->glwin_lock);
+    g_mutex_unlock (priv->x_lock);
   }
   g_debug ("QUIT LOOP OUT\n");
 }
@@ -692,35 +655,35 @@ gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointe
 
     GstGLWindowPrivate *priv = window->priv;
 
-    g_mutex_lock (priv->glwin_lock);
+    g_mutex_lock (priv->x_lock);
 
     if (priv->running)
     {
+      Display *disp;
       XEvent event;
 
-      g_mutex_lock (priv->x_lock);
+      disp = XOpenDisplay (priv->display_name);
 
       event.xclient.type = ClientMessage;
       event.xclient.send_event = TRUE;
-      event.xclient.display = priv->device;
+      event.xclient.display = disp;
       event.xclient.window = priv->internal_win_id;
       event.xclient.message_type = XInternAtom (priv->device, "WM_GL_WINDOW", True);
       event.xclient.format = 32;
       event.xclient.data.l[0] = (long) callback;
       event.xclient.data.l[1] = (long) data;
 
-      XSendEvent (priv->device, priv->internal_win_id, FALSE, NoEventMask, &event);
-      XSync (priv->device, FALSE);
-
-      g_mutex_unlock (priv->x_lock);
+      XSendEvent (disp, priv->internal_win_id, FALSE, NoEventMask, &event);
+      XSync (disp, FALSE);
 
-      g_cond_signal (priv->cond_x_event);
+      XCloseDisplay (disp);
 
-      g_cond_wait (priv->cond_send_message, priv->glwin_lock);
+      g_cond_wait (priv->cond_send_message, priv->x_lock);
 
     }
 
-    g_mutex_unlock (priv->glwin_lock);
+    g_mutex_unlock (priv->x_lock);
+
   }
   g_debug ("CUSTOM OUT\n");
 }