1 /*
2 * Copyright © 2015 Intel Corporation
3 * Copyright © 2014-2015 Collabora, Ltd.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * Authors:
25 * Micah Fedke <[email protected]>
26 * Daniel Stone <[email protected]>
27 * Pekka Paalanen <[email protected]>
28 */
29
30 /*
31 * Testcase: testing atomic modesetting API
32 */
33
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <xf86drmMode.h>
41 #include <cairo.h>
42 #include "drm.h"
43 #include "ioctl_wrappers.h"
44 #include "drmtest.h"
45 #include "igt.h"
46 #include "igt_aux.h"
47 #include "sw_sync.h"
48
49 #ifndef DRM_CAP_CURSOR_WIDTH
50 #define DRM_CAP_CURSOR_WIDTH 0x8
51 #endif
52
53 #ifndef DRM_CAP_CURSOR_HEIGHT
54 #define DRM_CAP_CURSOR_HEIGHT 0x9
55 #endif
56
57 IGT_TEST_DESCRIPTION("Test atomic modesetting API");
58
59 enum kms_atomic_check_relax {
60 ATOMIC_RELAX_NONE = 0,
61 CRTC_RELAX_MODE = (1 << 0),
62 PLANE_RELAX_FB = (1 << 1)
63 };
64
plane_filter(enum igt_atomic_plane_properties prop)65 static bool plane_filter(enum igt_atomic_plane_properties prop)
66 {
67 if ((1 << prop) & IGT_PLANE_COORD_CHANGED_MASK)
68 return false;
69
70 if (prop == IGT_PLANE_CRTC_ID || prop == IGT_PLANE_FB_ID)
71 return false;
72
73 if (prop == IGT_PLANE_IN_FENCE_FD)
74 return false;
75
76 /* Don't care about other properties */
77 return true;
78 }
79
plane_get_current_state(igt_plane_t * plane,uint64_t * values)80 static void plane_get_current_state(igt_plane_t *plane, uint64_t *values)
81 {
82 int i;
83
84 for (i = 0; i < IGT_NUM_PLANE_PROPS; i++) {
85 if (plane_filter(i)) {
86 values[i] = 0;
87 continue;
88 }
89
90 values[i] = igt_plane_get_prop(plane, i);
91 }
92 }
93
plane_check_current_state(igt_plane_t * plane,const uint64_t * values,enum kms_atomic_check_relax relax)94 static void plane_check_current_state(igt_plane_t *plane, const uint64_t *values,
95 enum kms_atomic_check_relax relax)
96 {
97 drmModePlanePtr legacy;
98 uint64_t current_values[IGT_NUM_PLANE_PROPS];
99 int i;
100
101 legacy = drmModeGetPlane(plane->pipe->display->drm_fd, plane->drm_plane->plane_id);
102 igt_assert(legacy);
103
104 igt_assert_eq_u32(legacy->crtc_id, values[IGT_PLANE_CRTC_ID]);
105
106 if (!(relax & PLANE_RELAX_FB))
107 igt_assert_eq_u32(legacy->fb_id, values[IGT_PLANE_FB_ID]);
108
109 plane_get_current_state(plane, current_values);
110
111 /* Legacy cursor ioctls create their own, unknowable, internal
112 * framebuffer which we can't reason about. */
113 if (relax & PLANE_RELAX_FB)
114 current_values[IGT_PLANE_FB_ID] = values[IGT_PLANE_FB_ID];
115
116 for (i = 0; i < IGT_NUM_PLANE_PROPS; i++)
117 if (!plane_filter(i))
118 igt_assert_eq_u64(current_values[i], values[i]);
119
120 drmModeFreePlane(legacy);
121 }
122
plane_commit(igt_plane_t * plane,enum igt_commit_style s,enum kms_atomic_check_relax relax)123 static void plane_commit(igt_plane_t *plane, enum igt_commit_style s,
124 enum kms_atomic_check_relax relax)
125 {
126 igt_display_commit2(plane->pipe->display, s);
127 plane_check_current_state(plane, plane->values, relax);
128 }
129
plane_commit_atomic_err(igt_plane_t * plane,enum kms_atomic_check_relax relax,int err)130 static void plane_commit_atomic_err(igt_plane_t *plane,
131 enum kms_atomic_check_relax relax,
132 int err)
133 {
134 uint64_t current_values[IGT_NUM_PLANE_PROPS];
135
136 plane_get_current_state(plane, current_values);
137
138 igt_assert_eq(-err, igt_display_try_commit2(plane->pipe->display, COMMIT_ATOMIC));
139
140 plane_check_current_state(plane, current_values, relax);
141 }
142
crtc_filter(enum igt_atomic_crtc_properties prop)143 static bool crtc_filter(enum igt_atomic_crtc_properties prop)
144 {
145 if (prop == IGT_CRTC_MODE_ID || prop == IGT_CRTC_ACTIVE)
146 return false;
147
148 return true;
149 }
150
crtc_get_current_state(igt_pipe_t * pipe,uint64_t * values)151 static void crtc_get_current_state(igt_pipe_t *pipe, uint64_t *values)
152 {
153 int i;
154
155 for (i = 0; i < IGT_NUM_CRTC_PROPS; i++) {
156 if (crtc_filter(i)) {
157 values[i] = 0;
158 continue;
159 }
160
161 values[i] = igt_pipe_obj_get_prop(pipe, i);
162 }
163 }
164
crtc_check_current_state(igt_pipe_t * pipe,const uint64_t * pipe_values,const uint64_t * primary_values,enum kms_atomic_check_relax relax)165 static void crtc_check_current_state(igt_pipe_t *pipe,
166 const uint64_t *pipe_values,
167 const uint64_t *primary_values,
168 enum kms_atomic_check_relax relax)
169 {
170 uint64_t current_pipe_values[IGT_NUM_CRTC_PROPS];
171 drmModeCrtcPtr legacy;
172 drmModePropertyBlobRes *mode_prop = NULL;
173 struct drm_mode_modeinfo *mode = NULL;
174
175 if (pipe_values[IGT_CRTC_MODE_ID]) {
176 mode_prop = drmModeGetPropertyBlob(pipe->display->drm_fd,
177 pipe_values[IGT_CRTC_MODE_ID]);
178
179 igt_assert(mode_prop);
180
181 igt_assert_eq(mode_prop->length,
182 sizeof(struct drm_mode_modeinfo));
183 mode = mode_prop->data;
184 }
185
186 legacy = drmModeGetCrtc(pipe->display->drm_fd, pipe->crtc_id);
187 igt_assert(legacy);
188
189 igt_assert_eq_u32(legacy->crtc_id, pipe->crtc_id);
190 igt_assert_eq_u32(legacy->x, primary_values[IGT_PLANE_SRC_X] >> 16);
191 igt_assert_eq_u32(legacy->y, primary_values[IGT_PLANE_SRC_Y] >> 16);
192
193 igt_assert_eq_u32(legacy->buffer_id, primary_values[IGT_PLANE_FB_ID]);
194
195 if (legacy->mode_valid) {
196 igt_assert(mode_prop);
197
198 do_or_die(memcmp(&legacy->mode, mode, sizeof(*mode)));
199
200 igt_assert_eq(legacy->width, legacy->mode.hdisplay);
201 igt_assert_eq(legacy->height, legacy->mode.vdisplay);
202
203 igt_assert_neq(pipe_values[IGT_CRTC_MODE_ID], 0);
204 } else {
205 igt_assert(!mode_prop);
206 }
207
208 crtc_get_current_state(pipe, current_pipe_values);
209
210 /* Optionally relax the check for MODE_ID: using the legacy SetCrtc
211 * API can potentially change MODE_ID even if the mode itself remains
212 * unchanged. */
213 if (relax & CRTC_RELAX_MODE && mode && current_pipe_values[IGT_CRTC_MODE_ID] &&
214 current_pipe_values[IGT_CRTC_MODE_ID] != pipe_values[IGT_CRTC_MODE_ID]) {
215 drmModePropertyBlobRes *cur_prop =
216 drmModeGetPropertyBlob(pipe->display->drm_fd,
217 current_pipe_values[IGT_CRTC_MODE_ID]);
218
219 igt_assert(cur_prop);
220 igt_assert_eq(cur_prop->length, sizeof(struct drm_mode_modeinfo));
221
222 if (!memcmp(cur_prop->data, mode, sizeof(*mode)))
223 current_pipe_values[IGT_CRTC_MODE_ID] = pipe_values[IGT_CRTC_MODE_ID];
224
225 drmModeFreePropertyBlob(cur_prop);
226 }
227
228 do_or_die(memcmp(pipe_values, current_pipe_values, sizeof(current_pipe_values)));
229
230 drmModeFreeCrtc(legacy);
231 drmModeFreePropertyBlob(mode_prop);
232 }
233
crtc_commit(igt_pipe_t * pipe,igt_plane_t * plane,enum igt_commit_style s,enum kms_atomic_check_relax relax)234 static void crtc_commit(igt_pipe_t *pipe, igt_plane_t *plane,
235 enum igt_commit_style s,
236 enum kms_atomic_check_relax relax)
237 {
238 igt_display_commit2(pipe->display, s);
239
240 crtc_check_current_state(pipe, pipe->values, plane->values, relax);
241 plane_check_current_state(plane, plane->values, relax);
242 }
243
crtc_commit_atomic_flags_err(igt_pipe_t * pipe,igt_plane_t * plane,unsigned flags,enum kms_atomic_check_relax relax,int err)244 static void crtc_commit_atomic_flags_err(igt_pipe_t *pipe, igt_plane_t *plane,
245 unsigned flags,
246 enum kms_atomic_check_relax relax,
247 int err)
248 {
249 uint64_t current_pipe_values[IGT_NUM_CRTC_PROPS];
250 uint64_t current_plane_values[IGT_NUM_PLANE_PROPS];
251
252 crtc_get_current_state(pipe, current_pipe_values);
253 plane_get_current_state(plane, current_plane_values);
254
255 igt_assert_eq(-err, igt_display_try_commit_atomic(pipe->display, flags, NULL));
256
257 crtc_check_current_state(pipe, current_pipe_values, current_plane_values, relax);
258 plane_check_current_state(plane, current_plane_values, relax);
259 }
260
261 #define crtc_commit_atomic_err(pipe, plane, relax, err) \
262 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_ATOMIC_ALLOW_MODESET, relax, err)
263
plane_get_igt_format(igt_plane_t * plane)264 static uint32_t plane_get_igt_format(igt_plane_t *plane)
265 {
266 drmModePlanePtr plane_kms;
267 int i;
268
269 plane_kms = plane->drm_plane;
270
271 for (i = 0; i < plane_kms->count_formats; i++) {
272 if (igt_fb_supported_format(plane_kms->formats[i]))
273 return plane_kms->formats[i];
274 }
275
276 return 0;
277 }
278
279 static void
plane_primary_overlay_zpos(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * primary,igt_plane_t * overlay,uint32_t format_primary,uint32_t format_overlay)280 plane_primary_overlay_zpos(igt_pipe_t *pipe, igt_output_t *output,
281 igt_plane_t *primary, igt_plane_t *overlay,
282 uint32_t format_primary, uint32_t format_overlay)
283 {
284 struct igt_fb fb_primary, fb_overlay;
285 drmModeModeInfo *mode = igt_output_get_mode(output);
286 cairo_t *cr;
287
288 /* for primary */
289 uint32_t w = mode->hdisplay;
290 uint32_t h = mode->vdisplay;
291
292 /* for overlay */
293 uint32_t w_overlay = mode->hdisplay / 2;
294 uint32_t h_overlay = mode->vdisplay / 2;
295
296 igt_create_color_pattern_fb(pipe->display->drm_fd,
297 w, h, format_primary, I915_TILING_NONE,
298 0.2, 0.2, 0.2, &fb_primary);
299
300 igt_create_color_pattern_fb(pipe->display->drm_fd,
301 w_overlay, h_overlay,
302 format_overlay, I915_TILING_NONE,
303 0.2, 0.2, 0.2, &fb_overlay);
304
305 #if defined(USE_CAIRO_PIXMAN)
306 /* Draw a hole in the overlay */
307 cr = igt_get_cairo_ctx(pipe->display->drm_fd, &fb_overlay);
308 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
309 igt_paint_color_alpha(cr, w_overlay / 4, h_overlay / 4,
310 w_overlay / 2, h_overlay / 2,
311 0.0, 0.0, 0.0, 0.0);
312 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
313 igt_put_cairo_ctx(pipe->display->drm_fd, &fb_overlay, cr);
314 #endif
315
316 igt_plane_set_fb(primary, &fb_primary);
317 igt_plane_set_fb(overlay, &fb_overlay);
318
319 igt_plane_set_position(overlay, w_overlay / 2, h_overlay / 2);
320
321 igt_plane_set_prop_value(primary, IGT_PLANE_ZPOS, 0);
322 igt_plane_set_prop_value(overlay, IGT_PLANE_ZPOS, 1);
323
324 igt_info("Committing with overlay on top, it has a hole "\
325 "through which the primary should be seen\n");
326 plane_commit(primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
327
328 igt_assert_eq_u64(igt_plane_get_prop(primary, IGT_PLANE_ZPOS), 0);
329 igt_assert_eq_u64(igt_plane_get_prop(overlay, IGT_PLANE_ZPOS), 1);
330
331 igt_plane_set_prop_value(primary, IGT_PLANE_ZPOS, 1);
332 igt_plane_set_prop_value(overlay, IGT_PLANE_ZPOS, 0);
333
334 igt_info("Committing with primary on top, only the primary "\
335 "should be visible\n");
336 plane_commit(primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
337
338 igt_assert_eq_u64(igt_plane_get_prop(primary, IGT_PLANE_ZPOS), 1);
339 igt_assert_eq_u64(igt_plane_get_prop(overlay, IGT_PLANE_ZPOS), 0);
340
341 /* Draw a hole in the primary exactly on top of the overlay plane */
342 #if defined(USE_CAIRO_PIXMAN)
343 cr = igt_get_cairo_ctx(pipe->display->drm_fd, &fb_primary);
344 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
345 igt_paint_color_alpha(cr, w_overlay / 2, h_overlay / 2,
346 w_overlay, h_overlay,
347 0.0, 0.0, 0.0, 0.5);
348 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
349 igt_put_cairo_ctx(pipe->display->drm_fd, &fb_primary, cr);
350 #endif
351
352 igt_info("Committing with a hole in the primary through "\
353 "which the underlay should be seen\n");
354 plane_commit(primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
355
356 /* reset it back to initial state */
357 igt_plane_set_prop_value(primary, IGT_PLANE_ZPOS, 0);
358 igt_plane_set_prop_value(overlay, IGT_PLANE_ZPOS, 1);
359 plane_commit(primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
360
361 igt_assert_eq_u64(igt_plane_get_prop(primary, IGT_PLANE_ZPOS), 0);
362 igt_assert_eq_u64(igt_plane_get_prop(overlay, IGT_PLANE_ZPOS), 1);
363 }
364
plane_overlay(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * plane)365 static void plane_overlay(igt_pipe_t *pipe, igt_output_t *output, igt_plane_t *plane)
366 {
367 drmModeModeInfo *mode = igt_output_get_mode(output);
368 uint32_t format = plane_get_igt_format(plane);
369 struct igt_fb fb;
370 uint32_t w = mode->hdisplay / 2;
371 uint32_t h = mode->vdisplay / 2;
372
373 igt_require(format != 0);
374
375 igt_create_pattern_fb(pipe->display->drm_fd, w, h,
376 format, I915_TILING_NONE, &fb);
377
378 igt_plane_set_fb(plane, &fb);
379 igt_plane_set_position(plane, w/2, h/2);
380
381 /* Enable the overlay plane using the atomic API, and double-check
382 * state is what we think it should be. */
383 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
384
385 /* Disable the plane and check the state matches the old. */
386 igt_plane_set_fb(plane, NULL);
387 igt_plane_set_position(plane, 0, 0);
388 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
389
390 /* Re-enable the plane through the legacy plane API, and verify through
391 * atomic. */
392 igt_plane_set_fb(plane, &fb);
393 igt_plane_set_position(plane, w/2, h/2);
394 plane_commit(plane, COMMIT_LEGACY, ATOMIC_RELAX_NONE);
395
396 /* Restore the plane to its original settings through the legacy plane
397 * API, and verify through atomic. */
398 igt_plane_set_fb(plane, NULL);
399 igt_plane_set_position(plane, 0, 0);
400 plane_commit(plane, COMMIT_LEGACY, ATOMIC_RELAX_NONE);
401
402 igt_remove_fb(pipe->display->drm_fd, &fb);
403 }
404
plane_primary(igt_pipe_t * pipe,igt_plane_t * plane,struct igt_fb * fb)405 static void plane_primary(igt_pipe_t *pipe, igt_plane_t *plane, struct igt_fb *fb)
406 {
407 struct igt_fb fb2;
408
409 igt_create_color_pattern_fb(pipe->display->drm_fd,
410 fb->width, fb->height,
411 fb->drm_format, I915_TILING_NONE,
412 0.2, 0.2, 0.2, &fb2);
413
414 /* Flip the primary plane using the atomic API, and double-check
415 * state is what we think it should be. */
416 igt_plane_set_fb(plane, &fb2);
417 crtc_commit(pipe, plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
418
419 /* Restore the primary plane and check the state matches the old. */
420 igt_plane_set_fb(plane, fb);
421 crtc_commit(pipe, plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
422
423 /* Set the plane through the legacy CRTC/primary-plane API, and
424 * verify through atomic. */
425 igt_plane_set_fb(plane, &fb2);
426 crtc_commit(pipe, plane, COMMIT_LEGACY, CRTC_RELAX_MODE);
427
428 /* Restore the plane to its original settings through the legacy CRTC
429 * API, and verify through atomic. */
430 igt_plane_set_fb(plane, fb);
431 crtc_commit(pipe, plane, COMMIT_LEGACY, CRTC_RELAX_MODE);
432
433 /* Set the plane through the universal setplane API, and
434 * verify through atomic. */
435 igt_plane_set_fb(plane, &fb2);
436 plane_commit(plane, COMMIT_UNIVERSAL, ATOMIC_RELAX_NONE);
437 }
438
439 /* test to ensure that DRM_MODE_ATOMIC_TEST_ONLY really only touches the
440 * free-standing state objects and nothing else.
441 */
test_only(igt_pipe_t * pipe_obj,igt_plane_t * primary,igt_output_t * output)442 static void test_only(igt_pipe_t *pipe_obj,
443 igt_plane_t *primary,
444 igt_output_t *output)
445 {
446 drmModeModeInfo *mode = igt_output_get_mode(output);
447 uint32_t format = plane_get_igt_format(primary);
448 struct igt_fb fb;
449 uint64_t old_plane_values[IGT_NUM_PLANE_PROPS], old_crtc_values[IGT_NUM_CRTC_PROPS];
450
451 igt_require(format != 0);
452
453 plane_get_current_state(primary, old_plane_values);
454 crtc_get_current_state(pipe_obj, old_crtc_values);
455
456 igt_assert(!old_crtc_values[IGT_CRTC_MODE_ID]);
457
458 igt_create_pattern_fb(pipe_obj->display->drm_fd,
459 mode->hdisplay, mode->vdisplay,
460 format, I915_TILING_NONE, &fb);
461 igt_plane_set_fb(primary, &fb);
462 igt_output_set_pipe(output, pipe_obj->pipe);
463
464 igt_display_commit_atomic(pipe_obj->display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
465
466 /* check the state, should still be old state */
467 crtc_check_current_state(pipe_obj, old_crtc_values, old_plane_values, ATOMIC_RELAX_NONE);
468 plane_check_current_state(primary, old_plane_values, ATOMIC_RELAX_NONE);
469
470 /*
471 * Enable the plane through the legacy CRTC/primary-plane API, and
472 * verify through atomic.
473 */
474 crtc_commit(pipe_obj, primary, COMMIT_LEGACY, CRTC_RELAX_MODE);
475
476 /* Same for disable.. */
477 plane_get_current_state(primary, old_plane_values);
478 crtc_get_current_state(pipe_obj, old_crtc_values);
479
480 igt_plane_set_fb(primary, NULL);
481 igt_output_set_pipe(output, PIPE_NONE);
482
483 igt_display_commit_atomic(pipe_obj->display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
484
485 /* for extra stress, go through dpms off/on cycle */
486 kmstest_set_connector_dpms(output->display->drm_fd, output->config.connector, DRM_MODE_DPMS_OFF);
487 kmstest_set_connector_dpms(output->display->drm_fd, output->config.connector, DRM_MODE_DPMS_ON);
488
489 /* check the state, should still be old state */
490 crtc_check_current_state(pipe_obj, old_crtc_values, old_plane_values, ATOMIC_RELAX_NONE);
491 plane_check_current_state(primary, old_plane_values, ATOMIC_RELAX_NONE);
492
493 /* And disable the pipe and remove fb, test complete */
494 crtc_commit(pipe_obj, primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
495 igt_remove_fb(pipe_obj->display->drm_fd, &fb);
496 }
497
plane_cursor(igt_pipe_t * pipe_obj,igt_output_t * output,igt_plane_t * cursor)498 static void plane_cursor(igt_pipe_t *pipe_obj,
499 igt_output_t *output,
500 igt_plane_t *cursor)
501 {
502 drmModeModeInfo *mode = igt_output_get_mode(output);
503 struct igt_fb fb;
504 uint64_t width, height;
505 int x = mode->hdisplay / 2;
506 int y = mode->vdisplay / 2;
507
508 /* Any kernel new enough for atomic, also has the cursor size caps. */
509 do_or_die(drmGetCap(pipe_obj->display->drm_fd,
510 DRM_CAP_CURSOR_WIDTH, &width));
511 do_or_die(drmGetCap(pipe_obj->display->drm_fd,
512 DRM_CAP_CURSOR_HEIGHT, &height));
513
514 igt_create_color_fb(pipe_obj->display->drm_fd,
515 width, height, DRM_FORMAT_ARGB8888,
516 LOCAL_DRM_FORMAT_MOD_NONE,
517 0.0, 0.0, 0.0, &fb);
518
519 /* Flip the cursor plane using the atomic API, and double-check
520 * state is what we think it should be. */
521 igt_plane_set_fb(cursor, &fb);
522 igt_plane_set_position(cursor, x, y);
523 plane_commit(cursor, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
524
525 /* Restore the cursor plane and check the state matches the old. */
526 igt_plane_set_fb(cursor, NULL);
527 igt_plane_set_position(cursor, 0, 0);
528 plane_commit(cursor, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
529
530 /* Re-enable the plane through the legacy cursor API, and verify
531 * through atomic. */
532 igt_plane_set_fb(cursor, &fb);
533 igt_plane_set_position(cursor, x, y);
534 plane_commit(cursor, COMMIT_LEGACY, PLANE_RELAX_FB);
535
536 /* Wiggle. */
537 igt_plane_set_position(cursor, x - 16, y - 16);
538 plane_commit(cursor, COMMIT_LEGACY, PLANE_RELAX_FB);
539
540 /* Restore the plane to its original settings through the legacy cursor
541 * API, and verify through atomic. */
542 igt_plane_set_fb(cursor, NULL);
543 igt_plane_set_position(cursor, 0, 0);
544 plane_commit(cursor, COMMIT_LEGACY, ATOMIC_RELAX_NONE);
545 }
546
plane_invalid_params(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * plane,struct igt_fb * fb)547 static void plane_invalid_params(igt_pipe_t *pipe,
548 igt_output_t *output,
549 igt_plane_t *plane,
550 struct igt_fb *fb)
551 {
552 struct igt_fb fb2;
553
554 /* Pass a series of invalid object IDs for the FB ID. */
555 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, plane->drm_plane->plane_id);
556 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
557
558 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, pipe->crtc_id);
559 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
560
561 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, output->id);
562 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
563
564 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, pipe->values[IGT_CRTC_MODE_ID]);
565 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
566
567 /* Valid, but invalid because CRTC_ID is set. */
568 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, 0);
569 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
570
571 igt_plane_set_fb(plane, fb);
572 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
573
574 /* Pass a series of invalid object IDs for the CRTC ID. */
575 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, plane->drm_plane->plane_id);
576 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
577
578 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, fb->fb_id);
579 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
580
581 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, output->id);
582 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
583
584 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, pipe->values[IGT_CRTC_MODE_ID]);
585 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
586
587 /* Valid, but invalid because FB_ID is set. */
588 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, 0);
589 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
590
591 igt_plane_set_fb(plane, fb);
592 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
593
594 /* Create a framebuffer too small for the plane configuration. */
595 igt_create_pattern_fb(pipe->display->drm_fd,
596 fb->width - 1, fb->height - 1,
597 fb->drm_format, I915_TILING_NONE, &fb2);
598
599 igt_plane_set_prop_value(plane, IGT_PLANE_FB_ID, fb2.fb_id);
600 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, ENOSPC);
601
602 /* Restore the primary plane and check the state matches the old. */
603 igt_plane_set_fb(plane, fb);
604 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
605 }
606
plane_invalid_params_fence(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * plane)607 static void plane_invalid_params_fence(igt_pipe_t *pipe,
608 igt_output_t *output,
609 igt_plane_t *plane)
610 {
611 int timeline, fence_fd;
612
613 igt_require_sw_sync();
614
615 timeline = sw_sync_timeline_create();
616
617 /* invalid fence fd */
618 igt_plane_set_fence_fd(plane, pipe->display->drm_fd);
619 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
620
621 /* Valid fence_fd but invalid CRTC */
622 fence_fd = sw_sync_timeline_create_fence(timeline, 1);
623
624 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, ~0);
625 igt_plane_set_fence_fd(plane, fence_fd);
626 plane_commit_atomic_err(plane, ATOMIC_RELAX_NONE, EINVAL);
627
628 sw_sync_timeline_inc(timeline, 1);
629 igt_plane_set_prop_value(plane, IGT_PLANE_CRTC_ID, pipe->crtc_id);
630 plane_commit(plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
631
632 close(fence_fd);
633 close(timeline);
634 }
635
crtc_invalid_params(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * plane,struct igt_fb * fb)636 static void crtc_invalid_params(igt_pipe_t *pipe,
637 igt_output_t *output,
638 igt_plane_t *plane,
639 struct igt_fb *fb)
640 {
641 uint64_t old_mode_id = pipe->values[IGT_CRTC_MODE_ID];
642 drmModeModeInfo *mode = igt_output_get_mode(output);
643
644 /* Pass a series of invalid object IDs for the mode ID. */
645 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, plane->drm_plane->plane_id);
646 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
647
648 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, pipe->crtc_id);
649 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
650
651 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, output->id);
652 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
653
654 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, fb->fb_id);
655 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
656
657 /* Can we restore mode? */
658 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, old_mode_id);
659 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_ATOMIC_TEST_ONLY, ATOMIC_RELAX_NONE, 0);
660
661 /*
662 * TEST_ONLY cannot be combined with DRM_MODE_PAGE_FLIP_EVENT,
663 * but DRM_MODE_PAGE_FLIP_EVENT will always generate EINVAL
664 * without valid crtc, so test it here.
665 */
666 crtc_commit_atomic_flags_err(pipe, plane,
667 DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_PAGE_FLIP_EVENT,
668 ATOMIC_RELAX_NONE, EINVAL);
669
670 /* Create a blob which is the wrong size to be a valid mode. */
671 igt_pipe_obj_replace_prop_blob(pipe, IGT_CRTC_MODE_ID, mode, sizeof(*mode) - 1);
672 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
673
674 igt_pipe_obj_replace_prop_blob(pipe, IGT_CRTC_MODE_ID, mode, sizeof(*mode) + 1);
675 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EINVAL);
676
677
678 /* Restore the CRTC and check the state matches the old. */
679 igt_pipe_obj_replace_prop_blob(pipe, IGT_CRTC_MODE_ID, mode, sizeof(*mode));
680 crtc_commit(pipe, plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
681 }
682
crtc_invalid_params_fence(igt_pipe_t * pipe,igt_output_t * output,igt_plane_t * plane,struct igt_fb * fb)683 static void crtc_invalid_params_fence(igt_pipe_t *pipe,
684 igt_output_t *output,
685 igt_plane_t *plane,
686 struct igt_fb *fb)
687 {
688 int timeline, fence_fd;
689 void *map;
690 const ptrdiff_t page_size = sysconf(_SC_PAGE_SIZE);
691
692 uint64_t old_mode_id = pipe->values[IGT_CRTC_MODE_ID];
693
694 igt_require_sw_sync();
695
696 timeline = sw_sync_timeline_create();
697
698 /* invalid out_fence_ptr */
699 map = mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
700 igt_assert(map != MAP_FAILED);
701
702 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_OUT_FENCE_PTR, (ptrdiff_t)map);
703 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EFAULT);
704 munmap(map, page_size);
705
706 /* invalid out_fence_ptr */
707 map = mmap(NULL, page_size, PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
708 igt_assert(map != MAP_FAILED);
709
710 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_OUT_FENCE_PTR, (ptrdiff_t)map);
711 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EFAULT);
712 munmap(map, page_size);
713
714 /* invalid out_fence_ptr */
715 map = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
716 igt_assert(map != MAP_FAILED);
717
718 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_OUT_FENCE_PTR, (ptrdiff_t)map);
719 crtc_commit_atomic_err(pipe, plane, ATOMIC_RELAX_NONE, EFAULT);
720 munmap(map, page_size);
721
722 /* valid in fence but not allowed prop on crtc */
723 fence_fd = sw_sync_timeline_create_fence(timeline, 1);
724 igt_plane_set_fence_fd(plane, fence_fd);
725
726 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_ACTIVE, 0);
727 igt_pipe_obj_clear_prop_changed(pipe, IGT_CRTC_OUT_FENCE_PTR);
728
729 crtc_commit_atomic_flags_err(pipe, plane, 0, ATOMIC_RELAX_NONE, EINVAL);
730
731 /* valid out fence ptr and flip event but not allowed prop on crtc */
732 igt_pipe_request_out_fence(pipe);
733 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_PAGE_FLIP_EVENT,
734 ATOMIC_RELAX_NONE, EINVAL);
735
736 /* valid flip event but not allowed prop on crtc */
737 igt_pipe_obj_clear_prop_changed(pipe, IGT_CRTC_OUT_FENCE_PTR);
738 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_PAGE_FLIP_EVENT,
739 ATOMIC_RELAX_NONE, EINVAL);
740
741 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_ACTIVE, 1);
742
743 /* Configuration should be valid again */
744 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_ATOMIC_TEST_ONLY,
745 ATOMIC_RELAX_NONE, 0);
746
747 /* Set invalid prop */
748 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, fb->fb_id);
749
750 /* valid out fence but invalid prop on crtc */
751 igt_pipe_request_out_fence(pipe);
752 crtc_commit_atomic_flags_err(pipe, plane, 0,
753 ATOMIC_RELAX_NONE, EINVAL);
754
755 /* valid out fence ptr and flip event but invalid prop on crtc */
756 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_PAGE_FLIP_EVENT,
757 ATOMIC_RELAX_NONE, EINVAL);
758
759 /* valid page flip event but invalid prop on crtc */
760 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_PAGE_FLIP_EVENT,
761 ATOMIC_RELAX_NONE, EINVAL);
762
763 /* successful TEST_ONLY with fences set */
764 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_MODE_ID, old_mode_id);
765 crtc_commit_atomic_flags_err(pipe, plane, DRM_MODE_ATOMIC_TEST_ONLY,
766 ATOMIC_RELAX_NONE, 0);
767 igt_assert(pipe->out_fence_fd == -1);
768 close(fence_fd);
769 close(timeline);
770
771 /* reset fences */
772 igt_plane_set_fence_fd(plane, -1);
773 igt_pipe_obj_set_prop_value(pipe, IGT_CRTC_OUT_FENCE_PTR, 0);
774 igt_pipe_obj_clear_prop_changed(pipe, IGT_CRTC_OUT_FENCE_PTR);
775 crtc_commit(pipe, plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
776
777 /* out fence ptr but not page flip event */
778 igt_pipe_request_out_fence(pipe);
779 crtc_commit(pipe, plane, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
780
781 igt_assert(pipe->out_fence_fd != -1);
782 }
783
784 /* Abuse the atomic ioctl directly in order to test various invalid conditions,
785 * which the libdrm wrapper won't allow us to create. */
atomic_invalid_params(igt_pipe_t * pipe,igt_plane_t * plane,igt_output_t * output,struct igt_fb * fb)786 static void atomic_invalid_params(igt_pipe_t *pipe,
787 igt_plane_t *plane,
788 igt_output_t *output,
789 struct igt_fb *fb)
790 {
791 igt_display_t *display = pipe->display;
792 struct drm_mode_atomic ioc;
793 uint32_t obj_raw[16]; /* array of objects (sized by count_objs) */
794 uint32_t num_props_raw[16]; /* array of num props per obj (ditto) */
795 uint32_t props_raw[256]; /* array of props (sum of count_props) */
796 uint64_t values_raw[256]; /* array of values for properties (ditto) */
797 int i;
798
799 memset(&ioc, 0, sizeof(ioc));
800
801 /* An empty request should do nothing. */
802 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
803
804 for (i = 0; i < ARRAY_SIZE(obj_raw); i++)
805 obj_raw[i] = 0;
806 for (i = 0; i < ARRAY_SIZE(num_props_raw); i++)
807 num_props_raw[i] = 0;
808 for (i = 0; i < ARRAY_SIZE(props_raw); i++)
809 props_raw[i] = 0;
810 for (i = 0; i < ARRAY_SIZE(values_raw); i++)
811 values_raw[i] = 0;
812
813 ioc.objs_ptr = (uintptr_t) obj_raw;
814 ioc.count_props_ptr = (uintptr_t) num_props_raw;
815 ioc.props_ptr = (uintptr_t) props_raw;
816 ioc.prop_values_ptr = (uintptr_t) values_raw;
817
818 /* Valid pointers, but still should copy nothing. */
819 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
820
821 /* Valid noop, but with event set should fail. */
822 ioc.flags = DRM_MODE_PAGE_FLIP_EVENT;
823 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EINVAL);
824
825 /* Nonsense flags. */
826 ioc.flags = 0xdeadbeef;
827 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EINVAL);
828
829 ioc.flags = 0;
830 /* Safety check that flags is reset properly. */
831 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
832
833 /* Reserved/MBZ. */
834 ioc.reserved = 1;
835 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EINVAL);
836 ioc.reserved = 0;
837 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
838
839 /* Zero is not a valid object ID. */
840 ioc.count_objs = ARRAY_SIZE(obj_raw);
841 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
842
843 /* Invalid object type (not a thing we can set properties on). */
844 ioc.count_objs = 1;
845 obj_raw[0] = pipe->values[IGT_CRTC_MODE_ID];
846 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
847 obj_raw[0] = fb->fb_id;
848 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
849
850 /* Filled object but with no properties; no-op. */
851 for (i = 0; i < ARRAY_SIZE(obj_raw); i++)
852 obj_raw[i] = pipe->crtc_id;
853 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
854
855 /* Pass in all sorts of things other than the property ID. */
856 num_props_raw[0] = 1;
857 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
858 props_raw[0] = pipe->crtc_id;
859 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
860 props_raw[0] = plane->drm_plane->plane_id;
861 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
862 props_raw[0] = output->id;
863 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
864 props_raw[0] = pipe->values[IGT_CRTC_MODE_ID];
865 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
866
867 /* Valid property, valid value. */
868
869 for (i = 0; i < ARRAY_SIZE(props_raw); i++) {
870 props_raw[i] = pipe->props[IGT_CRTC_MODE_ID];
871 values_raw[i] = pipe->values[IGT_CRTC_MODE_ID];
872 }
873 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
874
875 /* Setting the same thing multiple times is OK. */
876 for (i = 0; i < ARRAY_SIZE(obj_raw); i++)
877 num_props_raw[i] = ARRAY_SIZE(props_raw) / ARRAY_SIZE(obj_raw);
878 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
879 ioc.count_objs = ARRAY_SIZE(obj_raw);
880 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
881
882 /* Pass a series of outlandish addresses. */
883 ioc.objs_ptr = 0;
884 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
885
886 ioc.objs_ptr = (uintptr_t) obj_raw;
887 ioc.count_props_ptr = 0;
888 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
889
890 ioc.count_props_ptr = (uintptr_t) num_props_raw;
891 ioc.props_ptr = 0;
892 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
893
894 ioc.props_ptr = (uintptr_t) props_raw;
895 ioc.prop_values_ptr = 0;
896 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
897
898 ioc.prop_values_ptr = (uintptr_t) values_raw;
899 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc);
900
901 /* Attempt to overflow and/or trip various boundary conditions. */
902 ioc.count_objs = UINT32_MAX / sizeof(uint32_t);
903 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, ENOENT);
904
905 ioc.count_objs = ARRAY_SIZE(obj_raw);
906 ioc.objs_ptr = UINT64_MAX - sizeof(uint32_t);
907 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
908 ioc.count_objs = 1;
909 ioc.objs_ptr = UINT64_MAX - sizeof(uint32_t);
910 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
911
912 num_props_raw[0] = UINT32_MAX / sizeof(uint32_t);
913 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
914 num_props_raw[0] = UINT32_MAX - 1;
915 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
916
917 for (i = 0; i < ARRAY_SIZE(obj_raw); i++)
918 num_props_raw[i] = (UINT32_MAX / ARRAY_SIZE(obj_raw)) + 1;
919 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
920 for (i = 0; i < ARRAY_SIZE(obj_raw); i++)
921 num_props_raw[i] = ARRAY_SIZE(props_raw) / ARRAY_SIZE(obj_raw);
922 do_ioctl_err(display->drm_fd, DRM_IOCTL_MODE_ATOMIC, &ioc, EFAULT);
923 }
924
atomic_setup(igt_display_t * display,enum pipe pipe,igt_output_t * output,igt_plane_t * primary,struct igt_fb * fb)925 static void atomic_setup(igt_display_t *display, enum pipe pipe, igt_output_t *output, igt_plane_t *primary, struct igt_fb *fb)
926 {
927 igt_output_set_pipe(output, pipe);
928 igt_plane_set_fb(primary, fb);
929
930 crtc_commit(primary->pipe, primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
931 }
932
atomic_clear(igt_display_t * display,enum pipe pipe,igt_plane_t * primary,igt_output_t * output)933 static void atomic_clear(igt_display_t *display, enum pipe pipe, igt_plane_t *primary, igt_output_t *output)
934 {
935 igt_plane_t *plane;
936
937 for_each_plane_on_pipe(display, pipe, plane) {
938 igt_plane_set_fb(plane, NULL);
939 igt_plane_set_position(plane, 0, 0);
940 }
941
942 igt_output_set_pipe(output, PIPE_NONE);
943 crtc_commit(primary->pipe, primary, COMMIT_ATOMIC, ATOMIC_RELAX_NONE);
944 }
945
946 igt_main
947 {
948 igt_display_t display;
949 enum pipe pipe = PIPE_NONE;
950 igt_pipe_t *pipe_obj;
951 igt_output_t *output = NULL;
952 igt_plane_t *primary = NULL;
953 drmModeModeInfo *mode;
954 struct igt_fb fb;
955
956 igt_fixture {
957 display.drm_fd = drm_open_driver_master(DRIVER_ANY);
958
959 kmstest_set_vt_graphics_mode();
960
961 igt_display_require(&display, display.drm_fd);
962 igt_require(display.is_atomic);
963 igt_display_require_output(&display);
964
965 for_each_pipe_with_valid_output(&display, pipe, output)
966 break;
967
968 pipe_obj = &display.pipes[pipe];
969 primary = igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_PRIMARY);
970
971 mode = igt_output_get_mode(output);
972
973 igt_create_pattern_fb(display.drm_fd,
974 mode->hdisplay, mode->vdisplay,
975 plane_get_igt_format(primary),
976 LOCAL_DRM_FORMAT_MOD_NONE, &fb);
977 }
978
979 igt_subtest("plane_overlay_legacy") {
980 igt_plane_t *overlay =
981 igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_OVERLAY);
982
983 igt_require(overlay);
984
985 atomic_setup(&display, pipe, output, primary, &fb);
986 plane_overlay(pipe_obj, output, overlay);
987 }
988
989 igt_subtest("plane_primary_legacy") {
990 atomic_setup(&display, pipe, output, primary, &fb);
991
992 plane_primary(pipe_obj, primary, &fb);
993 }
994
995 igt_subtest("plane_primary_overlay_zpos") {
996 uint32_t format_primary = DRM_FORMAT_ARGB8888;
997 uint32_t format_overlay = DRM_FORMAT_ARGB1555;
998
999 igt_plane_t *overlay =
1000 igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_OVERLAY);
1001
1002 igt_require(overlay);
1003 igt_require(igt_plane_has_prop(primary, IGT_PLANE_ZPOS));
1004 igt_require(igt_plane_has_prop(overlay, IGT_PLANE_ZPOS));
1005
1006 igt_require(igt_plane_has_format_mod(primary, format_primary, 0x0));
1007 igt_require(igt_plane_has_format_mod(overlay, format_overlay, 0x0));
1008
1009 igt_output_set_pipe(output, pipe);
1010 plane_primary_overlay_zpos(pipe_obj, output, primary, overlay,
1011 format_primary, format_overlay);
1012 }
1013
1014 igt_subtest("test_only") {
1015 atomic_clear(&display, pipe, primary, output);
1016
1017 test_only(pipe_obj, primary, output);
1018 }
1019 igt_subtest("plane_cursor_legacy") {
1020 igt_plane_t *cursor =
1021 igt_pipe_get_plane_type(pipe_obj, DRM_PLANE_TYPE_CURSOR);
1022
1023 igt_require(cursor);
1024
1025 atomic_setup(&display, pipe, output, primary, &fb);
1026 plane_cursor(pipe_obj, output, cursor);
1027 }
1028
1029 igt_subtest("plane_invalid_params") {
1030 atomic_setup(&display, pipe, output, primary, &fb);
1031
1032 plane_invalid_params(pipe_obj, output, primary, &fb);
1033 }
1034
1035 igt_subtest("plane_invalid_params_fence") {
1036 atomic_setup(&display, pipe, output, primary, &fb);
1037
1038 plane_invalid_params_fence(pipe_obj, output, primary);
1039 }
1040
1041 igt_subtest("crtc_invalid_params") {
1042 atomic_setup(&display, pipe, output, primary, &fb);
1043
1044 crtc_invalid_params(pipe_obj, output, primary, &fb);
1045 }
1046
1047 igt_subtest("crtc_invalid_params_fence") {
1048 atomic_setup(&display, pipe, output, primary, &fb);
1049
1050 crtc_invalid_params_fence(pipe_obj, output, primary, &fb);
1051 }
1052
1053 igt_subtest("atomic_invalid_params") {
1054 atomic_setup(&display, pipe, output, primary, &fb);
1055
1056 atomic_invalid_params(pipe_obj, primary, output, &fb);
1057 }
1058
1059 igt_fixture {
1060 atomic_clear(&display, pipe, primary, output);
1061 igt_remove_fb(display.drm_fd, &fb);
1062
1063 igt_display_fini(&display);
1064 }
1065 }
1066