blob: f261e976e23dfb8cd136bf99761c1a6ffe4eb111 [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
169 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
170 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) {
183 if (!plane->is_cursor)
184 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
253static void flip_nonblocking(igt_display_t *display, enum pipe pipe, bool atomic, struct igt_fb *fb)
254{
255 igt_plane_t *primary = &display->pipes[pipe].planes[IGT_PLANE_PRIMARY];
256
257 if (!atomic) {
258 /* Schedule a nonblocking flip for the next vblank */
259 do_or_die(drmModePageFlip(display->drm_fd, display->pipes[pipe].crtc_id, fb->fb_id,
260 DRM_MODE_PAGE_FLIP_EVENT, fb));
261 } else {
262 igt_plane_set_fb(primary, fb);
263 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, fb);
264 }
265}
266
267enum flip_test {
268 flip_test_legacy = 0,
269 flip_test_varying_size,
270 flip_test_toggle_visibility,
271 flip_test_atomic,
272 flip_test_atomic_transitions,
273 flip_test_atomic_transitions_varying_size,
274 flip_test_last = flip_test_atomic_transitions_varying_size
275};
276
277static void transition_nonblocking(igt_display_t *display, enum pipe pipe,
278 struct igt_fb *prim_fb, struct igt_fb *argb_fb,
279 bool hide_sprite)
280{
281 igt_plane_t *primary = &display->pipes[pipe].planes[IGT_PLANE_PRIMARY];
282 igt_plane_t *sprite = &display->pipes[pipe].planes[IGT_PLANE_2];
283
284 if (hide_sprite) {
285 igt_plane_set_fb(primary, prim_fb);
286 igt_plane_set_fb(sprite, NULL);
287 } else {
288 igt_plane_set_fb(primary, NULL);
289 igt_plane_set_fb(sprite, argb_fb);
290 }
291
292 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
293}
294
295static void prepare_flip_test(igt_display_t *display,
296 enum flip_test mode,
297 enum pipe flip_pipe,
298 enum pipe cursor_pipe,
299 struct drm_mode_cursor *arg,
300 const struct igt_fb *prim_fb,
301 struct igt_fb *argb_fb,
302 struct igt_fb *cursor_fb2)
303{
304 argb_fb->gem_handle = 0;
305 cursor_fb2->gem_handle = 0;
306
307 if (mode == flip_test_varying_size ||
308 mode == flip_test_atomic_transitions_varying_size) {
309 uint64_t width, height;
310
311 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_WIDTH, &width));
312 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height));
313
314 igt_skip_on(width <= 64 && height <= 64);
315 igt_create_color_fb(display->drm_fd, width, height,
316 DRM_FORMAT_ARGB8888, 0, 1., 0., .7, cursor_fb2);
317
318 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
319 arg[1].handle = cursor_fb2->gem_handle;
320 arg[1].width = width;
321 arg[1].height = height;
322 }
323
324 if (mode == flip_test_legacy ||
325 mode == flip_test_atomic) {
326 arg[1].x = 192;
327 arg[1].y = 192;
328 }
329
330 if (mode == flip_test_toggle_visibility) {
331 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
332 arg[1].handle = 0;
333 arg[1].width = arg[1].height = 0;
334 }
335
336 if (mode == flip_test_atomic_transitions ||
337 mode == flip_test_atomic_transitions_varying_size) {
338 igt_require(display->pipes[flip_pipe].n_planes > 1 &&
339 !display->pipes[flip_pipe].planes[IGT_PLANE_2].is_cursor);
340
341 igt_create_color_pattern_fb(display->drm_fd, prim_fb->width, prim_fb->height,
342 DRM_FORMAT_ARGB8888, 0, .1, .1, .1, argb_fb);
343 }
344}
345
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200346static void flip(igt_display_t *display,
Chris Wilson162d4562016-06-22 15:41:23 +0100347 int cursor_pipe, int flip_pipe,
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200348 int timeout, enum flip_test mode)
Chris Wilson162d4562016-06-22 15:41:23 +0100349{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200350 struct drm_mode_cursor arg[2];
Chris Wilson162d4562016-06-22 15:41:23 +0100351 uint64_t *results;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200352 struct igt_fb fb_info, fb_info2, argb_fb, cursor_fb, cursor_fb2;
Chris Wilson162d4562016-06-22 15:41:23 +0100353
354 results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
355 igt_assert(results != MAP_FAILED);
356
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200357 flip_pipe = find_connected_pipe(display, !!flip_pipe);
358 cursor_pipe = find_connected_pipe(display, !!cursor_pipe);
359
360 igt_info("Using pipe %s for page flip, pipe %s for cursor\n",
361 kmstest_pipe_name(flip_pipe), kmstest_pipe_name(cursor_pipe));
362
363 if (mode >= flip_test_atomic)
364 igt_require(display->is_atomic);
365
366 igt_require(set_fb_on_crtc(display, flip_pipe, &fb_info));
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200367 if (flip_pipe != cursor_pipe)
368 igt_require(set_fb_on_crtc(display, cursor_pipe, &fb_info2));
Chris Wilson162d4562016-06-22 15:41:23 +0100369
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200370 igt_create_color_fb(display->drm_fd, fb_info.width, fb_info.height, DRM_FORMAT_ARGB8888, 0, .5, .5, .5, &cursor_fb);
371
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200372 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
373 set_cursor_on_pipe(display, cursor_pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200374 populate_cursor_args(display, cursor_pipe, arg, &cursor_fb);
375
376 prepare_flip_test(display, mode, flip_pipe, cursor_pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100377
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200378 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100379
Chris Wilson162d4562016-06-22 15:41:23 +0100380 igt_fork(child, 1) {
381 unsigned long count = 0;
382
383 igt_until_timeout(timeout) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200384 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[(count & 64)/64]);
Chris Wilson162d4562016-06-22 15:41:23 +0100385 count++;
386 }
387
388 igt_debug("cursor count=%lu\n", count);
389 results[0] = count;
390 }
391 igt_fork(child, 1) {
392 unsigned long count = 0;
Chris Wilson162d4562016-06-22 15:41:23 +0100393
394 igt_until_timeout(timeout) {
395 char buf[128];
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200396
397 switch (mode) {
398 default:
399 flip_nonblocking(display, flip_pipe, mode >= flip_test_atomic, &fb_info);
400 break;
401 case flip_test_atomic_transitions:
402 case flip_test_atomic_transitions_varying_size:
403 transition_nonblocking(display, flip_pipe, &fb_info, &argb_fb, count & 1);
404 break;
405 }
406
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200407 while (read(display->drm_fd, buf, sizeof(buf)) < 0 &&
Chris Wilsond86d6eb2016-06-23 21:07:36 +0100408 (errno == EINTR || errno == EAGAIN))
409 ;
Chris Wilson162d4562016-06-22 15:41:23 +0100410 count++;
411 }
412
413 igt_debug("flip count=%lu\n", count);
414 results[1] = count;
415 }
416 igt_waitchildren();
417
Chris Wilson162d4562016-06-22 15:41:23 +0100418 munmap(results, 4096);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200419
420 do_cleanup_display(display);
421
422 igt_remove_fb(display->drm_fd, &fb_info);
423 if (flip_pipe != cursor_pipe)
424 igt_remove_fb(display->drm_fd, &fb_info2);
425 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200426 if (argb_fb.gem_handle)
427 igt_remove_fb(display->drm_fd, &argb_fb);
428 if (cursor_fb2.gem_handle)
429 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100430}
431
432static inline uint32_t pipe_select(int pipe)
433{
434 if (pipe > 1)
435 return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
436 else if (pipe > 0)
437 return DRM_VBLANK_SECONDARY;
438 else
439 return 0;
440}
441
442static unsigned get_vblank(int fd, int pipe, unsigned flags)
443{
444 union drm_wait_vblank vbl;
445
446 memset(&vbl, 0, sizeof(vbl));
447 vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe) | flags;
448 if (drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
449 return 0;
450
451 return vbl.reply.sequence;
452}
453
Chris Wilson237cb892016-09-13 11:37:41 +0100454enum basic_flip_cursor {
455 FLIP_BEFORE_CURSOR,
456 FLIP_AFTER_CURSOR
457};
458
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100459static uint32_t *make_busy(int fd, uint32_t target)
460{
461 const int gen = intel_gen(intel_get_drm_devid(fd));
462 struct drm_i915_gem_exec_object2 obj[2];
463 struct drm_i915_gem_relocation_entry reloc[2];
464 struct drm_i915_gem_execbuffer2 execbuf;
465 uint32_t *batch;
466 int i;
467
468 memset(&execbuf, 0, sizeof(execbuf));
469 execbuf.buffers_ptr = (uintptr_t)obj;
470 execbuf.buffer_count = 2;
471
472 memset(obj, 0, sizeof(obj));
473 obj[0].handle = target;
474 obj[1].handle = gem_create(fd, 4096);
475 batch = gem_mmap__wc(fd, obj[1].handle, 0, 4096, PROT_WRITE);
476 gem_set_domain(fd, obj[1].handle,
477 I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
478
479
480 obj[1].relocs_ptr = (uintptr_t)reloc;
481 obj[1].relocation_count = 2;
482 memset(reloc, 0, sizeof(reloc));
483
484 reloc[0].target_handle = obj[1].handle; /* recurse */
485 reloc[0].presumed_offset = 0;
486 reloc[0].offset = sizeof(uint32_t);
487 reloc[0].delta = 0;
488 reloc[0].read_domains = I915_GEM_DOMAIN_COMMAND;
489 reloc[0].write_domain = 0;
490
491 reloc[1].target_handle = target;
492 reloc[1].presumed_offset = 0;
493 reloc[1].offset = 1024;
494 reloc[1].delta = 0;
495 reloc[1].read_domains = I915_GEM_DOMAIN_COMMAND;
496 reloc[1].write_domain = I915_GEM_DOMAIN_COMMAND;
497
498 i = 0;
499 batch[i] = MI_BATCH_BUFFER_START;
500 if (gen >= 8) {
501 batch[i] |= 1 << 8 | 1;
502 batch[++i] = 0;
503 batch[++i] = 0;
504 } else if (gen >= 6) {
505 batch[i] |= 1 << 8;
506 batch[++i] = 0;
507 } else {
508 batch[i] |= 2 << 6;
509 batch[++i] = 0;
510 if (gen < 4) {
511 batch[i] |= 1;
512 reloc[0].delta = 1;
513 }
514 }
515 i++;
516
517 gem_execbuf(fd, &execbuf);
518 gem_close(fd, obj[1].handle);
519
520 return batch;
521}
522
Chris Wilson18cd7962016-10-05 19:31:27 +0100523static void cancel_busy(uint32_t *busy)
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100524{
525 *busy = MI_BATCH_BUFFER_END;
526 munmap(busy, 4096);
527}
528
Chris Wilson18cd7962016-10-05 19:31:27 +0100529static uint32_t *
530make_fb_busy(int fd, const struct igt_fb *fb)
531{
532 uint32_t *busy;
533
534 busy = make_busy(fd, fb->gem_handle);
535 igt_assert(gem_bo_busy(fd, fb->gem_handle));
536
537 return busy;
538}
539
540static void finish_fb_busy(uint32_t *busy)
541{
542 cancel_busy(busy);
543}
544
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100545#define BASIC_BUSY 0x1
546
Chris Wilson237cb892016-09-13 11:37:41 +0100547static void basic_flip_cursor(igt_display_t *display,
548 enum flip_test mode,
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100549 enum basic_flip_cursor order,
550 unsigned flags)
Chris Wilson237cb892016-09-13 11:37:41 +0100551{
552 struct drm_mode_cursor arg[2];
553 struct drm_event_vblank vbl;
554 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
555 unsigned vblank_start;
556 enum pipe pipe = find_connected_pipe(display, false);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100557 uint32_t *busy;
Chris Wilson237cb892016-09-13 11:37:41 +0100558
559 if (mode >= flip_test_atomic)
560 igt_require(display->is_atomic);
561
562 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
563
564 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
565 set_cursor_on_pipe(display, pipe, &cursor_fb);
566 populate_cursor_args(display, pipe, arg, &cursor_fb);
567
568 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
569
570 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
571
572 /* Quick sanity check that we can update a cursor in a single vblank */
573 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
574 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
575 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
576 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
577
578 /* Bind the cursor first to warm up */
579 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
580
581 /* Start with a synchronous query to align with the vblank */
582 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
583
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100584 busy = NULL;
585 if (flags & BASIC_BUSY)
Chris Wilson18cd7962016-10-05 19:31:27 +0100586 busy = make_fb_busy(display->drm_fd, &fb_info);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100587
Chris Wilson237cb892016-09-13 11:37:41 +0100588 switch (order) {
589 case FLIP_BEFORE_CURSOR:
590 switch (mode) {
591 default:
592 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
593 break;
594 case flip_test_atomic_transitions:
595 case flip_test_atomic_transitions_varying_size:
596 transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
597 break;
598 }
599 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
600
601 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
602 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
603 break;
604
605 case FLIP_AFTER_CURSOR:
606 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
607 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
608
609 switch (mode) {
610 default:
611 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
612 break;
613 case flip_test_atomic_transitions:
614 case flip_test_atomic_transitions_varying_size:
615 transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
616 break;
617 }
618 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
619 }
620
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100621 if (busy) {
622 struct pollfd pfd = { display->drm_fd, POLLIN };
623 igt_assert(poll(&pfd, 1, 0) == 0);
Chris Wilson18cd7962016-10-05 19:31:27 +0100624 finish_fb_busy(busy);
Chris Wilsond2adbdf2016-10-04 13:50:50 +0100625 }
626
Chris Wilson237cb892016-09-13 11:37:41 +0100627 igt_set_timeout(1, "Stuck page flip");
628 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
629 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
630 igt_reset_timeout();
631
632 do_cleanup_display(display);
633 igt_remove_fb(display->drm_fd, &fb_info);
634 igt_remove_fb(display->drm_fd, &cursor_fb);
635
636 if (argb_fb.gem_handle)
637 igt_remove_fb(display->drm_fd, &argb_fb);
638 if (cursor_fb2.gem_handle)
639 igt_remove_fb(display->drm_fd, &cursor_fb2);
640}
641
642static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloops)
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200643{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200644 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100645 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200646 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson162d4562016-06-22 15:41:23 +0100647 unsigned vblank_start;
648 int target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200649 enum pipe pipe = find_connected_pipe(display, false);
650
651 if (mode >= flip_test_atomic)
652 igt_require(display->is_atomic);
Chris Wilson162d4562016-06-22 15:41:23 +0100653
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200654 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Chris Wilson162d4562016-06-22 15:41:23 +0100655
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200656 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 +0200657 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200658 populate_cursor_args(display, pipe, arg, &cursor_fb);
659
660 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100661
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200662 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100663
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100664 if (nloops) {
665 target = 4096;
666 do {
667 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
668 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
669 for (int n = 0; n < target; n++)
670 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
671 target /= 2;
672 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
673 break;
674 } while (target);
675 igt_require(target > 1);
Chris Wilson162d4562016-06-22 15:41:23 +0100676
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100677 igt_debug("Using a target of %d cursor updates per half-vblank\n", target);
678 } else
679 target = 1;
Chris Wilson162d4562016-06-22 15:41:23 +0100680
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200681 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
682 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200683 for (int n = 0; n < target; n++)
684 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200685 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson162d4562016-06-22 15:41:23 +0100686
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100687 do {
688 /* Bind the cursor first to warm up */
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200689 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson162d4562016-06-22 15:41:23 +0100690
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100691 /* Start with a synchronous query to align with the vblank */
692 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200693 switch (mode) {
694 default:
695 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
696 break;
697 case flip_test_atomic_transitions:
698 case flip_test_atomic_transitions_varying_size:
699 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (nloops & 2) /2);
700 break;
701 }
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100702
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100703 /* The nonblocking flip should not have delayed us */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200704 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100705 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200706 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100707 /* Nor should it have delayed the following cursor update */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200708 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100709
710 igt_set_timeout(1, "Stuck page flip");
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200711 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200712 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100713 igt_reset_timeout();
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100714 } while (nloops--);
Chris Wilson162d4562016-06-22 15:41:23 +0100715
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200716 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200717 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200718 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200719
720 if (argb_fb.gem_handle)
721 igt_remove_fb(display->drm_fd, &argb_fb);
722 if (cursor_fb2.gem_handle)
723 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100724}
725
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200726static bool skip_on_unsupported_nonblocking_modeset(igt_display_t *display)
727{
728 enum pipe pipe;
729 int ret;
730
731 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
732
733 ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
734
735 if (ret == -EINVAL)
736 return true;
737
738 igt_assert_eq(ret, 0);
739
740 /* Force the next state to update all crtc's, to synchronize with the nonblocking modeset. */
741 for_each_pipe(display, pipe)
742 display->pipes[pipe].mode_changed = true;
743
744 return false;
745}
746
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +0100747static void nonblocking_modeset_vs_cursor(igt_display_t *display, int loops)
748{
749 struct igt_fb fb_info, cursor_fb;
750 igt_output_t *output;
751 enum pipe pipe = find_connected_pipe(display, false);
752 struct drm_mode_cursor arg;
753 bool skip_test;
754 igt_plane_t *cursor = NULL, *plane;
755
756 igt_require(display->is_atomic);
757 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
758 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
759 set_cursor_on_pipe(display, pipe, &cursor_fb);
760 populate_cursor_args(display, pipe, &arg, &cursor_fb);
761 arg.flags |= DRM_MODE_CURSOR_BO;
762
763 for_each_plane_on_pipe(display, pipe, plane) {
764 if (!plane->is_cursor)
765 continue;
766
767 cursor = plane;
768 break;
769 }
770
771 igt_skip_on(!cursor);
772
773 if ((skip_test = skip_on_unsupported_nonblocking_modeset(display)))
774 goto cleanup;
775
776 /*
777 * Start disabled, because skip_on_unsupported_nonblocking_modeset
778 * will have enabled this pipe. No way around it, since the first
779 * atomic commit may be unreliable with amount of events sent.
780 */
781 igt_output_set_pipe(output, PIPE_NONE);
782 igt_display_commit2(display, COMMIT_ATOMIC);
783
784 while (loops--) {
785 unsigned flags;
786 struct pollfd pfd = { display->drm_fd, POLLIN };
787 struct drm_event_vblank vbl;
788
789 flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
790 flags |= DRM_MODE_ATOMIC_NONBLOCK;
791 flags |= DRM_MODE_PAGE_FLIP_EVENT;
792
793 /*
794 * Test that a cursor update after a nonblocking modeset
795 * works as intended. It should block until the modeset completes.
796 */
797
798 igt_output_set_pipe(output, pipe);
799 igt_plane_set_fb(cursor, NULL);
800 igt_display_commit_atomic(display, flags, NULL);
801
802 igt_assert_eq(0, poll(&pfd, 1, 0));
803 igt_assert_eq(0, pfd.revents);
804
805 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
806
807 igt_assert_eq(1, poll(&pfd, 1, 0));
808 igt_assert_eq(POLLIN, pfd.revents);
809
810 igt_set_timeout(1, "Stuck page flip");
811 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
812 igt_reset_timeout();
813
814 igt_output_set_pipe(output, PIPE_NONE);
815 igt_display_commit_atomic(display, flags, NULL);
816
817 igt_assert_eq(0, poll(&pfd, 1, 0));
818 igt_assert_eq(0, pfd.revents);
819
820 /* Same for cursor on disabled crtc. */
821 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
822
823 igt_assert_eq(1, poll(&pfd, 1, 0));
824 igt_assert_eq(POLLIN, pfd.revents);
825
826 igt_set_timeout(1, "Stuck page flip");
827 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
828 igt_reset_timeout();
829 }
830
831cleanup:
832 do_cleanup_display(display);
833 igt_remove_fb(display->drm_fd, &fb_info);
834 igt_remove_fb(display->drm_fd, &cursor_fb);
835
836 if (skip_test)
837 igt_skip("Nonblocking modeset is not supported by this kernel\n");
838}
839
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200840static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200841{
842 struct drm_mode_cursor arg[2], arg2[2];
843 struct drm_event_vblank vbl;
844 struct igt_fb fb_info, fb2_info, cursor_fb;
845 unsigned vblank_start;
846 enum pipe pipe = find_connected_pipe(display, false);
847 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200848 igt_output_t *output2;
849 bool skip_test = false;
850
851 if (modeset)
852 igt_require(display->is_atomic);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200853
854 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200855 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200856
857 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
858 set_cursor_on_pipe(display, pipe, &cursor_fb);
859 populate_cursor_args(display, pipe, arg, &cursor_fb);
860
861 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
862 arg[1].handle = 0;
863 arg[1].width = arg[1].height = 0;
864
865 set_cursor_on_pipe(display, pipe2, &cursor_fb);
866 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
867
868 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
869 arg2[0].handle = 0;
870 arg2[0].width = arg2[0].height = 0;
871
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200872 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
873 goto cleanup;
874
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200875 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
876
877 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
878 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
879 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
880 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
881 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
882
883 while (nloops--) {
884 /* Start with a synchronous query to align with the vblank */
885 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
886 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
887
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200888
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200889 flip_nonblocking(display, pipe, false, &fb_info);
890
891 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
892
893 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200894 if (!modeset) {
895 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
896 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
897 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
898 } else {
899 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
900
901 igt_output_set_pipe(output2, (nloops & 1) ? PIPE_NONE : pipe2);
902 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
903
904 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
905 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200906
907 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
908
909 igt_set_timeout(1, "Stuck page flip");
910 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
911 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
912 igt_reset_timeout();
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200913
914 if (modeset) {
915 /* wait for pending modeset to complete, to prevent -EBUSY */
916 display->pipes[pipe2].mode_changed = true;
917 igt_display_commit2(display, COMMIT_ATOMIC);
918 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200919 }
920
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200921cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200922 do_cleanup_display(display);
923 igt_remove_fb(display->drm_fd, &fb_info);
924 igt_remove_fb(display->drm_fd, &fb2_info);
925 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200926
927 if (skip_test)
928 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200929}
930
Chris Wilson237cb892016-09-13 11:37:41 +0100931static void cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloops)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100932{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200933 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100934 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200935 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100936 unsigned vblank_start, vblank_last;
937 volatile unsigned long *shared;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200938 long target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200939 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200940 igt_output_t *output;
941 uint32_t vrefresh;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200942
943 if (mode >= flip_test_atomic)
944 igt_require(display->is_atomic);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100945
946 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
947 igt_assert(shared != MAP_FAILED);
948
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200949 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
950 vrefresh = igt_output_get_mode(output)->vrefresh;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100951
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200952 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 +0200953 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200954 populate_cursor_args(display, pipe, arg, &cursor_fb);
955
956 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100957
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200958 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100959
960 target = 4096;
961 do {
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200962 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
963 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100964 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200965 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100966 target /= 2;
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200967 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100968 break;
969 } while (target);
970 igt_require(target > 1);
971
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200972 igt_debug("Using a target of %ld cursor updates per half-vblank (%u)\n",
973 target, vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100974
975 for (int i = 0; i < nloops; i++) {
976 shared[0] = 0;
977 igt_fork(child, 1) {
978 unsigned long count = 0;
979 while (!shared[0]) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200980 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100981 count++;
982 }
983 igt_debug("child: %lu cursor updates\n", count);
984 shared[0] = count;
985 }
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200986
987 switch (mode) {
988 default:
989 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
990 break;
991 case flip_test_atomic_transitions:
992 case flip_test_atomic_transitions_varying_size:
993 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (i & 2) >> 1);
994 break;
995 }
996
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200997 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100998 vblank_start = vblank_last = vbl.sequence;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200999 for (int n = 0; n < vrefresh; n++) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001000 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
1001
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001002 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001003 if (vbl.sequence != vblank_last + 1) {
1004 igt_warn("page flip %d was delayed, missed %d frames\n",
1005 n, vbl.sequence - vblank_last - 1);
1006 }
1007 vblank_last = vbl.sequence;
1008 }
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001009
1010 if (mode != flip_test_atomic_transitions &&
1011 mode != flip_test_atomic_transitions_varying_size)
1012 igt_assert_eq(vbl.sequence, vblank_start + vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001013
1014 shared[0] = 1;
1015 igt_waitchildren();
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001016 igt_assert_f(shared[0] > vrefresh*target,
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001017 "completed %lu cursor updated in a period of 60 flips, "
1018 "we expect to complete approximately %lu updateds, "
1019 "with the threshold set at %lu\n",
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +02001020 shared[0], 2ul*vrefresh*target, vrefresh*target);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001021 }
1022
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001023 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001024 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +02001025 igt_remove_fb(display->drm_fd, &cursor_fb);
Chris Wilson88c1f7c2016-06-23 22:53:23 +01001026 munmap((void *)shared, 4096);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001027 if (argb_fb.gem_handle)
1028 igt_remove_fb(display->drm_fd, &argb_fb);
1029 if (cursor_fb2.gem_handle)
1030 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +01001031}
1032
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001033static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001034{
1035 struct drm_mode_cursor arg[2], arg2[2];
1036 struct drm_event_vblank vbl;
1037 struct igt_fb fb_info, fb2_info, cursor_fb;
1038 unsigned vblank_start, vblank_last;
1039 volatile unsigned long *shared;
1040 int target;
1041 enum pipe pipe = find_connected_pipe(display, false);
1042 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001043 igt_output_t *output2;
1044 bool skip_test = false;
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001045
1046 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1047 igt_assert(shared != MAP_FAILED);
1048
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001049 if (modeset)
1050 igt_require(display->is_atomic);
1051
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001052 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001053 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001054
1055 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1056 set_cursor_on_pipe(display, pipe, &cursor_fb);
1057 populate_cursor_args(display, pipe, arg, &cursor_fb);
1058
1059 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
1060 arg[1].handle = 0;
1061 arg[1].width = arg[1].height = 0;
1062
1063 set_cursor_on_pipe(display, pipe2, &cursor_fb);
1064 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
1065
1066 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
1067 arg2[0].handle = 0;
1068 arg2[0].width = arg2[0].height = 0;
1069
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001070 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
1071 goto cleanup;
1072
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001073 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1074
1075 target = 4096;
1076 do {
1077 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1078 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1079
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001080 if (!modeset)
1081 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
1082
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001083 for (int n = 0; n < target; n++) {
1084 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
1085 }
1086 target /= 2;
1087 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
1088 break;
1089 } while (target);
1090 igt_require(target > 1);
1091
1092 igt_debug("Using a target of %d cursor updates per half-vblank\n",
1093 target);
1094
1095 for (int i = 0; i < nloops; i++) {
1096 shared[0] = 0;
1097 igt_fork(child, 1) {
1098 unsigned long count = 0;
1099
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001100 if (!modeset)
1101 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[i & 1]);
1102 else {
1103 igt_output_set_pipe(output2, (i & 1) ? pipe2 : PIPE_NONE);
1104 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET |
1105 DRM_MODE_ATOMIC_NONBLOCK, NULL);
1106 }
1107
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001108 while (!shared[0]) {
1109 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
1110 count++;
1111 }
1112 igt_debug("child: %lu cursor updates\n", count);
1113 shared[0] = count;
1114 }
1115
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001116 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001117
1118 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
1119 vblank_start = vblank_last = vbl.sequence;
1120 for (int n = 0; n < 60; n++) {
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001121 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001122
1123 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
1124 if (vbl.sequence != vblank_last + 1) {
1125 igt_warn("page flip %d was delayed, missed %d frames\n",
1126 n, vbl.sequence - vblank_last - 1);
1127 }
1128 vblank_last = vbl.sequence;
1129 }
1130 igt_assert_eq(vbl.sequence, vblank_start + 60);
1131
1132 shared[0] = 1;
1133 igt_waitchildren();
1134 igt_assert_f(shared[0] > 60*target,
1135 "completed %lu cursor updated in a period of 60 flips, "
1136 "we expect to complete approximately %lu updateds, "
1137 "with the threshold set at %lu\n",
1138 shared[0], 2*60ul*target, 60ul*target);
1139 }
1140
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001141cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001142 do_cleanup_display(display);
1143 igt_remove_fb(display->drm_fd, &fb_info);
1144 igt_remove_fb(display->drm_fd, &fb2_info);
1145 igt_remove_fb(display->drm_fd, &cursor_fb);
1146 munmap((void *)shared, 4096);
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001147
1148 if (skip_test)
1149 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001150}
1151
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001152static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
1153{
1154 struct drm_mode_cursor arg[2];
1155 struct drm_event_vblank vbl;
1156 struct igt_fb fb_info, cursor_fb;
1157 unsigned vblank_start;
1158 enum pipe pipe = find_connected_pipe(display, false);
1159 igt_pipe_crc_t *pipe_crc;
1160 igt_crc_t crcs[3];
1161
1162 if (atomic)
1163 igt_require(display->is_atomic);
1164
1165 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
1166
1167 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1168 populate_cursor_args(display, pipe, arg, &cursor_fb);
1169
1170 arg[0].flags = arg[1].flags |= DRM_MODE_CURSOR_BO;
1171 arg[1].handle = 0;
1172 arg[1].width = arg[1].height = 0;
1173
1174 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1175
1176 pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
1177
1178 /* Collect reference crc with cursor disabled. */
1179 igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
1180
1181 set_cursor_on_pipe(display, pipe, &cursor_fb);
1182 igt_display_commit2(display, COMMIT_UNIVERSAL);
1183
1184 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
1185
1186 /* Collect reference crc with cursor enabled. */
1187 igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1188
1189 /* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1190 for (int i = 1; i >= 0; i--) {
1191 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1192
1193 flip_nonblocking(display, pipe, atomic, &fb_info);
1194 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1195
1196 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1197
1198 igt_set_timeout(1, "Stuck page flip");
1199 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1200 igt_reset_timeout();
1201
1202 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
1203
1204 igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
1205
1206 igt_assert_crc_equal(&crcs[i], &crcs[2]);
1207 }
1208
1209 do_cleanup_display(display);
1210 igt_remove_fb(display->drm_fd, &fb_info);
1211 igt_remove_fb(display->drm_fd, &cursor_fb);
1212 igt_pipe_crc_free(pipe_crc);
1213}
1214
1215static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001216{
1217 struct drm_mode_cursor arg[2];
1218 struct drm_event_vblank vbl;
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001219 struct igt_fb fb_info[2], cursor_fb;
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001220 unsigned vblank_start;
1221 enum pipe pipe = find_connected_pipe(display, false);
1222 igt_pipe_crc_t *pipe_crc;
1223 igt_crc_t crcs[3];
1224
1225 if (atomic)
1226 igt_require(display->is_atomic);
1227
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001228 igt_require(set_fb_on_crtc(display, pipe, &fb_info[0]));
1229 igt_create_color_pattern_fb(display->drm_fd, fb_info[0].width, fb_info[0].height,
1230 DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, .1, .1, .1, &fb_info[1]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001231
1232 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1233 populate_cursor_args(display, pipe, arg, &cursor_fb);
1234
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001235 arg[0].flags = arg[1].flags |= DRM_MODE_CURSOR_BO;
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001236 arg[1].handle = 0;
1237 arg[1].width = arg[1].height = 0;
1238
1239 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1240
1241 pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
1242
1243 /* Collect reference crc with cursor disabled. */
1244 igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
1245
1246 set_cursor_on_pipe(display, pipe, &cursor_fb);
1247 igt_display_commit2(display, COMMIT_UNIVERSAL);
1248
1249 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
1250
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001251 /* Collect reference crc with cursor enabled. */
1252 igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1253
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001254 /*
1255 * Set fb 1 on primary at least once before flipping to force
1256 * setting the correct cache level, else we get a stall in the
1257 * page flip handler.
1258 */
1259 igt_plane_set_fb(&display->pipes[pipe].planes[IGT_PLANE_PRIMARY], &fb_info[1]);
1260 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001261
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001262 igt_plane_set_fb(&display->pipes[pipe].planes[IGT_PLANE_PRIMARY], &fb_info[0]);
1263 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001264
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001265 /* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1266 for (int i = 1; i >= 0; i--) {
Chris Wilson18cd7962016-10-05 19:31:27 +01001267 uint32_t *busy;
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001268
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001269 busy = make_fb_busy(display->drm_fd, &fb_info[1]);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001270
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001271 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1272
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001273 flip_nonblocking(display, pipe, atomic, &fb_info[1]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001274 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1275
1276 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1277
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001278 igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001279
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001280 finish_fb_busy(busy);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001281
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001282 igt_set_timeout(1, "Stuck page flip");
1283 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1284 igt_reset_timeout();
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001285
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001286 igt_assert_lte(vblank_start + 1, get_vblank(display->drm_fd, pipe, 0));
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001287
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001288 igt_plane_set_fb(&display->pipes[pipe].planes[IGT_PLANE_PRIMARY], &fb_info[0]);
1289 igt_display_commit2(display, COMMIT_UNIVERSAL);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001290
1291 igt_assert_crc_equal(&crcs[i], &crcs[2]);
1292 }
1293
1294 do_cleanup_display(display);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001295 igt_remove_fb(display->drm_fd, &fb_info[1]);
1296 igt_remove_fb(display->drm_fd, &fb_info[0]);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001297 igt_remove_fb(display->drm_fd, &cursor_fb);
1298 igt_pipe_crc_free(pipe_crc);
1299}
1300
Chris Wilson9579e542016-05-23 21:56:01 +01001301igt_main
1302{
Chris Wilsondab6b6b2016-05-24 16:14:32 +01001303 const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001304 igt_display_t display = { .drm_fd = -1 };
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001305 int i;
Chris Wilson9579e542016-05-23 21:56:01 +01001306
1307 igt_skip_on_simulation();
1308
1309 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001310 display.drm_fd = drm_open_driver_master(DRIVER_ANY);
Chris Wilson9579e542016-05-23 21:56:01 +01001311 kmstest_set_vt_graphics_mode();
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001312
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001313 igt_display_init(&display, display.drm_fd);
1314 igt_require(display.n_pipes > 0);
Chris Wilson9579e542016-05-23 21:56:01 +01001315 }
1316
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001317 igt_subtest_group {
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001318 for (int n = 0; n < I915_MAX_PIPES; n++) {
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001319 errno = 0;
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001320
Chris Wilson04b8f0e2016-05-25 14:53:34 +01001321 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001322 igt_skip_on(n >= display.n_pipes);
Chris Wilson04b8f0e2016-05-25 14:53:34 +01001323 }
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001324
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001325 igt_subtest_f("pipe-%s-single-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001326 stress(&display, n, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001327 igt_subtest_f("pipe-%s-single-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001328 stress(&display, n, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001329
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001330 igt_subtest_f("pipe-%s-forked-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001331 stress(&display, n, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001332 igt_subtest_f("pipe-%s-forked-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001333 stress(&display, n, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +01001334
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001335 igt_subtest_f("pipe-%s-torture-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001336 stress(&display, n, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001337 igt_subtest_f("pipe-%s-torture-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001338 stress(&display, n, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001339 }
1340 }
1341
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001342 igt_subtest("all-pipes-single-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001343 stress(&display, -1, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001344 igt_subtest("all-pipes-single-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001345 stress(&display, -1, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +01001346
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001347 igt_subtest("all-pipes-forked-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001348 stress(&display, -1, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001349 igt_subtest("all-pipes-forked-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001350 stress(&display, -1, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilson9579e542016-05-23 21:56:01 +01001351
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001352 igt_subtest("all-pipes-torture-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001353 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001354 igt_subtest("all-pipes-torture-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001355 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +01001356
Maarten Lankhorst59cdcf12016-11-02 13:38:48 +01001357 igt_subtest("nonblocking-modeset-vs-cursor-atomic")
1358 nonblocking_modeset_vs_cursor(&display, 1);
1359
1360 igt_subtest("long-nonblocking-modeset-vs-cursor-atomic")
1361 nonblocking_modeset_vs_cursor(&display, 16);
1362
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001363 igt_subtest("2x-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001364 two_screens_flip_vs_cursor(&display, 8, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001365
1366 igt_subtest("2x-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001367 two_screens_cursor_vs_flip(&display, 4, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001368
1369 igt_subtest("2x-long-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001370 two_screens_flip_vs_cursor(&display, 150, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001371
1372 igt_subtest("2x-long-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +02001373 two_screens_cursor_vs_flip(&display, 150, false);
1374
1375 igt_subtest("2x-nonblocking-modeset-vs-cursor-atomic")
1376 two_screens_flip_vs_cursor(&display, 8, true);
1377
1378 igt_subtest("2x-cursor-vs-nonblocking-modeset-atomic")
1379 two_screens_cursor_vs_flip(&display, 4, true);
1380
1381 igt_subtest("2x-long-nonblocking-modeset-vs-cursor-atomic")
1382 two_screens_flip_vs_cursor(&display, 150, true);
1383
1384 igt_subtest("2x-long-cursor-vs-nonblocking-modeset-atomic")
1385 two_screens_cursor_vs_flip(&display, 150, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +02001386
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001387 igt_subtest("flip-vs-cursor-crc-legacy")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001388 flip_vs_cursor_crc(&display, false);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001389
1390 igt_subtest("flip-vs-cursor-crc-atomic")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001391 flip_vs_cursor_crc(&display, true);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001392
1393 igt_subtest("flip-vs-cursor-busy-crc-legacy")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001394 flip_vs_cursor_busy_crc(&display, false);
Maarten Lankhorst4ef3fe92016-10-05 15:51:00 +02001395
1396 igt_subtest("flip-vs-cursor-busy-crc-atomic")
Maarten Lankhorst954923c2016-10-06 12:52:53 +02001397 flip_vs_cursor_busy_crc(&display, true);
Maarten Lankhorst4fb21782016-09-07 17:00:39 +02001398
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001399 for (i = 0; i <= flip_test_last; i++) {
1400 const char *modes[flip_test_last+1] = {
1401 "legacy",
1402 "varying-size",
1403 "toggle",
1404 "atomic",
1405 "atomic-transitions",
1406 "atomic-transitions-varying-size"
1407 };
1408 const char *prefix = "short-";
Chris Wilson162d4562016-06-22 15:41:23 +01001409
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001410 switch (i) {
1411 case flip_test_legacy:
1412 case flip_test_varying_size:
1413 case flip_test_atomic:
1414 prefix = "basic-";
1415 break;
1416 default: break;
1417 }
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001418
Chris Wilson237cb892016-09-13 11:37:41 +01001419 igt_subtest_f("%sflip-before-cursor-%s", prefix, modes[i])
Chris Wilsond2adbdf2016-10-04 13:50:50 +01001420 basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR, 0);
1421
1422 igt_subtest_f("%sbusy-flip-before-cursor-%s", prefix, modes[i])
1423 basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR,
1424 BASIC_BUSY);
Chris Wilson237cb892016-09-13 11:37:41 +01001425
1426 igt_subtest_f("%sflip-after-cursor-%s", prefix, modes[i])
Chris Wilsond2adbdf2016-10-04 13:50:50 +01001427 basic_flip_cursor(&display, i, FLIP_AFTER_CURSOR, 0);
Chris Wilson237cb892016-09-13 11:37:41 +01001428
1429 igt_subtest_f("flip-vs-cursor-%s", modes[i])
1430 flip_vs_cursor(&display, i, 150);
1431 igt_subtest_f("cursor-vs-flip-%s", modes[i])
1432 cursor_vs_flip(&display, i, 150);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +02001433
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +02001434 igt_subtest_f("cursorA-vs-flipA-%s", modes[i])
1435 flip(&display, 0, 0, 10, i);
1436
1437 igt_subtest_f("cursorA-vs-flipB-%s", modes[i])
1438 flip(&display, 0, 1, 10, i);
1439
1440 igt_subtest_f("cursorB-vs-flipA-%s", modes[i])
1441 flip(&display, 1, 0, 10, i);
1442
1443 igt_subtest_f("cursorB-vs-flipB-%s", modes[i])
1444 flip(&display, 1, 1, 10, i);
Chris Wilson162d4562016-06-22 15:41:23 +01001445 }
1446
Chris Wilson9579e542016-05-23 21:56:01 +01001447 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +02001448 igt_display_fini(&display);
Chris Wilson9579e542016-05-23 21:56:01 +01001449 }
1450}