blob: c9eef27bcf05c5c8249c149a32614a64c11d84d5 [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
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100475 if (nloops) {
476 target = 4096;
477 do {
478 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
479 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
480 for (int n = 0; n < target; n++)
481 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
482 target /= 2;
483 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
484 break;
485 } while (target);
486 igt_require(target > 1);
Chris Wilson162d4562016-06-22 15:41:23 +0100487
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100488 igt_debug("Using a target of %d cursor updates per half-vblank\n", target);
489 } else
490 target = 1;
Chris Wilson162d4562016-06-22 15:41:23 +0100491
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200492 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
493 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200494 for (int n = 0; n < target; n++)
495 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200496 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson162d4562016-06-22 15:41:23 +0100497
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100498 do {
499 /* Bind the cursor first to warm up */
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200500 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson162d4562016-06-22 15:41:23 +0100501
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100502 /* Start with a synchronous query to align with the vblank */
503 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200504 switch (mode) {
505 default:
506 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
507 break;
508 case flip_test_atomic_transitions:
509 case flip_test_atomic_transitions_varying_size:
510 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (nloops & 2) /2);
511 break;
512 }
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100513
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100514 /* The nonblocking flip should not have delayed us */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200515 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100516 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200517 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100518 /* Nor should it have delayed the following cursor update */
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200519 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100520
521 igt_set_timeout(1, "Stuck page flip");
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200522 igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200523 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100524 igt_reset_timeout();
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100525 } while (nloops--);
Chris Wilson162d4562016-06-22 15:41:23 +0100526
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200527 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200528 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200529 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200530
531 if (argb_fb.gem_handle)
532 igt_remove_fb(display->drm_fd, &argb_fb);
533 if (cursor_fb2.gem_handle)
534 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100535}
536
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200537static bool skip_on_unsupported_nonblocking_modeset(igt_display_t *display)
538{
539 enum pipe pipe;
540 int ret;
541
542 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
543
544 ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
545
546 if (ret == -EINVAL)
547 return true;
548
549 igt_assert_eq(ret, 0);
550
551 /* Force the next state to update all crtc's, to synchronize with the nonblocking modeset. */
552 for_each_pipe(display, pipe)
553 display->pipes[pipe].mode_changed = true;
554
555 return false;
556}
557
558static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200559{
560 struct drm_mode_cursor arg[2], arg2[2];
561 struct drm_event_vblank vbl;
562 struct igt_fb fb_info, fb2_info, cursor_fb;
563 unsigned vblank_start;
564 enum pipe pipe = find_connected_pipe(display, false);
565 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200566 igt_output_t *output2;
567 bool skip_test = false;
568
569 if (modeset)
570 igt_require(display->is_atomic);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200571
572 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200573 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200574
575 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
576 set_cursor_on_pipe(display, pipe, &cursor_fb);
577 populate_cursor_args(display, pipe, arg, &cursor_fb);
578
579 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
580 arg[1].handle = 0;
581 arg[1].width = arg[1].height = 0;
582
583 set_cursor_on_pipe(display, pipe2, &cursor_fb);
584 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
585
586 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
587 arg2[0].handle = 0;
588 arg2[0].width = arg2[0].height = 0;
589
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200590 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
591 goto cleanup;
592
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200593 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
594
595 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
596 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
597 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
598 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
599 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
600
601 while (nloops--) {
602 /* Start with a synchronous query to align with the vblank */
603 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
604 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
605
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200606
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200607 flip_nonblocking(display, pipe, false, &fb_info);
608
609 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
610
611 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200612 if (!modeset) {
613 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
614 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
615 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[nloops & 1]);
616 } else {
617 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
618
619 igt_output_set_pipe(output2, (nloops & 1) ? PIPE_NONE : pipe2);
620 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET | DRM_MODE_ATOMIC_NONBLOCK, NULL);
621
622 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
623 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200624
625 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
626
627 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();
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200631
632 if (modeset) {
633 /* wait for pending modeset to complete, to prevent -EBUSY */
634 display->pipes[pipe2].mode_changed = true;
635 igt_display_commit2(display, COMMIT_ATOMIC);
636 }
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200637 }
638
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200639cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200640 do_cleanup_display(display);
641 igt_remove_fb(display->drm_fd, &fb_info);
642 igt_remove_fb(display->drm_fd, &fb2_info);
643 igt_remove_fb(display->drm_fd, &cursor_fb);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200644
645 if (skip_test)
646 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200647}
648
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200649static void basic_cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloops)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100650{
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200651 struct drm_mode_cursor arg[2];
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100652 struct drm_event_vblank vbl;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200653 struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100654 unsigned vblank_start, vblank_last;
655 volatile unsigned long *shared;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200656 long target;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200657 enum pipe pipe = find_connected_pipe(display, false);
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200658 igt_output_t *output;
659 uint32_t vrefresh;
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200660
661 if (mode >= flip_test_atomic)
662 igt_require(display->is_atomic);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100663
664 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
665 igt_assert(shared != MAP_FAILED);
666
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200667 igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
668 vrefresh = igt_output_get_mode(output)->vrefresh;
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100669
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200670 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 +0200671 set_cursor_on_pipe(display, pipe, &cursor_fb);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200672 populate_cursor_args(display, pipe, arg, &cursor_fb);
673
674 prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100675
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200676 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100677
678 target = 4096;
679 do {
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200680 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
681 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100682 for (int n = 0; n < target; n++)
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200683 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100684 target /= 2;
Maarten Lankhorst29516cd2016-07-18 11:47:06 +0200685 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100686 break;
687 } while (target);
688 igt_require(target > 1);
689
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200690 igt_debug("Using a target of %ld cursor updates per half-vblank (%u)\n",
691 target, vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100692
693 for (int i = 0; i < nloops; i++) {
694 shared[0] = 0;
695 igt_fork(child, 1) {
696 unsigned long count = 0;
697 while (!shared[0]) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200698 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100699 count++;
700 }
701 igt_debug("child: %lu cursor updates\n", count);
702 shared[0] = count;
703 }
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200704
705 switch (mode) {
706 default:
707 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
708 break;
709 case flip_test_atomic_transitions:
710 case flip_test_atomic_transitions_varying_size:
711 transition_nonblocking(display, pipe, &fb_info, &argb_fb, (i & 2) >> 1);
712 break;
713 }
714
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200715 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100716 vblank_start = vblank_last = vbl.sequence;
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200717 for (int n = 0; n < vrefresh; n++) {
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200718 flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info);
719
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200720 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100721 if (vbl.sequence != vblank_last + 1) {
722 igt_warn("page flip %d was delayed, missed %d frames\n",
723 n, vbl.sequence - vblank_last - 1);
724 }
725 vblank_last = vbl.sequence;
726 }
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200727
728 if (mode != flip_test_atomic_transitions &&
729 mode != flip_test_atomic_transitions_varying_size)
730 igt_assert_eq(vbl.sequence, vblank_start + vrefresh);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100731
732 shared[0] = 1;
733 igt_waitchildren();
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200734 igt_assert_f(shared[0] > vrefresh*target,
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100735 "completed %lu cursor updated in a period of 60 flips, "
736 "we expect to complete approximately %lu updateds, "
737 "with the threshold set at %lu\n",
Maarten Lankhorstaaf46cb2016-08-10 13:13:19 +0200738 shared[0], 2ul*vrefresh*target, vrefresh*target);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100739 }
740
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200741 do_cleanup_display(display);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200742 igt_remove_fb(display->drm_fd, &fb_info);
Maarten Lankhorstcf84a942016-07-18 11:04:27 +0200743 igt_remove_fb(display->drm_fd, &cursor_fb);
Chris Wilson88c1f7c2016-06-23 22:53:23 +0100744 munmap((void *)shared, 4096);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200745 if (argb_fb.gem_handle)
746 igt_remove_fb(display->drm_fd, &argb_fb);
747 if (cursor_fb2.gem_handle)
748 igt_remove_fb(display->drm_fd, &cursor_fb2);
Chris Wilson162d4562016-06-22 15:41:23 +0100749}
750
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200751static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool modeset)
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200752{
753 struct drm_mode_cursor arg[2], arg2[2];
754 struct drm_event_vblank vbl;
755 struct igt_fb fb_info, fb2_info, cursor_fb;
756 unsigned vblank_start, vblank_last;
757 volatile unsigned long *shared;
758 int target;
759 enum pipe pipe = find_connected_pipe(display, false);
760 enum pipe pipe2 = find_connected_pipe(display, true);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200761 igt_output_t *output2;
762 bool skip_test = false;
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200763
764 shared = mmap(NULL, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
765 igt_assert(shared != MAP_FAILED);
766
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200767 if (modeset)
768 igt_require(display->is_atomic);
769
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200770 igt_require(set_fb_on_crtc(display, pipe, &fb_info));
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200771 igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200772
773 igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
774 set_cursor_on_pipe(display, pipe, &cursor_fb);
775 populate_cursor_args(display, pipe, arg, &cursor_fb);
776
777 arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
778 arg[1].handle = 0;
779 arg[1].width = arg[1].height = 0;
780
781 set_cursor_on_pipe(display, pipe2, &cursor_fb);
782 populate_cursor_args(display, pipe2, arg2, &cursor_fb);
783
784 arg2[0].flags = arg2[1].flags = DRM_MODE_CURSOR_BO;
785 arg2[0].handle = 0;
786 arg2[0].width = arg2[0].height = 0;
787
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200788 if (modeset && (skip_test = skip_on_unsupported_nonblocking_modeset(display)))
789 goto cleanup;
790
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200791 igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
792
793 target = 4096;
794 do {
795 vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
796 igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
797
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200798 if (!modeset)
799 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[0]);
800
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200801 for (int n = 0; n < target; n++) {
802 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
803 }
804 target /= 2;
805 if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
806 break;
807 } while (target);
808 igt_require(target > 1);
809
810 igt_debug("Using a target of %d cursor updates per half-vblank\n",
811 target);
812
813 for (int i = 0; i < nloops; i++) {
814 shared[0] = 0;
815 igt_fork(child, 1) {
816 unsigned long count = 0;
817
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200818 if (!modeset)
819 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg2[i & 1]);
820 else {
821 igt_output_set_pipe(output2, (i & 1) ? pipe2 : PIPE_NONE);
822 igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET |
823 DRM_MODE_ATOMIC_NONBLOCK, NULL);
824 }
825
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200826 while (!shared[0]) {
827 do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
828 count++;
829 }
830 igt_debug("child: %lu cursor updates\n", count);
831 shared[0] = count;
832 }
833
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200834 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200835
836 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
837 vblank_start = vblank_last = vbl.sequence;
838 for (int n = 0; n < 60; n++) {
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200839 flip_nonblocking(display, pipe, modeset, &fb_info);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200840
841 igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
842 if (vbl.sequence != vblank_last + 1) {
843 igt_warn("page flip %d was delayed, missed %d frames\n",
844 n, vbl.sequence - vblank_last - 1);
845 }
846 vblank_last = vbl.sequence;
847 }
848 igt_assert_eq(vbl.sequence, vblank_start + 60);
849
850 shared[0] = 1;
851 igt_waitchildren();
852 igt_assert_f(shared[0] > 60*target,
853 "completed %lu cursor updated in a period of 60 flips, "
854 "we expect to complete approximately %lu updateds, "
855 "with the threshold set at %lu\n",
856 shared[0], 2*60ul*target, 60ul*target);
857 }
858
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200859cleanup:
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200860 do_cleanup_display(display);
861 igt_remove_fb(display->drm_fd, &fb_info);
862 igt_remove_fb(display->drm_fd, &fb2_info);
863 igt_remove_fb(display->drm_fd, &cursor_fb);
864 munmap((void *)shared, 4096);
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200865
866 if (skip_test)
867 igt_skip("Nonblocking modeset is not supported by this kernel\n");
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200868}
869
Chris Wilson9579e542016-05-23 21:56:01 +0100870igt_main
871{
Chris Wilsondab6b6b2016-05-24 16:14:32 +0100872 const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200873 igt_display_t display = { .drm_fd = -1 };
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200874 int i;
Chris Wilson9579e542016-05-23 21:56:01 +0100875
876 igt_skip_on_simulation();
877
878 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200879 display.drm_fd = drm_open_driver_master(DRIVER_ANY);
Chris Wilson9579e542016-05-23 21:56:01 +0100880 kmstest_set_vt_graphics_mode();
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100881
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200882 igt_display_init(&display, display.drm_fd);
883 igt_require(display.n_pipes > 0);
Chris Wilson9579e542016-05-23 21:56:01 +0100884 }
885
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100886 igt_subtest_group {
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200887 for (int n = 0; n < I915_MAX_PIPES; n++) {
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100888 errno = 0;
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200889
Chris Wilson04b8f0e2016-05-25 14:53:34 +0100890 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200891 igt_skip_on(n >= display.n_pipes);
Chris Wilson04b8f0e2016-05-25 14:53:34 +0100892 }
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100893
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200894 igt_subtest_f("pipe-%s-single-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200895 stress(&display, n, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200896 igt_subtest_f("pipe-%s-single-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200897 stress(&display, n, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100898
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200899 igt_subtest_f("pipe-%s-forked-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200900 stress(&display, n, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200901 igt_subtest_f("pipe-%s-forked-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200902 stress(&display, n, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100903
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200904 igt_subtest_f("pipe-%s-torture-bo", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200905 stress(&display, n, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200906 igt_subtest_f("pipe-%s-torture-move", kmstest_pipe_name(n))
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200907 stress(&display, n, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100908 }
909 }
910
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200911 igt_subtest("all-pipes-single-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200912 stress(&display, -1, 1, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200913 igt_subtest("all-pipes-single-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200914 stress(&display, -1, 1, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsoncce2ff02016-05-25 08:34:25 +0100915
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200916 igt_subtest("all-pipes-forked-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200917 stress(&display, -1, ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200918 igt_subtest("all-pipes-forked-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200919 stress(&display, -1, ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilson9579e542016-05-23 21:56:01 +0100920
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200921 igt_subtest("all-pipes-torture-bo")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200922 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_BO, 20);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200923 igt_subtest("all-pipes-torture-move")
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200924 stress(&display, -1, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
Chris Wilsonf5d370c2016-06-04 21:25:17 +0100925
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200926 igt_subtest("2x-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200927 two_screens_flip_vs_cursor(&display, 8, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200928
929 igt_subtest("2x-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200930 two_screens_cursor_vs_flip(&display, 4, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200931
932 igt_subtest("2x-long-flip-vs-cursor-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200933 two_screens_flip_vs_cursor(&display, 150, false);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200934
935 igt_subtest("2x-long-cursor-vs-flip-legacy")
Maarten Lankhorstdba96672016-08-01 14:44:17 +0200936 two_screens_cursor_vs_flip(&display, 150, false);
937
938 igt_subtest("2x-nonblocking-modeset-vs-cursor-atomic")
939 two_screens_flip_vs_cursor(&display, 8, true);
940
941 igt_subtest("2x-cursor-vs-nonblocking-modeset-atomic")
942 two_screens_cursor_vs_flip(&display, 4, true);
943
944 igt_subtest("2x-long-nonblocking-modeset-vs-cursor-atomic")
945 two_screens_flip_vs_cursor(&display, 150, true);
946
947 igt_subtest("2x-long-cursor-vs-nonblocking-modeset-atomic")
948 two_screens_cursor_vs_flip(&display, 150, true);
Maarten Lankhorst9654d512016-07-25 10:53:54 +0200949
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200950 for (i = 0; i <= flip_test_last; i++) {
951 const char *modes[flip_test_last+1] = {
952 "legacy",
953 "varying-size",
954 "toggle",
955 "atomic",
956 "atomic-transitions",
957 "atomic-transitions-varying-size"
958 };
959 const char *prefix = "short-";
Chris Wilson162d4562016-06-22 15:41:23 +0100960
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200961 switch (i) {
962 case flip_test_legacy:
963 case flip_test_varying_size:
964 case flip_test_atomic:
965 prefix = "basic-";
966 break;
967 default: break;
968 }
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200969
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200970 igt_subtest_f("%sflip-vs-cursor-%s", prefix, modes[i])
Chris Wilson3a3c0fa2016-08-24 14:55:25 +0100971 basic_flip_vs_cursor(&display, i, 0);
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200972 igt_subtest_f("long-flip-vs-cursor-%s", modes[i])
973 basic_flip_vs_cursor(&display, i, 150);
974 igt_subtest_f("%scursor-vs-flip-%s", prefix, modes[i])
975 basic_cursor_vs_flip(&display, i, 4);
976 igt_subtest_f("long-cursor-vs-flip-%s", modes[i])
977 basic_cursor_vs_flip(&display, i, 150);
Maarten Lankhorst1b8d8bc2016-07-12 11:55:26 +0200978
Maarten Lankhorst69aa8a42016-07-19 13:07:32 +0200979 igt_subtest_f("cursorA-vs-flipA-%s", modes[i])
980 flip(&display, 0, 0, 10, i);
981
982 igt_subtest_f("cursorA-vs-flipB-%s", modes[i])
983 flip(&display, 0, 1, 10, i);
984
985 igt_subtest_f("cursorB-vs-flipA-%s", modes[i])
986 flip(&display, 1, 0, 10, i);
987
988 igt_subtest_f("cursorB-vs-flipB-%s", modes[i])
989 flip(&display, 1, 1, 10, i);
Chris Wilson162d4562016-06-22 15:41:23 +0100990 }
991
Chris Wilson9579e542016-05-23 21:56:01 +0100992 igt_fixture {
Maarten Lankhorst6b985872016-07-13 14:59:02 +0200993 igt_display_fini(&display);
Chris Wilson9579e542016-05-23 21:56:01 +0100994 }
995}