blob: 900fd5ce9f799bf456549484391ca7895593f056 [file] [log] [blame]
Chris Wilson9579e542016-05-23 21:56:01 +01001/*
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 */
24
25#define _GNU_SOURCE
26#include <sched.h>
Chris Wilsond2adbdf2016-10-04 13:50:50 +010027#include <sys/poll.h>
Chris Wilson9579e542016-05-23 21:56:01 +010028
29#include "igt.h"
Chris Wilson376b8132016-07-03 09:42:38 +010030#include "igt_rand.h"
Chris Wilsonc74e0712016-05-24 16:24:15 +010031#include "igt_stats.h"
Chris Wilson9579e542016-05-23 21:56:01 +010032
Tomeu Vizoso047c9992016-06-07 10:18:34 +020033#if defined(__x86_64__) || defined(__i386__)
34#define cpu_relax() __builtin_ia32_pause()
35#else
36#define cpu_relax() asm volatile("": : :"memory")
37#endif
38
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +020039#ifndef DRM_CAP_CURSOR_WIDTH
40#define DRM_CAP_CURSOR_WIDTH 0x8
41#endif
42
43#ifndef DRM_CAP_CURSOR_HEIGHT
44#define DRM_CAP_CURSOR_HEIGHT 0x9
45#endif
46
Chris Wilson9579e542016-05-23 21:56:01 +010047IGT_TEST_DESCRIPTION("Stress legacy cursor ioctl");
48
Maarten Lankhorst6b985872016-07-13 14:59:02 +020049static void stress(igt_display_t *display,
50 int pipe, int num_children, unsigned mode,
Chris Wilsoncce2ff02016-05-25 08:34:25 +010051 int timeout)
Chris Wilson9579e542016-05-23 21:56:01 +010052{
Chris Wilson9579e542016-05-23 21:56:01 +010053 struct drm_mode_cursor arg;
Chris Wilsonc74e0712016-05-24 16:24:15 +010054 uint64_t *results;
Chris Wilsonf5d370c2016-06-04 21:25:17 +010055 bool torture;
Chris Wilson9579e542016-05-23 21:56:01 +010056 int n;
Maarten Lankhorst6b985872016-07-13 14:59:02 +020057 unsigned crtc_id[I915_MAX_PIPES], num_crtcs;
Chris Wilson9579e542016-05-23 21:56:01 +010058
Chris Wilsonf5d370c2016-06-04 21:25:17 +010059 torture = false;
60 if (num_children < 0) {
61 torture = true;
62 num_children = -num_children;
63 }
64
Chris Wilsonc74e0712016-05-24 16:24:15 +010065 results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
66 igt_assert(results != MAP_FAILED);
67
Chris Wilson9579e542016-05-23 21:56:01 +010068 memset(&arg, 0, sizeof(arg));
69 arg.flags = DRM_MODE_CURSOR_BO;
70 arg.crtc_id = 0;
71 arg.width = 64;
72 arg.height = 64;
Maarten Lankhorst6b985872016-07-13 14:59:02 +020073 arg.handle = kmstest_dumb_create(display->drm_fd, 64, 64, 32, NULL, NULL);
Chris Wilson9579e542016-05-23 21:56:01 +010074
Maarten Lankhorst6b985872016-07-13 14:59:02 +020075 if (pipe < 0) {
76 num_crtcs = display->n_pipes;
77 for_each_pipe(display, n) {
78 arg.crtc_id = crtc_id[n] = display->pipes[n].crtc_id;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +020079 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Maarten Lankhorst6b985872016-07-13 14:59:02 +020080 }
81 } else {
82 num_crtcs = 1;
83 arg.crtc_id = crtc_id[0] = display->pipes[pipe].crtc_id;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +020084 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Chris Wilsoncce2ff02016-05-25 08:34:25 +010085 }
Chris Wilson9579e542016-05-23 21:56:01 +010086
87 arg.flags = mode;
Chris Wilsondab6b6b2016-05-24 16:14:32 +010088 igt_fork(child, num_children) {
Chris Wilson9579e542016-05-23 21:56:01 +010089 struct sched_param rt = {.sched_priority = 99 };
90 cpu_set_t allowed;
91 unsigned long count = 0;
92
93 sched_setscheduler(getpid(), SCHED_RR, &rt);
94
95 CPU_ZERO(&allowed);
96 CPU_SET(child, &allowed);
97 sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
98
Chris Wilson376b8132016-07-03 09:42:38 +010099 hars_petruska_f54_1_random_perturb(child);
Chris Wilson9579e542016-05-23 21:56:01 +0100100 igt_until_timeout(timeout) {
Chris Wilson376b8132016-07-03 09:42:38 +0100101 arg.crtc_id = crtc_id[hars_petruska_f54_1_random_unsafe() % num_crtcs];
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200102 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Chris Wilson9579e542016-05-23 21:56:01 +0100103 count++;
104 }
105
Chris Wilsonc74e0712016-05-24 16:24:15 +0100106 igt_debug("[%d] count=%lu\n", child, count);
107 results[child] = count;
Chris Wilson9579e542016-05-23 21:56:01 +0100108 }
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100109 if (torture) {
110 igt_fork(child, num_children) {
111 struct sched_param rt = {.sched_priority = 1 };
112 cpu_set_t allowed;
113 unsigned long long count = 0;
114
115 sched_setscheduler(getpid(), SCHED_RR, &rt);
116
117 CPU_ZERO(&allowed);
118 CPU_SET(child, &allowed);
119 sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
120 igt_until_timeout(timeout) {
121 count++;
Tomeu Vizoso047c9992016-06-07 10:18:34 +0200122 cpu_relax();
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100123 }
124 igt_debug("[hog:%d] count=%llu\n", child, count);
125 }
126 }
Chris Wilson9579e542016-05-23 21:56:01 +0100127 igt_waitchildren();
128
Chris Wilsonc74e0712016-05-24 16:24:15 +0100129 if (num_children > 1) {
130 igt_stats_t stats;
131
132 igt_stats_init_with_size(&stats, num_children);
133 results[num_children] = 0;
134 for (int child = 0; child < num_children; child++) {
135 igt_stats_push(&stats, results[child]);
136 results[num_children] += results[child];
137 }
138 igt_info("Total updates %llu (median of %d processes is %.2f)\n",
139 (long long)results[num_children],
140 num_children,
141 igt_stats_get_median(&stats));
142 igt_stats_fini(&stats);
143 } else {
144 igt_info("Total updates %llu\n", (long long)results[0]);
145 }
146
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200147 gem_close(display->drm_fd, arg.handle);
Chris Wilsonc74e0712016-05-24 16:24:15 +0100148 munmap(results, 4096);
Chris Wilson9579e542016-05-23 21:56:01 +0100149}
150
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200151static igt_output_t *set_fb_on_crtc(igt_display_t *display, int pipe, struct igt_fb *fb_info)
Chris Wilson162d4562016-06-22 15:41:23 +0100152{
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200153 igt_output_t *output;
Chris Wilson162d4562016-06-22 15:41:23 +0100154
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200155 for_each_valid_output_on_pipe(display, pipe, output) {
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200156 drmModeModeInfoPtr mode;
157 igt_plane_t *primary;
Chris Wilson162d4562016-06-22 15:41:23 +0100158
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200159 if (output->pending_crtc_idx_mask)
Chris Wilson162d4562016-06-22 15:41:23 +0100160 continue;
161
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200162 igt_output_set_pipe(output, pipe);
163 mode = igt_output_get_mode(output);
164
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200165 igt_create_pattern_fb(display->drm_fd,
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200166 mode->hdisplay, mode->vdisplay,
167 DRM_FORMAT_XRGB8888, I915_TILING_NONE, fb_info);
168
Robert Fossa7864792017-01-10 19:21:26 -0500169 primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200170 igt_plane_set_fb(primary, fb_info);
171
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200172 return output;
Chris Wilson162d4562016-06-22 15:41:23 +0100173 }
174
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200175 return NULL;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200176}
177
178static void set_cursor_on_pipe(igt_display_t *display, enum pipe pipe, struct igt_fb *fb)
179{
180 igt_plane_t *plane, *cursor = NULL;
181
182 for_each_plane_on_pipe(display, pipe, plane) {
Robert Fossa7864792017-01-10 19:21:26 -0500183 if (plane->type != DRM_PLANE_TYPE_CURSOR)
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200184 continue;
185
186 cursor = plane;
187 break;
188 }
189
190 igt_require(cursor);
191 igt_plane_set_fb(cursor, fb);
192}
193
194static void populate_cursor_args(igt_display_t *display, enum pipe pipe,
195 struct drm_mode_cursor *arg, struct igt_fb *fb)
196{
197 arg->crtc_id = display->pipes[pipe].crtc_id;
198 arg->flags = DRM_MODE_CURSOR_MOVE;
199 arg->x = 128;
200 arg->y = 128;
201 arg->width = fb->width;
202 arg->height = fb->height;
203 arg->handle = fb->gem_handle;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200204 arg[1] = *arg;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200205}
206
207static void do_cleanup_display(igt_display_t *display)
208{
209 enum pipe pipe;
210 igt_output_t *output;
211 igt_plane_t *plane;
212
213 for_each_pipe(display, pipe)
214 for_each_plane_on_pipe(display, pipe, plane)
215 igt_plane_set_fb(plane, NULL);
216
217 for_each_connected_output(display, output)
218 igt_output_set_pipe(output, PIPE_NONE);
219
220 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100221}
222
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200223static enum pipe find_connected_pipe(igt_display_t *display, bool second)
224{
225 enum pipe pipe, first = PIPE_NONE;
226 igt_output_t *output;
227 igt_output_t *first_output = NULL;
228 bool found = false;
229
230 for_each_pipe_with_valid_output(display, pipe, output) {
231 if (first == pipe || output == first_output)
232 continue;
233
234 if (second) {
235 first = pipe;
236 first_output = output;
237 second = false;
238 continue;
239 }
240
241 found = true;
242 break;
243 }
244
245 if (first_output)
246 igt_require_f(found, "No second valid output found\n");
247 else
Chris Wilson1105d9f2016-08-23 18:03:51 +0100248 igt_require_f(found, "No valid outputs found\n");
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200249
250 return pipe;
251}
252
Robert Fossa7864792017-01-10 19:21:26 -0500253static void flip_nonblocking(igt_display_t *display, enum pipe pipe_id, bool atomic, struct igt_fb *fb)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200254{
Robert Fossa7864792017-01-10 19:21:26 -0500255 igt_pipe_t *pipe = &display->pipes[pipe_id];
256 igt_plane_t *primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200257
258 if (!atomic) {
259 /* Schedule a nonblocking flip for the next vblank */
Robert Fossa7864792017-01-10 19:21:26 -0500260 do_or_die(drmModePageFlip(display->drm_fd, pipe->crtc_id, fb->fb_id,
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200261 DRM_MODE_PAGE_FLIP_EVENT, fb));
262 } else {
263 igt_plane_set_fb(primary, fb);
264 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, fb);
265 }
266}
267
268enum flip_test {
269 flip_test_legacy = 0,
270 flip_test_varying_size,
271 flip_test_toggle_visibility,
272 flip_test_atomic,
273 flip_test_atomic_transitions,
274 flip_test_atomic_transitions_varying_size,
275 flip_test_last = flip_test_atomic_transitions_varying_size
276};
277
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100278static bool cursor_slowpath(enum flip_test mode)
279{
280 /* cursor moving doesn't take slowpath, everything else does. */
281 if (mode == flip_test_legacy || mode == flip_test_atomic)
282 return false;
283
284 return true;
285}
286
Maarten Lankhorstda0b6ab2017-01-23 16:37:01 +0100287/*
288 * On platforms with two-stage watermark programming
289 * changing sprite visibility may require a extra vblank wait.
290 *
291 * Handle this here.
292 */
293static bool mode_requires_extra_vblank(enum flip_test mode)
294{
295 if (mode == flip_test_atomic_transitions ||
296 mode == flip_test_atomic_transitions_varying_size)
297 return true;
298
299 return false;
300}
301
Robert Fossa7864792017-01-10 19:21:26 -0500302static void transition_nonblocking(igt_display_t *display, enum pipe pipe_id,
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200303 struct igt_fb *prim_fb, struct igt_fb *argb_fb,
304 bool hide_sprite)
305{
Robert Fossa7864792017-01-10 19:21:26 -0500306 igt_pipe_t *pipe = &display->pipes[pipe_id];
307 igt_plane_t *primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
308 igt_plane_t *sprite = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_OVERLAY);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200309
310 if (hide_sprite) {
311 igt_plane_set_fb(primary, prim_fb);
312 igt_plane_set_fb(sprite, NULL);
313 } else {
Maarten Lankhorsta36e6272017-01-16 13:35:39 +0100314 int ret;
315
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200316 igt_plane_set_fb(primary, NULL);
317 igt_plane_set_fb(sprite, argb_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200318
Maarten Lankhorsta36e6272017-01-16 13:35:39 +0100319 ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
320 if (!ret)
321 return;
322
323 igt_assert(ret == -EINVAL);
324
325 igt_plane_set_fb(sprite, prim_fb);
326 }
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200327 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
328}
329
330static void prepare_flip_test(igt_display_t *display,
331 enum flip_test mode,
332 enum pipe flip_pipe,
333 enum pipe cursor_pipe,
334 struct drm_mode_cursor *arg,
335 const struct igt_fb *prim_fb,
336 struct igt_fb *argb_fb,
337 struct igt_fb *cursor_fb2)
338{
339 argb_fb->gem_handle = 0;
340 cursor_fb2->gem_handle = 0;
341
342 if (mode == flip_test_varying_size ||
343 mode == flip_test_atomic_transitions_varying_size) {
344 uint64_t width, height;
345
346 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_WIDTH, &width));
347 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height));
348
349 igt_skip_on(width <= 64 && height <= 64);
350 igt_create_color_fb(display->drm_fd, width, height,
351 DRM_FORMAT_ARGB8888, 0, 1., 0., .7, cursor_fb2);
352
353 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
354 arg[1].handle = cursor_fb2->gem_handle;
355 arg[1].width = width;
356 arg[1].height = height;
357 }
358
359 if (mode == flip_test_legacy ||
360 mode == flip_test_atomic) {
361 arg[1].x = 192;
362 arg[1].y = 192;
363 }
364
365 if (mode == flip_test_toggle_visibility) {
366 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
367 arg[1].handle = 0;
368 arg[1].width = arg[1].height = 0;
369 }
370
371 if (mode == flip_test_atomic_transitions ||
372 mode == flip_test_atomic_transitions_varying_size) {
373 igt_require(display->pipes[flip_pipe].n_planes > 1 &&
Robert Fossa7864792017-01-10 19:21:26 -0500374 display->pipes[flip_pipe].planes[1].type != DRM_PLANE_TYPE_CURSOR);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200375
376 igt_create_color_pattern_fb(display->drm_fd, prim_fb->width, prim_fb->height,
377 DRM_FORMAT_ARGB8888, 0, .1, .1, .1, argb_fb);
378 }
379}
380
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200381static void flip(igt_display_t *display,
Chris Wilson162d4562016-06-22 15:41:23 +0100382 int cursor_pipe, int flip_pipe,
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200383 int timeout, enum flip_test mode)
Chris Wilson162d4562016-06-22 15:41:23 +0100384{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200385 struct drm_mode_cursor arg[2];
Chris Wilson162d4562016-06-22 15:41:23 +0100386 uint64_t *results;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200387 struct igt_fb fb_info, fb_info2, argb_fb, cursor_fb, cursor_fb2;
Chris Wilson162d4562016-06-22 15:41:23 +0100388
389 results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
390 igt_assert(results != MAP_FAILED);
391
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200392 flip_pipe = find_connected_pipe(display, !!flip_pipe);
393 cursor_pipe = find_connected_pipe(display, !!cursor_pipe);
394
395 igt_info("Using pipe %s for page flip, pipe %s for cursor\n",
396 kmstest_pipe_name(flip_pipe), kmstest_pipe_name(cursor_pipe));
397
398 if (mode >= flip_test_atomic)
399 igt_require(display->is_atomic);
400
401 igt_require(set_fb_on_crtc(display, flip_pipe, &fb_info));
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200402 if (flip_pipe != cursor_pipe)
403 igt_require(set_fb_on_crtc(display, cursor_pipe, &fb_info2));
Chris Wilson162d4562016-06-22 15:41:23 +0100404
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200405 igt_create_color_fb(display->drm_fd, fb_info.width, fb_info.height, DRM_FORMAT_ARGB8888, 0, .5, .5, .5, &cursor_fb);
406
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200407 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
408 set_cursor_on_pipe(display, cursor_pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200409 populate_cursor_args(display, cursor_pipe, arg, &cursor_fb);
410
411 prepare_flip_test(display, mode, flip_pipe, cursor_pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100412
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200413 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100414
Chris Wilson162d4562016-06-22 15:41:23 +0100415 igt_fork(child, 1) {
416 unsigned long count = 0;
417
418 igt_until_timeout(timeout) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200419 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[(count & 64)/64]);
Chris Wilson162d4562016-06-22 15:41:23 +0100420 count++;
421 }
422
423 igt_debug("cursor count=%lu\n", count);
424 results[0] = count;
425 }
426 igt_fork(child, 1) {
427 unsigned long count = 0;
Chris Wilson162d4562016-06-22 15:41:23 +0100428
429 igt_until_timeout(timeout) {
430 char buf[128];
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200431
432 switch (mode) {
433 default:
434 flip_nonblocking(display, flip_pipe, mode >= flip_test_atomic, &fb_info);
435 break;
436 case flip_test_atomic_transitions:
437 case flip_test_atomic_transitions_varying_size:
438 transition_nonblocking(display, flip_pipe, &fb_info, &argb_fb, count & 1);
439 break;
440 }
441
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200442 while (read(display->drm_fd, buf, sizeof(buf)) < 0 &&
Chris Wilsond86d6eb2016-06-23 21:07:36 +0100443 (errno == EINTR || errno == EAGAIN))
444 ;
Chris Wilson162d4562016-06-22 15:41:23 +0100445 count++;
446 }
447
448 igt_debug("flip count=%lu\n", count);
449 results[1] = count;
450 }
451 igt_waitchildren();
452
Chris Wilson162d4562016-06-22 15:41:23 +0100453 munmap(results, 4096);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200454
455 do_cleanup_display(display);
456
457 igt_remove_fb(display->drm_fd, &fb_info);
458 if (flip_pipe != cursor_pipe)
459 igt_remove_fb(display->drm_fd, &fb_info2);
460 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200461 if (argb_fb.gem_handle)
462 igt_remove_fb(display->drm_fd, &argb_fb);
463 if (cursor_fb2.gem_handle)
464 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100465}
466
467static inline uint32_t pipe_select(int pipe)
468{
469 if (pipe > 1)
470 return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
471 else if (pipe > 0)
472 return DRM_VBLANK_SECONDARY;
473 else
474 return 0;
475}
476
477static unsigned get_vblank(int fd, int pipe, unsigned flags)
478{
479 union drm_wait_vblank vbl;
480
481 memset(&vbl, 0, sizeof(vbl));
482 vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe) | flags;
483 if (drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
484 return 0;
485
486 return vbl.reply.sequence;
487}
488
Chris Wilson237cb892016-09-13 11:37:41 +0100489enum basic_flip_cursor {
490 FLIP_BEFORE_CURSOR,
491 FLIP_AFTER_CURSOR
492};
493
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100494static uint32_t *make_busy(int fd, uint32_t target)
495{
496 const int gen = intel_gen(intel_get_drm_devid(fd));
497 struct drm_i915_gem_exec_object2 obj[2];
498 struct drm_i915_gem_relocation_entry reloc[2];
499 struct drm_i915_gem_execbuffer2 execbuf;
500 uint32_t *batch;
501 int i;
502
503 memset(&execbuf, 0, sizeof(execbuf));
504 execbuf.buffers_ptr = (uintptr_t)obj;
505 execbuf.buffer_count = 2;
506
507 memset(obj, 0, sizeof(obj));
508 obj[0].handle = target;
509 obj[1].handle = gem_create(fd, 4096);
510 batch = gem_mmap__wc(fd, obj[1].handle, 0, 4096, PROT_WRITE);
511 gem_set_domain(fd, obj[1].handle,
512 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
513
514
515 obj[1].relocs_ptr = (uintptr_t)reloc;
516 obj[1].relocation_count = 2;
517 memset(reloc, 0, sizeof(reloc));
518
519 reloc[0].target_handle = obj[1].handle; /* recurse */
520 reloc[0].presumed_offset = 0;
521 reloc[0].offset = sizeof(uint32_t);
522 reloc[0].delta = 0;
523 reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;
524 reloc[0].write_domain = 0;
525
526 reloc[1].target_handle = target;
527 reloc[1].presumed_offset = 0;
528 reloc[1].offset = 1024;
529 reloc[1].delta = 0;
530 reloc[1].read_domains = I915_GEM_DOMAIN_COMMAND;
531 reloc[1].write_domain = I915_GEM_DOMAIN_COMMAND;
532
533 i = 0;
534 batch[i] = MI_BATCH_BUFFER_START;
535 if (gen >= 8) {
536 batch[i] |= 1 << 8 | 1;
537 batch[++i] = 0;
538 batch[++i] = 0;
539 } else if (gen >= 6) {
540 batch[i] |= 1 << 8;
541 batch[++i] = 0;
542 } else {
543 batch[i] |= 2 << 6;
544 batch[++i] = 0;
545 if (gen < 4) {
546 batch[i] |= 1;
547 reloc[0].delta = 1;
548 }
549 }
550 i++;
551
552 gem_execbuf(fd, &execbuf);
553 gem_close(fd, obj[1].handle);
554
555 return batch;
556}
557
Chris Wilson18cd7962016-10-05 19:31:27 +0100558static void cancel_busy(uint32_t *busy)
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100559{
560 *busy = MI_BATCH_BUFFER_END;
561 munmap(busy, 4096);
562}
563
Chris Wilson18cd7962016-10-05 19:31:27 +0100564static uint32_t *
565make_fb_busy(int fd, const struct igt_fb *fb)
566{
567 uint32_t *busy;
568
569 busy = make_busy(fd, fb->gem_handle);
570 igt_assert(gem_bo_busy(fd, fb->gem_handle));
571
572 return busy;
573}
574
575static void finish_fb_busy(uint32_t *busy)
576{
577 cancel_busy(busy);
578}
579
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100580#define BASIC_BUSY 0x1
581
Chris Wilson237cb892016-09-13 11:37:41 +0100582static void basic_flip_cursor(igt_display_t *display,
583 enum flip_test mode,
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100584 enum basic_flip_cursor order,
585 unsigned flags)
Chris Wilson237cb892016-09-13 11:37:41 +0100586{
587 struct drm_mode_cursor arg[2];
588 struct drm_event_vblank vbl;
589 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
590 unsigned vblank_start;
591 enum pipe pipe = find_connected_pipe(display, false);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100592 uint32_t *busy;
Chris Wilson237cb892016-09-13 11:37:41 +0100593
594 if (mode >= flip_test_atomic)
595 igt_require(display->is_atomic);
596
597 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
598
599 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
600 set_cursor_on_pipe(display, pipe, &cursor_fb);
601 populate_cursor_args(display, pipe, arg, &cursor_fb);
602
603 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
604
605 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
606
607 /* Quick sanity check that we can update a cursor in a single vblank */
608 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
609 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
610 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
611 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
612
613 /* Bind the cursor first to warm up */
614 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
615
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100616 busy = NULL;
617 if (flags & BASIC_BUSY)
Chris Wilson18cd7962016-10-05 19:31:27 +0100618 busy = make_fb_busy(display->drm_fd, &fb_info);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100619
Ville Syrjäläd08d2632017-03-14 19:32:08 +0200620 /* Start with a synchronous query to align with the vblank */
621 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
622
Chris Wilson237cb892016-09-13 11:37:41 +0100623 switch (order) {
624 case FLIP_BEFORE_CURSOR:
625 switch (mode) {
626 default:
627 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
628 break;
629 case flip_test_atomic_transitions:
630 case flip_test_atomic_transitions_varying_size:
631 transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
632 break;
633 }
634 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
635
636 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Chris Wilson237cb892016-09-13 11:37:41 +0100637 break;
638
639 case FLIP_AFTER_CURSOR:
640 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
641 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
642
643 switch (mode) {
644 default:
645 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
646 break;
647 case flip_test_atomic_transitions:
648 case flip_test_atomic_transitions_varying_size:
649 transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
650 break;
651 }
Chris Wilson237cb892016-09-13 11:37:41 +0100652 }
653
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100654 if (!cursor_slowpath(mode))
655 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
656 else
657 igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
658
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100659 if (busy) {
660 struct pollfd pfd = { display->drm_fd, POLLIN };
661 igt_assert(poll(&pfd, 1, 0) == 0);
Chris Wilson18cd7962016-10-05 19:31:27 +0100662 finish_fb_busy(busy);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100663 }
664
Chris Wilson237cb892016-09-13 11:37:41 +0100665 igt_set_timeout(1, "Stuck page flip");
666 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
Maarten Lankhorstda0b6ab2017-01-23 16:37:01 +0100667
668 if (!mode_requires_extra_vblank(mode))
669 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
670 else
671 igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 2);
672
Chris Wilson237cb892016-09-13 11:37:41 +0100673 igt_reset_timeout();
674
675 do_cleanup_display(display);
676 igt_remove_fb(display->drm_fd, &fb_info);
677 igt_remove_fb(display->drm_fd, &cursor_fb);
678
679 if (argb_fb.gem_handle)
680 igt_remove_fb(display->drm_fd, &argb_fb);
681 if (cursor_fb2.gem_handle)
682 igt_remove_fb(display->drm_fd, &cursor_fb2);
683}
684
Maarten Lankhorstad718612016-12-27 13:50:31 +0100685static int
686get_cursor_updates_per_vblank(igt_display_t *display, enum pipe pipe,
687 struct drm_mode_cursor *arg)
688{
689 int target;
690
691 for (target = 65536; target; target /= 2) {
692 unsigned vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
693
694 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
695
696 for (int n = 0; n < target; n++)
697 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, arg);
698 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
699 break;
700 }
701
702 /*
703 * Divide by 4, to handle variations in amount of vblanks
704 * caused by cpufreq throttling.
705 */
706 target /= 4;
707 igt_require(target > 1);
708
709 igt_debug("Using a target of %d cursor updates per quarter-vblank\n", target);
710
711 return target;
712}
713
Chris Wilson237cb892016-09-13 11:37:41 +0100714static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloops)
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200715{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200716 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100717 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200718 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson162d4562016-06-22 15:41:23 +0100719 unsigned vblank_start;
Maarten Lankhorste5e8b7c2017-01-03 11:31:04 +0100720 int target, cpu;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200721 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorste5e8b7c2017-01-03 11:31:04 +0100722 volatile unsigned long *shared;
723 cpu_set_t mask, oldmask;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200724
725 if (mode >= flip_test_atomic)
726 igt_require(display->is_atomic);
Chris Wilson162d4562016-06-22 15:41:23 +0100727
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200728 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Chris Wilson162d4562016-06-22 15:41:23 +0100729
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200730 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200731 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200732 populate_cursor_args(display, pipe, arg, &cursor_fb);
733
734 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100735
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200736 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100737
Maarten Lankhorstad718612016-12-27 13:50:31 +0100738 if (nloops)
739 target = get_cursor_updates_per_vblank(display, pipe, &arg[0]);
740 else
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100741 target = 1;
Chris Wilson162d4562016-06-22 15:41:23 +0100742
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200743 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
744 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200745 for (int n = 0; n < target; n++)
746 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200747 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson162d4562016-06-22 15:41:23 +0100748
Maarten Lankhorste5e8b7c2017-01-03 11:31:04 +0100749 /*
750 * There are variations caused by using cpu frequency changing. To
751 * eliminate those we force this test to run on the same cpu as an
752 * idle thread that does a busy loop of sched_yield(); The effect is
753 * that we don't throttle the cpu to a lower frequency, and the
754 * variations caused by cpu speed changing are eliminated.
755 */
756 if (target > 1) {
757 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
758 igt_assert(shared != MAP_FAILED);
759
760 cpu = sched_getcpu();
761 igt_assert(cpu >= 0);
762
763 CPU_ZERO(&mask);
764 CPU_SET(cpu, &mask);
765 sched_getaffinity(0, sizeof(oldmask), &oldmask);
766 sched_setaffinity(0, sizeof(mask), &mask);
767
768 shared[0] = 0;
769
770 igt_fork(child, 1) {
771 struct sched_param parm = { .sched_priority = 0 };
772
773 igt_assert(sched_setscheduler(0, SCHED_IDLE, &parm) == 0);
774
775 while (!shared[0])
776 sched_yield();
777 }
778 }
779
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100780 do {
781 /* Bind the cursor first to warm up */
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200782 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson162d4562016-06-22 15:41:23 +0100783
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100784 /* Start with a synchronous query to align with the vblank */
785 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200786 switch (mode) {
787 default:
788 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
789 break;
790 case flip_test_atomic_transitions:
791 case flip_test_atomic_transitions_varying_size:
792 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (nloops & 2) /2);
793 break;
794 }
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100795
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100796 /* The nonblocking flip should not have delayed us */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200797 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100798 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200799 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100800
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100801 /* Nor should it have delayed the following cursor update */
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100802 if (!cursor_slowpath(mode))
803 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
804 else
805 igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100806
807 igt_set_timeout(1, "Stuck page flip");
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200808 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
Maarten Lankhorstda0b6ab2017-01-23 16:37:01 +0100809
810 if (!mode_requires_extra_vblank(mode))
811 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
812 else
813 igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 2);
814
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100815 igt_reset_timeout();
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100816 } while (nloops--);
Chris Wilson162d4562016-06-22 15:41:23 +0100817
Maarten Lankhorste5e8b7c2017-01-03 11:31:04 +0100818 if (target > 1) {
819 shared[0] = 1;
820 igt_waitchildren();
821 munmap((void *)shared, 4096);
822 sched_setaffinity(0, sizeof(oldmask), &oldmask);
823 }
824
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200825 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200826 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200827 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200828
829 if (argb_fb.gem_handle)
830 igt_remove_fb(display->drm_fd, &argb_fb);
831 if (cursor_fb2.gem_handle)
832 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100833}
834
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200835static bool skip_on_unsupported_nonblocking_modeset(igt_display_t *display)
836{
837 enum pipe pipe;
838 int ret;
839
840 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
841
842 ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
843
844 if (ret == -EINVAL)
845 return true;
846
847 igt_assert_eq(ret, 0);
848
849 /* Force the next state to update all crtc's, to synchronize with the nonblocking modeset. */
850 for_each_pipe(display, pipe)
851 display->pipes[pipe].mode_changed = true;
852
853 return false;
854}
855
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100856static void nonblocking_modeset_vs_cursor(igt_display_t *display, int loops)
857{
858 struct igt_fb fb_info, cursor_fb;
859 igt_output_t *output;
860 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100861 struct drm_mode_cursor arg[2];
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100862 bool skip_test;
863 igt_plane_t *cursor = NULL, *plane;
864
865 igt_require(display->is_atomic);
866 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
867 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
868 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100869 populate_cursor_args(display, pipe, arg, &cursor_fb);
870 arg[0].flags |= DRM_MODE_CURSOR_BO;
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100871
872 for_each_plane_on_pipe(display, pipe, plane) {
Robert Fossa7864792017-01-10 19:21:26 -0500873 if (plane->type != DRM_PLANE_TYPE_CURSOR)
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100874 continue;
875
876 cursor = plane;
877 break;
878 }
879
880 igt_skip_on(!cursor);
881
882 if ((skip_test = skip_on_unsupported_nonblocking_modeset(display)))
883 goto cleanup;
884
885 /*
886 * Start disabled, because skip_on_unsupported_nonblocking_modeset
887 * will have enabled this pipe. No way around it, since the first
888 * atomic commit may be unreliable with amount of events sent.
889 */
890 igt_output_set_pipe(output, PIPE_NONE);
891 igt_display_commit2(display, COMMIT_ATOMIC);
892
893 while (loops--) {
894 unsigned flags;
895 struct pollfd pfd = { display->drm_fd, POLLIN };
896 struct drm_event_vblank vbl;
897
898 flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
899 flags |= DRM_MODE_ATOMIC_NONBLOCK;
900 flags |= DRM_MODE_PAGE_FLIP_EVENT;
901
902 /*
903 * Test that a cursor update after a nonblocking modeset
904 * works as intended. It should block until the modeset completes.
905 */
906
907 igt_output_set_pipe(output, pipe);
908 igt_plane_set_fb(cursor, NULL);
909 igt_display_commit_atomic(display, flags, NULL);
910
911 igt_assert_eq(0, poll(&pfd, 1, 0));
912 igt_assert_eq(0, pfd.revents);
913
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100914 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100915
916 igt_assert_eq(1, poll(&pfd, 1, 0));
917 igt_assert_eq(POLLIN, pfd.revents);
918
919 igt_set_timeout(1, "Stuck page flip");
920 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
921 igt_reset_timeout();
922
923 igt_output_set_pipe(output, PIPE_NONE);
924 igt_display_commit_atomic(display, flags, NULL);
925
926 igt_assert_eq(0, poll(&pfd, 1, 0));
927 igt_assert_eq(0, pfd.revents);
928
929 /* Same for cursor on disabled crtc. */
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +0100930 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100931
932 igt_assert_eq(1, poll(&pfd, 1, 0));
933 igt_assert_eq(POLLIN, pfd.revents);
934
935 igt_set_timeout(1, "Stuck page flip");
936 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
937 igt_reset_timeout();
938 }
939
940cleanup:
941 do_cleanup_display(display);
942 igt_remove_fb(display->drm_fd, &fb_info);
943 igt_remove_fb(display->drm_fd, &cursor_fb);
944
945 if (skip_test)
946 igt_skip("Nonblocking modeset is not supported by this kernel\n");
947}
948
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100949static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset, bool atomic)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200950{
951 struct drm_mode_cursor arg[2], arg2[2];
952 struct drm_event_vblank vbl;
953 struct igt_fb fb_info, fb2_info, cursor_fb;
954 unsigned vblank_start;
955 enum pipe pipe = find_connected_pipe(display, false);
956 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100957 igt_output_t *output, *output2;
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200958 bool skip_test = false;
959
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100960 igt_fail_on(modeset && !atomic);
961
962 if (atomic)
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200963 igt_require(display->is_atomic);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200964
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100965 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200966 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200967
968 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
969 set_cursor_on_pipe(display, pipe, &cursor_fb);
970 populate_cursor_args(display, pipe, arg, &cursor_fb);
971
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100972 arg[1].x = arg[1].y = 192;
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200973
974 set_cursor_on_pipe(display, pipe2, &cursor_fb);
975 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
976
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100977 arg2[1].x = arg2[1].y = 192;
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200978
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200979 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
980 goto cleanup;
981
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200982 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
983
984 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
985 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
986 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
987 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
988 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
989
990 while (nloops--) {
991 /* Start with a synchronous query to align with the vblank */
992 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
993 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
994
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +0100995 if (!modeset)
996 flip_nonblocking(display, pipe, false, &fb_info);
997 else {
998 /*
999 * There are 2 design issues that prevent us from doing
1000 * the test we would like here:
1001 *
1002 * - drm_event_vblank doesn't set crtc_id, so if we
1003 * use events we don't know which pipe fired the event,
1004 * no way to distinguish.
1005 * - Doing a modeset may add unrelated pipes, and fail with
1006 * -EBUSY if a page flip is queued on one of those.
1007 *
1008 * Work around it by not setting an event, but doing a synchronous
1009 * commit to wait for completion, and queue the page flip and modeset
1010 * in the same commit.
1011 */
1012
Robert Fossa7864792017-01-10 19:21:26 -05001013 igt_plane_set_fb(igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY), &fb_info);
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001014 igt_output_set_pipe(output2, (nloops & 1) ? PIPE_NONE : pipe2);
1015 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
1016 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001017
1018 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1019
1020 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001021 if (!modeset) {
1022 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
1023 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
1024 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001025
1026 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1027
1028 igt_set_timeout(1, "Stuck page flip");
1029 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1030 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
1031 igt_reset_timeout();
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001032 } else {
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001033 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001034 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001035
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001036 if (modeset) {
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001037 /* wait for pending modeset and page flip to complete, to prevent -EBUSY */
1038 display->pipes[pipe].mode_changed = true;
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001039 display->pipes[pipe2].mode_changed = true;
1040 igt_display_commit2(display, COMMIT_ATOMIC);
1041 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001042 }
1043
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001044cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001045 do_cleanup_display(display);
1046 igt_remove_fb(display->drm_fd, &fb_info);
1047 igt_remove_fb(display->drm_fd, &fb2_info);
1048 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001049
1050 if (skip_test)
1051 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001052}
1053
Chris Wilson237cb892016-09-13 11:37:41 +01001054static void cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloops)
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001055{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001056 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001057 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001058 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001059 unsigned vblank_start, vblank_last;
1060 volatile unsigned long *shared;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001061 long target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001062 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001063 igt_output_t *output;
1064 uint32_t vrefresh;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001065
1066 if (mode >= flip_test_atomic)
1067 igt_require(display->is_atomic);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001068
1069 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1070 igt_assert(shared != MAP_FAILED);
1071
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001072 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
1073 vrefresh = igt_output_get_mode(output)->vrefresh;
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001074
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001075 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +02001076 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001077 populate_cursor_args(display, pipe, arg, &cursor_fb);
1078
1079 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001080
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001081 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001082
Maarten Lankhorstad718612016-12-27 13:50:31 +01001083 target = get_cursor_updates_per_vblank(display, pipe, &arg[0]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001084
1085 for (int i = 0; i < nloops; i++) {
1086 shared[0] = 0;
1087 igt_fork(child, 1) {
1088 unsigned long count = 0;
1089 while (!shared[0]) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001090 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001091 count++;
1092 }
1093 igt_debug("child: %lu cursor updates\n", count);
1094 shared[0] = count;
1095 }
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001096
1097 switch (mode) {
1098 default:
1099 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
1100 break;
1101 case flip_test_atomic_transitions:
1102 case flip_test_atomic_transitions_varying_size:
1103 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (i & 2) >> 1);
1104 break;
1105 }
1106
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001107 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001108 vblank_start = vblank_last = vbl.sequence;
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001109 for (int n = 0; n < vrefresh / 2; n++) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001110 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
1111
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001112 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001113 if (vbl.sequence != vblank_last + 1) {
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +01001114 igt_info("page flip %d was delayed, missed %d frames\n",
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001115 n, vbl.sequence - vblank_last - 1);
1116 }
1117 vblank_last = vbl.sequence;
1118 }
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001119
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +01001120 if (!cursor_slowpath(mode))
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001121 igt_assert_lte(vbl.sequence, vblank_start + 5 * vrefresh / 8);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001122
1123 shared[0] = 1;
1124 igt_waitchildren();
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001125 igt_assert_f(shared[0] > vrefresh*target / 2,
1126 "completed %lu cursor updated in a period of %u flips, "
1127 "we expect to complete approximately %lu updates, "
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001128 "with the threshold set at %lu\n",
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001129 shared[0], vrefresh / 2,
1130 vrefresh*target, vrefresh*target / 2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001131 }
1132
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001133 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001134 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001135 igt_remove_fb(display->drm_fd, &cursor_fb);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001136 munmap((void *)shared, 4096);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001137 if (argb_fb.gem_handle)
1138 igt_remove_fb(display->drm_fd, &argb_fb);
1139 if (cursor_fb2.gem_handle)
1140 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +01001141}
1142
Maarten Lankhorst39660182017-01-17 17:07:52 +01001143static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool atomic)
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001144{
Maarten Lankhorst39660182017-01-17 17:07:52 +01001145 struct drm_mode_cursor arg[2][2];
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001146 struct drm_event_vblank vbl;
Maarten Lankhorst39660182017-01-17 17:07:52 +01001147 struct igt_fb fb_info[2], cursor_fb;
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001148 volatile unsigned long *shared;
Maarten Lankhorst39660182017-01-17 17:07:52 +01001149 int target[2];
1150 enum pipe pipe[2] = {
1151 find_connected_pipe(display, false),
1152 find_connected_pipe(display, true)
1153 };
1154 igt_output_t *outputs[2];
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001155
1156 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1157 igt_assert(shared != MAP_FAILED);
1158
Maarten Lankhorst39660182017-01-17 17:07:52 +01001159 if (atomic)
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001160 igt_require(display->is_atomic);
1161
Maarten Lankhorst39660182017-01-17 17:07:52 +01001162 igt_require((outputs[0] = set_fb_on_crtc(display, pipe[0], &fb_info[0])));
1163 igt_require((outputs[1] = set_fb_on_crtc(display, pipe[1], &fb_info[1])));
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001164
1165 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001166
Maarten Lankhorst39660182017-01-17 17:07:52 +01001167 set_cursor_on_pipe(display, pipe[0], &cursor_fb);
1168 populate_cursor_args(display, pipe[0], arg[0], &cursor_fb);
1169 arg[0][1].x = arg[0][1].y = 192;
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001170
Maarten Lankhorst39660182017-01-17 17:07:52 +01001171 set_cursor_on_pipe(display, pipe[1], &cursor_fb);
1172 populate_cursor_args(display, pipe[1], arg[1], &cursor_fb);
1173 arg[1][1].x = arg[1][1].y = 192;
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001174
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001175 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1176
Maarten Lankhorst39660182017-01-17 17:07:52 +01001177 target[0] = get_cursor_updates_per_vblank(display, pipe[0], &arg[0][0]);
1178 target[1] = get_cursor_updates_per_vblank(display, pipe[1], &arg[1][0]);
Maarten Lankhorstad718612016-12-27 13:50:31 +01001179
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001180 for (int i = 0; i < nloops; i++) {
Maarten Lankhorst39660182017-01-17 17:07:52 +01001181 unsigned long vrefresh[2];
1182 unsigned vblank_start[2], vblank_last[2];
1183 int done[2] = {};
1184
1185 vrefresh[0] = igt_output_get_mode(outputs[0])->vrefresh;
1186 vrefresh[1] = igt_output_get_mode(outputs[1])->vrefresh;
1187
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001188 shared[0] = 0;
Maarten Lankhorst39660182017-01-17 17:07:52 +01001189 shared[1] = 0;
1190 igt_fork(child, 2) {
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001191 unsigned long count = 0;
1192
Maarten Lankhorst39660182017-01-17 17:07:52 +01001193 while (!shared[child]) {
1194 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[child][(i >> child) & 1]);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001195 count++;
1196 }
Maarten Lankhorst39660182017-01-17 17:07:52 +01001197 igt_debug("child %i: %lu cursor updates\n", child, count);
1198 shared[child] = count;
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001199 }
1200
Maarten Lankhorst39660182017-01-17 17:07:52 +01001201 flip_nonblocking(display, pipe[0], atomic, &fb_info[0]);
1202 flip_nonblocking(display, pipe[1], atomic, &fb_info[1]);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001203
Maarten Lankhorst39660182017-01-17 17:07:52 +01001204 for (int n = 0; n < vrefresh[0] / 2 + vrefresh[1] / 2; n++) {
1205 int child;
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001206
1207 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Maarten Lankhorst39660182017-01-17 17:07:52 +01001208 child = vbl.user_data == (unsigned long)&fb_info[1];
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001209
Maarten Lankhorst39660182017-01-17 17:07:52 +01001210 if (!done[child]++)
1211 vblank_start[child] = vbl.sequence;
1212 else if (vbl.sequence != vblank_last[child] + 1)
1213 igt_info("page flip %d was delayed, missed %d frames\n",
1214 done[child], vbl.sequence - vblank_last[child] - 1);
1215
1216 vblank_last[child] = vbl.sequence;
1217
1218 if (done[child] < vrefresh[child] / 2) {
1219 flip_nonblocking(display, pipe[child], atomic, &fb_info[child]);
1220 } else {
1221 igt_assert_lte(vbl.sequence, vblank_start[child] + 5 * vrefresh[child] / 8);
1222
1223 shared[child] = 1;
1224 }
1225 }
1226
1227 igt_assert_eq(done[0], vrefresh[0] / 2);
1228 igt_assert_eq(done[1], vrefresh[1] / 2);
1229
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001230 igt_waitchildren();
Maarten Lankhorst39660182017-01-17 17:07:52 +01001231 for (int child = 0; child < 2; child++)
1232 igt_assert_f(shared[child] > vrefresh[child]*target[child] / 2,
1233 "completed %lu cursor updated in a period of %lu flips, "
1234 "we expect to complete approximately %lu updates, "
1235 "with the threshold set at %lu\n",
1236 shared[child], vrefresh[child] / 2,
1237 vrefresh[child]*target[child], vrefresh[child]*target[child] / 2);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001238 }
1239
1240 do_cleanup_display(display);
Maarten Lankhorst39660182017-01-17 17:07:52 +01001241 igt_remove_fb(display->drm_fd, &fb_info[0]);
1242 igt_remove_fb(display->drm_fd, &fb_info[1]);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001243 igt_remove_fb(display->drm_fd, &cursor_fb);
1244 munmap((void *)shared, 4096);
1245}
1246
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +01001247static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001248{
1249 struct drm_mode_cursor arg[2];
1250 struct drm_event_vblank vbl;
1251 struct igt_fb fb_info, cursor_fb;
1252 unsigned vblank_start;
1253 enum pipe pipe = find_connected_pipe(display, false);
1254 igt_pipe_crc_t *pipe_crc;
1255 igt_crc_t crcs[3];
1256
1257 if (atomic)
1258 igt_require(display->is_atomic);
1259
1260 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
1261
1262 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1263 populate_cursor_args(display, pipe, arg, &cursor_fb);
1264
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001265 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1266
Chris Wilson83884e92017-03-21 17:16:03 +00001267 pipe_crc = igt_pipe_crc_new(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001268
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001269 set_cursor_on_pipe(display, pipe, &cursor_fb);
1270 igt_display_commit2(display, COMMIT_UNIVERSAL);
1271
Maarten Lankhorst4f086662016-12-08 10:56:13 +01001272 /* Collect reference crcs, crcs[0] last. */
1273 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[1]);
1274 igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001275
Maarten Lankhorst4f086662016-12-08 10:56:13 +01001276 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001277 igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1278
1279 /* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1280 for (int i = 1; i >= 0; i--) {
1281 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1282
1283 flip_nonblocking(display, pipe, atomic, &fb_info);
1284 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1285
1286 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1287
1288 igt_set_timeout(1, "Stuck page flip");
1289 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1290 igt_reset_timeout();
1291
1292 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
1293
1294 igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
1295
1296 igt_assert_crc_equal(&crcs[i], &crcs[2]);
1297 }
1298
1299 do_cleanup_display(display);
1300 igt_remove_fb(display->drm_fd, &fb_info);
1301 igt_remove_fb(display->drm_fd, &cursor_fb);
1302 igt_pipe_crc_free(pipe_crc);
1303}
1304
1305static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001306{
1307 struct drm_mode_cursor arg[2];
1308 struct drm_event_vblank vbl;
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001309 struct igt_fb fb_info[2], cursor_fb;
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001310 unsigned vblank_start;
1311 enum pipe pipe = find_connected_pipe(display, false);
1312 igt_pipe_crc_t *pipe_crc;
Robert Fossa7864792017-01-10 19:21:26 -05001313 igt_pipe_t *pipe_connected = &display->pipes[pipe];
1314 igt_plane_t *plane_primary = igt_pipe_get_plane_type(pipe_connected, DRM_PLANE_TYPE_PRIMARY);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001315 igt_crc_t crcs[3];
1316
1317 if (atomic)
1318 igt_require(display->is_atomic);
1319
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001320 igt_require(set_fb_on_crtc(display, pipe, &fb_info[0]));
1321 igt_create_color_pattern_fb(display->drm_fd, fb_info[0].width, fb_info[0].height,
1322 DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, .1, .1, .1, &fb_info[1]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001323
1324 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1325 populate_cursor_args(display, pipe, arg, &cursor_fb);
1326
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001327 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1328
Chris Wilson83884e92017-03-21 17:16:03 +00001329 pipe_crc = igt_pipe_crc_new(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001330
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001331 set_cursor_on_pipe(display, pipe, &cursor_fb);
1332 igt_display_commit2(display, COMMIT_UNIVERSAL);
1333
Maarten Lankhorst4f086662016-12-08 10:56:13 +01001334 /* Collect reference crcs, crc[0] last for the loop. */
1335 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[1]);
1336 igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001337
Maarten Lankhorst4f086662016-12-08 10:56:13 +01001338 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001339 igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1340
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001341 /*
1342 * Set fb 1 on primary at least once before flipping to force
1343 * setting the correct cache level, else we get a stall in the
1344 * page flip handler.
1345 */
Robert Fossa7864792017-01-10 19:21:26 -05001346 igt_plane_set_fb(plane_primary, &fb_info[1]);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001347 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001348
Robert Fossa7864792017-01-10 19:21:26 -05001349 igt_plane_set_fb(plane_primary, &fb_info[0]);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001350 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001351
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001352 /* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1353 for (int i = 1; i >= 0; i--) {
Chris Wilson18cd7962016-10-05 19:31:27 +01001354 uint32_t *busy;
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001355
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001356 busy = make_fb_busy(display->drm_fd, &fb_info[1]);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001357
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001358 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1359
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001360 flip_nonblocking(display, pipe, atomic, &fb_info[1]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001361 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1362
1363 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1364
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001365 igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001366
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001367 finish_fb_busy(busy);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001368
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001369 igt_set_timeout(1, "Stuck page flip");
1370 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1371 igt_reset_timeout();
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001372
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001373 igt_assert_lte(vblank_start + 1, get_vblank(display->drm_fd, pipe, 0));
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001374
Robert Fossa7864792017-01-10 19:21:26 -05001375 igt_plane_set_fb(plane_primary, &fb_info[0]);
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001376 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001377
1378 igt_assert_crc_equal(&crcs[i], &crcs[2]);
1379 }
1380
1381 do_cleanup_display(display);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001382 igt_remove_fb(display->drm_fd, &fb_info[1]);
1383 igt_remove_fb(display->drm_fd, &fb_info[0]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001384 igt_remove_fb(display->drm_fd, &cursor_fb);
1385 igt_pipe_crc_free(pipe_crc);
1386}
1387
Chris Wilson9579e542016-05-23 21:56:01 +01001388igt_main
1389{
Chris Wilsondab6b6b2016-05-24 16:14:32 +01001390 const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001391 igt_display_t display = { .drm_fd = -1 };
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001392 int i;
Chris Wilson9579e542016-05-23 21:56:01 +01001393
1394 igt_skip_on_simulation();
1395
1396 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001397 display.drm_fd = drm_open_driver_master(DRIVER_ANY);
Chris Wilson9579e542016-05-23 21:56:01 +01001398 kmstest_set_vt_graphics_mode();
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001399
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001400 igt_display_init(&display, display.drm_fd);
1401 igt_require(display.n_pipes > 0);
Chris Wilson9579e542016-05-23 21:56:01 +01001402 }
1403
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001404 igt_subtest_group {
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001405 for (int n = 0; n < I915_MAX_PIPES; n++) {
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001406 errno = 0;
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001407
Chris Wilson04b8f0e2016-05-25 14:53:34 +01001408 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001409 igt_skip_on(n >= display.n_pipes);
Chris Wilson04b8f0e2016-05-25 14:53:34 +01001410 }
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001411
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001412 igt_subtest_f("pipe-%s-single-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001413 stress(&display, n, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001414 igt_subtest_f("pipe-%s-single-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001415 stress(&display, n, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001416
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001417 igt_subtest_f("pipe-%s-forked-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001418 stress(&display, n, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001419 igt_subtest_f("pipe-%s-forked-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001420 stress(&display, n, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +01001421
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001422 igt_subtest_f("pipe-%s-torture-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001423 stress(&display, n, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001424 igt_subtest_f("pipe-%s-torture-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001425 stress(&display, n, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001426 }
1427 }
1428
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001429 igt_subtest("all-pipes-single-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001430 stress(&display, -1, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001431 igt_subtest("all-pipes-single-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001432 stress(&display, -1, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001433
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001434 igt_subtest("all-pipes-forked-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001435 stress(&display, -1, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001436 igt_subtest("all-pipes-forked-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001437 stress(&display, -1, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilson9579e542016-05-23 21:56:01 +01001438
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001439 igt_subtest("all-pipes-torture-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001440 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001441 igt_subtest("all-pipes-torture-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001442 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +01001443
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +01001444 igt_subtest("nonblocking-modeset-vs-cursor-atomic")
1445 nonblocking_modeset_vs_cursor(&display, 1);
1446
1447 igt_subtest("long-nonblocking-modeset-vs-cursor-atomic")
1448 nonblocking_modeset_vs_cursor(&display, 16);
1449
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001450 igt_subtest("2x-flip-vs-cursor-legacy")
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001451 two_screens_flip_vs_cursor(&display, 8, false, false);
1452
1453 igt_subtest("2x-flip-vs-cursor-atomic")
1454 two_screens_flip_vs_cursor(&display, 4, false, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001455
1456 igt_subtest("2x-cursor-vs-flip-legacy")
Maarten Lankhorst39660182017-01-17 17:07:52 +01001457 two_screens_cursor_vs_flip(&display, 8, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001458
1459 igt_subtest("2x-long-flip-vs-cursor-legacy")
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001460 two_screens_flip_vs_cursor(&display, 150, false, false);
1461
1462 igt_subtest("2x-long-flip-vs-cursor-atomic")
1463 two_screens_flip_vs_cursor(&display, 150, false, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001464
1465 igt_subtest("2x-long-cursor-vs-flip-legacy")
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001466 two_screens_cursor_vs_flip(&display, 50, false);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001467
1468 igt_subtest("2x-nonblocking-modeset-vs-cursor-atomic")
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001469 two_screens_flip_vs_cursor(&display, 8, true, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001470
Maarten Lankhorst39660182017-01-17 17:07:52 +01001471 igt_subtest("2x-cursor-vs-flip-atomic")
1472 two_screens_cursor_vs_flip(&display, 8, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001473
1474 igt_subtest("2x-long-nonblocking-modeset-vs-cursor-atomic")
Maarten Lankhorst5b8a1ba2017-01-18 10:41:37 +01001475 two_screens_flip_vs_cursor(&display, 150, true, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001476
Maarten Lankhorst39660182017-01-17 17:07:52 +01001477 igt_subtest("2x-long-cursor-vs-flip-atomic")
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001478 two_screens_cursor_vs_flip(&display, 50, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001479
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001480 igt_subtest("flip-vs-cursor-crc-legacy")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001481 flip_vs_cursor_crc(&display, false);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001482
1483 igt_subtest("flip-vs-cursor-crc-atomic")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001484 flip_vs_cursor_crc(&display, true);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001485
1486 igt_subtest("flip-vs-cursor-busy-crc-legacy")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001487 flip_vs_cursor_busy_crc(&display, false);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001488
1489 igt_subtest("flip-vs-cursor-busy-crc-atomic")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001490 flip_vs_cursor_busy_crc(&display, true);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001491
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001492 for (i = 0; i <= flip_test_last; i++) {
1493 const char *modes[flip_test_last+1] = {
1494 "legacy",
1495 "varying-size",
1496 "toggle",
1497 "atomic",
1498 "atomic-transitions",
1499 "atomic-transitions-varying-size"
1500 };
1501 const char *prefix = "short-";
Chris Wilson162d4562016-06-22 15:41:23 +01001502
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001503 switch (i) {
1504 case flip_test_legacy:
1505 case flip_test_varying_size:
1506 case flip_test_atomic:
1507 prefix = "basic-";
1508 break;
1509 default: break;
1510 }
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001511
Chris Wilson237cb892016-09-13 11:37:41 +01001512 igt_subtest_f("%sflip-before-cursor-%s", prefix, modes[i])
Chris Wilsond2adbdf2016-10-04 13:50:50 +01001513 basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR, 0);
1514
Chris Wilson83cab8a2017-04-27 09:22:54 +01001515 if (!cursor_slowpath(i)) {
1516 igt_subtest_f("%sbusy-flip-before-cursor-%s", prefix, modes[i]) {
1517 igt_require_gem(display.drm_fd);
Maarten Lankhorst7baf4ee2016-12-21 18:26:54 +01001518 basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR,
1519 BASIC_BUSY);
Chris Wilson83cab8a2017-04-27 09:22:54 +01001520 }
1521 }
Chris Wilson237cb892016-09-13 11:37:41 +01001522
1523 igt_subtest_f("%sflip-after-cursor-%s", prefix, modes[i])
Chris Wilsond2adbdf2016-10-04 13:50:50 +01001524 basic_flip_cursor(&display, i, FLIP_AFTER_CURSOR, 0);
Chris Wilson237cb892016-09-13 11:37:41 +01001525
1526 igt_subtest_f("flip-vs-cursor-%s", modes[i])
1527 flip_vs_cursor(&display, i, 150);
1528 igt_subtest_f("cursor-vs-flip-%s", modes[i])
Maarten Lankhorstbc000862016-12-22 10:54:37 +01001529 cursor_vs_flip(&display, i, 50);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001530
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001531 igt_subtest_f("cursorA-vs-flipA-%s", modes[i])
1532 flip(&display, 0, 0, 10, i);
1533
1534 igt_subtest_f("cursorA-vs-flipB-%s", modes[i])
1535 flip(&display, 0, 1, 10, i);
1536
1537 igt_subtest_f("cursorB-vs-flipA-%s", modes[i])
1538 flip(&display, 1, 0, 10, i);
1539
1540 igt_subtest_f("cursorB-vs-flipB-%s", modes[i])
1541 flip(&display, 1, 1, 10, i);
Chris Wilson162d4562016-06-22 15:41:23 +01001542 }
1543
Chris Wilson9579e542016-05-23 21:56:01 +01001544 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001545 igt_display_fini(&display);
Chris Wilson9579e542016-05-23 21:56:01 +01001546 }
1547}