• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2013 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Daniel Vetter <daniel.vetter@ffwll.ch>
25  *
26  */
27 
28 #include "igt.h"
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <fcntl.h>
34 #include <inttypes.h>
35 #include <errno.h>
36 #include <sys/stat.h>
37 #include <sys/ioctl.h>
38 #include "drm.h"
39 #include "drm_fourcc.h"
40 
41 #include "igt_rand.h"
42 #include "igt_device.h"
43 
44 uint32_t gem_bo;
45 uint32_t gem_bo_small;
46 
legacy_addfb(int fd,struct drm_mode_fb_cmd * arg)47 static int legacy_addfb(int fd, struct drm_mode_fb_cmd *arg)
48 {
49 	int err;
50 
51 	err = 0;
52 	if (igt_ioctl(fd, DRM_IOCTL_MODE_ADDFB, arg))
53 		err = -errno;
54 
55 	errno = 0;
56 	return err;
57 }
58 
rmfb(int fd,uint32_t id)59 static int rmfb(int fd, uint32_t id)
60 {
61 	int err;
62 
63 	err = 0;
64 	if (igt_ioctl(fd, DRM_IOCTL_MODE_RMFB, &id))
65 		err = -errno;
66 
67 	errno = 0;
68 	return err;
69 }
70 
invalid_tests(int fd)71 static void invalid_tests(int fd)
72 {
73 	struct local_drm_mode_fb_cmd2 f = {};
74 
75 	f.width = 512;
76 	f.height = 512;
77 	f.pixel_format = DRM_FORMAT_XRGB8888;
78 	f.pitches[0] = 512*4;
79 
80 	igt_fixture {
81 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
82 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
83 		igt_assert(gem_bo);
84 		gem_bo_small = igt_create_bo_with_dimensions(fd, 1024, 1023,
85 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
86 		igt_assert(gem_bo_small);
87 
88 		f.handles[0] = gem_bo;
89 
90 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
91 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
92 		f.fb_id = 0;
93 	}
94 
95 	f.flags = LOCAL_DRM_MODE_FB_MODIFIERS;
96 
97 	igt_subtest("unused-handle") {
98 		igt_require_fb_modifiers(fd);
99 
100 		f.handles[1] = gem_bo_small;
101 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
102 			   errno == EINVAL);
103 		f.handles[1] = 0;
104 	}
105 
106 	igt_subtest("unused-pitches") {
107 		igt_require_fb_modifiers(fd);
108 
109 		f.pitches[1] = 512;
110 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
111 			   errno == EINVAL);
112 		f.pitches[1] = 0;
113 	}
114 
115 	igt_subtest("unused-offsets") {
116 		igt_require_fb_modifiers(fd);
117 
118 		f.offsets[1] = 512;
119 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
120 			   errno == EINVAL);
121 		f.offsets[1] = 0;
122 	}
123 
124 	igt_subtest("unused-modifier") {
125 		igt_require_fb_modifiers(fd);
126 
127 		f.modifier[1] =  LOCAL_I915_FORMAT_MOD_X_TILED;
128 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
129 			   errno == EINVAL);
130 		f.modifier[1] = 0;
131 	}
132 
133 	igt_subtest("clobberred-modifier") {
134 		igt_require_intel(fd);
135 		f.flags = 0;
136 		f.modifier[0] = 0;
137 		gem_set_tiling(fd, gem_bo, I915_TILING_X, 512*4);
138 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == 0);
139 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
140 		f.fb_id = 0;
141 		igt_assert(f.modifier[0] == 0);
142 	}
143 
144 	igt_subtest("legacy-format") {
145 		struct {
146 			/* drm_mode_legacy_fb_format() */
147 			int bpp, depth;
148 			int expect;
149 		} known_formats[] = {
150 			{  8,  8 }, /* c8 (palette) */
151 			{ 16, 15 }, /* x1r5g5b5 */
152 			{ 16, 16 }, /* r5g6b5 or a1r5g5b5! */
153 			{ 24, 24 }, /* r8g8b8 */
154 			{ 32, 24 }, /* x8r8g8b8 */
155 			{ 32, 30 }, /* x2r10g10b10 */
156 			{ 32, 32 }, /* a8r8g8b8 or a2r10g10b10! */
157 		};
158 		struct drm_mode_fb_cmd arg = {
159 			.handle = f.handles[0],
160 			.width  = f.width,
161 			.height = f.height,
162 			.pitch  = f.pitches[0],
163 		};
164 		uint32_t prng = 0x12345678;
165 		unsigned long timeout = 1;
166 		unsigned long count = 0;
167 
168 		/*
169 		 * First confirm the kernel recognises our known_formats;
170 		 * some may be invalid for different devices.
171 		 */
172 		for (int i = 0; i < ARRAY_SIZE(known_formats); i++) {
173 			arg.bpp = known_formats[i].bpp;
174 			arg.depth = known_formats[i].depth;
175 			known_formats[i].expect = legacy_addfb(fd, &arg);
176 			igt_debug("{bpp:%d, depth:%d} -> expect:%d\n",
177 				  arg.bpp, arg.depth, known_formats[i].expect);
178 			if (arg.fb_id) {
179 				igt_assert_eq(rmfb(fd, arg.fb_id), 0);
180 				arg.fb_id = 0;
181 			}
182 		}
183 
184 		igt_until_timeout(timeout) {
185 			int expect = -EINVAL;
186 			int err;
187 
188 			arg.bpp = hars_petruska_f54_1_random(&prng);
189 			arg.depth = hars_petruska_f54_1_random(&prng);
190 			for (int start = 0, end = ARRAY_SIZE(known_formats);
191 			     start < end; ) {
192 				int mid = start + (end - start) / 2;
193 				typeof(*known_formats) *tbl = &known_formats[mid];
194 
195 				if (arg.bpp < tbl->bpp) {
196 					end = mid;
197 				} else if (arg.bpp > tbl->bpp) {
198 					start = mid + 1;
199 				} else {
200 					if (arg.depth < tbl->depth) {
201 						end = mid;
202 					} else if (arg.depth > tbl->depth) {
203 						start = mid + 1;
204 					} else {
205 						expect = tbl->expect;
206 						break;
207 					}
208 				}
209 			}
210 
211 			err = legacy_addfb(fd, &arg);
212 			igt_assert_f(err == expect,
213 				     "Expected %d with {bpp:%d, depth:%d}, got %d instead\n",
214 				     expect, arg.bpp, arg.depth, err);
215 			if (arg.fb_id) {
216 				igt_assert_eq(rmfb(fd, arg.fb_id), 0);
217 				arg.fb_id = 0;
218 			}
219 
220 			count++;
221 		}
222 
223 		/* After all the abuse, confirm the known_formats */
224 		for (int i = 0; i < ARRAY_SIZE(known_formats); i++) {
225 			int err;
226 
227 			arg.bpp = known_formats[i].bpp;
228 			arg.depth = known_formats[i].depth;
229 
230 			err = legacy_addfb(fd, &arg);
231 			igt_assert_f(err == known_formats[i].expect,
232 				     "Expected %d with {bpp:%d, depth:%d}, got %d instead\n",
233 				     known_formats[i].expect,
234 				     arg.bpp, arg.depth,
235 				     err);
236 			if (arg.fb_id) {
237 				igt_assert_eq(rmfb(fd, arg.fb_id), 0);
238 				arg.fb_id = 0;
239 			}
240 		}
241 
242 		igt_info("Successfully fuzzed %lu {bpp, depth} variations\n",
243 			 count);
244 	}
245 
246 	igt_fixture {
247 		gem_close(fd, gem_bo);
248 		gem_close(fd, gem_bo_small);
249 	}
250 }
251 
pitch_tests(int fd)252 static void pitch_tests(int fd)
253 {
254 	struct drm_mode_fb_cmd2 f = {};
255 	int bad_pitches[] = { 0, 32, 63, 128, 256, 256*4, 999, 64*1024 };
256 	int i;
257 
258 	f.width = 512;
259 	f.height = 512;
260 	f.pixel_format = DRM_FORMAT_XRGB8888;
261 	f.pitches[0] = 1024*4;
262 
263 	igt_fixture {
264 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
265 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
266 		igt_assert(gem_bo);
267 	}
268 
269 	igt_subtest("no-handle") {
270 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
271 			   errno == EINVAL);
272 	}
273 
274 	f.handles[0] = gem_bo;
275 	igt_subtest("basic") {
276 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
277 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
278 		f.fb_id = 0;
279 	}
280 
281 	for (i = 0; i < ARRAY_SIZE(bad_pitches); i++) {
282 		igt_subtest_f("bad-pitch-%i", bad_pitches[i]) {
283 			f.pitches[0] = bad_pitches[i];
284 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
285 				   errno == EINVAL);
286 		}
287 	}
288 
289 	igt_fixture
290 		gem_close(fd, gem_bo);
291 }
292 
tiling_tests(int fd)293 static void tiling_tests(int fd)
294 {
295 	struct drm_mode_fb_cmd2 f = {};
296 	uint32_t tiled_x_bo = 0;
297 	uint32_t tiled_y_bo = 0;
298 
299 	f.width = 512;
300 	f.height = 512;
301 	f.pixel_format = DRM_FORMAT_XRGB8888;
302 	f.pitches[0] = 1024*4;
303 
304 	igt_subtest_group {
305 		igt_fixture {
306 			igt_require_intel(fd);
307 			tiled_x_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
308 				DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED,
309 				1024*4, NULL, NULL, NULL);
310 			igt_assert(tiled_x_bo);
311 
312 			tiled_y_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
313 				DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_Y_TILED,
314 				1024*4, NULL, NULL, NULL);
315 			igt_assert(tiled_y_bo);
316 
317 			gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
318 				DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
319 			igt_assert(gem_bo);
320 		}
321 
322 		f.pitches[0] = 1024*4;
323 		igt_subtest("basic-X-tiled") {
324 			f.handles[0] = tiled_x_bo;
325 
326 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
327 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
328 			f.fb_id = 0;
329 		}
330 
331 		igt_subtest("framebuffer-vs-set-tiling") {
332 			f.handles[0] = gem_bo;
333 
334 			gem_set_tiling(fd, gem_bo, I915_TILING_X, 1024*4);
335 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
336 			igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_X, 512*4) == -EBUSY);
337 			igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_Y, 1024*4) == -EBUSY);
338 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
339 			f.fb_id = 0;
340 		}
341 
342 		f.pitches[0] = 512*4;
343 		igt_subtest("tile-pitch-mismatch") {
344 			f.handles[0] = tiled_x_bo;
345 
346 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
347 				   errno == EINVAL);
348 		}
349 
350 		f.pitches[0] = 1024*4;
351 		igt_subtest("basic-Y-tiled") {
352 			f.handles[0] = tiled_y_bo;
353 
354 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
355 				   errno == EINVAL);
356 		}
357 
358 		igt_fixture {
359 			gem_close(fd, tiled_x_bo);
360 			gem_close(fd, tiled_y_bo);
361 		}
362 	}
363 }
364 
size_tests(int fd)365 static void size_tests(int fd)
366 {
367 	struct drm_mode_fb_cmd2 f = {};
368 	struct drm_mode_fb_cmd2 f_16 = {};
369 	struct drm_mode_fb_cmd2 f_8 = {};
370 
371 	f.width = 1024;
372 	f.height = 1024;
373 	f.pixel_format = DRM_FORMAT_XRGB8888;
374 	f.pitches[0] = 1024*4;
375 
376 	f_16.width = 1024;
377 	f_16.height = 1024*2;
378 	f_16.pixel_format = DRM_FORMAT_RGB565;
379 	f_16.pitches[0] = 1024*2;
380 
381 	f_8.width = 1024*2;
382 	f_8.height = 1024*2;
383 	f_8.pixel_format = DRM_FORMAT_C8;
384 	f_8.pitches[0] = 1024*2;
385 
386 	igt_fixture {
387 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
388 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
389 		igt_assert(gem_bo);
390 		gem_bo_small = igt_create_bo_with_dimensions(fd, 1024, 1023,
391 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
392 		igt_assert(gem_bo_small);
393 	}
394 
395 	f.handles[0] = gem_bo;
396 	f_16.handles[0] = gem_bo;
397 	f_8.handles[0] = gem_bo;
398 
399 	igt_subtest("size-max") {
400 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
401 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
402 		f.fb_id = 0;
403 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == 0);
404 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f_16.fb_id) == 0);
405 		f.fb_id = 0;
406 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == 0);
407 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f_8.fb_id) == 0);
408 		f.fb_id = 0;
409 	}
410 
411 	f.width++;
412 	f_16.width++;
413 	f_8.width++;
414 	igt_subtest("too-wide") {
415 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
416 			   errno == EINVAL);
417 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == -1 &&
418 			   errno == EINVAL);
419 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == -1 &&
420 			   errno == EINVAL);
421 	}
422 	f.width--;
423 	f_16.width--;
424 	f_8.width--;
425 	f.height++;
426 	f_16.height++;
427 	f_8.height++;
428 	igt_subtest("too-high") {
429 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
430 			   errno == EINVAL);
431 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_16) == -1 &&
432 			   errno == EINVAL);
433 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f_8) == -1 &&
434 			   errno == EINVAL);
435 	}
436 
437 	f.handles[0] = gem_bo_small;
438 	igt_subtest("bo-too-small") {
439 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
440 			   errno == EINVAL);
441 	}
442 
443 	/* Just to check that the parameters would work. */
444 	f.height = 1020;
445 	igt_subtest("small-bo") {
446 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
447 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
448 		f.fb_id = 0;
449 	}
450 
451 	igt_subtest("bo-too-small-due-to-tiling") {
452 		igt_require_intel(fd);
453 		gem_set_tiling(fd, gem_bo_small, I915_TILING_X, 1024*4);
454 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == -1 &&
455 			   errno == EINVAL);
456 	}
457 
458 
459 	igt_fixture {
460 		gem_close(fd, gem_bo);
461 		gem_close(fd, gem_bo_small);
462 	}
463 }
464 
addfb25_tests(int fd)465 static void addfb25_tests(int fd)
466 {
467 	struct local_drm_mode_fb_cmd2 f = {};
468 
469 	igt_fixture {
470 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
471 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
472 		igt_assert(gem_bo);
473 
474 		memset(&f, 0, sizeof(f));
475 
476 		f.width = 1024;
477 		f.height = 1024;
478 		f.pixel_format = DRM_FORMAT_XRGB8888;
479 		f.pitches[0] = 1024*4;
480 		f.modifier[0] = LOCAL_DRM_FORMAT_MOD_NONE;
481 
482 		f.handles[0] = gem_bo;
483 	}
484 
485 	igt_subtest("addfb25-modifier-no-flag") {
486 		igt_require_fb_modifiers(fd);
487 
488 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED;
489 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
490 	}
491 
492 	igt_fixture
493 		f.flags = LOCAL_DRM_MODE_FB_MODIFIERS;
494 
495 	igt_subtest("addfb25-bad-modifier") {
496 		igt_require_fb_modifiers(fd);
497 
498 		f.modifier[0] = ~0;
499 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
500 	}
501 
502 	igt_subtest_group {
503 		igt_fixture {
504 			igt_require_intel(fd);
505 			gem_set_tiling(fd, gem_bo, I915_TILING_X, 1024*4);
506 			igt_require_fb_modifiers(fd);
507 		}
508 
509 		igt_subtest("addfb25-X-tiled-mismatch") {
510 			f.modifier[0] = LOCAL_DRM_FORMAT_MOD_NONE;
511 			igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
512 		}
513 
514 		igt_subtest("addfb25-X-tiled") {
515 			f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED;
516 			igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == 0);
517 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
518 			f.fb_id = 0;
519 		}
520 
521 		igt_subtest("addfb25-framebuffer-vs-set-tiling") {
522 			f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED;
523 			igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == 0);
524 			igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_X, 512*4) == -EBUSY);
525 			igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_Y, 1024*4) == -EBUSY);
526 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
527 			f.fb_id = 0;
528 		}
529 	}
530 	igt_fixture
531 		gem_close(fd, gem_bo);
532 }
533 
addfb_expected_ret(int fd,uint64_t modifier)534 static int addfb_expected_ret(int fd, uint64_t modifier)
535 {
536 	int gen;
537 
538 	if (!is_i915_device(fd))
539 		return 0;
540 
541 	gen = intel_gen(intel_get_drm_devid(fd));
542 
543 	if (modifier == LOCAL_I915_FORMAT_MOD_Yf_TILED)
544 		return gen >= 9 && gen < 12 ? 0 : -1;
545 	return gen >= 9 ? 0 : -1;
546 }
547 
addfb25_ytile(int fd)548 static void addfb25_ytile(int fd)
549 {
550 	struct local_drm_mode_fb_cmd2 f = {};
551 	int gen;
552 
553 	igt_fixture {
554 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
555 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
556 		igt_assert(gem_bo);
557 		gem_bo_small = igt_create_bo_with_dimensions(fd, 1024, 1023,
558 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
559 		igt_assert(gem_bo_small);
560 
561 		memset(&f, 0, sizeof(f));
562 
563 		f.width = 1024;
564 		f.height = 1024;
565 		f.pixel_format = DRM_FORMAT_XRGB8888;
566 		f.pitches[0] = 1024*4;
567 		f.flags = LOCAL_DRM_MODE_FB_MODIFIERS;
568 		f.modifier[0] = LOCAL_DRM_FORMAT_MOD_NONE;
569 
570 		f.handles[0] = gem_bo;
571 	}
572 
573 	igt_subtest("addfb25-Y-tiled") {
574 		igt_require_fb_modifiers(fd);
575 
576 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_Y_TILED;
577 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
578 			   addfb_expected_ret(fd, f.modifier[0]));
579 		if (!addfb_expected_ret(fd, f.modifier[0]))
580 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
581 		f.fb_id = 0;
582 	}
583 
584 	igt_subtest("addfb25-Yf-tiled") {
585 		igt_require_fb_modifiers(fd);
586 
587 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_Yf_TILED;
588 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
589 			   addfb_expected_ret(fd, f.modifier[0]));
590 		if (!addfb_expected_ret(fd, f.modifier[0]))
591 			igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
592 		f.fb_id = 0;
593 	}
594 
595 	igt_subtest("addfb25-Y-tiled-small") {
596 		igt_require_fb_modifiers(fd);
597 
598 		gen = intel_gen(intel_get_drm_devid(fd));
599 		igt_require(gen >= 9);
600 
601 		f.modifier[0] = LOCAL_I915_FORMAT_MOD_Y_TILED;
602 		f.height = 1023;
603 		f.handles[0] = gem_bo_small;
604 		igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
605 		f.fb_id = 0;
606 	}
607 
608 	igt_fixture {
609 		gem_close(fd, gem_bo);
610 		gem_close(fd, gem_bo_small);
611 	}
612 }
613 
prop_tests(int fd)614 static void prop_tests(int fd)
615 {
616 	struct drm_mode_fb_cmd2 f = {};
617 	struct drm_mode_obj_get_properties get_props = {};
618 	struct drm_mode_obj_set_property set_prop = {};
619 	uint64_t prop, prop_val;
620 
621 	f.width = 1024;
622 	f.height = 1024;
623 	f.pixel_format = DRM_FORMAT_XRGB8888;
624 	f.pitches[0] = 1024*4;
625 
626 	igt_fixture {
627 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
628 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
629 		igt_assert(gem_bo);
630 
631 		f.handles[0] = gem_bo;
632 
633 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
634 	}
635 
636 	get_props.props_ptr = (uintptr_t) &prop;
637 	get_props.prop_values_ptr = (uintptr_t) &prop_val;
638 	get_props.count_props = 1;
639 	get_props.obj_id = f.fb_id;
640 
641 	igt_subtest("invalid-get-prop-any") {
642 		get_props.obj_type = 0; /* DRM_MODE_OBJECT_ANY */
643 
644 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES,
645 				    &get_props) == -1 && errno == EINVAL);
646 	}
647 
648 	igt_subtest("invalid-get-prop") {
649 		get_props.obj_type = DRM_MODE_OBJECT_FB;
650 
651 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES,
652 				    &get_props) == -1 && errno == EINVAL);
653 	}
654 
655 	set_prop.value = 0;
656 	set_prop.prop_id = 1;
657 	set_prop.obj_id = f.fb_id;
658 
659 	igt_subtest("invalid-set-prop-any") {
660 		set_prop.obj_type = 0; /* DRM_MODE_OBJECT_ANY */
661 
662 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY,
663 				    &set_prop) == -1 && errno == EINVAL);
664 	}
665 
666 	igt_subtest("invalid-set-prop") {
667 		set_prop.obj_type = DRM_MODE_OBJECT_FB;
668 
669 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY,
670 				    &set_prop) == -1 && errno == EINVAL);
671 	}
672 
673 	igt_fixture
674 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
675 
676 }
677 
master_tests(int fd)678 static void master_tests(int fd)
679 {
680 	struct drm_mode_fb_cmd2 f = {};
681 
682 	f.width = 1024;
683 	f.height = 1024;
684 	f.pixel_format = DRM_FORMAT_XRGB8888;
685 	f.pitches[0] = 1024*4;
686 
687 	igt_fixture {
688 		gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
689 			DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
690 		igt_assert(gem_bo);
691 
692 		f.handles[0] = gem_bo;
693 
694 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
695 	}
696 
697 	igt_subtest("master-rmfb") {
698 		int master2_fd;
699 
700 		igt_device_drop_master(fd);
701 
702 		master2_fd = drm_open_driver_master(DRIVER_ANY);
703 
704 		igt_assert_eq(rmfb(master2_fd, f.fb_id), -ENOENT);
705 
706 		igt_device_drop_master(master2_fd);
707 		close(master2_fd);
708 
709 		igt_device_set_master(fd);
710 	}
711 
712 	igt_fixture
713 		igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
714 
715 }
716 
has_addfb2_iface(int fd)717 static bool has_addfb2_iface(int fd)
718 {
719 	struct local_drm_mode_fb_cmd2 f = {};
720 	int err;
721 
722 	err = 0;
723 	if (drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f))
724 		err = -errno;
725 	switch (err) {
726 	case -ENOTTY: /* ioctl unrecognised (kernel too old) */
727 	case -ENOTSUP: /* driver doesn't support KMS */
728 		return false;
729 
730 		/*
731 		 * The only other valid response is -EINVAL, but we leave
732 		 * that for the actual tests themselves to discover for
733 		 * more accurate reporting.
734 		 */
735 	default:
736 		return true;
737 	}
738 }
739 
740 int fd;
741 
742 igt_main
743 {
744 	igt_fixture {
745 		fd = drm_open_driver_master(DRIVER_ANY);
746 		igt_require(has_addfb2_iface(fd));
747 	}
748 
749 	invalid_tests(fd);
750 
751 	pitch_tests(fd);
752 
753 	size_tests(fd);
754 
755 	addfb25_tests(fd);
756 
757 	addfb25_ytile(fd);
758 
759 	tiling_tests(fd);
760 
761 	prop_tests(fd);
762 
763 	master_tests(fd);
764 
765 	igt_fixture
766 		close(fd);
767 }
768