summaryrefslogtreecommitdiffstats
path: root/patches/0002-Fix-for-issues-with-threaded-GL-drivers.patch
blob: 902d7f4bf037b8653d32b761325e420f7063950d (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
From d0fb8027cea418531f25be8750c8da1d7fcfe5e2 Mon Sep 17 00:00:00 2001
From: Paul Olav Tvete <paul.tvete@nokia.com>
Date: Wed, 16 Nov 2011 16:55:33 +0100
Subject: [PATCH 2/2] Fix for issues with threaded GL drivers

Two problems arise with asynchronous GL drivers that allow issuing
GL commands for the next frame before the GPU is done with the current frame:

1. The client code never knows when it is necessary to call wl_display_iterate.

Solution: Write to a pipe when there is data to be sent. The client can then select() on
the pipe's fd.

2. The GL library might call  wl_surface_attach/wl_surface_damage while the main thread is
doing wl_display_iterate.

Solution: Protect wl_display_iterate and wl_proxy_marshal with a mutex
---
 src/wayland-client.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/wayland-client.h |    9 +++++++
 2 files changed, 69 insertions(+), 1 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index fd5a8fa..979dadf 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -34,6 +34,7 @@
 #include <assert.h>
 #include <fcntl.h>
 #include <sys/poll.h>
+#include <pthread.h>
 
 #include "wayland-util.h"
 #include "wayland-client.h"
@@ -62,6 +63,9 @@ struct wl_display {
 	struct wl_proxy proxy;
 	struct wl_connection *connection;
 	int fd;
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+	int pipefd[2];
+#endif
 	uint32_t mask;
 	struct wl_map objects;
 	struct wl_list global_listener_list;
@@ -186,9 +190,42 @@ wl_proxy_add_listener(struct wl_proxy *proxy,
 	return 0;
 }
 
+static void 
+display_signal_flush_needed(struct wl_display *display)
+{
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+	const char data = '!';
+	if (display->pipefd[1])
+		write(display->pipefd[1], &data, 1);
+#endif
+}
+
+
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_t foo_locker;
+
+#define FOO_MUTEX_LOCK \
+    int foo_needLock = (pthread_self() != foo_locker); \
+	if (foo_needLock) { \
+		pthread_mutex_lock(&foo_mutex); \
+		foo_locker = pthread_self(); \
+	}
+
+#define FOO_MUTEX_UNLOCK \
+	if (foo_needLock) { \
+        foo_locker = 0; \
+		pthread_mutex_unlock(&foo_mutex); \
+    }
+#else
+#define FOO_MUTEX_LOCK
+#define FOO_MUTEX_UNLOCK
+#endif
+
 WL_EXPORT void
 wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 {
+	FOO_MUTEX_LOCK;
 	struct wl_closure *closure;
 	va_list ap;
 
@@ -204,6 +241,8 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
 		wl_closure_print(closure, &proxy->object, true);
 
 	wl_closure_destroy(closure);
+	display_signal_flush_needed(proxy->display);
+	FOO_MUTEX_UNLOCK;
 }
 
 /* Can't do this, there may be more than one instance of an
@@ -414,6 +453,17 @@ wl_display_get_fd(struct wl_display *display,
 	return display->fd;
 }
 
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+WL_EXPORT int 
+wl_display_get_write_notification_fd(struct wl_display *display)
+{
+	if (!display->pipefd[0]) {
+		pipe2(display->pipefd, O_CLOEXEC | O_NONBLOCK);
+	}
+	return display->pipefd[0];
+}
+#endif
+
 static void
 sync_callback(void *data, struct wl_callback *callback, uint32_t time)
 {
@@ -482,16 +532,24 @@ handle_event(struct wl_display *display,
 WL_EXPORT void
 wl_display_iterate(struct wl_display *display, uint32_t mask)
 {
+	FOO_MUTEX_LOCK;
 	uint32_t p[2], object, opcode, size;
 	int len;
-
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+	if ((mask & WL_DISPLAY_WRITABLE) && display->pipefd[0]) {
+		char buf[80];
+		int n = read(display->pipefd[0], buf, 80);
+	}
+#endif
 	mask &= display->mask;
 	if (mask == 0) {
 		fprintf(stderr,
 			"wl_display_iterate called with unsolicited flags");
+		FOO_MUTEX_UNLOCK;
 		return;
 	}
 
+
 	len = wl_connection_data(display->connection, mask);
 
 	while (len > 0) {
@@ -513,6 +571,7 @@ wl_display_iterate(struct wl_display *display, uint32_t mask)
 		fprintf(stderr, "read error: %m\n");
 		exit(EXIT_FAILURE);
 	}
+	FOO_MUTEX_UNLOCK;
 }
 
 WL_EXPORT void
diff --git a/src/wayland-client.h b/src/wayland-client.h
index efeee4a..050f7f2 100644
--- a/src/wayland-client.h
+++ b/src/wayland-client.h
@@ -94,6 +94,15 @@ uint32_t
 wl_display_get_global(struct wl_display *display,
 		      const char *interface, uint32_t version);
 
+
+
+#define QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+
+#ifdef QTWAYLAND_EXPERIMENTAL_THREAD_SUPPORT
+int wl_display_get_write_notification_fd(struct wl_display *display);
+#endif
+
+
 #ifdef  __cplusplus
 }
 #endif
-- 
1.7.8.rc2