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 <[email protected]>
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 // TODO: b/254808989
496 /*
497 igt_subtest("addfb25-bad-modifier") {
498 igt_require_fb_modifiers(fd);
499
500 f.modifier[0] = ~0;
501 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
502 }
503 */
504
505 igt_subtest_group {
506 igt_fixture {
507 igt_require_intel(fd);
508 gem_set_tiling(fd, gem_bo, I915_TILING_X, 1024*4);
509 igt_require_fb_modifiers(fd);
510 }
511
512 igt_subtest("addfb25-X-tiled-mismatch") {
513 f.modifier[0] = LOCAL_DRM_FORMAT_MOD_NONE;
514 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
515 }
516
517 igt_subtest("addfb25-X-tiled") {
518 f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED;
519 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == 0);
520 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
521 f.fb_id = 0;
522 }
523
524 igt_subtest("addfb25-framebuffer-vs-set-tiling") {
525 f.modifier[0] = LOCAL_I915_FORMAT_MOD_X_TILED;
526 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) == 0);
527 igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_X, 512*4) == -EBUSY);
528 igt_assert(__gem_set_tiling(fd, gem_bo, I915_TILING_Y, 1024*4) == -EBUSY);
529 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
530 f.fb_id = 0;
531 }
532 }
533 igt_fixture
534 gem_close(fd, gem_bo);
535 }
536
addfb_expected_ret(int fd,uint64_t modifier)537 static int addfb_expected_ret(int fd, uint64_t modifier)
538 {
539 int gen;
540
541 if (!is_i915_device(fd))
542 return 0;
543
544 gen = intel_gen(intel_get_drm_devid(fd));
545
546 if (modifier == LOCAL_I915_FORMAT_MOD_Yf_TILED)
547 return gen >= 9 && gen < 12 ? 0 : -1;
548 return gen >= 9 ? 0 : -1;
549 }
550
addfb25_ytile(int fd)551 static void addfb25_ytile(int fd)
552 {
553 struct local_drm_mode_fb_cmd2 f = {};
554 int gen;
555
556 igt_fixture {
557 gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
558 DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
559 igt_assert(gem_bo);
560 gem_bo_small = igt_create_bo_with_dimensions(fd, 1024, 1023,
561 DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
562 igt_assert(gem_bo_small);
563
564 memset(&f, 0, sizeof(f));
565
566 f.width = 1024;
567 f.height = 1024;
568 f.pixel_format = DRM_FORMAT_XRGB8888;
569 f.pitches[0] = 1024*4;
570 f.flags = LOCAL_DRM_MODE_FB_MODIFIERS;
571 f.modifier[0] = LOCAL_DRM_FORMAT_MOD_NONE;
572
573 f.handles[0] = gem_bo;
574 }
575
576 igt_subtest("addfb25-Y-tiled") {
577 igt_require_fb_modifiers(fd);
578
579 f.modifier[0] = LOCAL_I915_FORMAT_MOD_Y_TILED;
580 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
581 addfb_expected_ret(fd, f.modifier[0]));
582 if (!addfb_expected_ret(fd, f.modifier[0]))
583 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
584 f.fb_id = 0;
585 }
586
587 igt_subtest("addfb25-Yf-tiled") {
588 igt_require_fb_modifiers(fd);
589
590 f.modifier[0] = LOCAL_I915_FORMAT_MOD_Yf_TILED;
591 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) ==
592 addfb_expected_ret(fd, f.modifier[0]));
593 if (!addfb_expected_ret(fd, f.modifier[0]))
594 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
595 f.fb_id = 0;
596 }
597
598 igt_subtest("addfb25-Y-tiled-small") {
599 igt_require_fb_modifiers(fd);
600
601 gen = intel_gen(intel_get_drm_devid(fd));
602 igt_require(gen >= 9);
603
604 f.modifier[0] = LOCAL_I915_FORMAT_MOD_Y_TILED;
605 f.height = 1023;
606 f.handles[0] = gem_bo_small;
607 igt_assert(drmIoctl(fd, LOCAL_DRM_IOCTL_MODE_ADDFB2, &f) < 0 && errno == EINVAL);
608 f.fb_id = 0;
609 }
610
611 igt_fixture {
612 gem_close(fd, gem_bo);
613 gem_close(fd, gem_bo_small);
614 }
615 }
616
prop_tests(int fd)617 static void prop_tests(int fd)
618 {
619 struct drm_mode_fb_cmd2 f = {};
620 struct drm_mode_obj_get_properties get_props = {};
621 struct drm_mode_obj_set_property set_prop = {};
622 uint64_t prop, prop_val;
623
624 f.width = 1024;
625 f.height = 1024;
626 f.pixel_format = DRM_FORMAT_XRGB8888;
627 f.pitches[0] = 1024*4;
628
629 igt_fixture {
630 gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
631 DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
632 igt_assert(gem_bo);
633
634 f.handles[0] = gem_bo;
635
636 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
637 }
638
639 get_props.props_ptr = (uintptr_t) ∝
640 get_props.prop_values_ptr = (uintptr_t) &prop_val;
641 get_props.count_props = 1;
642 get_props.obj_id = f.fb_id;
643
644 igt_subtest("invalid-get-prop-any") {
645 get_props.obj_type = 0; /* DRM_MODE_OBJECT_ANY */
646
647 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES,
648 &get_props) == -1 && errno == EINVAL);
649 }
650
651 igt_subtest("invalid-get-prop") {
652 get_props.obj_type = DRM_MODE_OBJECT_FB;
653
654 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES,
655 &get_props) == -1 && errno == EINVAL);
656 }
657
658 set_prop.value = 0;
659 set_prop.prop_id = 1;
660 set_prop.obj_id = f.fb_id;
661
662 igt_subtest("invalid-set-prop-any") {
663 set_prop.obj_type = 0; /* DRM_MODE_OBJECT_ANY */
664
665 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY,
666 &set_prop) == -1 && errno == EINVAL);
667 }
668
669 igt_subtest("invalid-set-prop") {
670 set_prop.obj_type = DRM_MODE_OBJECT_FB;
671
672 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY,
673 &set_prop) == -1 && errno == EINVAL);
674 }
675
676 igt_fixture
677 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
678
679 }
680
master_tests(int fd)681 static void master_tests(int fd)
682 {
683 struct drm_mode_fb_cmd2 f = {};
684
685 f.width = 1024;
686 f.height = 1024;
687 f.pixel_format = DRM_FORMAT_XRGB8888;
688 f.pitches[0] = 1024*4;
689
690 igt_fixture {
691 gem_bo = igt_create_bo_with_dimensions(fd, 1024, 1024,
692 DRM_FORMAT_XRGB8888, 0, 0, NULL, NULL, NULL);
693 igt_assert(gem_bo);
694
695 f.handles[0] = gem_bo;
696
697 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f) == 0);
698 }
699
700 igt_subtest("master-rmfb") {
701 int master2_fd;
702
703 igt_device_drop_master(fd);
704
705 master2_fd = drm_open_driver_master(DRIVER_ANY);
706
707 igt_assert_eq(rmfb(master2_fd, f.fb_id), -ENOENT);
708
709 igt_device_drop_master(master2_fd);
710 close(master2_fd);
711
712 igt_device_set_master(fd);
713 }
714
715 igt_fixture
716 igt_assert(drmIoctl(fd, DRM_IOCTL_MODE_RMFB, &f.fb_id) == 0);
717
718 }
719
has_addfb2_iface(int fd)720 static bool has_addfb2_iface(int fd)
721 {
722 struct local_drm_mode_fb_cmd2 f = {};
723 int err;
724
725 err = 0;
726 if (drmIoctl(fd, DRM_IOCTL_MODE_ADDFB2, &f))
727 err = -errno;
728 switch (err) {
729 case -ENOTTY: /* ioctl unrecognised (kernel too old) */
730 case -ENOTSUP: /* driver doesn't support KMS */
731 return false;
732
733 /*
734 * The only other valid response is -EINVAL, but we leave
735 * that for the actual tests themselves to discover for
736 * more accurate reporting.
737 */
738 default:
739 return true;
740 }
741 }
742
743 int fd;
744
745 igt_main
746 {
747 igt_fixture {
748 fd = drm_open_driver_master(DRIVER_ANY);
749 igt_require(has_addfb2_iface(fd));
750 }
751
752 invalid_tests(fd);
753
754 pitch_tests(fd);
755
756 size_tests(fd);
757
758 addfb25_tests(fd);
759
760 addfb25_ytile(fd);
761
762 tiling_tests(fd);
763
764 prop_tests(fd);
765
766 master_tests(fd);
767
768 igt_fixture
769 close(fd);
770 }
771