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
126
127
128
|
From 6d8d73beeef3a618c553e89b0b3e532ec3654a30 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 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)
{
--
2.18.1
|