1 /*
2 * Copyright © 2018 Collabora, Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <string.h>
29 #include <unistd.h>
30
31 #include "linux-explicit-synchronization-unstable-v1-client-protocol.h"
32 #include "weston-test-client-helper.h"
33 #include "wayland-server-protocol.h"
34 #include "weston-test-fixture-compositor.h"
35
36 static enum test_result_code
fixture_setup(struct weston_test_harness * harness)37 fixture_setup(struct weston_test_harness *harness)
38 {
39 struct compositor_setup setup;
40
41 compositor_setup_defaults(&setup);
42
43 /* We need to use the pixman renderer, since a few of the tests depend
44 * on the renderer holding onto a surface buffer until the next one
45 * is committed, which the noop renderer doesn't do. */
46 setup.renderer = RENDERER_PIXMAN;
47
48 return weston_test_harness_execute_as_client(harness, &setup);
49 }
50 DECLARE_FIXTURE_SETUP(fixture_setup);
51
52 static struct zwp_linux_explicit_synchronization_v1 *
get_linux_explicit_synchronization(struct client * client)53 get_linux_explicit_synchronization(struct client *client)
54 {
55 struct global *g;
56 struct global *global_sync = NULL;
57 struct zwp_linux_explicit_synchronization_v1 *sync = NULL;
58
59 wl_list_for_each(g, &client->global_list, link) {
60 if (strcmp(g->interface,
61 zwp_linux_explicit_synchronization_v1_interface.name))
62 continue;
63
64 if (global_sync)
65 assert(!"Multiple linux explicit sync objects");
66
67 global_sync = g;
68 }
69
70 assert(global_sync);
71 assert(global_sync->version == 2);
72
73 sync = wl_registry_bind(
74 client->wl_registry, global_sync->name,
75 &zwp_linux_explicit_synchronization_v1_interface, 2);
76 assert(sync);
77
78 return sync;
79 }
80
81 static struct client *
create_test_client(void)82 create_test_client(void)
83 {
84 struct client *cl = create_client_and_test_surface(0, 0, 100, 100);
85 assert(cl);
86 return cl;
87 }
88
TEST(second_surface_synchronization_on_surface_raises_error)89 TEST(second_surface_synchronization_on_surface_raises_error)
90 {
91 struct client *client = create_test_client();
92 struct zwp_linux_explicit_synchronization_v1 *sync =
93 get_linux_explicit_synchronization(client);
94 struct zwp_linux_surface_synchronization_v1 *surface_sync1;
95 struct zwp_linux_surface_synchronization_v1 *surface_sync2;
96
97 surface_sync1 =
98 zwp_linux_explicit_synchronization_v1_get_synchronization(
99 sync, client->surface->wl_surface);
100 client_roundtrip(client);
101
102 /* Second surface_synchronization creation should fail */
103 surface_sync2 =
104 zwp_linux_explicit_synchronization_v1_get_synchronization(
105 sync, client->surface->wl_surface);
106 expect_protocol_error(
107 client,
108 &zwp_linux_explicit_synchronization_v1_interface,
109 ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS);
110
111 zwp_linux_surface_synchronization_v1_destroy(surface_sync2);
112 zwp_linux_surface_synchronization_v1_destroy(surface_sync1);
113 zwp_linux_explicit_synchronization_v1_destroy(sync);
114 }
115
TEST(set_acquire_fence_with_invalid_fence_raises_error)116 TEST(set_acquire_fence_with_invalid_fence_raises_error)
117 {
118 struct client *client = create_test_client();
119 struct zwp_linux_explicit_synchronization_v1 *sync =
120 get_linux_explicit_synchronization(client);
121 struct zwp_linux_surface_synchronization_v1 *surface_sync =
122 zwp_linux_explicit_synchronization_v1_get_synchronization(
123 sync, client->surface->wl_surface);
124 int pipefd[2] = { -1, -1 };
125
126 assert(pipe(pipefd) == 0);
127
128 zwp_linux_surface_synchronization_v1_set_acquire_fence(surface_sync,
129 pipefd[0]);
130 expect_protocol_error(
131 client,
132 &zwp_linux_surface_synchronization_v1_interface,
133 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_INVALID_FENCE);
134
135 close(pipefd[0]);
136 close(pipefd[1]);
137 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
138 zwp_linux_explicit_synchronization_v1_destroy(sync);
139 }
140
TEST(set_acquire_fence_on_destroyed_surface_raises_error)141 TEST(set_acquire_fence_on_destroyed_surface_raises_error)
142 {
143 struct client *client = create_test_client();
144 struct zwp_linux_explicit_synchronization_v1 *sync =
145 get_linux_explicit_synchronization(client);
146 struct zwp_linux_surface_synchronization_v1 *surface_sync =
147 zwp_linux_explicit_synchronization_v1_get_synchronization(
148 sync, client->surface->wl_surface);
149 int pipefd[2] = { -1, -1 };
150
151 assert(pipe(pipefd) == 0);
152
153 wl_surface_destroy(client->surface->wl_surface);
154 zwp_linux_surface_synchronization_v1_set_acquire_fence(surface_sync,
155 pipefd[0]);
156 expect_protocol_error(
157 client,
158 &zwp_linux_surface_synchronization_v1_interface,
159 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE);
160
161 close(pipefd[0]);
162 close(pipefd[1]);
163 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
164 zwp_linux_explicit_synchronization_v1_destroy(sync);
165 }
166
TEST(second_buffer_release_in_commit_raises_error)167 TEST(second_buffer_release_in_commit_raises_error)
168 {
169 struct client *client = create_test_client();
170 struct zwp_linux_explicit_synchronization_v1 *sync =
171 get_linux_explicit_synchronization(client);
172 struct zwp_linux_surface_synchronization_v1 *surface_sync =
173 zwp_linux_explicit_synchronization_v1_get_synchronization(
174 sync, client->surface->wl_surface);
175 struct zwp_linux_buffer_release_v1 *buffer_release1;
176 struct zwp_linux_buffer_release_v1 *buffer_release2;
177
178 buffer_release1 =
179 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
180 client_roundtrip(client);
181
182 /* Second buffer_release creation should fail */
183 buffer_release2 =
184 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
185 expect_protocol_error(
186 client,
187 &zwp_linux_surface_synchronization_v1_interface,
188 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_DUPLICATE_RELEASE);
189
190 zwp_linux_buffer_release_v1_destroy(buffer_release2);
191 zwp_linux_buffer_release_v1_destroy(buffer_release1);
192 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
193 zwp_linux_explicit_synchronization_v1_destroy(sync);
194 }
195
TEST(get_release_without_buffer_raises_commit_error)196 TEST(get_release_without_buffer_raises_commit_error)
197 {
198 struct client *client = create_test_client();
199 struct zwp_linux_explicit_synchronization_v1 *sync =
200 get_linux_explicit_synchronization(client);
201 struct zwp_linux_surface_synchronization_v1 *surface_sync =
202 zwp_linux_explicit_synchronization_v1_get_synchronization(
203 sync, client->surface->wl_surface);
204 struct wl_surface *surface = client->surface->wl_surface;
205 struct zwp_linux_buffer_release_v1 *buffer_release;
206
207 buffer_release =
208 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
209 wl_surface_commit(surface);
210 expect_protocol_error(
211 client,
212 &zwp_linux_surface_synchronization_v1_interface,
213 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER);
214
215 zwp_linux_buffer_release_v1_destroy(buffer_release);
216 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
217 zwp_linux_explicit_synchronization_v1_destroy(sync);
218 }
219
TEST(get_release_on_destroyed_surface_raises_error)220 TEST(get_release_on_destroyed_surface_raises_error)
221 {
222 struct client *client = create_test_client();
223 struct zwp_linux_explicit_synchronization_v1 *sync =
224 get_linux_explicit_synchronization(client);
225 struct zwp_linux_surface_synchronization_v1 *surface_sync =
226 zwp_linux_explicit_synchronization_v1_get_synchronization(
227 sync, client->surface->wl_surface);
228 struct zwp_linux_buffer_release_v1 *buffer_release;
229
230 wl_surface_destroy(client->surface->wl_surface);
231 buffer_release =
232 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
233 expect_protocol_error(
234 client,
235 &zwp_linux_surface_synchronization_v1_interface,
236 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE);
237
238 zwp_linux_buffer_release_v1_destroy(buffer_release);
239 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
240 zwp_linux_explicit_synchronization_v1_destroy(sync);
241 }
242
TEST(get_release_after_commit_succeeds)243 TEST(get_release_after_commit_succeeds)
244 {
245 struct client *client = create_test_client();
246 struct zwp_linux_explicit_synchronization_v1 *sync =
247 get_linux_explicit_synchronization(client);
248 struct wl_surface *surface = client->surface->wl_surface;
249 struct zwp_linux_surface_synchronization_v1 *surface_sync =
250 zwp_linux_explicit_synchronization_v1_get_synchronization(
251 sync, surface);
252 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
253 struct zwp_linux_buffer_release_v1 *buffer_release1;
254 struct zwp_linux_buffer_release_v1 *buffer_release2;
255
256 buffer_release1 =
257 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
258 client_roundtrip(client);
259
260 wl_surface_attach(surface, buf1->proxy, 0, 0);
261 wl_surface_commit(surface);
262
263 buffer_release2 =
264 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
265 client_roundtrip(client);
266
267 buffer_destroy(buf1);
268 zwp_linux_buffer_release_v1_destroy(buffer_release2);
269 zwp_linux_buffer_release_v1_destroy(buffer_release1);
270 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
271 zwp_linux_explicit_synchronization_v1_destroy(sync);
272 }
273
274 static void
buffer_release_fenced_handler(void * data,struct zwp_linux_buffer_release_v1 * buffer_release,int32_t fence)275 buffer_release_fenced_handler(void *data,
276 struct zwp_linux_buffer_release_v1 *buffer_release,
277 int32_t fence)
278 {
279 assert(!"Fenced release not supported yet");
280 }
281
282 static void
buffer_release_immediate_handler(void * data,struct zwp_linux_buffer_release_v1 * buffer_release)283 buffer_release_immediate_handler(void *data,
284 struct zwp_linux_buffer_release_v1 *buffer_release)
285 {
286 int *released = data;
287
288 *released += 1;
289 }
290
291 struct zwp_linux_buffer_release_v1_listener buffer_release_listener = {
292 buffer_release_fenced_handler,
293 buffer_release_immediate_handler
294 };
295
296 /* The following release event tests depend on the behavior of the used
297 * backend, in this case the pixman backend. This doesn't limit their
298 * usefulness, though, since it allows them to check if, given a typical
299 * backend implementation, weston core supports the per commit nature of the
300 * release events.
301 */
302
TEST(get_release_events_are_emitted_for_different_buffers)303 TEST(get_release_events_are_emitted_for_different_buffers)
304 {
305 struct client *client = create_test_client();
306 struct zwp_linux_explicit_synchronization_v1 *sync =
307 get_linux_explicit_synchronization(client);
308 struct zwp_linux_surface_synchronization_v1 *surface_sync =
309 zwp_linux_explicit_synchronization_v1_get_synchronization(
310 sync, client->surface->wl_surface);
311 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
312 struct buffer *buf2 = create_shm_buffer_a8r8g8b8(client, 100, 100);
313 struct wl_surface *surface = client->surface->wl_surface;
314 struct zwp_linux_buffer_release_v1 *buffer_release1;
315 struct zwp_linux_buffer_release_v1 *buffer_release2;
316 int buf_released1 = 0;
317 int buf_released2 = 0;
318 int frame;
319
320 buffer_release1 =
321 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
322 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
323 &buffer_release_listener,
324 &buf_released1);
325 wl_surface_attach(surface, buf1->proxy, 0, 0);
326 frame_callback_set(surface, &frame);
327 wl_surface_commit(surface);
328 frame_callback_wait(client, &frame);
329 /* No release event should have been emitted yet (we are using the
330 * pixman renderer, which holds buffers until they are replaced). */
331 assert(buf_released1 == 0);
332
333 buffer_release2 =
334 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
335 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
336 &buffer_release_listener,
337 &buf_released2);
338 wl_surface_attach(surface, buf2->proxy, 0, 0);
339 frame_callback_set(surface, &frame);
340 wl_surface_commit(surface);
341 frame_callback_wait(client, &frame);
342 /* Check that exactly one buffer_release event was emitted for the
343 * previous commit (buf1). */
344 assert(buf_released1 == 1);
345 assert(buf_released2 == 0);
346
347 wl_surface_attach(surface, buf1->proxy, 0, 0);
348 frame_callback_set(surface, &frame);
349 wl_surface_commit(surface);
350 frame_callback_wait(client, &frame);
351 /* Check that exactly one buffer_release event was emitted for the
352 * previous commit (buf2). */
353 assert(buf_released1 == 1);
354 assert(buf_released2 == 1);
355
356 buffer_destroy(buf2);
357 buffer_destroy(buf1);
358 zwp_linux_buffer_release_v1_destroy(buffer_release2);
359 zwp_linux_buffer_release_v1_destroy(buffer_release1);
360 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
361 zwp_linux_explicit_synchronization_v1_destroy(sync);
362 }
363
TEST(get_release_events_are_emitted_for_same_buffer_on_surface)364 TEST(get_release_events_are_emitted_for_same_buffer_on_surface)
365 {
366 struct client *client = create_test_client();
367 struct zwp_linux_explicit_synchronization_v1 *sync =
368 get_linux_explicit_synchronization(client);
369 struct zwp_linux_surface_synchronization_v1 *surface_sync =
370 zwp_linux_explicit_synchronization_v1_get_synchronization(
371 sync, client->surface->wl_surface);
372 struct buffer *buf = create_shm_buffer_a8r8g8b8(client, 100, 100);
373 struct wl_surface *surface = client->surface->wl_surface;
374 struct zwp_linux_buffer_release_v1 *buffer_release1;
375 struct zwp_linux_buffer_release_v1 *buffer_release2;
376 int buf_released1 = 0;
377 int buf_released2 = 0;
378 int frame;
379
380 buffer_release1 =
381 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
382 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
383 &buffer_release_listener,
384 &buf_released1);
385 wl_surface_attach(surface, buf->proxy, 0, 0);
386 frame_callback_set(surface, &frame);
387 wl_surface_commit(surface);
388 frame_callback_wait(client, &frame);
389 /* No release event should have been emitted yet (we are using the
390 * pixman renderer, which holds buffers until they are replaced). */
391 assert(buf_released1 == 0);
392
393 buffer_release2 =
394 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
395 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
396 &buffer_release_listener,
397 &buf_released2);
398 wl_surface_attach(surface, buf->proxy, 0, 0);
399 frame_callback_set(surface, &frame);
400 wl_surface_commit(surface);
401 frame_callback_wait(client, &frame);
402 /* Check that exactly one buffer_release event was emitted for the
403 * previous commit (buf). */
404 assert(buf_released1 == 1);
405 assert(buf_released2 == 0);
406
407 wl_surface_attach(surface, buf->proxy, 0, 0);
408 frame_callback_set(surface, &frame);
409 wl_surface_commit(surface);
410 frame_callback_wait(client, &frame);
411 /* Check that exactly one buffer_release event was emitted for the
412 * previous commit (buf again). */
413 assert(buf_released1 == 1);
414 assert(buf_released2 == 1);
415
416 buffer_destroy(buf);
417 zwp_linux_buffer_release_v1_destroy(buffer_release2);
418 zwp_linux_buffer_release_v1_destroy(buffer_release1);
419 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
420 zwp_linux_explicit_synchronization_v1_destroy(sync);
421 }
422
TEST(get_release_events_are_emitted_for_same_buffer_on_different_surfaces)423 TEST(get_release_events_are_emitted_for_same_buffer_on_different_surfaces)
424 {
425 struct client *client = create_test_client();
426 struct surface *other_surface = create_test_surface(client);
427 struct wl_surface *surface1 = client->surface->wl_surface;
428 struct wl_surface *surface2 = other_surface->wl_surface;
429 struct zwp_linux_explicit_synchronization_v1 *sync =
430 get_linux_explicit_synchronization(client);
431 struct zwp_linux_surface_synchronization_v1 *surface_sync1 =
432 zwp_linux_explicit_synchronization_v1_get_synchronization(
433 sync, surface1);
434 struct zwp_linux_surface_synchronization_v1 *surface_sync2 =
435 zwp_linux_explicit_synchronization_v1_get_synchronization(
436 sync, surface2);
437 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
438 struct buffer *buf2 = create_shm_buffer_a8r8g8b8(client, 100, 100);
439 struct zwp_linux_buffer_release_v1 *buffer_release1;
440 struct zwp_linux_buffer_release_v1 *buffer_release2;
441 int buf_released1 = 0;
442 int buf_released2 = 0;
443 int frame;
444
445 weston_test_move_surface(client->test->weston_test, surface2, 0, 0);
446
447 /* Attach buf1 to both surface1 and surface2. */
448 buffer_release1 =
449 zwp_linux_surface_synchronization_v1_get_release(surface_sync1);
450 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
451 &buffer_release_listener,
452 &buf_released1);
453 wl_surface_attach(surface1, buf1->proxy, 0, 0);
454 frame_callback_set(surface1, &frame);
455 wl_surface_commit(surface1);
456 frame_callback_wait(client, &frame);
457
458 buffer_release2 =
459 zwp_linux_surface_synchronization_v1_get_release(surface_sync2);
460 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
461 &buffer_release_listener,
462 &buf_released2);
463 wl_surface_attach(surface2, buf1->proxy, 0, 0);
464 frame_callback_set(surface2, &frame);
465 wl_surface_commit(surface2);
466 frame_callback_wait(client, &frame);
467
468 assert(buf_released1 == 0);
469 assert(buf_released2 == 0);
470
471 /* Attach buf2 to surface1, and check that a buffer_release event for
472 * the previous commit (buf1) for that surface is emitted. */
473 wl_surface_attach(surface1, buf2->proxy, 0, 0);
474 frame_callback_set(surface1, &frame);
475 wl_surface_commit(surface1);
476 frame_callback_wait(client, &frame);
477
478 assert(buf_released1 == 1);
479 assert(buf_released2 == 0);
480
481 /* Attach buf2 to surface2, and check that a buffer_release event for
482 * the previous commit (buf1) for that surface is emitted. */
483 wl_surface_attach(surface2, buf2->proxy, 0, 0);
484 frame_callback_set(surface2, &frame);
485 wl_surface_commit(surface2);
486 frame_callback_wait(client, &frame);
487
488 assert(buf_released1 == 1);
489 assert(buf_released2 == 1);
490
491 buffer_destroy(buf2);
492 buffer_destroy(buf1);
493 zwp_linux_buffer_release_v1_destroy(buffer_release2);
494 zwp_linux_buffer_release_v1_destroy(buffer_release1);
495 zwp_linux_surface_synchronization_v1_destroy(surface_sync2);
496 zwp_linux_surface_synchronization_v1_destroy(surface_sync1);
497 zwp_linux_explicit_synchronization_v1_destroy(sync);
498 }
499