blob: e0f39f771ca0a83acd7dae4d793243dec8654c91 [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>
27
28#include "igt.h"
Chris Wilson376b8132016-07-03 09:42:38 +010029#include "igt_rand.h"
Chris Wilsonc74e0712016-05-24 16:24:15 +010030#include "igt_stats.h"
Chris Wilson9579e542016-05-23 21:56:01 +010031
Tomeu Vizoso047c9992016-06-07 10:18:34 +020032#if defined(__x86_64__) || defined(__i386__)
33#define cpu_relax() __builtin_ia32_pause()
34#else
35#define cpu_relax() asm volatile("": : :"memory")
36#endif
37
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +020038#ifndef DRM_CAP_CURSOR_WIDTH
39#define DRM_CAP_CURSOR_WIDTH 0x8
40#endif
41
42#ifndef DRM_CAP_CURSOR_HEIGHT
43#define DRM_CAP_CURSOR_HEIGHT 0x9
44#endif
45
Chris Wilson9579e542016-05-23 21:56:01 +010046IGT_TEST_DESCRIPTION("Stress legacy cursor ioctl");
47
Maarten Lankhorst6b985872016-07-13 14:59:02 +020048static void stress(igt_display_t *display,
49 int pipe, int num_children, unsigned mode,
Chris Wilsoncce2ff02016-05-25 08:34:25 +010050 int timeout)
Chris Wilson9579e542016-05-23 21:56:01 +010051{
Chris Wilson9579e542016-05-23 21:56:01 +010052 struct drm_mode_cursor arg;
Chris Wilsonc74e0712016-05-24 16:24:15 +010053 uint64_t *results;
Chris Wilsonf5d370c2016-06-04 21:25:17 +010054 bool torture;
Chris Wilson9579e542016-05-23 21:56:01 +010055 int n;
Maarten Lankhorst6b985872016-07-13 14:59:02 +020056 unsigned crtc_id[I915_MAX_PIPES], num_crtcs;
Chris Wilson9579e542016-05-23 21:56:01 +010057
Chris Wilsonf5d370c2016-06-04 21:25:17 +010058 torture = false;
59 if (num_children < 0) {
60 torture = true;
61 num_children = -num_children;
62 }
63
Chris Wilsonc74e0712016-05-24 16:24:15 +010064 results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
65 igt_assert(results != MAP_FAILED);
66
Chris Wilson9579e542016-05-23 21:56:01 +010067 memset(&arg, 0, sizeof(arg));
68 arg.flags = DRM_MODE_CURSOR_BO;
69 arg.crtc_id = 0;
70 arg.width = 64;
71 arg.height = 64;
Maarten Lankhorst6b985872016-07-13 14:59:02 +020072 arg.handle = kmstest_dumb_create(display->drm_fd, 64, 64, 32, NULL, NULL);
Chris Wilson9579e542016-05-23 21:56:01 +010073
Maarten Lankhorst6b985872016-07-13 14:59:02 +020074 if (pipe < 0) {
75 num_crtcs = display->n_pipes;
76 for_each_pipe(display, n) {
77 arg.crtc_id = crtc_id[n] = display->pipes[n].crtc_id;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +020078 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Maarten Lankhorst6b985872016-07-13 14:59:02 +020079 }
80 } else {
81 num_crtcs = 1;
82 arg.crtc_id = crtc_id[0] = display->pipes[pipe].crtc_id;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +020083 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Chris Wilsoncce2ff02016-05-25 08:34:25 +010084 }
Chris Wilson9579e542016-05-23 21:56:01 +010085
86 arg.flags = mode;
Chris Wilsondab6b6b2016-05-24 16:14:32 +010087 igt_fork(child, num_children) {
Chris Wilson9579e542016-05-23 21:56:01 +010088 struct sched_param rt = {.sched_priority = 99 };
89 cpu_set_t allowed;
90 unsigned long count = 0;
91
92 sched_setscheduler(getpid(), SCHED_RR, &rt);
93
94 CPU_ZERO(&allowed);
95 CPU_SET(child, &allowed);
96 sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
97
Chris Wilson376b8132016-07-03 09:42:38 +010098 hars_petruska_f54_1_random_perturb(child);
Chris Wilson9579e542016-05-23 21:56:01 +010099 igt_until_timeout(timeout) {
Chris Wilson376b8132016-07-03 09:42:38 +0100100 arg.crtc_id = crtc_id[hars_petruska_f54_1_random_unsafe() % num_crtcs];
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200101 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
Chris Wilson9579e542016-05-23 21:56:01 +0100102 count++;
103 }
104
Chris Wilsonc74e0712016-05-24 16:24:15 +0100105 igt_debug("[%d] count=%lu\n", child, count);
106 results[child] = count;
Chris Wilson9579e542016-05-23 21:56:01 +0100107 }
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100108 if (torture) {
109 igt_fork(child, num_children) {
110 struct sched_param rt = {.sched_priority = 1 };
111 cpu_set_t allowed;
112 unsigned long long count = 0;
113
114 sched_setscheduler(getpid(), SCHED_RR, &rt);
115
116 CPU_ZERO(&allowed);
117 CPU_SET(child, &allowed);
118 sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
119 igt_until_timeout(timeout) {
120 count++;
Tomeu Vizoso047c9992016-06-07 10:18:34 +0200121 cpu_relax();
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100122 }
123 igt_debug("[hog:%d] count=%llu\n", child, count);
124 }
125 }
Chris Wilson9579e542016-05-23 21:56:01 +0100126 igt_waitchildren();
127
Chris Wilsonc74e0712016-05-24 16:24:15 +0100128 if (num_children > 1) {
129 igt_stats_t stats;
130
131 igt_stats_init_with_size(&stats, num_children);
132 results[num_children] = 0;
133 for (int child = 0; child < num_children; child++) {
134 igt_stats_push(&stats, results[child]);
135 results[num_children] += results[child];
136 }
137 igt_info("Total updates %llu (median of %d processes is %.2f)\n",
138 (long long)results[num_children],
139 num_children,
140 igt_stats_get_median(&stats));
141 igt_stats_fini(&stats);
142 } else {
143 igt_info("Total updates %llu\n", (long long)results[0]);
144 }
145
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200146 gem_close(display->drm_fd, arg.handle);
Chris Wilsonc74e0712016-05-24 16:24:15 +0100147 munmap(results, 4096);
Chris Wilson9579e542016-05-23 21:56:01 +0100148}
149
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200150static 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 +0100151{
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200152 igt_output_t *output;
Chris Wilson162d4562016-06-22 15:41:23 +0100153
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200154 for_each_valid_output_on_pipe(display, pipe, output) {
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200155 drmModeModeInfoPtr mode;
156 igt_plane_t *primary;
Chris Wilson162d4562016-06-22 15:41:23 +0100157
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200158 if (output->pending_crtc_idx_mask)
Chris Wilson162d4562016-06-22 15:41:23 +0100159 continue;
160
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200161 igt_output_set_pipe(output, pipe);
162 mode = igt_output_get_mode(output);
163
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200164 igt_create_pattern_fb(display->drm_fd,
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200165 mode->hdisplay, mode->vdisplay,
166 DRM_FORMAT_XRGB8888, I915_TILING_NONE, fb_info);
167
168 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
169 igt_plane_set_fb(primary, fb_info);
170
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200171 return output;
Chris Wilson162d4562016-06-22 15:41:23 +0100172 }
173
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200174 return NULL;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200175}
176
177static void set_cursor_on_pipe(igt_display_t *display, enum pipe pipe, struct igt_fb *fb)
178{
179 igt_plane_t *plane, *cursor = NULL;
180
181 for_each_plane_on_pipe(display, pipe, plane) {
182 if (!plane->is_cursor)
183 continue;
184
185 cursor = plane;
186 break;
187 }
188
189 igt_require(cursor);
190 igt_plane_set_fb(cursor, fb);
191}
192
193static void populate_cursor_args(igt_display_t *display, enum pipe pipe,
194 struct drm_mode_cursor *arg, struct igt_fb *fb)
195{
196 arg->crtc_id = display->pipes[pipe].crtc_id;
197 arg->flags = DRM_MODE_CURSOR_MOVE;
198 arg->x = 128;
199 arg->y = 128;
200 arg->width = fb->width;
201 arg->height = fb->height;
202 arg->handle = fb->gem_handle;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200203 arg[1] = *arg;
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200204}
205
206static void do_cleanup_display(igt_display_t *display)
207{
208 enum pipe pipe;
209 igt_output_t *output;
210 igt_plane_t *plane;
211
212 for_each_pipe(display, pipe)
213 for_each_plane_on_pipe(display, pipe, plane)
214 igt_plane_set_fb(plane, NULL);
215
216 for_each_connected_output(display, output)
217 igt_output_set_pipe(output, PIPE_NONE);
218
219 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100220}
221
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200222static enum pipe find_connected_pipe(igt_display_t *display, bool second)
223{
224 enum pipe pipe, first = PIPE_NONE;
225 igt_output_t *output;
226 igt_output_t *first_output = NULL;
227 bool found = false;
228
229 for_each_pipe_with_valid_output(display, pipe, output) {
230 if (first == pipe || output == first_output)
231 continue;
232
233 if (second) {
234 first = pipe;
235 first_output = output;
236 second = false;
237 continue;
238 }
239
240 found = true;
241 break;
242 }
243
244 if (first_output)
245 igt_require_f(found, "No second valid output found\n");
246 else
Chris Wilson1105d9f2016-08-23 18:03:51 +0100247 igt_require_f(found, "No valid outputs found\n");
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200248
249 return pipe;
250}
251
252static void flip_nonblocking(igt_display_t *display, enum pipe pipe, bool atomic, struct igt_fb *fb)
253{
254 igt_plane_t *primary = &display->pipes[pipe].planes[IGT_PLANE_PRIMARY];
255
256 if (!atomic) {
257 /* Schedule a nonblocking flip for the next vblank */
258 do_or_die(drmModePageFlip(display->drm_fd, display->pipes[pipe].crtc_id, fb->fb_id,
259 DRM_MODE_PAGE_FLIP_EVENT, fb));
260 } else {
261 igt_plane_set_fb(primary, fb);
262 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, fb);
263 }
264}
265
266enum flip_test {
267 flip_test_legacy = 0,
268 flip_test_varying_size,
269 flip_test_toggle_visibility,
270 flip_test_atomic,
271 flip_test_atomic_transitions,
272 flip_test_atomic_transitions_varying_size,
273 flip_test_last = flip_test_atomic_transitions_varying_size
274};
275
276static void transition_nonblocking(igt_display_t *display, enum pipe pipe,
277 struct igt_fb *prim_fb, struct igt_fb *argb_fb,
278 bool hide_sprite)
279{
280 igt_plane_t *primary = &display->pipes[pipe].planes[IGT_PLANE_PRIMARY];
281 igt_plane_t *sprite = &display->pipes[pipe].planes[IGT_PLANE_2];
282
283 if (hide_sprite) {
284 igt_plane_set_fb(primary, prim_fb);
285 igt_plane_set_fb(sprite, NULL);
286 } else {
287 igt_plane_set_fb(primary, NULL);
288 igt_plane_set_fb(sprite, argb_fb);
289 }
290
291 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
292}
293
294static void prepare_flip_test(igt_display_t *display,
295 enum flip_test mode,
296 enum pipe flip_pipe,
297 enum pipe cursor_pipe,
298 struct drm_mode_cursor *arg,
299 const struct igt_fb *prim_fb,
300 struct igt_fb *argb_fb,
301 struct igt_fb *cursor_fb2)
302{
303 argb_fb->gem_handle = 0;
304 cursor_fb2->gem_handle = 0;
305
306 if (mode == flip_test_varying_size ||
307 mode == flip_test_atomic_transitions_varying_size) {
308 uint64_t width, height;
309
310 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_WIDTH, &width));
311 do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height));
312
313 igt_skip_on(width <= 64 && height <= 64);
314 igt_create_color_fb(display->drm_fd, width, height,
315 DRM_FORMAT_ARGB8888, 0, 1., 0., .7, cursor_fb2);
316
317 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
318 arg[1].handle = cursor_fb2->gem_handle;
319 arg[1].width = width;
320 arg[1].height = height;
321 }
322
323 if (mode == flip_test_legacy ||
324 mode == flip_test_atomic) {
325 arg[1].x = 192;
326 arg[1].y = 192;
327 }
328
329 if (mode == flip_test_toggle_visibility) {
330 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
331 arg[1].handle = 0;
332 arg[1].width = arg[1].height = 0;
333 }
334
335 if (mode == flip_test_atomic_transitions ||
336 mode == flip_test_atomic_transitions_varying_size) {
337 igt_require(display->pipes[flip_pipe].n_planes > 1 &&
338 !display->pipes[flip_pipe].planes[IGT_PLANE_2].is_cursor);
339
340 igt_create_color_pattern_fb(display->drm_fd, prim_fb->width, prim_fb->height,
341 DRM_FORMAT_ARGB8888, 0, .1, .1, .1, argb_fb);
342 }
343}
344
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200345static void flip(igt_display_t *display,
Chris Wilson162d4562016-06-22 15:41:23 +0100346 int cursor_pipe, int flip_pipe,
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200347 int timeout, enum flip_test mode)
Chris Wilson162d4562016-06-22 15:41:23 +0100348{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200349 struct drm_mode_cursor arg[2];
Chris Wilson162d4562016-06-22 15:41:23 +0100350 uint64_t *results;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200351 struct igt_fb fb_info, fb_info2, argb_fb, cursor_fb, cursor_fb2;
Chris Wilson162d4562016-06-22 15:41:23 +0100352
353 results = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
354 igt_assert(results != MAP_FAILED);
355
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200356 flip_pipe = find_connected_pipe(display, !!flip_pipe);
357 cursor_pipe = find_connected_pipe(display, !!cursor_pipe);
358
359 igt_info("Using pipe %s for page flip, pipe %s for cursor\n",
360 kmstest_pipe_name(flip_pipe), kmstest_pipe_name(cursor_pipe));
361
362 if (mode >= flip_test_atomic)
363 igt_require(display->is_atomic);
364
365 igt_require(set_fb_on_crtc(display, flip_pipe, &fb_info));
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200366 if (flip_pipe != cursor_pipe)
367 igt_require(set_fb_on_crtc(display, cursor_pipe, &fb_info2));
Chris Wilson162d4562016-06-22 15:41:23 +0100368
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200369 igt_create_color_fb(display->drm_fd, fb_info.width, fb_info.height, DRM_FORMAT_ARGB8888, 0, .5, .5, .5, &cursor_fb);
370
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200371 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
372 set_cursor_on_pipe(display, cursor_pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200373 populate_cursor_args(display, cursor_pipe, arg, &cursor_fb);
374
375 prepare_flip_test(display, mode, flip_pipe, cursor_pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100376
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200377 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100378
Chris Wilson162d4562016-06-22 15:41:23 +0100379 igt_fork(child, 1) {
380 unsigned long count = 0;
381
382 igt_until_timeout(timeout) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200383 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[(count & 64)/64]);
Chris Wilson162d4562016-06-22 15:41:23 +0100384 count++;
385 }
386
387 igt_debug("cursor count=%lu\n", count);
388 results[0] = count;
389 }
390 igt_fork(child, 1) {
391 unsigned long count = 0;
Chris Wilson162d4562016-06-22 15:41:23 +0100392
393 igt_until_timeout(timeout) {
394 char buf[128];
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200395
396 switch (mode) {
397 default:
398 flip_nonblocking(display, flip_pipe, mode >= flip_test_atomic, &fb_info);
399 break;
400 case flip_test_atomic_transitions:
401 case flip_test_atomic_transitions_varying_size:
402 transition_nonblocking(display, flip_pipe, &fb_info, &argb_fb, count & 1);
403 break;
404 }
405
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200406 while (read(display->drm_fd, buf, sizeof(buf)) < 0 &&
Chris Wilsond86d6eb2016-06-23 21:07:36 +0100407 (errno == EINTR || errno == EAGAIN))
408 ;
Chris Wilson162d4562016-06-22 15:41:23 +0100409 count++;
410 }
411
412 igt_debug("flip count=%lu\n", count);
413 results[1] = count;
414 }
415 igt_waitchildren();
416
Chris Wilson162d4562016-06-22 15:41:23 +0100417 munmap(results, 4096);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200418
419 do_cleanup_display(display);
420
421 igt_remove_fb(display->drm_fd, &fb_info);
422 if (flip_pipe != cursor_pipe)
423 igt_remove_fb(display->drm_fd, &fb_info2);
424 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200425 if (argb_fb.gem_handle)
426 igt_remove_fb(display->drm_fd, &argb_fb);
427 if (cursor_fb2.gem_handle)
428 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100429}
430
431static inline uint32_t pipe_select(int pipe)
432{
433 if (pipe > 1)
434 return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
435 else if (pipe > 0)
436 return DRM_VBLANK_SECONDARY;
437 else
438 return 0;
439}
440
441static unsigned get_vblank(int fd, int pipe, unsigned flags)
442{
443 union drm_wait_vblank vbl;
444
445 memset(&vbl, 0, sizeof(vbl));
446 vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe) | flags;
447 if (drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
448 return 0;
449
450 return vbl.reply.sequence;
451}
452
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200453static void basic_flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloops)
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200454{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200455 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100456 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200457 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson162d4562016-06-22 15:41:23 +0100458 unsigned vblank_start;
459 int target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200460 enum pipe pipe = find_connected_pipe(display, false);
461
462 if (mode >= flip_test_atomic)
463 igt_require(display->is_atomic);
Chris Wilson162d4562016-06-22 15:41:23 +0100464
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200465 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Chris Wilson162d4562016-06-22 15:41:23 +0100466
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200467 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 +0200468 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200469 populate_cursor_args(display, pipe, arg, &cursor_fb);
470
471 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100472
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200473 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson162d4562016-06-22 15:41:23 +0100474
475 target = 4096;
476 do {
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200477 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
478 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson162d4562016-06-22 15:41:23 +0100479 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200480 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Chris Wilson162d4562016-06-22 15:41:23 +0100481 target /= 2;
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200482 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
Chris Wilson162d4562016-06-22 15:41:23 +0100483 break;
484 } while (target);
485 igt_require(target > 1);
486
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200487 igt_debug("Using a target of %d cursor updates per half-vblank\n", target);
Chris Wilson162d4562016-06-22 15:41:23 +0100488
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200489 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
490 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200491 for (int n = 0; n < target; n++)
492 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200493 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson162d4562016-06-22 15:41:23 +0100494
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100495 while (nloops--) {
496 /* Start with a synchronous query to align with the vblank */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200497 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200498 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson162d4562016-06-22 15:41:23 +0100499
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200500 switch (mode) {
501 default:
502 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
503 break;
504 case flip_test_atomic_transitions:
505 case flip_test_atomic_transitions_varying_size:
506 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (nloops & 2) /2);
507 break;
508 }
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100509
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200510 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100511 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200512 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200513 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100514
515 igt_set_timeout(1, "Stuck page flip");
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200516 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200517 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100518 igt_reset_timeout();
519 }
Chris Wilson162d4562016-06-22 15:41:23 +0100520
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200521 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200522 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200523 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200524
525 if (argb_fb.gem_handle)
526 igt_remove_fb(display->drm_fd, &argb_fb);
527 if (cursor_fb2.gem_handle)
528 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100529}
530
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200531static bool skip_on_unsupported_nonblocking_modeset(igt_display_t *display)
532{
533 enum pipe pipe;
534 int ret;
535
536 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
537
538 ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
539
540 if (ret == -EINVAL)
541 return true;
542
543 igt_assert_eq(ret, 0);
544
545 /* Force the next state to update all crtc's, to synchronize with the nonblocking modeset. */
546 for_each_pipe(display, pipe)
547 display->pipes[pipe].mode_changed = true;
548
549 return false;
550}
551
552static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200553{
554 struct drm_mode_cursor arg[2], arg2[2];
555 struct drm_event_vblank vbl;
556 struct igt_fb fb_info, fb2_info, cursor_fb;
557 unsigned vblank_start;
558 enum pipe pipe = find_connected_pipe(display, false);
559 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200560 igt_output_t *output2;
561 bool skip_test = false;
562
563 if (modeset)
564 igt_require(display->is_atomic);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200565
566 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200567 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200568
569 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
570 set_cursor_on_pipe(display, pipe, &cursor_fb);
571 populate_cursor_args(display, pipe, arg, &cursor_fb);
572
573 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
574 arg[1].handle = 0;
575 arg[1].width = arg[1].height = 0;
576
577 set_cursor_on_pipe(display, pipe2, &cursor_fb);
578 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
579
580 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
581 arg2[0].handle = 0;
582 arg2[0].width = arg2[0].height = 0;
583
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200584 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
585 goto cleanup;
586
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200587 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
588
589 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
590 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
591 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
592 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
593 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
594
595 while (nloops--) {
596 /* Start with a synchronous query to align with the vblank */
597 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
598 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
599
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200600
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200601 flip_nonblocking(display, pipe, false, &fb_info);
602
603 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
604
605 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200606 if (!modeset) {
607 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
608 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
609 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
610 } else {
611 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
612
613 igt_output_set_pipe(output2, (nloops & 1) ? PIPE_NONE : pipe2);
614 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
615
616 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
617 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200618
619 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
620
621 igt_set_timeout(1, "Stuck page flip");
622 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
623 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
624 igt_reset_timeout();
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200625
626 if (modeset) {
627 /* wait for pending modeset to complete, to prevent -EBUSY */
628 display->pipes[pipe2].mode_changed = true;
629 igt_display_commit2(display, COMMIT_ATOMIC);
630 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200631 }
632
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200633cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200634 do_cleanup_display(display);
635 igt_remove_fb(display->drm_fd, &fb_info);
636 igt_remove_fb(display->drm_fd, &fb2_info);
637 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200638
639 if (skip_test)
640 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200641}
642
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200643static void basic_cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloops)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100644{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200645 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100646 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200647 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100648 unsigned vblank_start, vblank_last;
649 volatile unsigned long *shared;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200650 long target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200651 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200652 igt_output_t *output;
653 uint32_t vrefresh;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200654
655 if (mode >= flip_test_atomic)
656 igt_require(display->is_atomic);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100657
658 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
659 igt_assert(shared != MAP_FAILED);
660
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200661 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
662 vrefresh = igt_output_get_mode(output)->vrefresh;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100663
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200664 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 +0200665 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200666 populate_cursor_args(display, pipe, arg, &cursor_fb);
667
668 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100669
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200670 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100671
672 target = 4096;
673 do {
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200674 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
675 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100676 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200677 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100678 target /= 2;
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200679 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100680 break;
681 } while (target);
682 igt_require(target > 1);
683
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200684 igt_debug("Using a target of %ld cursor updates per half-vblank (%u)\n",
685 target, vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100686
687 for (int i = 0; i < nloops; i++) {
688 shared[0] = 0;
689 igt_fork(child, 1) {
690 unsigned long count = 0;
691 while (!shared[0]) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200692 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100693 count++;
694 }
695 igt_debug("child: %lu cursor updates\n", count);
696 shared[0] = count;
697 }
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200698
699 switch (mode) {
700 default:
701 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
702 break;
703 case flip_test_atomic_transitions:
704 case flip_test_atomic_transitions_varying_size:
705 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (i & 2) >> 1);
706 break;
707 }
708
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200709 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100710 vblank_start = vblank_last = vbl.sequence;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200711 for (int n = 0; n < vrefresh; n++) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200712 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
713
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200714 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100715 if (vbl.sequence != vblank_last + 1) {
716 igt_warn("page flip %d was delayed, missed %d frames\n",
717 n, vbl.sequence - vblank_last - 1);
718 }
719 vblank_last = vbl.sequence;
720 }
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200721
722 if (mode != flip_test_atomic_transitions &&
723 mode != flip_test_atomic_transitions_varying_size)
724 igt_assert_eq(vbl.sequence, vblank_start + vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100725
726 shared[0] = 1;
727 igt_waitchildren();
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200728 igt_assert_f(shared[0] > vrefresh*target,
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100729 "completed %lu cursor updated in a period of 60 flips, "
730 "we expect to complete approximately %lu updateds, "
731 "with the threshold set at %lu\n",
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200732 shared[0], 2ul*vrefresh*target, vrefresh*target);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100733 }
734
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200735 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200736 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200737 igt_remove_fb(display->drm_fd, &cursor_fb);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100738 munmap((void *)shared, 4096);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200739 if (argb_fb.gem_handle)
740 igt_remove_fb(display->drm_fd, &argb_fb);
741 if (cursor_fb2.gem_handle)
742 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100743}
744
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200745static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200746{
747 struct drm_mode_cursor arg[2], arg2[2];
748 struct drm_event_vblank vbl;
749 struct igt_fb fb_info, fb2_info, cursor_fb;
750 unsigned vblank_start, vblank_last;
751 volatile unsigned long *shared;
752 int target;
753 enum pipe pipe = find_connected_pipe(display, false);
754 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200755 igt_output_t *output2;
756 bool skip_test = false;
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200757
758 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
759 igt_assert(shared != MAP_FAILED);
760
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200761 if (modeset)
762 igt_require(display->is_atomic);
763
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200764 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200765 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200766
767 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
768 set_cursor_on_pipe(display, pipe, &cursor_fb);
769 populate_cursor_args(display, pipe, arg, &cursor_fb);
770
771 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
772 arg[1].handle = 0;
773 arg[1].width = arg[1].height = 0;
774
775 set_cursor_on_pipe(display, pipe2, &cursor_fb);
776 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
777
778 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
779 arg2[0].handle = 0;
780 arg2[0].width = arg2[0].height = 0;
781
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200782 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
783 goto cleanup;
784
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200785 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
786
787 target = 4096;
788 do {
789 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
790 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
791
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200792 if (!modeset)
793 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
794
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200795 for (int n = 0; n < target; n++) {
796 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
797 }
798 target /= 2;
799 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
800 break;
801 } while (target);
802 igt_require(target > 1);
803
804 igt_debug("Using a target of %d cursor updates per half-vblank\n",
805 target);
806
807 for (int i = 0; i < nloops; i++) {
808 shared[0] = 0;
809 igt_fork(child, 1) {
810 unsigned long count = 0;
811
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200812 if (!modeset)
813 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[i & 1]);
814 else {
815 igt_output_set_pipe(output2, (i & 1) ? pipe2 : PIPE_NONE);
816 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET |
817 DRM_MODE_ATOMIC_NONBLOCK, NULL);
818 }
819
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200820 while (!shared[0]) {
821 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
822 count++;
823 }
824 igt_debug("child: %lu cursor updates\n", count);
825 shared[0] = count;
826 }
827
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200828 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200829
830 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
831 vblank_start = vblank_last = vbl.sequence;
832 for (int n = 0; n < 60; n++) {
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200833 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200834
835 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
836 if (vbl.sequence != vblank_last + 1) {
837 igt_warn("page flip %d was delayed, missed %d frames\n",
838 n, vbl.sequence - vblank_last - 1);
839 }
840 vblank_last = vbl.sequence;
841 }
842 igt_assert_eq(vbl.sequence, vblank_start + 60);
843
844 shared[0] = 1;
845 igt_waitchildren();
846 igt_assert_f(shared[0] > 60*target,
847 "completed %lu cursor updated in a period of 60 flips, "
848 "we expect to complete approximately %lu updateds, "
849 "with the threshold set at %lu\n",
850 shared[0], 2*60ul*target, 60ul*target);
851 }
852
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200853cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200854 do_cleanup_display(display);
855 igt_remove_fb(display->drm_fd, &fb_info);
856 igt_remove_fb(display->drm_fd, &fb2_info);
857 igt_remove_fb(display->drm_fd, &cursor_fb);
858 munmap((void *)shared, 4096);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200859
860 if (skip_test)
861 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200862}
863
Chris Wilson9579e542016-05-23 21:56:01 +0100864igt_main
865{
Chris Wilsondab6b6b2016-05-24 16:14:32 +0100866 const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200867 igt_display_t display = { .drm_fd = -1 };
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200868 int i;
Chris Wilson9579e542016-05-23 21:56:01 +0100869
870 igt_skip_on_simulation();
871
872 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200873 display.drm_fd = drm_open_driver_master(DRIVER_ANY);
Chris Wilson9579e542016-05-23 21:56:01 +0100874 kmstest_set_vt_graphics_mode();
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100875
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200876 igt_display_init(&display, display.drm_fd);
877 igt_require(display.n_pipes > 0);
Chris Wilson9579e542016-05-23 21:56:01 +0100878 }
879
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100880 igt_subtest_group {
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200881 for (int n = 0; n < I915_MAX_PIPES; n++) {
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100882 errno = 0;
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200883
Chris Wilson04b8f0e2016-05-25 14:53:34 +0100884 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200885 igt_skip_on(n >= display.n_pipes);
Chris Wilson04b8f0e2016-05-25 14:53:34 +0100886 }
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100887
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200888 igt_subtest_f("pipe-%s-single-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200889 stress(&display, n, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200890 igt_subtest_f("pipe-%s-single-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200891 stress(&display, n, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100892
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200893 igt_subtest_f("pipe-%s-forked-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200894 stress(&display, n, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200895 igt_subtest_f("pipe-%s-forked-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200896 stress(&display, n, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100897
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200898 igt_subtest_f("pipe-%s-torture-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200899 stress(&display, n, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200900 igt_subtest_f("pipe-%s-torture-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200901 stress(&display, n, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100902 }
903 }
904
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200905 igt_subtest("all-pipes-single-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200906 stress(&display, -1, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200907 igt_subtest("all-pipes-single-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200908 stress(&display, -1, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100909
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200910 igt_subtest("all-pipes-forked-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200911 stress(&display, -1, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200912 igt_subtest("all-pipes-forked-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200913 stress(&display, -1, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilson9579e542016-05-23 21:56:01 +0100914
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200915 igt_subtest("all-pipes-torture-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200916 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200917 igt_subtest("all-pipes-torture-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200918 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100919
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200920 igt_subtest("2x-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200921 two_screens_flip_vs_cursor(&display, 8, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200922
923 igt_subtest("2x-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200924 two_screens_cursor_vs_flip(&display, 4, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200925
926 igt_subtest("2x-long-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200927 two_screens_flip_vs_cursor(&display, 150, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200928
929 igt_subtest("2x-long-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200930 two_screens_cursor_vs_flip(&display, 150, false);
931
932 igt_subtest("2x-nonblocking-modeset-vs-cursor-atomic")
933 two_screens_flip_vs_cursor(&display, 8, true);
934
935 igt_subtest("2x-cursor-vs-nonblocking-modeset-atomic")
936 two_screens_cursor_vs_flip(&display, 4, true);
937
938 igt_subtest("2x-long-nonblocking-modeset-vs-cursor-atomic")
939 two_screens_flip_vs_cursor(&display, 150, true);
940
941 igt_subtest("2x-long-cursor-vs-nonblocking-modeset-atomic")
942 two_screens_cursor_vs_flip(&display, 150, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200943
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200944 for (i = 0; i <= flip_test_last; i++) {
945 const char *modes[flip_test_last+1] = {
946 "legacy",
947 "varying-size",
948 "toggle",
949 "atomic",
950 "atomic-transitions",
951 "atomic-transitions-varying-size"
952 };
953 const char *prefix = "short-";
Chris Wilson162d4562016-06-22 15:41:23 +0100954
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200955 switch (i) {
956 case flip_test_legacy:
957 case flip_test_varying_size:
958 case flip_test_atomic:
959 prefix = "basic-";
960 break;
961 default: break;
962 }
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200963
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200964 igt_subtest_f("%sflip-vs-cursor-%s", prefix, modes[i])
965 basic_flip_vs_cursor(&display, i, 8);
966 igt_subtest_f("long-flip-vs-cursor-%s", modes[i])
967 basic_flip_vs_cursor(&display, i, 150);
968 igt_subtest_f("%scursor-vs-flip-%s", prefix, modes[i])
969 basic_cursor_vs_flip(&display, i, 4);
970 igt_subtest_f("long-cursor-vs-flip-%s", modes[i])
971 basic_cursor_vs_flip(&display, i, 150);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200972
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200973 igt_subtest_f("cursorA-vs-flipA-%s", modes[i])
974 flip(&display, 0, 0, 10, i);
975
976 igt_subtest_f("cursorA-vs-flipB-%s", modes[i])
977 flip(&display, 0, 1, 10, i);
978
979 igt_subtest_f("cursorB-vs-flipA-%s", modes[i])
980 flip(&display, 1, 0, 10, i);
981
982 igt_subtest_f("cursorB-vs-flipB-%s", modes[i])
983 flip(&display, 1, 1, 10, i);
Chris Wilson162d4562016-06-22 15:41:23 +0100984 }
985
Chris Wilson9579e542016-05-23 21:56:01 +0100986 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200987 igt_display_fini(&display);
Chris Wilson9579e542016-05-23 21:56:01 +0100988 }
989}