blob: a89b252b1d92f986d17efff0ba9258e5837c5492 [file] [log] [blame]
Alexandros Frantzis27d7c392018-10-19 12:14:11 +03001/*
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>
Alexandros Frantzisacff29b2018-10-19 12:14:11 +030029#include <unistd.h>
Alexandros Frantzis27d7c392018-10-19 12:14:11 +030030
31#include "linux-explicit-synchronization-unstable-v1-client-protocol.h"
32#include "weston-test-client-helper.h"
33#include "wayland-server-protocol.h"
34
Alexandros Frantzisc715c752018-11-12 18:33:54 +020035/* We need to use the pixman renderer, since a few of the tests depend
36 * on the renderer holding onto a surface buffer until the next one
37 * is committed, which the noop renderer doesn't do. */
38char *server_parameters = "--use-pixman";
39
Alexandros Frantzis27d7c392018-10-19 12:14:11 +030040static struct zwp_linux_explicit_synchronization_v1 *
41get_linux_explicit_synchronization(struct client *client)
42{
43 struct global *g;
44 struct global *global_sync = NULL;
45 struct zwp_linux_explicit_synchronization_v1 *sync = NULL;
46
47 wl_list_for_each(g, &client->global_list, link) {
48 if (strcmp(g->interface,
49 zwp_linux_explicit_synchronization_v1_interface.name))
50 continue;
51
52 if (global_sync)
53 assert(!"Multiple linux explicit sync objects");
54
55 global_sync = g;
56 }
57
58 assert(global_sync);
59 assert(global_sync->version == 1);
60
61 sync = wl_registry_bind(
62 client->wl_registry, global_sync->name,
63 &zwp_linux_explicit_synchronization_v1_interface, 1);
64 assert(sync);
65
66 return sync;
67}
68
69static struct client *
70create_test_client(void)
71{
72 struct client *cl = create_client_and_test_surface(0, 0, 100, 100);
73 assert(cl);
74 return cl;
75}
76
77TEST(second_surface_synchronization_on_surface_raises_error)
78{
79 struct client *client = create_test_client();
80 struct zwp_linux_explicit_synchronization_v1 *sync =
81 get_linux_explicit_synchronization(client);
82 struct zwp_linux_surface_synchronization_v1 *surface_sync1;
83 struct zwp_linux_surface_synchronization_v1 *surface_sync2;
84
85 surface_sync1 =
86 zwp_linux_explicit_synchronization_v1_get_synchronization(
87 sync, client->surface->wl_surface);
88 client_roundtrip(client);
89
90 /* Second surface_synchronization creation should fail */
91 surface_sync2 =
92 zwp_linux_explicit_synchronization_v1_get_synchronization(
93 sync, client->surface->wl_surface);
94 expect_protocol_error(
95 client,
96 &zwp_linux_explicit_synchronization_v1_interface,
97 ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS);
98
99 zwp_linux_surface_synchronization_v1_destroy(surface_sync2);
100 zwp_linux_surface_synchronization_v1_destroy(surface_sync1);
101 zwp_linux_explicit_synchronization_v1_destroy(sync);
102}
Alexandros Frantzisacff29b2018-10-19 12:14:11 +0300103
104TEST(set_acquire_fence_with_invalid_fence_raises_error)
105{
106 struct client *client = create_test_client();
107 struct zwp_linux_explicit_synchronization_v1 *sync =
108 get_linux_explicit_synchronization(client);
109 struct zwp_linux_surface_synchronization_v1 *surface_sync =
110 zwp_linux_explicit_synchronization_v1_get_synchronization(
111 sync, client->surface->wl_surface);
112 int pipefd[2] = { -1, -1 };
113
114 assert(pipe(pipefd) == 0);
115
116 zwp_linux_surface_synchronization_v1_set_acquire_fence(surface_sync,
117 pipefd[0]);
118 expect_protocol_error(
119 client,
120 &zwp_linux_surface_synchronization_v1_interface,
121 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_INVALID_FENCE);
122
123 close(pipefd[0]);
124 close(pipefd[1]);
125 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
126 zwp_linux_explicit_synchronization_v1_destroy(sync);
127}
128
129TEST(set_acquire_fence_on_destroyed_surface_raises_error)
130{
131 struct client *client = create_test_client();
132 struct zwp_linux_explicit_synchronization_v1 *sync =
133 get_linux_explicit_synchronization(client);
134 struct zwp_linux_surface_synchronization_v1 *surface_sync =
135 zwp_linux_explicit_synchronization_v1_get_synchronization(
136 sync, client->surface->wl_surface);
137 int pipefd[2] = { -1, -1 };
138
139 assert(pipe(pipefd) == 0);
140
141 wl_surface_destroy(client->surface->wl_surface);
142 zwp_linux_surface_synchronization_v1_set_acquire_fence(surface_sync,
143 pipefd[0]);
144 expect_protocol_error(
145 client,
146 &zwp_linux_surface_synchronization_v1_interface,
147 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE);
148
149 close(pipefd[0]);
150 close(pipefd[1]);
151 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
152 zwp_linux_explicit_synchronization_v1_destroy(sync);
153}
Alexandros Frantzis67629672018-10-19 12:14:11 +0300154
155TEST(second_buffer_release_in_commit_raises_error)
156{
157 struct client *client = create_test_client();
158 struct zwp_linux_explicit_synchronization_v1 *sync =
159 get_linux_explicit_synchronization(client);
160 struct zwp_linux_surface_synchronization_v1 *surface_sync =
161 zwp_linux_explicit_synchronization_v1_get_synchronization(
162 sync, client->surface->wl_surface);
163 struct zwp_linux_buffer_release_v1 *buffer_release1;
164 struct zwp_linux_buffer_release_v1 *buffer_release2;
165
166 buffer_release1 =
167 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
168 client_roundtrip(client);
169
170 /* Second buffer_release creation should fail */
171 buffer_release2 =
172 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
173 expect_protocol_error(
174 client,
175 &zwp_linux_surface_synchronization_v1_interface,
176 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_DUPLICATE_RELEASE);
177
178 zwp_linux_buffer_release_v1_destroy(buffer_release2);
179 zwp_linux_buffer_release_v1_destroy(buffer_release1);
180 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
181 zwp_linux_explicit_synchronization_v1_destroy(sync);
182}
183
184TEST(get_release_without_buffer_raises_commit_error)
185{
186 struct client *client = create_test_client();
187 struct zwp_linux_explicit_synchronization_v1 *sync =
188 get_linux_explicit_synchronization(client);
189 struct zwp_linux_surface_synchronization_v1 *surface_sync =
190 zwp_linux_explicit_synchronization_v1_get_synchronization(
191 sync, client->surface->wl_surface);
192 struct wl_surface *surface = client->surface->wl_surface;
193 struct zwp_linux_buffer_release_v1 *buffer_release;
194
195 buffer_release =
196 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
197 wl_surface_commit(surface);
198 expect_protocol_error(
199 client,
200 &zwp_linux_surface_synchronization_v1_interface,
201 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER);
202
203 zwp_linux_buffer_release_v1_destroy(buffer_release);
204 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
205 zwp_linux_explicit_synchronization_v1_destroy(sync);
206}
207
208TEST(get_release_on_destroyed_surface_raises_error)
209{
210 struct client *client = create_test_client();
211 struct zwp_linux_explicit_synchronization_v1 *sync =
212 get_linux_explicit_synchronization(client);
213 struct zwp_linux_surface_synchronization_v1 *surface_sync =
214 zwp_linux_explicit_synchronization_v1_get_synchronization(
215 sync, client->surface->wl_surface);
216 struct zwp_linux_buffer_release_v1 *buffer_release;
217
218 wl_surface_destroy(client->surface->wl_surface);
219 buffer_release =
220 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
221 expect_protocol_error(
222 client,
223 &zwp_linux_surface_synchronization_v1_interface,
224 ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE);
225
226 zwp_linux_buffer_release_v1_destroy(buffer_release);
227 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
228 zwp_linux_explicit_synchronization_v1_destroy(sync);
229}
230
231TEST(get_release_after_commit_succeeds)
232{
233 struct client *client = create_test_client();
234 struct zwp_linux_explicit_synchronization_v1 *sync =
235 get_linux_explicit_synchronization(client);
236 struct wl_surface *surface = client->surface->wl_surface;
237 struct zwp_linux_surface_synchronization_v1 *surface_sync =
238 zwp_linux_explicit_synchronization_v1_get_synchronization(
239 sync, surface);
240 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
241 struct zwp_linux_buffer_release_v1 *buffer_release1;
242 struct zwp_linux_buffer_release_v1 *buffer_release2;
243
244 buffer_release1 =
245 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
246 client_roundtrip(client);
247
248 wl_surface_attach(surface, buf1->proxy, 0, 0);
249 wl_surface_commit(surface);
250
251 buffer_release2 =
252 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
253 client_roundtrip(client);
254
255 buffer_destroy(buf1);
256 zwp_linux_buffer_release_v1_destroy(buffer_release2);
257 zwp_linux_buffer_release_v1_destroy(buffer_release1);
258 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
259 zwp_linux_explicit_synchronization_v1_destroy(sync);
260}
261
262static void
263buffer_release_fenced_handler(void *data,
264 struct zwp_linux_buffer_release_v1 *buffer_release,
265 int32_t fence)
266{
267 assert(!"Fenced release not supported yet");
268}
269
270static void
271buffer_release_immediate_handler(void *data,
272 struct zwp_linux_buffer_release_v1 *buffer_release)
273{
274 int *released = data;
275
276 *released += 1;
277}
278
279struct zwp_linux_buffer_release_v1_listener buffer_release_listener = {
280 buffer_release_fenced_handler,
281 buffer_release_immediate_handler
282};
283
Alexandros Frantzisc715c752018-11-12 18:33:54 +0200284/* The following release event tests depend on the behavior of the used
285 * backend, in this case the pixman backend. This doesn't limit their
286 * usefulness, though, since it allows them to check if, given a typical
287 * backend implementation, weston core supports the per commit nature of the
288 * release events.
289 */
290
291TEST(get_release_events_are_emitted_for_different_buffers)
Alexandros Frantzis67629672018-10-19 12:14:11 +0300292{
293 struct client *client = create_test_client();
294 struct zwp_linux_explicit_synchronization_v1 *sync =
295 get_linux_explicit_synchronization(client);
296 struct zwp_linux_surface_synchronization_v1 *surface_sync =
297 zwp_linux_explicit_synchronization_v1_get_synchronization(
298 sync, client->surface->wl_surface);
299 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
300 struct buffer *buf2 = create_shm_buffer_a8r8g8b8(client, 100, 100);
301 struct wl_surface *surface = client->surface->wl_surface;
302 struct zwp_linux_buffer_release_v1 *buffer_release1;
303 struct zwp_linux_buffer_release_v1 *buffer_release2;
304 int buf_released1 = 0;
305 int buf_released2 = 0;
306 int frame;
307
308 buffer_release1 =
309 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
310 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
311 &buffer_release_listener,
312 &buf_released1);
313 wl_surface_attach(surface, buf1->proxy, 0, 0);
314 frame_callback_set(surface, &frame);
315 wl_surface_commit(surface);
316 frame_callback_wait(client, &frame);
Alexandros Frantzisc715c752018-11-12 18:33:54 +0200317 /* No release event should have been emitted yet (we are using the
318 * pixman renderer, which holds buffers until they are replaced). */
319 assert(buf_released1 == 0);
Alexandros Frantzis67629672018-10-19 12:14:11 +0300320
321 buffer_release2 =
322 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
323 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
324 &buffer_release_listener,
325 &buf_released2);
326 wl_surface_attach(surface, buf2->proxy, 0, 0);
327 frame_callback_set(surface, &frame);
328 wl_surface_commit(surface);
329 frame_callback_wait(client, &frame);
Alexandros Frantzisc715c752018-11-12 18:33:54 +0200330 /* Check that exactly one buffer_release event was emitted for the
331 * previous commit (buf1). */
Alexandros Frantzis67629672018-10-19 12:14:11 +0300332 assert(buf_released1 == 1);
Alexandros Frantzisc715c752018-11-12 18:33:54 +0200333 assert(buf_released2 == 0);
334
335 wl_surface_attach(surface, buf1->proxy, 0, 0);
336 frame_callback_set(surface, &frame);
337 wl_surface_commit(surface);
338 frame_callback_wait(client, &frame);
339 /* Check that exactly one buffer_release event was emitted for the
340 * previous commit (buf2). */
341 assert(buf_released1 == 1);
Alexandros Frantzis67629672018-10-19 12:14:11 +0300342 assert(buf_released2 == 1);
343
344 buffer_destroy(buf2);
345 buffer_destroy(buf1);
346 zwp_linux_buffer_release_v1_destroy(buffer_release2);
347 zwp_linux_buffer_release_v1_destroy(buffer_release1);
348 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
349 zwp_linux_explicit_synchronization_v1_destroy(sync);
350}
Alexandros Frantzisc715c752018-11-12 18:33:54 +0200351
352TEST(get_release_events_are_emitted_for_same_buffer_on_surface)
353{
354 struct client *client = create_test_client();
355 struct zwp_linux_explicit_synchronization_v1 *sync =
356 get_linux_explicit_synchronization(client);
357 struct zwp_linux_surface_synchronization_v1 *surface_sync =
358 zwp_linux_explicit_synchronization_v1_get_synchronization(
359 sync, client->surface->wl_surface);
360 struct buffer *buf = create_shm_buffer_a8r8g8b8(client, 100, 100);
361 struct wl_surface *surface = client->surface->wl_surface;
362 struct zwp_linux_buffer_release_v1 *buffer_release1;
363 struct zwp_linux_buffer_release_v1 *buffer_release2;
364 int buf_released1 = 0;
365 int buf_released2 = 0;
366 int frame;
367
368 buffer_release1 =
369 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
370 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
371 &buffer_release_listener,
372 &buf_released1);
373 wl_surface_attach(surface, buf->proxy, 0, 0);
374 frame_callback_set(surface, &frame);
375 wl_surface_commit(surface);
376 frame_callback_wait(client, &frame);
377 /* No release event should have been emitted yet (we are using the
378 * pixman renderer, which holds buffers until they are replaced). */
379 assert(buf_released1 == 0);
380
381 buffer_release2 =
382 zwp_linux_surface_synchronization_v1_get_release(surface_sync);
383 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
384 &buffer_release_listener,
385 &buf_released2);
386 wl_surface_attach(surface, buf->proxy, 0, 0);
387 frame_callback_set(surface, &frame);
388 wl_surface_commit(surface);
389 frame_callback_wait(client, &frame);
390 /* Check that exactly one buffer_release event was emitted for the
391 * previous commit (buf). */
392 assert(buf_released1 == 1);
393 assert(buf_released2 == 0);
394
395 wl_surface_attach(surface, buf->proxy, 0, 0);
396 frame_callback_set(surface, &frame);
397 wl_surface_commit(surface);
398 frame_callback_wait(client, &frame);
399 /* Check that exactly one buffer_release event was emitted for the
400 * previous commit (buf again). */
401 assert(buf_released1 == 1);
402 assert(buf_released2 == 1);
403
404 buffer_destroy(buf);
405 zwp_linux_buffer_release_v1_destroy(buffer_release2);
406 zwp_linux_buffer_release_v1_destroy(buffer_release1);
407 zwp_linux_surface_synchronization_v1_destroy(surface_sync);
408 zwp_linux_explicit_synchronization_v1_destroy(sync);
409}
410
411TEST(get_release_events_are_emitted_for_same_buffer_on_different_surfaces)
412{
413 struct client *client = create_test_client();
414 struct surface *other_surface = create_test_surface(client);
415 struct wl_surface *surface1 = client->surface->wl_surface;
416 struct wl_surface *surface2 = other_surface->wl_surface;
417 struct zwp_linux_explicit_synchronization_v1 *sync =
418 get_linux_explicit_synchronization(client);
419 struct zwp_linux_surface_synchronization_v1 *surface_sync1 =
420 zwp_linux_explicit_synchronization_v1_get_synchronization(
421 sync, surface1);
422 struct zwp_linux_surface_synchronization_v1 *surface_sync2 =
423 zwp_linux_explicit_synchronization_v1_get_synchronization(
424 sync, surface2);
425 struct buffer *buf1 = create_shm_buffer_a8r8g8b8(client, 100, 100);
426 struct buffer *buf2 = create_shm_buffer_a8r8g8b8(client, 100, 100);
427 struct zwp_linux_buffer_release_v1 *buffer_release1;
428 struct zwp_linux_buffer_release_v1 *buffer_release2;
429 int buf_released1 = 0;
430 int buf_released2 = 0;
431 int frame;
432
433 weston_test_move_surface(client->test->weston_test, surface2, 0, 0);
434
435 /* Attach buf1 to both surface1 and surface2. */
436 buffer_release1 =
437 zwp_linux_surface_synchronization_v1_get_release(surface_sync1);
438 zwp_linux_buffer_release_v1_add_listener(buffer_release1,
439 &buffer_release_listener,
440 &buf_released1);
441 wl_surface_attach(surface1, buf1->proxy, 0, 0);
442 frame_callback_set(surface1, &frame);
443 wl_surface_commit(surface1);
444 frame_callback_wait(client, &frame);
445
446 buffer_release2 =
447 zwp_linux_surface_synchronization_v1_get_release(surface_sync2);
448 zwp_linux_buffer_release_v1_add_listener(buffer_release2,
449 &buffer_release_listener,
450 &buf_released2);
451 wl_surface_attach(surface2, buf1->proxy, 0, 0);
452 frame_callback_set(surface2, &frame);
453 wl_surface_commit(surface2);
454 frame_callback_wait(client, &frame);
455
456 assert(buf_released1 == 0);
457 assert(buf_released2 == 0);
458
459 /* Attach buf2 to surface1, and check that a buffer_release event for
460 * the previous commit (buf1) for that surface is emitted. */
461 wl_surface_attach(surface1, buf2->proxy, 0, 0);
462 frame_callback_set(surface1, &frame);
463 wl_surface_commit(surface1);
464 frame_callback_wait(client, &frame);
465
466 assert(buf_released1 == 1);
467 assert(buf_released2 == 0);
468
469 /* Attach buf2 to surface2, and check that a buffer_release event for
470 * the previous commit (buf1) for that surface is emitted. */
471 wl_surface_attach(surface2, buf2->proxy, 0, 0);
472 frame_callback_set(surface2, &frame);
473 wl_surface_commit(surface2);
474 frame_callback_wait(client, &frame);
475
476 assert(buf_released1 == 1);
477 assert(buf_released2 == 1);
478
479 buffer_destroy(buf2);
480 buffer_destroy(buf1);
481 zwp_linux_buffer_release_v1_destroy(buffer_release2);
482 zwp_linux_buffer_release_v1_destroy(buffer_release1);
483 zwp_linux_surface_synchronization_v1_destroy(surface_sync2);
484 zwp_linux_surface_synchronization_v1_destroy(surface_sync1);
485 zwp_linux_explicit_synchronization_v1_destroy(sync);
486}