• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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