• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014, 2016 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 <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <time.h>
33 
34 #include "shared/helpers.h"
35 #include "shared/xalloc.h"
36 #include "weston-test-client-helper.h"
37 #include "weston-test-fixture-compositor.h"
38 
39 static enum test_result_code
fixture_setup(struct weston_test_harness * harness)40 fixture_setup(struct weston_test_harness *harness)
41 {
42 	struct compositor_setup setup;
43 
44 	compositor_setup_defaults(&setup);
45 
46 	return weston_test_harness_execute_as_client(harness, &setup);
47 }
48 DECLARE_FIXTURE_SETUP(fixture_setup);
49 
50 static void
set_source(struct wp_viewport * vp,int x,int y,int w,int h)51 set_source(struct wp_viewport *vp, int x, int y, int w, int h)
52 {
53 	wp_viewport_set_source(vp, wl_fixed_from_int(x), wl_fixed_from_int(y),
54 				   wl_fixed_from_int(w), wl_fixed_from_int(h));
55 }
56 
TEST(test_viewporter_double_create)57 TEST(test_viewporter_double_create)
58 {
59 	struct wp_viewporter *viewporter;
60 	struct client *client;
61 
62 	client = create_client_and_test_surface(100, 50, 123, 77);
63 
64 	viewporter = bind_to_singleton_global(client,
65 					      &wp_viewporter_interface, 1);
66 	wp_viewporter_get_viewport(viewporter, client->surface->wl_surface);
67 	wp_viewporter_get_viewport(viewporter, client->surface->wl_surface);
68 
69 	expect_protocol_error(client, &wp_viewporter_interface,
70 			      WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS);
71 }
72 
73 struct bad_source_rect_args {
74 	int x, y, w, h;
75 };
76 
77 static const struct bad_source_rect_args bad_source_rect_args[] = {
78 	{ -5,  0,  20,  10 },
79 	{  0, -5,  20,  10 },
80 	{  5,  6,   0,  10 },
81 	{  5,  6,  20,   0 },
82 	{  5,  6, -20,  10 },
83 	{  5,  6,  20, -10 },
84 	{ -1, -1,  20,  10 },
85 	{  5,  6,  -1,  -1 },
86 };
87 
TEST_P(test_viewporter_bad_source_rect,bad_source_rect_args)88 TEST_P(test_viewporter_bad_source_rect, bad_source_rect_args)
89 {
90 	const struct bad_source_rect_args *args = data;
91 	struct client *client;
92 	struct wp_viewport *vp;
93 
94 	client = create_client_and_test_surface(100, 50, 123, 77);
95 
96 	vp = client_create_viewport(client);
97 
98 	testlog("wp_viewport.set_source x=%d, y=%d, w=%d, h=%d\n",
99 		args->x, args->y, args->w, args->h);
100 	set_source(vp, args->x, args->y, args->w, args->h);
101 
102 	expect_protocol_error(client, &wp_viewport_interface,
103 			      WP_VIEWPORT_ERROR_BAD_VALUE);
104 }
105 
TEST(test_viewporter_unset_source_rect)106 TEST(test_viewporter_unset_source_rect)
107 {
108 	struct client *client;
109 	struct wp_viewport *vp;
110 
111 	client = create_client_and_test_surface(100, 50, 123, 77);
112 
113 	vp = client_create_viewport(client);
114 	set_source(vp, -1, -1, -1, -1);
115 	wl_surface_commit(client->surface->wl_surface);
116 
117 	client_roundtrip(client);
118 }
119 
120 struct bad_destination_args {
121 	int w, h;
122 };
123 
124 static const struct bad_destination_args bad_destination_args[] = {
125 	{   0,  10 },
126 	{  20,   0 },
127 	{ -20,  10 },
128 	{  -1,  10 },
129 	{  20, -10 },
130 	{  20,  -1 },
131 };
132 
TEST_P(test_viewporter_bad_destination_size,bad_destination_args)133 TEST_P(test_viewporter_bad_destination_size, bad_destination_args)
134 {
135 	const struct bad_destination_args *args = data;
136 	struct client *client;
137 	struct wp_viewport *vp;
138 
139 	client = create_client_and_test_surface(100, 50, 123, 77);
140 
141 	vp = client_create_viewport(client);
142 
143 	testlog("wp_viewport.set_destination w=%d, h=%d\n", args->w, args->h);
144 	wp_viewport_set_destination(vp, args->w, args->h);
145 
146 	expect_protocol_error(client, &wp_viewport_interface,
147 			      WP_VIEWPORT_ERROR_BAD_VALUE);
148 }
149 
TEST(test_viewporter_unset_destination_size)150 TEST(test_viewporter_unset_destination_size)
151 {
152 	struct client *client;
153 	struct wp_viewport *vp;
154 
155 	client = create_client_and_test_surface(100, 50, 123, 77);
156 
157 	vp = client_create_viewport(client);
158 	wp_viewport_set_destination(vp, -1, -1);
159 	wl_surface_commit(client->surface->wl_surface);
160 
161 	client_roundtrip(client);
162 }
163 
164 struct nonint_destination_args {
165 	wl_fixed_t w, h;
166 };
167 
168 static const struct nonint_destination_args nonint_destination_args[] = {
169 #define F(i,f) ((i) * 256 + (f))
170 	{ F(20, 0),   F(10, 1) },
171 	{ F(20, 0),   F(10, -1) },
172 	{ F(20, 1),   F(10, 0) },
173 	{ F(20, -1),  F(10, 0) },
174 	{ F(20, 128), F(10, 128) },
175 #undef F
176 };
177 
TEST_P(test_viewporter_non_integer_destination_size,nonint_destination_args)178 TEST_P(test_viewporter_non_integer_destination_size, nonint_destination_args)
179 {
180 	const struct nonint_destination_args *args = data;
181 	struct client *client;
182 	struct wp_viewport *vp;
183 
184 	client = create_client_and_test_surface(100, 50, 123, 77);
185 
186 	vp = client_create_viewport(client);
187 
188 	testlog("non-integer size w=%f, h=%f\n",
189 		wl_fixed_to_double(args->w), wl_fixed_to_double(args->h));
190 	wp_viewport_set_source(vp, 5, 6, args->w, args->h);
191 	wp_viewport_set_destination(vp, -1, -1);
192 	wl_surface_commit(client->surface->wl_surface);
193 
194 	expect_protocol_error(client, &wp_viewport_interface,
195 			      WP_VIEWPORT_ERROR_BAD_SIZE);
196 }
197 
198 struct source_buffer_args {
199 	wl_fixed_t x, y;
200 	wl_fixed_t w, h;
201 	int buffer_scale;
202 	enum wl_output_transform buffer_transform;
203 };
204 
205 static int
get_surface_width(struct surface * surface,int buffer_scale,enum wl_output_transform buffer_transform)206 get_surface_width(struct surface *surface,
207 		  int buffer_scale,
208 		  enum wl_output_transform buffer_transform)
209 {
210 	switch (buffer_transform) {
211 	case WL_OUTPUT_TRANSFORM_NORMAL:
212 	case WL_OUTPUT_TRANSFORM_180:
213 	case WL_OUTPUT_TRANSFORM_FLIPPED:
214 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
215 		return surface->width / buffer_scale;
216 	case WL_OUTPUT_TRANSFORM_90:
217 	case WL_OUTPUT_TRANSFORM_270:
218 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
219 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
220 		return surface->height / buffer_scale;
221 	}
222 
223 	return -1;
224 }
225 
226 static int
get_surface_height(struct surface * surface,int buffer_scale,enum wl_output_transform buffer_transform)227 get_surface_height(struct surface *surface,
228 		   int buffer_scale,
229 		   enum wl_output_transform buffer_transform)
230 {
231 	switch (buffer_transform) {
232 	case WL_OUTPUT_TRANSFORM_NORMAL:
233 	case WL_OUTPUT_TRANSFORM_180:
234 	case WL_OUTPUT_TRANSFORM_FLIPPED:
235 	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
236 		return surface->height / buffer_scale;
237 	case WL_OUTPUT_TRANSFORM_90:
238 	case WL_OUTPUT_TRANSFORM_270:
239 	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
240 	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
241 		return surface->width / buffer_scale;
242 	}
243 
244 	return -1;
245 }
246 
247 static void
setup_source_vs_buffer(struct client * client,const struct source_buffer_args * args)248 setup_source_vs_buffer(struct client *client,
249 		       const struct source_buffer_args *args)
250 {
251 	struct wl_surface *surf;
252 	struct wp_viewport *vp;
253 
254 	surf = client->surface->wl_surface;
255 	vp = client_create_viewport(client);
256 
257 	testlog("surface %dx%d\n",
258 		get_surface_width(client->surface,
259 				  args->buffer_scale, args->buffer_transform),
260 		get_surface_height(client->surface,
261 				   args->buffer_scale, args->buffer_transform));
262 	testlog("source x=%f, y=%f, w=%f, h=%f; "
263 		"buffer scale=%d, transform=%d\n",
264 		wl_fixed_to_double(args->x), wl_fixed_to_double(args->y),
265 		wl_fixed_to_double(args->w), wl_fixed_to_double(args->h),
266 		args->buffer_scale, args->buffer_transform);
267 
268 	wl_surface_set_buffer_scale(surf, args->buffer_scale);
269 	wl_surface_set_buffer_transform(surf, args->buffer_transform);
270 	wl_surface_attach(surf, client->surface->buffer->proxy, 0, 0);
271 	wp_viewport_set_source(vp, args->x, args->y, args->w, args->h);
272 	wp_viewport_set_destination(vp, 99, 99);
273 	wl_surface_commit(surf);
274 }
275 
276 /* buffer dimensions */
277 #define WIN_W 124
278 #define WIN_H 78
279 
280 /* source rect base size */
281 #define SRC_W 20
282 #define SRC_H 10
283 
284 /* margin */
285 #define MRG 10
286 /* epsilon of wl_fixed_t */
287 #define EPS 1
288 
TEST(test_viewporter_source_buffer_params)289 TEST(test_viewporter_source_buffer_params)
290 {
291 	const int max_scale = 2;
292 
293 	/* buffer_scale requirement */
294 	assert(WIN_W % max_scale == 0);
295 	assert(WIN_H % max_scale == 0);
296 
297 	/* source rect must fit inside regardless of scale and transform */
298 	assert(SRC_W < WIN_W / max_scale);
299 	assert(SRC_H < WIN_H / max_scale);
300 	assert(SRC_W < WIN_H / max_scale);
301 	assert(SRC_H < WIN_W / max_scale);
302 
303 	/* If buffer scale was ignored, source rect should be inside instead */
304 	assert(WIN_W / max_scale + SRC_W + MRG < WIN_W);
305 	assert(WIN_H / max_scale + SRC_H + MRG < WIN_H);
306 	assert(WIN_W / max_scale + SRC_H + MRG < WIN_W);
307 	assert(WIN_H / max_scale + SRC_W + MRG < WIN_H);
308 }
309 
310 static const struct source_buffer_args bad_source_buffer_args[] = {
311 #define F(i) ((i) * 256)
312 
313 /* Flush right-top, but epsilon too far right. */
314 	{ F(WIN_W - SRC_W) + EPS, F(0), F(SRC_W),       F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
315 	{ F(WIN_W - SRC_W),       F(0), F(SRC_W) + EPS, F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
316 /* Flush left-bottom, but epsilon too far down. */
317 	{ F(0), F(WIN_H - SRC_H) + EPS, F(SRC_W), F(SRC_H),       1, WL_OUTPUT_TRANSFORM_NORMAL },
318 	{ F(0), F(WIN_H - SRC_H),       F(SRC_W), F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_NORMAL },
319 /* Completely outside on the right. */
320 	{ F(WIN_W + MRG), F(0), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
321 /* Competely outside on the bottom. */
322 	{ F(0), F(WIN_H + MRG), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
323 
324 /*
325  * buffer_scale=2, so the surface size will be halved.
326  * If buffer_scale was not taken into account, these would all be inside.
327  * These are the same as above, but adapted to buffer_scale=2.
328  */
329 	{ F(WIN_W / 2 - SRC_W) + EPS, F(0),                       F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_NORMAL },
330 	{ F(WIN_W / 2 - SRC_W),       F(0),                       F(SRC_W) + EPS, F(SRC_H),       2, WL_OUTPUT_TRANSFORM_NORMAL },
331 
332 	{ F(0),                       F(WIN_H / 2 - SRC_H) + EPS, F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_NORMAL },
333 	{ F(0),                       F(WIN_H / 2 - SRC_H),       F(SRC_W),       F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_NORMAL },
334 
335 	{ F(WIN_W / 2 + MRG),         F(0),                       F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_NORMAL },
336 
337 	{ F(0),                       F(WIN_H / 2 + MRG),         F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_NORMAL },
338 
339 /* Exceeding bottom-right corner by epsilon: */
340 /* non-dimension-swapping transforms */
341 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H),       F(SRC_W),       F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
342 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H) + EPS, F(SRC_W),       F(SRC_H),       1, WL_OUTPUT_TRANSFORM_FLIPPED },
343 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H),       F(SRC_W) + EPS, F(SRC_H),       1, WL_OUTPUT_TRANSFORM_180 },
344 
345 /* dimension-swapping transforms */
346 	{ F(WIN_H - SRC_W) + EPS, F(WIN_W - SRC_H),       F(SRC_W),       F(SRC_H),       1, WL_OUTPUT_TRANSFORM_90 },
347 	{ F(WIN_H - SRC_W),       F(WIN_W - SRC_H) + EPS, F(SRC_W),       F(SRC_H),       1, WL_OUTPUT_TRANSFORM_270 },
348 	{ F(WIN_H - SRC_W),       F(WIN_W - SRC_H),       F(SRC_W) + EPS, F(SRC_H),       1, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
349 	{ F(WIN_H - SRC_W),       F(WIN_W - SRC_H),       F(SRC_W),       F(SRC_H) + EPS, 1, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
350 
351 /* non-dimension-swapping transforms, buffer_scale=2 */
352 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H) + EPS, F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
353 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H),       F(SRC_W) + EPS, F(SRC_H),       2, WL_OUTPUT_TRANSFORM_FLIPPED },
354 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H),       F(SRC_W),       F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_180 },
355 
356 /* dimension-swapping transforms, buffer_scale=2 */
357 	{ F(WIN_H / 2 - SRC_W) + EPS, F(WIN_W / 2 - SRC_H),       F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_90 },
358 	{ F(WIN_H / 2 - SRC_W),       F(WIN_W / 2 - SRC_H) + EPS, F(SRC_W),       F(SRC_H),       2, WL_OUTPUT_TRANSFORM_270 },
359 	{ F(WIN_H / 2 - SRC_W),       F(WIN_W / 2 - SRC_H),       F(SRC_W) + EPS, F(SRC_H),       2, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
360 	{ F(WIN_H / 2 - SRC_W),       F(WIN_W / 2 - SRC_H),       F(SRC_W),       F(SRC_H) + EPS, 2, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
361 
362 #undef F
363 };
364 
TEST_P(test_viewporter_source_outside_buffer,bad_source_buffer_args)365 TEST_P(test_viewporter_source_outside_buffer, bad_source_buffer_args)
366 {
367 	const struct source_buffer_args *args = data;
368 	struct client *client;
369 
370 	client = create_client_and_test_surface(100, 50, WIN_W, WIN_H);
371 	setup_source_vs_buffer(client, args);
372 
373 	expect_protocol_error(client, &wp_viewport_interface,
374 			      WP_VIEWPORT_ERROR_OUT_OF_BUFFER);
375 }
376 
377 static const struct source_buffer_args good_source_buffer_args[] = {
378 #define F(i) ((i) * 256)
379 
380 /* top-left, top-right, bottom-left, and bottom-right corner */
381 	{ F(0),             F(0),             F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
382 	{ F(WIN_W - SRC_W), F(0),             F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
383 	{ F(0),             F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
384 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_NORMAL },
385 
386 /* buffer_scale=2, so the surface size will be halved */
387 	{ F(0),                 F(0),                 F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
388 	{ F(WIN_W / 2 - SRC_W), F(0),                 F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
389 	{ F(0),                 F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
390 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_NORMAL },
391 
392 /* with half pixel offset */
393 	{ F(WIN_W / 2 - SRC_W) + 128, F(WIN_H / 2 - SRC_H) + 128, F(SRC_W) - 128, F(SRC_H) - 128, 2, WL_OUTPUT_TRANSFORM_NORMAL },
394 
395 /* Flushed to bottom-right corner: */
396 /* non-dimension-swapping transforms */
397 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
398 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED },
399 	{ F(WIN_W - SRC_W), F(WIN_H - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_180 },
400 
401 /* dimension-swapping transforms */
402 	{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_90 },
403 	{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_270 },
404 	{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
405 	{ F(WIN_H - SRC_W), F(WIN_W - SRC_H), F(SRC_W), F(SRC_H), 1, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
406 
407 /* non-dimension-swapping transforms, buffer_scale=2 */
408 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_180 },
409 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED },
410 	{ F(WIN_W / 2 - SRC_W), F(WIN_H / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_180 },
411 
412 /* dimension-swapping transforms, buffer_scale=2 */
413 	{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_90 },
414 	{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_270 },
415 	{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_90 },
416 	{ F(WIN_H / 2 - SRC_W), F(WIN_W / 2 - SRC_H), F(SRC_W), F(SRC_H), 2, WL_OUTPUT_TRANSFORM_FLIPPED_270 },
417 
418 #undef F
419 };
420 
TEST_P(test_viewporter_source_inside_buffer,good_source_buffer_args)421 TEST_P(test_viewporter_source_inside_buffer, good_source_buffer_args)
422 {
423 	const struct source_buffer_args *args = data;
424 	struct client *client;
425 
426 	client = create_client_and_test_surface(100, 50, WIN_W, WIN_H);
427 	setup_source_vs_buffer(client, args);
428 	client_roundtrip(client);
429 }
430 
431 #undef WIN_W
432 #undef WIN_H
433 #undef SRC_W
434 #undef SRC_H
435 #undef MRG
436 #undef EPS
437 
TEST(test_viewporter_outside_null_buffer)438 TEST(test_viewporter_outside_null_buffer)
439 {
440 	struct client *client;
441 	struct wp_viewport *vp;
442 	struct wl_surface *surf;
443 
444 	client = create_client_and_test_surface(100, 50, 123, 77);
445 	surf = client->surface->wl_surface;
446 
447 	/* If buffer is NULL, does not matter what the source rect is. */
448 	vp = client_create_viewport(client);
449 	wl_surface_attach(surf, NULL, 0, 0);
450 	set_source(vp, 1000, 1000, 20, 10);
451 	wp_viewport_set_destination(vp, 99, 99);
452 	wl_surface_commit(surf);
453 	client_roundtrip(client);
454 
455 	/* Try again, with all old values. */
456 	wl_surface_commit(surf);
457 	client_roundtrip(client);
458 
459 	/* Try once more with old NULL buffer. */
460 	set_source(vp, 1200, 1200, 20, 10);
461 	wl_surface_commit(surf);
462 	client_roundtrip(client);
463 
464 	/* When buffer comes back, source rect matters again. */
465 	wl_surface_attach(surf, client->surface->buffer->proxy, 0, 0);
466 	wl_surface_commit(surf);
467 	expect_protocol_error(client, &wp_viewport_interface,
468 			      WP_VIEWPORT_ERROR_OUT_OF_BUFFER);
469 }
470 
TEST(test_viewporter_no_surface_set_source)471 TEST(test_viewporter_no_surface_set_source)
472 {
473 	struct client *client;
474 	struct wp_viewport *vp;
475 
476 	client = create_client_and_test_surface(100, 50, 123, 77);
477 	vp = client_create_viewport(client);
478 	wl_surface_destroy(client->surface->wl_surface);
479 	client->surface->wl_surface = NULL;
480 
481 	/* But the wl_surface does not exist anymore. */
482 	set_source(vp, 1000, 1000, 20, 10);
483 
484 	expect_protocol_error(client, &wp_viewport_interface,
485 			      WP_VIEWPORT_ERROR_NO_SURFACE);
486 }
487 
TEST(test_viewporter_no_surface_set_destination)488 TEST(test_viewporter_no_surface_set_destination)
489 {
490 	struct client *client;
491 	struct wp_viewport *vp;
492 
493 	client = create_client_and_test_surface(100, 50, 123, 77);
494 	vp = client_create_viewport(client);
495 	wl_surface_destroy(client->surface->wl_surface);
496 	client->surface->wl_surface = NULL;
497 
498 	/* But the wl_surface does not exist anymore. */
499 	wp_viewport_set_destination(vp, 99, 99);
500 
501 	expect_protocol_error(client, &wp_viewport_interface,
502 			      WP_VIEWPORT_ERROR_NO_SURFACE);
503 }
504 
TEST(test_viewporter_no_surface_destroy)505 TEST(test_viewporter_no_surface_destroy)
506 {
507 	struct client *client;
508 	struct wp_viewport *vp;
509 
510 	client = create_client_and_test_surface(100, 50, 123, 77);
511 	vp = client_create_viewport(client);
512 	wl_surface_destroy(client->surface->wl_surface);
513 	client->surface->wl_surface = NULL;
514 
515 	/* But the wl_surface does not exist anymore. */
516 	wp_viewport_destroy(vp);
517 
518 	client_roundtrip(client);
519 }
520