summarylogtreecommitdiffstats
path: root/216.patch
blob: 43e53440fb57c8900023c82409fd95c87d2276d5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
From ab03f010df7b78854433093030f08a81c059aa26 Mon Sep 17 00:00:00 2001
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
Date: Mon, 23 Jul 2018 16:28:56 +0800
Subject: [PATCH] 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 was that CoglBool can only count to one pending notification,
so we just change that to an integer and count properly.
---
 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 012c712bd..2cf6e95fc 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;
-  CoglBool pending_sync_notify;
-  CoglBool pending_complete_notify;
-  CoglBool 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;
-      CoglBool pending_sync_notify = glx_onscreen->pending_sync_notify;
-      CoglBool 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)
     {
-- 
2.18.1