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) ∝
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