[mutter] cogl-winsys-glx: Fix frame notification race/leak



commit 20c1295a33fff5071d405ac5d0eaf55d6d382180
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Mon Jul 23 16:28:56 2018 +0800

    cogl-winsys-glx: Fix frame notification race/leak
    
    If a second `set_{sync,complete}_pending` was queued before the idle
    handler had flushed the first then one of them would be forgotten.
    It would stay queued forever and never emitted as a notification.
    
    This could happen repeatedly causing a slow leak. But worse still,
    `clutter-stage-cogl` would then have `pending_swaps` permanently stuck
    above zero preventing the presentation timing logic from being used.
    
    The problem is that a boolean can only count to one, but in some cases
    (triple buffering, whether intentional or accidental #334) we need it to
    count to two. So just change booleans to integers and count properly.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/216

 cogl/cogl/winsys/cogl-winsys-glx.c | 58 +++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 29 deletions(-)
---
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
index 2623d02c6..235cfe81f 100644
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -99,9 +99,9 @@ typedef struct _CoglOnscreenGLX
   CoglOnscreenXlib _parent;
   GLXDrawable glxwin;
   uint32_t last_swap_vsync_counter;
-  gboolean pending_sync_notify;
-  gboolean pending_complete_notify;
-  gboolean pending_resize_notify;
+  uint32_t pending_sync_notify;
+  uint32_t pending_complete_notify;
+  uint32_t pending_resize_notify;
 
   GThread *swap_wait_thread;
   GQueue *swap_wait_queue;
@@ -347,35 +347,35 @@ flush_pending_notifications_cb (void *data,
     {
       CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
       CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
-      gboolean pending_sync_notify = glx_onscreen->pending_sync_notify;
-      gboolean pending_complete_notify = glx_onscreen->pending_complete_notify;
 
-      /* If swap_region is called then notifying the sync event could
-       * potentially immediately queue a subsequent pending notify so
-       * we need to clear the flag before invoking the callback */
-      glx_onscreen->pending_sync_notify = FALSE;
-      glx_onscreen->pending_complete_notify = FALSE;
-
-      if (pending_sync_notify)
+      while (glx_onscreen->pending_sync_notify > 0 ||
+             glx_onscreen->pending_complete_notify > 0 ||
+             glx_onscreen->pending_resize_notify > 0)
         {
-          CoglFrameInfo *info = g_queue_peek_head (&onscreen->pending_frame_infos);
-
-          _cogl_onscreen_notify_frame_sync (onscreen, info);
-        }
+          if (glx_onscreen->pending_sync_notify > 0)
+            {
+              CoglFrameInfo *info =
+                g_queue_peek_head (&onscreen->pending_frame_infos);
 
-      if (pending_complete_notify)
-        {
-          CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos);
+              _cogl_onscreen_notify_frame_sync (onscreen, info);
+              glx_onscreen->pending_sync_notify--;
+            }
 
-          _cogl_onscreen_notify_complete (onscreen, info);
+          if (glx_onscreen->pending_complete_notify > 0)
+            {
+              CoglFrameInfo *info =
+                g_queue_pop_head (&onscreen->pending_frame_infos);
 
-          cogl_object_unref (info);
-        }
+              _cogl_onscreen_notify_complete (onscreen, info);
+              cogl_object_unref (info);
+              glx_onscreen->pending_complete_notify--;
+            }
 
-      if (glx_onscreen->pending_resize_notify)
-        {
-          _cogl_onscreen_notify_resize (onscreen);
-          glx_onscreen->pending_resize_notify = FALSE;
+          if (glx_onscreen->pending_resize_notify > 0)
+            {
+              _cogl_onscreen_notify_resize (onscreen);
+              glx_onscreen->pending_resize_notify--;
+            }
         }
     }
 }
@@ -417,7 +417,7 @@ set_sync_pending (CoglOnscreen *onscreen)
                                       NULL);
     }
 
-  glx_onscreen->pending_sync_notify = TRUE;
+  glx_onscreen->pending_sync_notify++;
 }
 
 static void
@@ -440,7 +440,7 @@ set_complete_pending (CoglOnscreen *onscreen)
                                       NULL);
     }
 
-  glx_onscreen->pending_complete_notify = TRUE;
+  glx_onscreen->pending_complete_notify++;
 }
 
 static void
@@ -533,7 +533,7 @@ notify_resize (CoglContext *context,
                                       NULL);
     }
 
-  glx_onscreen->pending_resize_notify = TRUE;
+  glx_onscreen->pending_resize_notify++;
 
   if (!xlib_onscreen->is_foreign_xwin)
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]