xref: /aosp_15_r20/external/igt-gpu-tools/tests/kms_cursor_legacy.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2013 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  */
24*d83cc019SAndroid Build Coastguard Worker 
25*d83cc019SAndroid Build Coastguard Worker #include <sched.h>
26*d83cc019SAndroid Build Coastguard Worker #include <sys/poll.h>
27*d83cc019SAndroid Build Coastguard Worker 
28*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
29*d83cc019SAndroid Build Coastguard Worker #include "igt_rand.h"
30*d83cc019SAndroid Build Coastguard Worker #include "igt_stats.h"
31*d83cc019SAndroid Build Coastguard Worker 
32*d83cc019SAndroid Build Coastguard Worker #if defined(__x86_64__) || defined(__i386__)
33*d83cc019SAndroid Build Coastguard Worker #define cpu_relax()	__builtin_ia32_pause()
34*d83cc019SAndroid Build Coastguard Worker #else
35*d83cc019SAndroid Build Coastguard Worker #define cpu_relax()	asm volatile("": : :"memory")
36*d83cc019SAndroid Build Coastguard Worker #endif
37*d83cc019SAndroid Build Coastguard Worker 
38*d83cc019SAndroid Build Coastguard Worker #ifndef DRM_CAP_CURSOR_WIDTH
39*d83cc019SAndroid Build Coastguard Worker #define DRM_CAP_CURSOR_WIDTH 0x8
40*d83cc019SAndroid Build Coastguard Worker #endif
41*d83cc019SAndroid Build Coastguard Worker 
42*d83cc019SAndroid Build Coastguard Worker #ifndef DRM_CAP_CURSOR_HEIGHT
43*d83cc019SAndroid Build Coastguard Worker #define DRM_CAP_CURSOR_HEIGHT 0x9
44*d83cc019SAndroid Build Coastguard Worker #endif
45*d83cc019SAndroid Build Coastguard Worker 
46*d83cc019SAndroid Build Coastguard Worker #define PAGE_SIZE	4096
47*d83cc019SAndroid Build Coastguard Worker 
48*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Stress legacy cursor ioctl");
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_t *pipe_crc;
51*d83cc019SAndroid Build Coastguard Worker 
stress(igt_display_t * display,enum pipe pipe,int num_children,unsigned mode,int timeout)52*d83cc019SAndroid Build Coastguard Worker static void stress(igt_display_t *display,
53*d83cc019SAndroid Build Coastguard Worker 		   enum pipe pipe, int num_children, unsigned mode,
54*d83cc019SAndroid Build Coastguard Worker 		   int timeout)
55*d83cc019SAndroid Build Coastguard Worker {
56*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg;
57*d83cc019SAndroid Build Coastguard Worker 	uint64_t *results;
58*d83cc019SAndroid Build Coastguard Worker 	bool torture;
59*d83cc019SAndroid Build Coastguard Worker 	int n;
60*d83cc019SAndroid Build Coastguard Worker 	unsigned crtc_id[IGT_MAX_PIPES], num_crtcs;
61*d83cc019SAndroid Build Coastguard Worker 
62*d83cc019SAndroid Build Coastguard Worker 	torture = false;
63*d83cc019SAndroid Build Coastguard Worker 	if (num_children < 0) {
64*d83cc019SAndroid Build Coastguard Worker 		torture = true;
65*d83cc019SAndroid Build Coastguard Worker 		num_children = -num_children;
66*d83cc019SAndroid Build Coastguard Worker 	}
67*d83cc019SAndroid Build Coastguard Worker 
68*d83cc019SAndroid Build Coastguard Worker 	results = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
69*d83cc019SAndroid Build Coastguard Worker 	igt_assert(results != MAP_FAILED);
70*d83cc019SAndroid Build Coastguard Worker 
71*d83cc019SAndroid Build Coastguard Worker 	memset(&arg, 0, sizeof(arg));
72*d83cc019SAndroid Build Coastguard Worker 	arg.flags = DRM_MODE_CURSOR_BO;
73*d83cc019SAndroid Build Coastguard Worker 	arg.crtc_id = 0;
74*d83cc019SAndroid Build Coastguard Worker 	arg.width = 64;
75*d83cc019SAndroid Build Coastguard Worker 	arg.height = 64;
76*d83cc019SAndroid Build Coastguard Worker 	arg.handle = kmstest_dumb_create(display->drm_fd, 64, 64, 32, NULL, NULL);
77*d83cc019SAndroid Build Coastguard Worker 
78*d83cc019SAndroid Build Coastguard Worker 	if (pipe < 0) {
79*d83cc019SAndroid Build Coastguard Worker 		num_crtcs = display->n_pipes;
80*d83cc019SAndroid Build Coastguard Worker 		for_each_pipe(display, n) {
81*d83cc019SAndroid Build Coastguard Worker 			arg.crtc_id = crtc_id[n] = display->pipes[n].crtc_id;
82*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
83*d83cc019SAndroid Build Coastguard Worker 		}
84*d83cc019SAndroid Build Coastguard Worker 	} else {
85*d83cc019SAndroid Build Coastguard Worker 		num_crtcs = 1;
86*d83cc019SAndroid Build Coastguard Worker 		arg.crtc_id = crtc_id[0] = display->pipes[pipe].crtc_id;
87*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
88*d83cc019SAndroid Build Coastguard Worker 	}
89*d83cc019SAndroid Build Coastguard Worker 
90*d83cc019SAndroid Build Coastguard Worker 	arg.flags = mode;
91*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, num_children) {
92*d83cc019SAndroid Build Coastguard Worker 		struct sched_param rt = {.sched_priority = 99 };
93*d83cc019SAndroid Build Coastguard Worker 		cpu_set_t allowed;
94*d83cc019SAndroid Build Coastguard Worker 		unsigned long count = 0;
95*d83cc019SAndroid Build Coastguard Worker 
96*d83cc019SAndroid Build Coastguard Worker 		sched_setscheduler(getpid(), SCHED_RR, &rt);
97*d83cc019SAndroid Build Coastguard Worker 
98*d83cc019SAndroid Build Coastguard Worker 		CPU_ZERO(&allowed);
99*d83cc019SAndroid Build Coastguard Worker 		CPU_SET(child, &allowed);
100*d83cc019SAndroid Build Coastguard Worker 		sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
101*d83cc019SAndroid Build Coastguard Worker 
102*d83cc019SAndroid Build Coastguard Worker 		hars_petruska_f54_1_random_perturb(child);
103*d83cc019SAndroid Build Coastguard Worker 		igt_until_timeout(timeout) {
104*d83cc019SAndroid Build Coastguard Worker 			arg.crtc_id = crtc_id[hars_petruska_f54_1_random_unsafe() % num_crtcs];
105*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg);
106*d83cc019SAndroid Build Coastguard Worker 			count++;
107*d83cc019SAndroid Build Coastguard Worker 		}
108*d83cc019SAndroid Build Coastguard Worker 
109*d83cc019SAndroid Build Coastguard Worker 		igt_debug("[%d] count=%lu\n", child, count);
110*d83cc019SAndroid Build Coastguard Worker 		results[child] = count;
111*d83cc019SAndroid Build Coastguard Worker 	}
112*d83cc019SAndroid Build Coastguard Worker 	if (torture) {
113*d83cc019SAndroid Build Coastguard Worker 		igt_fork(child, num_children) {
114*d83cc019SAndroid Build Coastguard Worker 			struct sched_param rt = {.sched_priority = 1 };
115*d83cc019SAndroid Build Coastguard Worker 			cpu_set_t allowed;
116*d83cc019SAndroid Build Coastguard Worker 			unsigned long long count = 0;
117*d83cc019SAndroid Build Coastguard Worker 
118*d83cc019SAndroid Build Coastguard Worker 			sched_setscheduler(getpid(), SCHED_RR, &rt);
119*d83cc019SAndroid Build Coastguard Worker 
120*d83cc019SAndroid Build Coastguard Worker 			CPU_ZERO(&allowed);
121*d83cc019SAndroid Build Coastguard Worker 			CPU_SET(child, &allowed);
122*d83cc019SAndroid Build Coastguard Worker 			sched_setaffinity(getpid(), sizeof(cpu_set_t), &allowed);
123*d83cc019SAndroid Build Coastguard Worker 			igt_until_timeout(timeout) {
124*d83cc019SAndroid Build Coastguard Worker 				count++;
125*d83cc019SAndroid Build Coastguard Worker 				cpu_relax();
126*d83cc019SAndroid Build Coastguard Worker 			}
127*d83cc019SAndroid Build Coastguard Worker 			igt_debug("[hog:%d] count=%llu\n", child, count);
128*d83cc019SAndroid Build Coastguard Worker 		}
129*d83cc019SAndroid Build Coastguard Worker 	}
130*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
131*d83cc019SAndroid Build Coastguard Worker 
132*d83cc019SAndroid Build Coastguard Worker 	if (num_children > 1) {
133*d83cc019SAndroid Build Coastguard Worker 		igt_stats_t stats;
134*d83cc019SAndroid Build Coastguard Worker 
135*d83cc019SAndroid Build Coastguard Worker 		igt_stats_init_with_size(&stats, num_children);
136*d83cc019SAndroid Build Coastguard Worker 		results[num_children] = 0;
137*d83cc019SAndroid Build Coastguard Worker 		for (int child = 0; child < num_children; child++) {
138*d83cc019SAndroid Build Coastguard Worker 			igt_stats_push(&stats, results[child]);
139*d83cc019SAndroid Build Coastguard Worker 			results[num_children] += results[child];
140*d83cc019SAndroid Build Coastguard Worker 		}
141*d83cc019SAndroid Build Coastguard Worker 		igt_info("Total updates %llu (median of %d processes is %.2f)\n",
142*d83cc019SAndroid Build Coastguard Worker 			 (long long)results[num_children],
143*d83cc019SAndroid Build Coastguard Worker 			 num_children,
144*d83cc019SAndroid Build Coastguard Worker 			 igt_stats_get_median(&stats));
145*d83cc019SAndroid Build Coastguard Worker 		igt_stats_fini(&stats);
146*d83cc019SAndroid Build Coastguard Worker 	} else {
147*d83cc019SAndroid Build Coastguard Worker 		igt_info("Total updates %llu\n", (long long)results[0]);
148*d83cc019SAndroid Build Coastguard Worker 	}
149*d83cc019SAndroid Build Coastguard Worker 
150*d83cc019SAndroid Build Coastguard Worker 	gem_close(display->drm_fd, arg.handle);
151*d83cc019SAndroid Build Coastguard Worker 	munmap(results, PAGE_SIZE);
152*d83cc019SAndroid Build Coastguard Worker }
153*d83cc019SAndroid Build Coastguard Worker 
set_fb_on_crtc(igt_display_t * display,enum pipe pipe,struct igt_fb * fb_info)154*d83cc019SAndroid Build Coastguard Worker static igt_output_t *set_fb_on_crtc(igt_display_t *display, enum pipe pipe, struct igt_fb *fb_info)
155*d83cc019SAndroid Build Coastguard Worker {
156*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
157*d83cc019SAndroid Build Coastguard Worker 
158*d83cc019SAndroid Build Coastguard Worker 	for_each_valid_output_on_pipe(display, pipe, output) {
159*d83cc019SAndroid Build Coastguard Worker 		drmModeModeInfoPtr mode;
160*d83cc019SAndroid Build Coastguard Worker 		igt_plane_t *primary;
161*d83cc019SAndroid Build Coastguard Worker 
162*d83cc019SAndroid Build Coastguard Worker 		if (output->pending_pipe != PIPE_NONE)
163*d83cc019SAndroid Build Coastguard Worker 			continue;
164*d83cc019SAndroid Build Coastguard Worker 
165*d83cc019SAndroid Build Coastguard Worker 		igt_output_set_pipe(output, pipe);
166*d83cc019SAndroid Build Coastguard Worker 		mode = igt_output_get_mode(output);
167*d83cc019SAndroid Build Coastguard Worker 
168*d83cc019SAndroid Build Coastguard Worker 		igt_create_pattern_fb(display->drm_fd,
169*d83cc019SAndroid Build Coastguard Worker 			      mode->hdisplay, mode->vdisplay,
170*d83cc019SAndroid Build Coastguard Worker 			      DRM_FORMAT_XRGB8888, I915_TILING_NONE, fb_info);
171*d83cc019SAndroid Build Coastguard Worker 
172*d83cc019SAndroid Build Coastguard Worker 		primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
173*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(primary, fb_info);
174*d83cc019SAndroid Build Coastguard Worker 
175*d83cc019SAndroid Build Coastguard Worker 		return output;
176*d83cc019SAndroid Build Coastguard Worker 	}
177*d83cc019SAndroid Build Coastguard Worker 
178*d83cc019SAndroid Build Coastguard Worker 	return NULL;
179*d83cc019SAndroid Build Coastguard Worker }
180*d83cc019SAndroid Build Coastguard Worker 
set_cursor_on_pipe(igt_display_t * display,enum pipe pipe,struct igt_fb * fb)181*d83cc019SAndroid Build Coastguard Worker static void set_cursor_on_pipe(igt_display_t *display, enum pipe pipe, struct igt_fb *fb)
182*d83cc019SAndroid Build Coastguard Worker {
183*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *plane, *cursor = NULL;
184*d83cc019SAndroid Build Coastguard Worker 
185*d83cc019SAndroid Build Coastguard Worker 	for_each_plane_on_pipe(display, pipe, plane) {
186*d83cc019SAndroid Build Coastguard Worker 		if (plane->type != DRM_PLANE_TYPE_CURSOR)
187*d83cc019SAndroid Build Coastguard Worker 			continue;
188*d83cc019SAndroid Build Coastguard Worker 
189*d83cc019SAndroid Build Coastguard Worker 		cursor = plane;
190*d83cc019SAndroid Build Coastguard Worker 		break;
191*d83cc019SAndroid Build Coastguard Worker 	}
192*d83cc019SAndroid Build Coastguard Worker 
193*d83cc019SAndroid Build Coastguard Worker 	igt_require(cursor);
194*d83cc019SAndroid Build Coastguard Worker 	igt_plane_set_fb(cursor, fb);
195*d83cc019SAndroid Build Coastguard Worker }
196*d83cc019SAndroid Build Coastguard Worker 
populate_cursor_args(igt_display_t * display,enum pipe pipe,struct drm_mode_cursor * arg,struct igt_fb * fb)197*d83cc019SAndroid Build Coastguard Worker static void populate_cursor_args(igt_display_t *display, enum pipe pipe,
198*d83cc019SAndroid Build Coastguard Worker 				 struct drm_mode_cursor *arg, struct igt_fb *fb)
199*d83cc019SAndroid Build Coastguard Worker {
200*d83cc019SAndroid Build Coastguard Worker 	arg->crtc_id = display->pipes[pipe].crtc_id;
201*d83cc019SAndroid Build Coastguard Worker 	arg->flags = DRM_MODE_CURSOR_MOVE;
202*d83cc019SAndroid Build Coastguard Worker 	arg->x = 128;
203*d83cc019SAndroid Build Coastguard Worker 	arg->y = 128;
204*d83cc019SAndroid Build Coastguard Worker 	arg->width = fb->width;
205*d83cc019SAndroid Build Coastguard Worker 	arg->height = fb->height;
206*d83cc019SAndroid Build Coastguard Worker 	arg->handle = fb->gem_handle;
207*d83cc019SAndroid Build Coastguard Worker 	arg[1] = *arg;
208*d83cc019SAndroid Build Coastguard Worker }
209*d83cc019SAndroid Build Coastguard Worker 
find_connected_pipe(igt_display_t * display,bool second)210*d83cc019SAndroid Build Coastguard Worker static enum pipe find_connected_pipe(igt_display_t *display, bool second)
211*d83cc019SAndroid Build Coastguard Worker {
212*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe, first = PIPE_NONE;
213*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
214*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *first_output = NULL;
215*d83cc019SAndroid Build Coastguard Worker 	bool found = false;
216*d83cc019SAndroid Build Coastguard Worker 
217*d83cc019SAndroid Build Coastguard Worker 	if (!second) {
218*d83cc019SAndroid Build Coastguard Worker 		igt_pipe_crc_free(pipe_crc);
219*d83cc019SAndroid Build Coastguard Worker 		pipe_crc = NULL;
220*d83cc019SAndroid Build Coastguard Worker 
221*d83cc019SAndroid Build Coastguard Worker 		/* Clear display, events will be eaten by commit.. */
222*d83cc019SAndroid Build Coastguard Worker 		igt_display_reset(display);
223*d83cc019SAndroid Build Coastguard Worker 	}
224*d83cc019SAndroid Build Coastguard Worker 
225*d83cc019SAndroid Build Coastguard Worker 	for_each_pipe_with_valid_output(display, pipe, output) {
226*d83cc019SAndroid Build Coastguard Worker 		if (first == pipe || output == first_output)
227*d83cc019SAndroid Build Coastguard Worker 			continue;
228*d83cc019SAndroid Build Coastguard Worker 
229*d83cc019SAndroid Build Coastguard Worker 		if (second) {
230*d83cc019SAndroid Build Coastguard Worker 			first = pipe;
231*d83cc019SAndroid Build Coastguard Worker 			first_output = output;
232*d83cc019SAndroid Build Coastguard Worker 			second = false;
233*d83cc019SAndroid Build Coastguard Worker 			continue;
234*d83cc019SAndroid Build Coastguard Worker 		}
235*d83cc019SAndroid Build Coastguard Worker 
236*d83cc019SAndroid Build Coastguard Worker 		found = true;
237*d83cc019SAndroid Build Coastguard Worker 		break;
238*d83cc019SAndroid Build Coastguard Worker 	}
239*d83cc019SAndroid Build Coastguard Worker 
240*d83cc019SAndroid Build Coastguard Worker 	if (first_output)
241*d83cc019SAndroid Build Coastguard Worker 		igt_require_f(found, "No second valid output found\n");
242*d83cc019SAndroid Build Coastguard Worker 	else
243*d83cc019SAndroid Build Coastguard Worker 		igt_require_f(found, "No valid outputs found\n");
244*d83cc019SAndroid Build Coastguard Worker 
245*d83cc019SAndroid Build Coastguard Worker 	return pipe;
246*d83cc019SAndroid Build Coastguard Worker }
247*d83cc019SAndroid Build Coastguard Worker 
flip_nonblocking(igt_display_t * display,enum pipe pipe_id,bool atomic,struct igt_fb * fb,void * data)248*d83cc019SAndroid Build Coastguard Worker static void flip_nonblocking(igt_display_t *display, enum pipe pipe_id, bool atomic, struct igt_fb *fb, void *data)
249*d83cc019SAndroid Build Coastguard Worker {
250*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_t *pipe = &display->pipes[pipe_id];
251*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
252*d83cc019SAndroid Build Coastguard Worker 	int ret;
253*d83cc019SAndroid Build Coastguard Worker 
254*d83cc019SAndroid Build Coastguard Worker 	igt_set_timeout(1, "Scheduling page flip\n");
255*d83cc019SAndroid Build Coastguard Worker 	if (!atomic) {
256*d83cc019SAndroid Build Coastguard Worker 		/* Schedule a nonblocking flip for the next vblank */
257*d83cc019SAndroid Build Coastguard Worker 		do {
258*d83cc019SAndroid Build Coastguard Worker 			ret = drmModePageFlip(display->drm_fd, pipe->crtc_id, fb->fb_id,
259*d83cc019SAndroid Build Coastguard Worker 					      DRM_MODE_PAGE_FLIP_EVENT, data);
260*d83cc019SAndroid Build Coastguard Worker 		} while (ret == -EBUSY);
261*d83cc019SAndroid Build Coastguard Worker 	} else {
262*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(primary, fb);
263*d83cc019SAndroid Build Coastguard Worker 		do {
264*d83cc019SAndroid Build Coastguard Worker 			ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, data);
265*d83cc019SAndroid Build Coastguard Worker 		} while (ret == -EBUSY);
266*d83cc019SAndroid Build Coastguard Worker 	}
267*d83cc019SAndroid Build Coastguard Worker 	igt_assert(!ret);
268*d83cc019SAndroid Build Coastguard Worker 	igt_reset_timeout();
269*d83cc019SAndroid Build Coastguard Worker }
270*d83cc019SAndroid Build Coastguard Worker 
271*d83cc019SAndroid Build Coastguard Worker enum flip_test {
272*d83cc019SAndroid Build Coastguard Worker 	flip_test_legacy = 0,
273*d83cc019SAndroid Build Coastguard Worker 	flip_test_varying_size,
274*d83cc019SAndroid Build Coastguard Worker 	flip_test_toggle_visibility,
275*d83cc019SAndroid Build Coastguard Worker 	flip_test_atomic,
276*d83cc019SAndroid Build Coastguard Worker 	flip_test_atomic_transitions,
277*d83cc019SAndroid Build Coastguard Worker 	flip_test_atomic_transitions_varying_size,
278*d83cc019SAndroid Build Coastguard Worker 	flip_test_last = flip_test_atomic_transitions_varying_size
279*d83cc019SAndroid Build Coastguard Worker };
280*d83cc019SAndroid Build Coastguard Worker 
cursor_slowpath(enum flip_test mode)281*d83cc019SAndroid Build Coastguard Worker static bool cursor_slowpath(enum flip_test mode)
282*d83cc019SAndroid Build Coastguard Worker {
283*d83cc019SAndroid Build Coastguard Worker 	/* cursor moving doesn't take slowpath, everything else does. */
284*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_legacy || mode == flip_test_atomic)
285*d83cc019SAndroid Build Coastguard Worker 		return false;
286*d83cc019SAndroid Build Coastguard Worker 
287*d83cc019SAndroid Build Coastguard Worker 	return true;
288*d83cc019SAndroid Build Coastguard Worker }
289*d83cc019SAndroid Build Coastguard Worker 
290*d83cc019SAndroid Build Coastguard Worker /*
291*d83cc019SAndroid Build Coastguard Worker  * On platforms with two-stage watermark programming
292*d83cc019SAndroid Build Coastguard Worker  * changing sprite visibility may require a extra vblank wait.
293*d83cc019SAndroid Build Coastguard Worker  *
294*d83cc019SAndroid Build Coastguard Worker  * Handle this here.
295*d83cc019SAndroid Build Coastguard Worker  */
mode_requires_extra_vblank(enum flip_test mode)296*d83cc019SAndroid Build Coastguard Worker static bool mode_requires_extra_vblank(enum flip_test mode)
297*d83cc019SAndroid Build Coastguard Worker {
298*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_atomic_transitions ||
299*d83cc019SAndroid Build Coastguard Worker 	    mode == flip_test_atomic_transitions_varying_size)
300*d83cc019SAndroid Build Coastguard Worker 		return true;
301*d83cc019SAndroid Build Coastguard Worker 
302*d83cc019SAndroid Build Coastguard Worker 	return false;
303*d83cc019SAndroid Build Coastguard Worker }
304*d83cc019SAndroid Build Coastguard Worker 
transition_nonblocking(igt_display_t * display,enum pipe pipe_id,struct igt_fb * prim_fb,struct igt_fb * argb_fb,bool hide_sprite)305*d83cc019SAndroid Build Coastguard Worker static void transition_nonblocking(igt_display_t *display, enum pipe pipe_id,
306*d83cc019SAndroid Build Coastguard Worker 				   struct igt_fb *prim_fb, struct igt_fb *argb_fb,
307*d83cc019SAndroid Build Coastguard Worker 				   bool hide_sprite)
308*d83cc019SAndroid Build Coastguard Worker {
309*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_t *pipe = &display->pipes[pipe_id];
310*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *primary = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_PRIMARY);
311*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *sprite = igt_pipe_get_plane_type(pipe, DRM_PLANE_TYPE_OVERLAY);
312*d83cc019SAndroid Build Coastguard Worker 
313*d83cc019SAndroid Build Coastguard Worker 	if (hide_sprite) {
314*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(primary, prim_fb);
315*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(sprite, NULL);
316*d83cc019SAndroid Build Coastguard Worker 	} else {
317*d83cc019SAndroid Build Coastguard Worker 		int ret;
318*d83cc019SAndroid Build Coastguard Worker 
319*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(primary, NULL);
320*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(sprite, argb_fb);
321*d83cc019SAndroid Build Coastguard Worker 
322*d83cc019SAndroid Build Coastguard Worker 		ret = igt_display_try_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
323*d83cc019SAndroid Build Coastguard Worker 		if (!ret)
324*d83cc019SAndroid Build Coastguard Worker 			return;
325*d83cc019SAndroid Build Coastguard Worker 
326*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == -EINVAL);
327*d83cc019SAndroid Build Coastguard Worker 
328*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(sprite, prim_fb);
329*d83cc019SAndroid Build Coastguard Worker 	}
330*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit_atomic(display, DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT, display);
331*d83cc019SAndroid Build Coastguard Worker }
332*d83cc019SAndroid Build Coastguard Worker 
prepare_flip_test(igt_display_t * display,enum flip_test mode,enum pipe flip_pipe,enum pipe cursor_pipe,struct drm_mode_cursor * arg,const struct igt_fb * prim_fb,struct igt_fb * argb_fb,struct igt_fb * cursor_fb2)333*d83cc019SAndroid Build Coastguard Worker static void prepare_flip_test(igt_display_t *display,
334*d83cc019SAndroid Build Coastguard Worker 			      enum flip_test mode,
335*d83cc019SAndroid Build Coastguard Worker 			      enum pipe flip_pipe,
336*d83cc019SAndroid Build Coastguard Worker 			      enum pipe cursor_pipe,
337*d83cc019SAndroid Build Coastguard Worker 			      struct drm_mode_cursor *arg,
338*d83cc019SAndroid Build Coastguard Worker 			      const struct igt_fb *prim_fb,
339*d83cc019SAndroid Build Coastguard Worker 			      struct igt_fb *argb_fb,
340*d83cc019SAndroid Build Coastguard Worker 			      struct igt_fb *cursor_fb2)
341*d83cc019SAndroid Build Coastguard Worker {
342*d83cc019SAndroid Build Coastguard Worker 	argb_fb->gem_handle = 0;
343*d83cc019SAndroid Build Coastguard Worker 	cursor_fb2->gem_handle = 0;
344*d83cc019SAndroid Build Coastguard Worker 
345*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_varying_size ||
346*d83cc019SAndroid Build Coastguard Worker 	    mode == flip_test_atomic_transitions_varying_size) {
347*d83cc019SAndroid Build Coastguard Worker 		uint64_t width, height;
348*d83cc019SAndroid Build Coastguard Worker 
349*d83cc019SAndroid Build Coastguard Worker 		do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_WIDTH, &width));
350*d83cc019SAndroid Build Coastguard Worker 		do_or_die(drmGetCap(display->drm_fd, DRM_CAP_CURSOR_HEIGHT, &height));
351*d83cc019SAndroid Build Coastguard Worker 
352*d83cc019SAndroid Build Coastguard Worker 		igt_skip_on(width <= 64 && height <= 64);
353*d83cc019SAndroid Build Coastguard Worker 		igt_create_color_fb(display->drm_fd, width, height,
354*d83cc019SAndroid Build Coastguard Worker 				    DRM_FORMAT_ARGB8888, 0, 1., 0., .7, cursor_fb2);
355*d83cc019SAndroid Build Coastguard Worker 
356*d83cc019SAndroid Build Coastguard Worker 		arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
357*d83cc019SAndroid Build Coastguard Worker 		arg[1].handle = cursor_fb2->gem_handle;
358*d83cc019SAndroid Build Coastguard Worker 		arg[1].width = width;
359*d83cc019SAndroid Build Coastguard Worker 		arg[1].height = height;
360*d83cc019SAndroid Build Coastguard Worker 	}
361*d83cc019SAndroid Build Coastguard Worker 
362*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_legacy ||
363*d83cc019SAndroid Build Coastguard Worker 	    mode == flip_test_atomic) {
364*d83cc019SAndroid Build Coastguard Worker 		arg[1].x = 192;
365*d83cc019SAndroid Build Coastguard Worker 		arg[1].y = 192;
366*d83cc019SAndroid Build Coastguard Worker 	}
367*d83cc019SAndroid Build Coastguard Worker 
368*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_toggle_visibility) {
369*d83cc019SAndroid Build Coastguard Worker 		arg[0].flags = arg[1].flags = DRM_MODE_CURSOR_BO;
370*d83cc019SAndroid Build Coastguard Worker 		arg[1].handle = 0;
371*d83cc019SAndroid Build Coastguard Worker 		arg[1].width = arg[1].height = 0;
372*d83cc019SAndroid Build Coastguard Worker 	}
373*d83cc019SAndroid Build Coastguard Worker 
374*d83cc019SAndroid Build Coastguard Worker 	if (mode == flip_test_atomic_transitions ||
375*d83cc019SAndroid Build Coastguard Worker 	    mode == flip_test_atomic_transitions_varying_size) {
376*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->pipes[flip_pipe].n_planes > 1 &&
377*d83cc019SAndroid Build Coastguard Worker 		            display->pipes[flip_pipe].planes[1].type != DRM_PLANE_TYPE_CURSOR);
378*d83cc019SAndroid Build Coastguard Worker 
379*d83cc019SAndroid Build Coastguard Worker 		igt_create_color_pattern_fb(display->drm_fd, prim_fb->width, prim_fb->height,
380*d83cc019SAndroid Build Coastguard Worker 					    DRM_FORMAT_ARGB8888, 0, .1, .1, .1, argb_fb);
381*d83cc019SAndroid Build Coastguard Worker 	}
382*d83cc019SAndroid Build Coastguard Worker }
383*d83cc019SAndroid Build Coastguard Worker 
flip(igt_display_t * display,int cursor_pipe,int flip_pipe,int timeout,enum flip_test mode)384*d83cc019SAndroid Build Coastguard Worker static void flip(igt_display_t *display,
385*d83cc019SAndroid Build Coastguard Worker 		int cursor_pipe, int flip_pipe,
386*d83cc019SAndroid Build Coastguard Worker 		int timeout, enum flip_test mode)
387*d83cc019SAndroid Build Coastguard Worker {
388*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
389*d83cc019SAndroid Build Coastguard Worker 	uint64_t *results;
390*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, fb_info2, argb_fb, cursor_fb, cursor_fb2;
391*d83cc019SAndroid Build Coastguard Worker 
392*d83cc019SAndroid Build Coastguard Worker 	results = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
393*d83cc019SAndroid Build Coastguard Worker 	igt_assert(results != MAP_FAILED);
394*d83cc019SAndroid Build Coastguard Worker 
395*d83cc019SAndroid Build Coastguard Worker 	flip_pipe = find_connected_pipe(display, !!flip_pipe);
396*d83cc019SAndroid Build Coastguard Worker 	cursor_pipe = find_connected_pipe(display, !!cursor_pipe);
397*d83cc019SAndroid Build Coastguard Worker 
398*d83cc019SAndroid Build Coastguard Worker 	igt_info("Using pipe %s for page flip, pipe %s for cursor\n",
399*d83cc019SAndroid Build Coastguard Worker 		  kmstest_pipe_name(flip_pipe), kmstest_pipe_name(cursor_pipe));
400*d83cc019SAndroid Build Coastguard Worker 
401*d83cc019SAndroid Build Coastguard Worker 	if (mode >= flip_test_atomic)
402*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
403*d83cc019SAndroid Build Coastguard Worker 
404*d83cc019SAndroid Build Coastguard Worker 	igt_require(set_fb_on_crtc(display, flip_pipe, &fb_info));
405*d83cc019SAndroid Build Coastguard Worker 	if (flip_pipe != cursor_pipe)
406*d83cc019SAndroid Build Coastguard Worker 		igt_require(set_fb_on_crtc(display, cursor_pipe, &fb_info2));
407*d83cc019SAndroid Build Coastguard Worker 
408*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, fb_info.width, fb_info.height, DRM_FORMAT_ARGB8888, 0, .5, .5, .5, &cursor_fb);
409*d83cc019SAndroid Build Coastguard Worker 
410*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
411*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, cursor_pipe, &cursor_fb);
412*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, cursor_pipe, arg, &cursor_fb);
413*d83cc019SAndroid Build Coastguard Worker 
414*d83cc019SAndroid Build Coastguard Worker 	prepare_flip_test(display, mode, flip_pipe, cursor_pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
415*d83cc019SAndroid Build Coastguard Worker 
416*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
417*d83cc019SAndroid Build Coastguard Worker 
418*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, 1) {
419*d83cc019SAndroid Build Coastguard Worker 		unsigned long count = 0;
420*d83cc019SAndroid Build Coastguard Worker 
421*d83cc019SAndroid Build Coastguard Worker 		igt_until_timeout(timeout) {
422*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[(count & 64)/64]);
423*d83cc019SAndroid Build Coastguard Worker 			count++;
424*d83cc019SAndroid Build Coastguard Worker 		}
425*d83cc019SAndroid Build Coastguard Worker 
426*d83cc019SAndroid Build Coastguard Worker 		igt_debug("cursor count=%lu\n", count);
427*d83cc019SAndroid Build Coastguard Worker 		results[0] = count;
428*d83cc019SAndroid Build Coastguard Worker 	}
429*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, 1) {
430*d83cc019SAndroid Build Coastguard Worker 		unsigned long count = 0;
431*d83cc019SAndroid Build Coastguard Worker 
432*d83cc019SAndroid Build Coastguard Worker 		igt_until_timeout(timeout) {
433*d83cc019SAndroid Build Coastguard Worker 			char buf[128];
434*d83cc019SAndroid Build Coastguard Worker 
435*d83cc019SAndroid Build Coastguard Worker 			switch (mode) {
436*d83cc019SAndroid Build Coastguard Worker 			default:
437*d83cc019SAndroid Build Coastguard Worker 				flip_nonblocking(display, flip_pipe, mode >= flip_test_atomic, &fb_info, NULL);
438*d83cc019SAndroid Build Coastguard Worker 				break;
439*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions:
440*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions_varying_size:
441*d83cc019SAndroid Build Coastguard Worker 				transition_nonblocking(display, flip_pipe, &fb_info, &argb_fb, count & 1);
442*d83cc019SAndroid Build Coastguard Worker 				break;
443*d83cc019SAndroid Build Coastguard Worker 			}
444*d83cc019SAndroid Build Coastguard Worker 
445*d83cc019SAndroid Build Coastguard Worker 			while (read(display->drm_fd, buf, sizeof(buf)) < 0 &&
446*d83cc019SAndroid Build Coastguard Worker 			       (errno == EINTR || errno == EAGAIN))
447*d83cc019SAndroid Build Coastguard Worker 				;
448*d83cc019SAndroid Build Coastguard Worker 			count++;
449*d83cc019SAndroid Build Coastguard Worker 		}
450*d83cc019SAndroid Build Coastguard Worker 
451*d83cc019SAndroid Build Coastguard Worker 		igt_debug("flip count=%lu\n", count);
452*d83cc019SAndroid Build Coastguard Worker 		results[1] = count;
453*d83cc019SAndroid Build Coastguard Worker 	}
454*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
455*d83cc019SAndroid Build Coastguard Worker 
456*d83cc019SAndroid Build Coastguard Worker 	munmap(results, PAGE_SIZE);
457*d83cc019SAndroid Build Coastguard Worker 
458*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
459*d83cc019SAndroid Build Coastguard Worker 	if (flip_pipe != cursor_pipe)
460*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &fb_info2);
461*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
462*d83cc019SAndroid Build Coastguard Worker 	if (argb_fb.gem_handle)
463*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &argb_fb);
464*d83cc019SAndroid Build Coastguard Worker 	if (cursor_fb2.gem_handle)
465*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &cursor_fb2);
466*d83cc019SAndroid Build Coastguard Worker }
467*d83cc019SAndroid Build Coastguard Worker 
pipe_select(enum pipe pipe)468*d83cc019SAndroid Build Coastguard Worker static inline uint32_t pipe_select(enum pipe pipe)
469*d83cc019SAndroid Build Coastguard Worker {
470*d83cc019SAndroid Build Coastguard Worker 	if (pipe > 1)
471*d83cc019SAndroid Build Coastguard Worker 		return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
472*d83cc019SAndroid Build Coastguard Worker 	else if (pipe > 0)
473*d83cc019SAndroid Build Coastguard Worker 		return DRM_VBLANK_SECONDARY;
474*d83cc019SAndroid Build Coastguard Worker 	else
475*d83cc019SAndroid Build Coastguard Worker 		return 0;
476*d83cc019SAndroid Build Coastguard Worker }
477*d83cc019SAndroid Build Coastguard Worker 
get_vblank(int fd,enum pipe pipe,unsigned flags)478*d83cc019SAndroid Build Coastguard Worker static unsigned get_vblank(int fd, enum pipe pipe, unsigned flags)
479*d83cc019SAndroid Build Coastguard Worker {
480*d83cc019SAndroid Build Coastguard Worker 	union drm_wait_vblank vbl;
481*d83cc019SAndroid Build Coastguard Worker 
482*d83cc019SAndroid Build Coastguard Worker 	memset(&vbl, 0, sizeof(vbl));
483*d83cc019SAndroid Build Coastguard Worker 	vbl.request.type = DRM_VBLANK_RELATIVE | pipe_select(pipe) | flags;
484*d83cc019SAndroid Build Coastguard Worker 	if (drmIoctl(fd, DRM_IOCTL_WAIT_VBLANK, &vbl))
485*d83cc019SAndroid Build Coastguard Worker 		return 0;
486*d83cc019SAndroid Build Coastguard Worker 
487*d83cc019SAndroid Build Coastguard Worker 	return vbl.reply.sequence;
488*d83cc019SAndroid Build Coastguard Worker }
489*d83cc019SAndroid Build Coastguard Worker 
490*d83cc019SAndroid Build Coastguard Worker enum basic_flip_cursor {
491*d83cc019SAndroid Build Coastguard Worker 	FLIP_BEFORE_CURSOR,
492*d83cc019SAndroid Build Coastguard Worker 	FLIP_AFTER_CURSOR
493*d83cc019SAndroid Build Coastguard Worker };
494*d83cc019SAndroid Build Coastguard Worker 
495*d83cc019SAndroid Build Coastguard Worker #define BASIC_BUSY 0x1
496*d83cc019SAndroid Build Coastguard Worker 
basic_flip_cursor(igt_display_t * display,enum flip_test mode,enum basic_flip_cursor order,unsigned flags)497*d83cc019SAndroid Build Coastguard Worker static void basic_flip_cursor(igt_display_t *display,
498*d83cc019SAndroid Build Coastguard Worker 			      enum flip_test mode,
499*d83cc019SAndroid Build Coastguard Worker 			      enum basic_flip_cursor order,
500*d83cc019SAndroid Build Coastguard Worker 			      unsigned flags)
501*d83cc019SAndroid Build Coastguard Worker {
502*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
503*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
504*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
505*d83cc019SAndroid Build Coastguard Worker 	unsigned vblank_start;
506*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
507*d83cc019SAndroid Build Coastguard Worker 	igt_spin_t *spin;
508*d83cc019SAndroid Build Coastguard Worker 	int i, miss1 = 0, miss2 = 0, delta;
509*d83cc019SAndroid Build Coastguard Worker 
510*d83cc019SAndroid Build Coastguard Worker 	if (mode >= flip_test_atomic)
511*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
512*d83cc019SAndroid Build Coastguard Worker 
513*d83cc019SAndroid Build Coastguard Worker 	igt_require(set_fb_on_crtc(display, pipe, &fb_info));
514*d83cc019SAndroid Build Coastguard Worker 
515*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
516*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
517*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
518*d83cc019SAndroid Build Coastguard Worker 
519*d83cc019SAndroid Build Coastguard Worker 	prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
520*d83cc019SAndroid Build Coastguard Worker 
521*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
522*d83cc019SAndroid Build Coastguard Worker 
523*d83cc019SAndroid Build Coastguard Worker 	/* Quick sanity check that we can update a cursor in a single vblank */
524*d83cc019SAndroid Build Coastguard Worker 	vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
525*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
526*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
527*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
528*d83cc019SAndroid Build Coastguard Worker 
529*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < 25; i++) {
530*d83cc019SAndroid Build Coastguard Worker 		bool miss;
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 		/* Bind the cursor first to warm up */
533*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
534*d83cc019SAndroid Build Coastguard Worker 
535*d83cc019SAndroid Build Coastguard Worker 		spin = NULL;
536*d83cc019SAndroid Build Coastguard Worker 		if (flags & BASIC_BUSY)
537*d83cc019SAndroid Build Coastguard Worker 			spin = igt_spin_new(display->drm_fd,
538*d83cc019SAndroid Build Coastguard Worker 					    .dependency = fb_info.gem_handle);
539*d83cc019SAndroid Build Coastguard Worker 
540*d83cc019SAndroid Build Coastguard Worker 		/* Start with a synchronous query to align with the vblank */
541*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
542*d83cc019SAndroid Build Coastguard Worker 
543*d83cc019SAndroid Build Coastguard Worker 		switch (order) {
544*d83cc019SAndroid Build Coastguard Worker 		case FLIP_BEFORE_CURSOR:
545*d83cc019SAndroid Build Coastguard Worker 			switch (mode) {
546*d83cc019SAndroid Build Coastguard Worker 			default:
547*d83cc019SAndroid Build Coastguard Worker 				flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info, NULL);
548*d83cc019SAndroid Build Coastguard Worker 				break;
549*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions:
550*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions_varying_size:
551*d83cc019SAndroid Build Coastguard Worker 				transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
552*d83cc019SAndroid Build Coastguard Worker 				break;
553*d83cc019SAndroid Build Coastguard Worker 			}
554*d83cc019SAndroid Build Coastguard Worker 
555*d83cc019SAndroid Build Coastguard Worker 			delta = get_vblank(display->drm_fd, pipe, 0) - vblank_start;
556*d83cc019SAndroid Build Coastguard Worker 			miss = delta != 0;
557*d83cc019SAndroid Build Coastguard Worker 
558*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
559*d83cc019SAndroid Build Coastguard Worker 			break;
560*d83cc019SAndroid Build Coastguard Worker 
561*d83cc019SAndroid Build Coastguard Worker 		case FLIP_AFTER_CURSOR:
562*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
563*d83cc019SAndroid Build Coastguard Worker 
564*d83cc019SAndroid Build Coastguard Worker 			delta = get_vblank(display->drm_fd, pipe, 0) - vblank_start;
565*d83cc019SAndroid Build Coastguard Worker 			miss = delta != 0;
566*d83cc019SAndroid Build Coastguard Worker 
567*d83cc019SAndroid Build Coastguard Worker 			switch (mode) {
568*d83cc019SAndroid Build Coastguard Worker 			default:
569*d83cc019SAndroid Build Coastguard Worker 				flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info, NULL);
570*d83cc019SAndroid Build Coastguard Worker 				break;
571*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions:
572*d83cc019SAndroid Build Coastguard Worker 			case flip_test_atomic_transitions_varying_size:
573*d83cc019SAndroid Build Coastguard Worker 				transition_nonblocking(display, pipe, &fb_info, &argb_fb, 0);
574*d83cc019SAndroid Build Coastguard Worker 				break;
575*d83cc019SAndroid Build Coastguard Worker 			}
576*d83cc019SAndroid Build Coastguard Worker 		}
577*d83cc019SAndroid Build Coastguard Worker 
578*d83cc019SAndroid Build Coastguard Worker 		delta = get_vblank(display->drm_fd, pipe, 0) - vblank_start;
579*d83cc019SAndroid Build Coastguard Worker 
580*d83cc019SAndroid Build Coastguard Worker 		if (spin) {
581*d83cc019SAndroid Build Coastguard Worker 			struct pollfd pfd = { display->drm_fd, POLLIN };
582*d83cc019SAndroid Build Coastguard Worker 			igt_assert(poll(&pfd, 1, 0) == 0);
583*d83cc019SAndroid Build Coastguard Worker 			igt_spin_free(display->drm_fd, spin);
584*d83cc019SAndroid Build Coastguard Worker 		}
585*d83cc019SAndroid Build Coastguard Worker 
586*d83cc019SAndroid Build Coastguard Worker 		if (miss)
587*d83cc019SAndroid Build Coastguard Worker 			{ /* compare nothing, already failed */ }
588*d83cc019SAndroid Build Coastguard Worker 		else if (!cursor_slowpath(mode))
589*d83cc019SAndroid Build Coastguard Worker 			miss = delta != 0;
590*d83cc019SAndroid Build Coastguard Worker 		else
591*d83cc019SAndroid Build Coastguard Worker 			miss = delta != 0 && delta != 1;
592*d83cc019SAndroid Build Coastguard Worker 
593*d83cc019SAndroid Build Coastguard Worker 		miss1 += miss;
594*d83cc019SAndroid Build Coastguard Worker 
595*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
596*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
597*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
598*d83cc019SAndroid Build Coastguard Worker 
599*d83cc019SAndroid Build Coastguard Worker 		if (miss1)
600*d83cc019SAndroid Build Coastguard Worker 			continue;
601*d83cc019SAndroid Build Coastguard Worker 
602*d83cc019SAndroid Build Coastguard Worker 		delta = get_vblank(display->drm_fd, pipe, 0) - vblank_start;
603*d83cc019SAndroid Build Coastguard Worker 
604*d83cc019SAndroid Build Coastguard Worker 		if (!mode_requires_extra_vblank(mode))
605*d83cc019SAndroid Build Coastguard Worker 			miss2 += delta != 1;
606*d83cc019SAndroid Build Coastguard Worker 		else
607*d83cc019SAndroid Build Coastguard Worker 			miss2 += delta != 1 && delta != 2;
608*d83cc019SAndroid Build Coastguard Worker 	}
609*d83cc019SAndroid Build Coastguard Worker 
610*d83cc019SAndroid Build Coastguard Worker 	igt_fail_on_f(miss1 > 2 || miss1 + miss2 > 5, "Failed to evade %i vblanks and missed %i page flips\n", miss1, miss2);
611*d83cc019SAndroid Build Coastguard Worker 	if (miss1 || miss2)
612*d83cc019SAndroid Build Coastguard Worker 		igt_info("Failed to evade %i vblanks and missed %i page flips\n", miss1, miss2);
613*d83cc019SAndroid Build Coastguard Worker 
614*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
615*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
616*d83cc019SAndroid Build Coastguard Worker 
617*d83cc019SAndroid Build Coastguard Worker 	if (argb_fb.gem_handle)
618*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &argb_fb);
619*d83cc019SAndroid Build Coastguard Worker 	if (cursor_fb2.gem_handle)
620*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &cursor_fb2);
621*d83cc019SAndroid Build Coastguard Worker }
622*d83cc019SAndroid Build Coastguard Worker 
623*d83cc019SAndroid Build Coastguard Worker static int
get_cursor_updates_per_vblank(igt_display_t * display,enum pipe pipe,struct drm_mode_cursor * arg)624*d83cc019SAndroid Build Coastguard Worker get_cursor_updates_per_vblank(igt_display_t *display, enum pipe pipe,
625*d83cc019SAndroid Build Coastguard Worker 			      struct drm_mode_cursor *arg)
626*d83cc019SAndroid Build Coastguard Worker {
627*d83cc019SAndroid Build Coastguard Worker 	int target;
628*d83cc019SAndroid Build Coastguard Worker 
629*d83cc019SAndroid Build Coastguard Worker 	for (target = 65536; target; target /= 2) {
630*d83cc019SAndroid Build Coastguard Worker 		unsigned vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
631*d83cc019SAndroid Build Coastguard Worker 
632*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
633*d83cc019SAndroid Build Coastguard Worker 
634*d83cc019SAndroid Build Coastguard Worker 		for (int n = 0; n < target; n++)
635*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, arg);
636*d83cc019SAndroid Build Coastguard Worker 		if (get_vblank(display->drm_fd, pipe, 0) == vblank_start)
637*d83cc019SAndroid Build Coastguard Worker 			break;
638*d83cc019SAndroid Build Coastguard Worker 	}
639*d83cc019SAndroid Build Coastguard Worker 
640*d83cc019SAndroid Build Coastguard Worker 	/*
641*d83cc019SAndroid Build Coastguard Worker 	  * Divide by 4, to handle variations in amount of vblanks
642*d83cc019SAndroid Build Coastguard Worker 	  * caused by cpufreq throttling.
643*d83cc019SAndroid Build Coastguard Worker 	  */
644*d83cc019SAndroid Build Coastguard Worker 	target /= 4;
645*d83cc019SAndroid Build Coastguard Worker 	igt_require(target > 1);
646*d83cc019SAndroid Build Coastguard Worker 
647*d83cc019SAndroid Build Coastguard Worker 	igt_info("Using a target of %d cursor updates per quarter-vblank\n", target);
648*d83cc019SAndroid Build Coastguard Worker 
649*d83cc019SAndroid Build Coastguard Worker 	return target;
650*d83cc019SAndroid Build Coastguard Worker }
651*d83cc019SAndroid Build Coastguard Worker 
flip_vs_cursor(igt_display_t * display,enum flip_test mode,int nloops)652*d83cc019SAndroid Build Coastguard Worker static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloops)
653*d83cc019SAndroid Build Coastguard Worker {
654*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
655*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
656*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
657*d83cc019SAndroid Build Coastguard Worker 	unsigned vblank_start;
658*d83cc019SAndroid Build Coastguard Worker 	int target, cpu;
659*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
660*d83cc019SAndroid Build Coastguard Worker 	volatile unsigned long *shared;
661*d83cc019SAndroid Build Coastguard Worker 	cpu_set_t mask, oldmask;
662*d83cc019SAndroid Build Coastguard Worker 
663*d83cc019SAndroid Build Coastguard Worker 	if (mode >= flip_test_atomic)
664*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
665*d83cc019SAndroid Build Coastguard Worker 
666*d83cc019SAndroid Build Coastguard Worker 	igt_require(set_fb_on_crtc(display, pipe, &fb_info));
667*d83cc019SAndroid Build Coastguard Worker 
668*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
669*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
670*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
671*d83cc019SAndroid Build Coastguard Worker 
672*d83cc019SAndroid Build Coastguard Worker 	prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
673*d83cc019SAndroid Build Coastguard Worker 
674*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
675*d83cc019SAndroid Build Coastguard Worker 
676*d83cc019SAndroid Build Coastguard Worker 	if (nloops)
677*d83cc019SAndroid Build Coastguard Worker 		target = get_cursor_updates_per_vblank(display, pipe, &arg[0]);
678*d83cc019SAndroid Build Coastguard Worker 	else
679*d83cc019SAndroid Build Coastguard Worker 		target = 1;
680*d83cc019SAndroid Build Coastguard Worker 
681*d83cc019SAndroid Build Coastguard Worker 	vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
682*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
683*d83cc019SAndroid Build Coastguard Worker 	for (int n = 0; n < target; n++)
684*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
685*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
686*d83cc019SAndroid Build Coastguard Worker 
687*d83cc019SAndroid Build Coastguard Worker 	/*
688*d83cc019SAndroid Build Coastguard Worker 	 * There are variations caused by using cpu frequency changing. To
689*d83cc019SAndroid Build Coastguard Worker 	 * eliminate those we force this test to run on the same cpu as an
690*d83cc019SAndroid Build Coastguard Worker 	 * idle thread that does a busy loop of sched_yield(); The effect is
691*d83cc019SAndroid Build Coastguard Worker 	 * that we don't throttle the cpu to a lower frequency, and the
692*d83cc019SAndroid Build Coastguard Worker 	 * variations caused by cpu speed changing are eliminated.
693*d83cc019SAndroid Build Coastguard Worker 	 */
694*d83cc019SAndroid Build Coastguard Worker 	if (target > 1) {
695*d83cc019SAndroid Build Coastguard Worker 		shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
696*d83cc019SAndroid Build Coastguard Worker 		igt_assert(shared != MAP_FAILED);
697*d83cc019SAndroid Build Coastguard Worker 
698*d83cc019SAndroid Build Coastguard Worker 		cpu = sched_getcpu();
699*d83cc019SAndroid Build Coastguard Worker 		igt_assert(cpu >= 0);
700*d83cc019SAndroid Build Coastguard Worker 
701*d83cc019SAndroid Build Coastguard Worker 		CPU_ZERO(&mask);
702*d83cc019SAndroid Build Coastguard Worker 		CPU_SET(cpu, &mask);
703*d83cc019SAndroid Build Coastguard Worker 		sched_getaffinity(0, sizeof(oldmask), &oldmask);
704*d83cc019SAndroid Build Coastguard Worker 		sched_setaffinity(0, sizeof(mask), &mask);
705*d83cc019SAndroid Build Coastguard Worker 
706*d83cc019SAndroid Build Coastguard Worker 		shared[0] = 0;
707*d83cc019SAndroid Build Coastguard Worker 
708*d83cc019SAndroid Build Coastguard Worker 		igt_fork(child, 1) {
709*d83cc019SAndroid Build Coastguard Worker 			struct sched_param parm = { .sched_priority = 0 };
710*d83cc019SAndroid Build Coastguard Worker 
711*d83cc019SAndroid Build Coastguard Worker 			igt_assert(sched_setscheduler(0, SCHED_IDLE, &parm) == 0);
712*d83cc019SAndroid Build Coastguard Worker 
713*d83cc019SAndroid Build Coastguard Worker 			while (!shared[0])
714*d83cc019SAndroid Build Coastguard Worker 				sched_yield();
715*d83cc019SAndroid Build Coastguard Worker 		}
716*d83cc019SAndroid Build Coastguard Worker 	}
717*d83cc019SAndroid Build Coastguard Worker 
718*d83cc019SAndroid Build Coastguard Worker 	do {
719*d83cc019SAndroid Build Coastguard Worker 		/* Bind the cursor first to warm up */
720*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
721*d83cc019SAndroid Build Coastguard Worker 
722*d83cc019SAndroid Build Coastguard Worker 		/* Start with a synchronous query to align with the vblank */
723*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
724*d83cc019SAndroid Build Coastguard Worker 		switch (mode) {
725*d83cc019SAndroid Build Coastguard Worker 		default:
726*d83cc019SAndroid Build Coastguard Worker 			flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info, NULL);
727*d83cc019SAndroid Build Coastguard Worker 			break;
728*d83cc019SAndroid Build Coastguard Worker 		case flip_test_atomic_transitions:
729*d83cc019SAndroid Build Coastguard Worker 		case flip_test_atomic_transitions_varying_size:
730*d83cc019SAndroid Build Coastguard Worker 			transition_nonblocking(display, pipe, &fb_info, &argb_fb, (nloops & 2) /2);
731*d83cc019SAndroid Build Coastguard Worker 			break;
732*d83cc019SAndroid Build Coastguard Worker 		}
733*d83cc019SAndroid Build Coastguard Worker 
734*d83cc019SAndroid Build Coastguard Worker 		/* The nonblocking flip should not have delayed us */
735*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
736*d83cc019SAndroid Build Coastguard Worker 		for (int n = 0; n < target; n++)
737*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
738*d83cc019SAndroid Build Coastguard Worker 
739*d83cc019SAndroid Build Coastguard Worker 		/* Nor should it have delayed the following cursor update */
740*d83cc019SAndroid Build Coastguard Worker 		if (!cursor_slowpath(mode))
741*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
742*d83cc019SAndroid Build Coastguard Worker 		else
743*d83cc019SAndroid Build Coastguard Worker 			igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
744*d83cc019SAndroid Build Coastguard Worker 
745*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
746*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
747*d83cc019SAndroid Build Coastguard Worker 
748*d83cc019SAndroid Build Coastguard Worker 		if (!mode_requires_extra_vblank(mode))
749*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
750*d83cc019SAndroid Build Coastguard Worker 		else
751*d83cc019SAndroid Build Coastguard Worker 			igt_assert_lte(get_vblank(display->drm_fd, pipe, 0), vblank_start + 2);
752*d83cc019SAndroid Build Coastguard Worker 
753*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
754*d83cc019SAndroid Build Coastguard Worker 	} while (nloops--);
755*d83cc019SAndroid Build Coastguard Worker 
756*d83cc019SAndroid Build Coastguard Worker 	if (target > 1) {
757*d83cc019SAndroid Build Coastguard Worker 		shared[0] = 1;
758*d83cc019SAndroid Build Coastguard Worker 		igt_waitchildren();
759*d83cc019SAndroid Build Coastguard Worker 		munmap((void *)shared, PAGE_SIZE);
760*d83cc019SAndroid Build Coastguard Worker 		sched_setaffinity(0, sizeof(oldmask), &oldmask);
761*d83cc019SAndroid Build Coastguard Worker 	}
762*d83cc019SAndroid Build Coastguard Worker 
763*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
764*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
765*d83cc019SAndroid Build Coastguard Worker 
766*d83cc019SAndroid Build Coastguard Worker 	if (argb_fb.gem_handle)
767*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &argb_fb);
768*d83cc019SAndroid Build Coastguard Worker 	if (cursor_fb2.gem_handle)
769*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &cursor_fb2);
770*d83cc019SAndroid Build Coastguard Worker }
771*d83cc019SAndroid Build Coastguard Worker 
nonblocking_modeset_vs_cursor(igt_display_t * display,int loops)772*d83cc019SAndroid Build Coastguard Worker static void nonblocking_modeset_vs_cursor(igt_display_t *display, int loops)
773*d83cc019SAndroid Build Coastguard Worker {
774*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, cursor_fb;
775*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
776*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
777*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
778*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *cursor = NULL, *plane;
779*d83cc019SAndroid Build Coastguard Worker 
780*d83cc019SAndroid Build Coastguard Worker 	igt_require(display->is_atomic);
781*d83cc019SAndroid Build Coastguard Worker 	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
782*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
783*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
784*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
785*d83cc019SAndroid Build Coastguard Worker 	arg[0].flags |= DRM_MODE_CURSOR_BO;
786*d83cc019SAndroid Build Coastguard Worker 
787*d83cc019SAndroid Build Coastguard Worker 	for_each_plane_on_pipe(display, pipe, plane) {
788*d83cc019SAndroid Build Coastguard Worker 		if (plane->type != DRM_PLANE_TYPE_CURSOR)
789*d83cc019SAndroid Build Coastguard Worker 			continue;
790*d83cc019SAndroid Build Coastguard Worker 
791*d83cc019SAndroid Build Coastguard Worker 		cursor = plane;
792*d83cc019SAndroid Build Coastguard Worker 		break;
793*d83cc019SAndroid Build Coastguard Worker 	}
794*d83cc019SAndroid Build Coastguard Worker 
795*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(!cursor);
796*d83cc019SAndroid Build Coastguard Worker 
797*d83cc019SAndroid Build Coastguard Worker 	/*
798*d83cc019SAndroid Build Coastguard Worker 	 * Start disabled. No way around it, since the first atomic
799*d83cc019SAndroid Build Coastguard Worker 	 * commit may be unreliable with amount of events sent.
800*d83cc019SAndroid Build Coastguard Worker 	 */
801*d83cc019SAndroid Build Coastguard Worker 	igt_output_set_pipe(output, PIPE_NONE);
802*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, COMMIT_ATOMIC);
803*d83cc019SAndroid Build Coastguard Worker 
804*d83cc019SAndroid Build Coastguard Worker 	while (loops--) {
805*d83cc019SAndroid Build Coastguard Worker 		unsigned flags;
806*d83cc019SAndroid Build Coastguard Worker 		struct pollfd pfd = { display->drm_fd, POLLIN };
807*d83cc019SAndroid Build Coastguard Worker 		struct drm_event_vblank vbl;
808*d83cc019SAndroid Build Coastguard Worker 
809*d83cc019SAndroid Build Coastguard Worker 		flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
810*d83cc019SAndroid Build Coastguard Worker 		flags |= DRM_MODE_ATOMIC_NONBLOCK;
811*d83cc019SAndroid Build Coastguard Worker 		flags |= DRM_MODE_PAGE_FLIP_EVENT;
812*d83cc019SAndroid Build Coastguard Worker 
813*d83cc019SAndroid Build Coastguard Worker 		/*
814*d83cc019SAndroid Build Coastguard Worker 		 * Test that a cursor update after a nonblocking modeset
815*d83cc019SAndroid Build Coastguard Worker 		 * works as intended. It should block until the modeset completes.
816*d83cc019SAndroid Build Coastguard Worker 		 */
817*d83cc019SAndroid Build Coastguard Worker 
818*d83cc019SAndroid Build Coastguard Worker 		igt_output_set_pipe(output, pipe);
819*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(cursor, NULL);
820*d83cc019SAndroid Build Coastguard Worker 		igt_display_commit_atomic(display, flags, NULL);
821*d83cc019SAndroid Build Coastguard Worker 
822*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(0, poll(&pfd, 1, 0));
823*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(0, pfd.revents);
824*d83cc019SAndroid Build Coastguard Worker 
825*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
826*d83cc019SAndroid Build Coastguard Worker 
827*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(1, poll(&pfd, 1, 0));
828*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(POLLIN, pfd.revents);
829*d83cc019SAndroid Build Coastguard Worker 
830*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
831*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
832*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
833*d83cc019SAndroid Build Coastguard Worker 
834*d83cc019SAndroid Build Coastguard Worker 		igt_output_set_pipe(output, PIPE_NONE);
835*d83cc019SAndroid Build Coastguard Worker 		igt_display_commit_atomic(display, flags, NULL);
836*d83cc019SAndroid Build Coastguard Worker 
837*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(0, poll(&pfd, 1, 0));
838*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(0, pfd.revents);
839*d83cc019SAndroid Build Coastguard Worker 
840*d83cc019SAndroid Build Coastguard Worker 		/* Same for cursor on disabled crtc. */
841*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
842*d83cc019SAndroid Build Coastguard Worker 
843*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(1, poll(&pfd, 1, 0));
844*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(POLLIN, pfd.revents);
845*d83cc019SAndroid Build Coastguard Worker 
846*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
847*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
848*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
849*d83cc019SAndroid Build Coastguard Worker 	}
850*d83cc019SAndroid Build Coastguard Worker 
851*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
852*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
853*d83cc019SAndroid Build Coastguard Worker }
854*d83cc019SAndroid Build Coastguard Worker 
two_screens_flip_vs_cursor(igt_display_t * display,int nloops,bool modeset,bool atomic)855*d83cc019SAndroid Build Coastguard Worker static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool modeset, bool atomic)
856*d83cc019SAndroid Build Coastguard Worker {
857*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg1[2], arg2[2];
858*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, fb2_info, cursor_fb;
859*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
860*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe2 = find_connected_pipe(display, true);
861*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output, *output2;
862*d83cc019SAndroid Build Coastguard Worker 	bool enabled = false;
863*d83cc019SAndroid Build Coastguard Worker 	volatile unsigned long *shared;
864*d83cc019SAndroid Build Coastguard Worker 	unsigned flags = 0, vblank_start;
865*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
866*d83cc019SAndroid Build Coastguard Worker 	int ret;
867*d83cc019SAndroid Build Coastguard Worker 
868*d83cc019SAndroid Build Coastguard Worker 	if (modeset) {
869*d83cc019SAndroid Build Coastguard Worker 		uint64_t val;
870*d83cc019SAndroid Build Coastguard Worker 
871*d83cc019SAndroid Build Coastguard Worker 		igt_fail_on(!atomic);
872*d83cc019SAndroid Build Coastguard Worker 		igt_require(drmGetCap(display->drm_fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &val) == 0);
873*d83cc019SAndroid Build Coastguard Worker 	}
874*d83cc019SAndroid Build Coastguard Worker 
875*d83cc019SAndroid Build Coastguard Worker 	shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
876*d83cc019SAndroid Build Coastguard Worker 	igt_assert(shared != MAP_FAILED);
877*d83cc019SAndroid Build Coastguard Worker 
878*d83cc019SAndroid Build Coastguard Worker 	igt_fail_on(modeset && !atomic);
879*d83cc019SAndroid Build Coastguard Worker 
880*d83cc019SAndroid Build Coastguard Worker 	if (atomic)
881*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
882*d83cc019SAndroid Build Coastguard Worker 
883*d83cc019SAndroid Build Coastguard Worker 	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
884*d83cc019SAndroid Build Coastguard Worker 	igt_require((output2 = set_fb_on_crtc(display, pipe2, &fb2_info)));
885*d83cc019SAndroid Build Coastguard Worker 
886*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
887*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
888*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg1, &cursor_fb);
889*d83cc019SAndroid Build Coastguard Worker 
890*d83cc019SAndroid Build Coastguard Worker 	arg1[1].x = arg1[1].y = 192;
891*d83cc019SAndroid Build Coastguard Worker 
892*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe2, &cursor_fb);
893*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe2, arg2, &cursor_fb);
894*d83cc019SAndroid Build Coastguard Worker 
895*d83cc019SAndroid Build Coastguard Worker 	arg2[1].x = arg2[1].y = 192;
896*d83cc019SAndroid Build Coastguard Worker 
897*d83cc019SAndroid Build Coastguard Worker 
898*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
899*d83cc019SAndroid Build Coastguard Worker 
900*d83cc019SAndroid Build Coastguard Worker 	igt_fork(child, 2) {
901*d83cc019SAndroid Build Coastguard Worker 		struct drm_mode_cursor *arg = child ? arg2 : arg1;
902*d83cc019SAndroid Build Coastguard Worker 
903*d83cc019SAndroid Build Coastguard Worker 		while (!shared[0])
904*d83cc019SAndroid Build Coastguard Worker 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR,
905*d83cc019SAndroid Build Coastguard Worker 				 &arg[!shared[1]]);
906*d83cc019SAndroid Build Coastguard Worker 	}
907*d83cc019SAndroid Build Coastguard Worker 
908*d83cc019SAndroid Build Coastguard Worker 	if (modeset) {
909*d83cc019SAndroid Build Coastguard Worker 		igt_plane_t *plane = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
910*d83cc019SAndroid Build Coastguard Worker 
911*d83cc019SAndroid Build Coastguard Worker 		flags = DRM_MODE_ATOMIC_ALLOW_MODESET |
912*d83cc019SAndroid Build Coastguard Worker 			DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT;
913*d83cc019SAndroid Build Coastguard Worker 
914*d83cc019SAndroid Build Coastguard Worker 		/* Disable pipe2 */
915*d83cc019SAndroid Build Coastguard Worker 		igt_output_set_pipe(output2, PIPE_NONE);
916*d83cc019SAndroid Build Coastguard Worker 		igt_display_commit_atomic(display, flags, NULL);
917*d83cc019SAndroid Build Coastguard Worker 		enabled = false;
918*d83cc019SAndroid Build Coastguard Worker 
919*d83cc019SAndroid Build Coastguard Worker 		/*
920*d83cc019SAndroid Build Coastguard Worker 		 * Try a page flip on crtc 1, if we succeed pump page flips and
921*d83cc019SAndroid Build Coastguard Worker 		 * modesets interleaved, else do a single atomic commit with both.
922*d83cc019SAndroid Build Coastguard Worker 		 */
923*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
924*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(plane, &fb_info);
925*d83cc019SAndroid Build Coastguard Worker 		ret = igt_display_try_commit_atomic(display, flags, (void*)(ptrdiff_t)vblank_start);
926*d83cc019SAndroid Build Coastguard Worker 		igt_assert(!ret || ret == -EBUSY);
927*d83cc019SAndroid Build Coastguard Worker 
928*d83cc019SAndroid Build Coastguard Worker 		if (ret == -EBUSY) {
929*d83cc019SAndroid Build Coastguard Worker 			/* Force completion on both pipes, and generate event. */
930*d83cc019SAndroid Build Coastguard Worker 			igt_display_commit_atomic(display, flags, NULL);
931*d83cc019SAndroid Build Coastguard Worker 
932*d83cc019SAndroid Build Coastguard Worker 			while (nloops--) {
933*d83cc019SAndroid Build Coastguard Worker 				shared[1] = nloops & 1;
934*d83cc019SAndroid Build Coastguard Worker 
935*d83cc019SAndroid Build Coastguard Worker 				igt_set_timeout(35, "Stuck modeset");
936*d83cc019SAndroid Build Coastguard Worker 				igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
937*d83cc019SAndroid Build Coastguard Worker 				igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
938*d83cc019SAndroid Build Coastguard Worker 				igt_reset_timeout();
939*d83cc019SAndroid Build Coastguard Worker 
940*d83cc019SAndroid Build Coastguard Worker 				if (!nloops)
941*d83cc019SAndroid Build Coastguard Worker 					break;
942*d83cc019SAndroid Build Coastguard Worker 
943*d83cc019SAndroid Build Coastguard Worker 				/* Commit page flip and modeset simultaneously. */
944*d83cc019SAndroid Build Coastguard Worker 				igt_plane_set_fb(plane, &fb_info);
945*d83cc019SAndroid Build Coastguard Worker 				igt_output_set_pipe(output2, enabled ? PIPE_NONE : pipe2);
946*d83cc019SAndroid Build Coastguard Worker 				enabled = !enabled;
947*d83cc019SAndroid Build Coastguard Worker 
948*d83cc019SAndroid Build Coastguard Worker 				igt_set_timeout(5, "Scheduling modeset\n");
949*d83cc019SAndroid Build Coastguard Worker 				do {
950*d83cc019SAndroid Build Coastguard Worker 					ret = igt_display_try_commit_atomic(display, flags, NULL);
951*d83cc019SAndroid Build Coastguard Worker 				} while (ret == -EBUSY);
952*d83cc019SAndroid Build Coastguard Worker 				igt_assert(!ret);
953*d83cc019SAndroid Build Coastguard Worker 				igt_reset_timeout();
954*d83cc019SAndroid Build Coastguard Worker 			}
955*d83cc019SAndroid Build Coastguard Worker 
956*d83cc019SAndroid Build Coastguard Worker 			goto done;
957*d83cc019SAndroid Build Coastguard Worker 		}
958*d83cc019SAndroid Build Coastguard Worker 	} else {
959*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
960*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe, atomic, &fb_info, (void*)(ptrdiff_t)vblank_start);
961*d83cc019SAndroid Build Coastguard Worker 
962*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe2, DRM_VBLANK_NEXTONMISS);
963*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe2, atomic, &fb2_info, (void*)(ptrdiff_t)vblank_start);
964*d83cc019SAndroid Build Coastguard Worker 	}
965*d83cc019SAndroid Build Coastguard Worker 
966*d83cc019SAndroid Build Coastguard Worker 	while (nloops) {
967*d83cc019SAndroid Build Coastguard Worker 		shared[1] = nloops & 1;
968*d83cc019SAndroid Build Coastguard Worker 
969*d83cc019SAndroid Build Coastguard Worker 		if (!modeset || nloops > 1)
970*d83cc019SAndroid Build Coastguard Worker 			igt_set_timeout(1, "Stuck page flip");
971*d83cc019SAndroid Build Coastguard Worker 		else
972*d83cc019SAndroid Build Coastguard Worker 			igt_set_timeout(35, "Stuck modeset");
973*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
974*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
975*d83cc019SAndroid Build Coastguard Worker 
976*d83cc019SAndroid Build Coastguard Worker 		vblank_start = vbl.user_data;
977*d83cc019SAndroid Build Coastguard Worker 		if (!modeset)
978*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(vbl.sequence, vblank_start + 1);
979*d83cc019SAndroid Build Coastguard Worker 
980*d83cc019SAndroid Build Coastguard Worker 		/* Do not requeue on the last 2 events. */
981*d83cc019SAndroid Build Coastguard Worker 		if (nloops <= 2) {
982*d83cc019SAndroid Build Coastguard Worker 			nloops--;
983*d83cc019SAndroid Build Coastguard Worker 			continue;
984*d83cc019SAndroid Build Coastguard Worker 		}
985*d83cc019SAndroid Build Coastguard Worker 
986*d83cc019SAndroid Build Coastguard Worker 		if (vbl.crtc_id == display->pipes[pipe].crtc_id) {
987*d83cc019SAndroid Build Coastguard Worker 			vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
988*d83cc019SAndroid Build Coastguard Worker 			flip_nonblocking(display, pipe, atomic, &fb_info, (void*)(ptrdiff_t)vblank_start);
989*d83cc019SAndroid Build Coastguard Worker 		} else {
990*d83cc019SAndroid Build Coastguard Worker 			igt_assert(vbl.crtc_id == display->pipes[pipe2].crtc_id);
991*d83cc019SAndroid Build Coastguard Worker 
992*d83cc019SAndroid Build Coastguard Worker 			nloops--;
993*d83cc019SAndroid Build Coastguard Worker 
994*d83cc019SAndroid Build Coastguard Worker 			if (!modeset) {
995*d83cc019SAndroid Build Coastguard Worker 				vblank_start = get_vblank(display->drm_fd, pipe2, DRM_VBLANK_NEXTONMISS);
996*d83cc019SAndroid Build Coastguard Worker 				flip_nonblocking(display, pipe2, atomic, &fb2_info, (void*)(ptrdiff_t)vblank_start);
997*d83cc019SAndroid Build Coastguard Worker 			} else {
998*d83cc019SAndroid Build Coastguard Worker 				igt_output_set_pipe(output2, enabled ? PIPE_NONE : pipe2);
999*d83cc019SAndroid Build Coastguard Worker 
1000*d83cc019SAndroid Build Coastguard Worker 				igt_set_timeout(1, "Scheduling modeset\n");
1001*d83cc019SAndroid Build Coastguard Worker 				do {
1002*d83cc019SAndroid Build Coastguard Worker 					ret = igt_display_try_commit_atomic(display, flags, NULL);
1003*d83cc019SAndroid Build Coastguard Worker 				} while (ret == -EBUSY);
1004*d83cc019SAndroid Build Coastguard Worker 				igt_assert(!ret);
1005*d83cc019SAndroid Build Coastguard Worker 				igt_reset_timeout();
1006*d83cc019SAndroid Build Coastguard Worker 
1007*d83cc019SAndroid Build Coastguard Worker 				enabled = !enabled;
1008*d83cc019SAndroid Build Coastguard Worker 			}
1009*d83cc019SAndroid Build Coastguard Worker 		}
1010*d83cc019SAndroid Build Coastguard Worker 	}
1011*d83cc019SAndroid Build Coastguard Worker 
1012*d83cc019SAndroid Build Coastguard Worker done:
1013*d83cc019SAndroid Build Coastguard Worker 	shared[0] = 1;
1014*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
1015*d83cc019SAndroid Build Coastguard Worker 
1016*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
1017*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb2_info);
1018*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
1019*d83cc019SAndroid Build Coastguard Worker 	munmap((void *)shared, PAGE_SIZE);
1020*d83cc019SAndroid Build Coastguard Worker }
1021*d83cc019SAndroid Build Coastguard Worker 
cursor_vs_flip(igt_display_t * display,enum flip_test mode,int nloops)1022*d83cc019SAndroid Build Coastguard Worker static void cursor_vs_flip(igt_display_t *display, enum flip_test mode, int nloops)
1023*d83cc019SAndroid Build Coastguard Worker {
1024*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
1025*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
1026*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, cursor_fb, cursor_fb2, argb_fb;
1027*d83cc019SAndroid Build Coastguard Worker 	unsigned vblank_start, vblank_last;
1028*d83cc019SAndroid Build Coastguard Worker 	volatile unsigned long *shared;
1029*d83cc019SAndroid Build Coastguard Worker 	long target;
1030*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
1031*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *output;
1032*d83cc019SAndroid Build Coastguard Worker 	uint32_t vrefresh;
1033*d83cc019SAndroid Build Coastguard Worker 	int fail_count;
1034*d83cc019SAndroid Build Coastguard Worker 
1035*d83cc019SAndroid Build Coastguard Worker 	if (mode >= flip_test_atomic)
1036*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
1037*d83cc019SAndroid Build Coastguard Worker 
1038*d83cc019SAndroid Build Coastguard Worker 	shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1039*d83cc019SAndroid Build Coastguard Worker 	igt_assert(shared != MAP_FAILED);
1040*d83cc019SAndroid Build Coastguard Worker 
1041*d83cc019SAndroid Build Coastguard Worker 	igt_require((output = set_fb_on_crtc(display, pipe, &fb_info)));
1042*d83cc019SAndroid Build Coastguard Worker 	vrefresh = igt_output_get_mode(output)->vrefresh;
1043*d83cc019SAndroid Build Coastguard Worker 
1044*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1045*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
1046*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
1047*d83cc019SAndroid Build Coastguard Worker 
1048*d83cc019SAndroid Build Coastguard Worker 	prepare_flip_test(display, mode, pipe, pipe, arg, &fb_info, &argb_fb, &cursor_fb2);
1049*d83cc019SAndroid Build Coastguard Worker 
1050*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1051*d83cc019SAndroid Build Coastguard Worker 
1052*d83cc019SAndroid Build Coastguard Worker 	target = get_cursor_updates_per_vblank(display, pipe, &arg[0]);
1053*d83cc019SAndroid Build Coastguard Worker 
1054*d83cc019SAndroid Build Coastguard Worker 	fail_count = 0;
1055*d83cc019SAndroid Build Coastguard Worker 
1056*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < nloops; i++) {
1057*d83cc019SAndroid Build Coastguard Worker 		shared[0] = 0;
1058*d83cc019SAndroid Build Coastguard Worker 		igt_fork(child, 1) {
1059*d83cc019SAndroid Build Coastguard Worker 			unsigned long count = 0;
1060*d83cc019SAndroid Build Coastguard Worker 			while (!shared[0]) {
1061*d83cc019SAndroid Build Coastguard Worker 				do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i & 1]);
1062*d83cc019SAndroid Build Coastguard Worker 				count++;
1063*d83cc019SAndroid Build Coastguard Worker 			}
1064*d83cc019SAndroid Build Coastguard Worker 			igt_debug("child: %lu cursor updates\n", count);
1065*d83cc019SAndroid Build Coastguard Worker 			shared[0] = count;
1066*d83cc019SAndroid Build Coastguard Worker 		}
1067*d83cc019SAndroid Build Coastguard Worker 
1068*d83cc019SAndroid Build Coastguard Worker 		switch (mode) {
1069*d83cc019SAndroid Build Coastguard Worker 		default:
1070*d83cc019SAndroid Build Coastguard Worker 			flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info, NULL);
1071*d83cc019SAndroid Build Coastguard Worker 			break;
1072*d83cc019SAndroid Build Coastguard Worker 		case flip_test_atomic_transitions:
1073*d83cc019SAndroid Build Coastguard Worker 		case flip_test_atomic_transitions_varying_size:
1074*d83cc019SAndroid Build Coastguard Worker 			transition_nonblocking(display, pipe, &fb_info, &argb_fb, (i & 2) >> 1);
1075*d83cc019SAndroid Build Coastguard Worker 			break;
1076*d83cc019SAndroid Build Coastguard Worker 		}
1077*d83cc019SAndroid Build Coastguard Worker 
1078*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
1079*d83cc019SAndroid Build Coastguard Worker 		vblank_start = vblank_last = vbl.sequence;
1080*d83cc019SAndroid Build Coastguard Worker 		for (int n = 0; n < vrefresh / 2; n++) {
1081*d83cc019SAndroid Build Coastguard Worker 			flip_nonblocking(display, pipe, mode >= flip_test_atomic, &fb_info, NULL);
1082*d83cc019SAndroid Build Coastguard Worker 
1083*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
1084*d83cc019SAndroid Build Coastguard Worker 			if (vbl.sequence != vblank_last + 1) {
1085*d83cc019SAndroid Build Coastguard Worker 				igt_info("page flip %d was delayed, missed %d frames\n",
1086*d83cc019SAndroid Build Coastguard Worker 					 n, vbl.sequence - vblank_last - 1);
1087*d83cc019SAndroid Build Coastguard Worker 			}
1088*d83cc019SAndroid Build Coastguard Worker 			vblank_last = vbl.sequence;
1089*d83cc019SAndroid Build Coastguard Worker 		}
1090*d83cc019SAndroid Build Coastguard Worker 
1091*d83cc019SAndroid Build Coastguard Worker 		if (!cursor_slowpath(mode))
1092*d83cc019SAndroid Build Coastguard Worker 			igt_assert_lte(vbl.sequence, vblank_start + 5 * vrefresh / 8);
1093*d83cc019SAndroid Build Coastguard Worker 
1094*d83cc019SAndroid Build Coastguard Worker 		shared[0] = 1;
1095*d83cc019SAndroid Build Coastguard Worker 		igt_waitchildren();
1096*d83cc019SAndroid Build Coastguard Worker 		if (shared[0] <= vrefresh*target / 2) {
1097*d83cc019SAndroid Build Coastguard Worker 			fail_count++;
1098*d83cc019SAndroid Build Coastguard Worker 			igt_critical("completed %lu cursor updated in a period of %u flips, "
1099*d83cc019SAndroid Build Coastguard Worker 				     "we expect to complete approximately %lu updates, "
1100*d83cc019SAndroid Build Coastguard Worker 				     "with the threshold set at %lu\n",
1101*d83cc019SAndroid Build Coastguard Worker 				     shared[0], vrefresh / 2,
1102*d83cc019SAndroid Build Coastguard Worker 				     vrefresh*target, vrefresh*target / 2);
1103*d83cc019SAndroid Build Coastguard Worker 		}
1104*d83cc019SAndroid Build Coastguard Worker 	}
1105*d83cc019SAndroid Build Coastguard Worker 
1106*d83cc019SAndroid Build Coastguard Worker 	igt_assert_f(fail_count == 0,
1107*d83cc019SAndroid Build Coastguard Worker 		     "Failed to meet cursor update expectations in %d out of %d iterations\n",
1108*d83cc019SAndroid Build Coastguard Worker 		     fail_count, nloops);
1109*d83cc019SAndroid Build Coastguard Worker 
1110*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
1111*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
1112*d83cc019SAndroid Build Coastguard Worker 	munmap((void *)shared, PAGE_SIZE);
1113*d83cc019SAndroid Build Coastguard Worker 	if (argb_fb.gem_handle)
1114*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &argb_fb);
1115*d83cc019SAndroid Build Coastguard Worker 	if (cursor_fb2.gem_handle)
1116*d83cc019SAndroid Build Coastguard Worker 		igt_remove_fb(display->drm_fd, &cursor_fb2);
1117*d83cc019SAndroid Build Coastguard Worker }
1118*d83cc019SAndroid Build Coastguard Worker 
two_screens_cursor_vs_flip(igt_display_t * display,int nloops,bool atomic)1119*d83cc019SAndroid Build Coastguard Worker static void two_screens_cursor_vs_flip(igt_display_t *display, int nloops, bool atomic)
1120*d83cc019SAndroid Build Coastguard Worker {
1121*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2][2];
1122*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
1123*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info[2], cursor_fb;
1124*d83cc019SAndroid Build Coastguard Worker 	volatile unsigned long *shared;
1125*d83cc019SAndroid Build Coastguard Worker 	int target[2];
1126*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe[2] = {
1127*d83cc019SAndroid Build Coastguard Worker 		find_connected_pipe(display, false),
1128*d83cc019SAndroid Build Coastguard Worker 		find_connected_pipe(display, true)
1129*d83cc019SAndroid Build Coastguard Worker 	};
1130*d83cc019SAndroid Build Coastguard Worker 	igt_output_t *outputs[2];
1131*d83cc019SAndroid Build Coastguard Worker 
1132*d83cc019SAndroid Build Coastguard Worker 	shared = mmap(NULL, PAGE_SIZE, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
1133*d83cc019SAndroid Build Coastguard Worker 	igt_assert(shared != MAP_FAILED);
1134*d83cc019SAndroid Build Coastguard Worker 
1135*d83cc019SAndroid Build Coastguard Worker 	if (atomic)
1136*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
1137*d83cc019SAndroid Build Coastguard Worker 
1138*d83cc019SAndroid Build Coastguard Worker 	igt_require((outputs[0] = set_fb_on_crtc(display, pipe[0], &fb_info[0])));
1139*d83cc019SAndroid Build Coastguard Worker 	igt_require((outputs[1] = set_fb_on_crtc(display, pipe[1], &fb_info[1])));
1140*d83cc019SAndroid Build Coastguard Worker 
1141*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1142*d83cc019SAndroid Build Coastguard Worker 
1143*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe[0], &cursor_fb);
1144*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe[0], arg[0], &cursor_fb);
1145*d83cc019SAndroid Build Coastguard Worker 	arg[0][1].x = arg[0][1].y = 192;
1146*d83cc019SAndroid Build Coastguard Worker 
1147*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe[1], &cursor_fb);
1148*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe[1], arg[1], &cursor_fb);
1149*d83cc019SAndroid Build Coastguard Worker 	arg[1][1].x =  arg[1][1].y = 192;
1150*d83cc019SAndroid Build Coastguard Worker 
1151*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1152*d83cc019SAndroid Build Coastguard Worker 
1153*d83cc019SAndroid Build Coastguard Worker 	target[0] = get_cursor_updates_per_vblank(display, pipe[0], &arg[0][0]);
1154*d83cc019SAndroid Build Coastguard Worker 	target[1] = get_cursor_updates_per_vblank(display, pipe[1], &arg[1][0]);
1155*d83cc019SAndroid Build Coastguard Worker 
1156*d83cc019SAndroid Build Coastguard Worker 	for (int i = 0; i < nloops; i++) {
1157*d83cc019SAndroid Build Coastguard Worker 		unsigned long vrefresh[2];
1158*d83cc019SAndroid Build Coastguard Worker 		unsigned vblank_start[2], vblank_last[2];
1159*d83cc019SAndroid Build Coastguard Worker 		int done[2] = {};
1160*d83cc019SAndroid Build Coastguard Worker 
1161*d83cc019SAndroid Build Coastguard Worker 		vrefresh[0] = igt_output_get_mode(outputs[0])->vrefresh;
1162*d83cc019SAndroid Build Coastguard Worker 		vrefresh[1] = igt_output_get_mode(outputs[1])->vrefresh;
1163*d83cc019SAndroid Build Coastguard Worker 
1164*d83cc019SAndroid Build Coastguard Worker 		shared[0] = 0;
1165*d83cc019SAndroid Build Coastguard Worker 		shared[1] = 0;
1166*d83cc019SAndroid Build Coastguard Worker 		igt_fork(child, 2) {
1167*d83cc019SAndroid Build Coastguard Worker 			unsigned long count = 0;
1168*d83cc019SAndroid Build Coastguard Worker 
1169*d83cc019SAndroid Build Coastguard Worker 			while (!shared[child]) {
1170*d83cc019SAndroid Build Coastguard Worker 				do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[child][(i >> child) & 1]);
1171*d83cc019SAndroid Build Coastguard Worker 				count++;
1172*d83cc019SAndroid Build Coastguard Worker 			}
1173*d83cc019SAndroid Build Coastguard Worker 			igt_debug("child %i: %lu cursor updates\n", child, count);
1174*d83cc019SAndroid Build Coastguard Worker 			shared[child] = count;
1175*d83cc019SAndroid Build Coastguard Worker 		}
1176*d83cc019SAndroid Build Coastguard Worker 
1177*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe[0], atomic, &fb_info[0], (void *)0UL);
1178*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe[1], atomic, &fb_info[1], (void *)1UL);
1179*d83cc019SAndroid Build Coastguard Worker 
1180*d83cc019SAndroid Build Coastguard Worker 		for (int n = 0; n < vrefresh[0] / 2 + vrefresh[1] / 2; n++) {
1181*d83cc019SAndroid Build Coastguard Worker 			unsigned long child;
1182*d83cc019SAndroid Build Coastguard Worker 
1183*d83cc019SAndroid Build Coastguard Worker 			igt_assert_eq(read(display->drm_fd, &vbl, sizeof(vbl)), sizeof(vbl));
1184*d83cc019SAndroid Build Coastguard Worker 			child = vbl.user_data;
1185*d83cc019SAndroid Build Coastguard Worker 
1186*d83cc019SAndroid Build Coastguard Worker 			if (!done[child]++)
1187*d83cc019SAndroid Build Coastguard Worker 				vblank_start[child] = vbl.sequence;
1188*d83cc019SAndroid Build Coastguard Worker 			else if (vbl.sequence != vblank_last[child] + 1)
1189*d83cc019SAndroid Build Coastguard Worker 				igt_info("page flip %d was delayed, missed %d frames\n",
1190*d83cc019SAndroid Build Coastguard Worker 					 done[child], vbl.sequence - vblank_last[child] - 1);
1191*d83cc019SAndroid Build Coastguard Worker 
1192*d83cc019SAndroid Build Coastguard Worker 			vblank_last[child] = vbl.sequence;
1193*d83cc019SAndroid Build Coastguard Worker 
1194*d83cc019SAndroid Build Coastguard Worker 			if (done[child] < vrefresh[child] / 2) {
1195*d83cc019SAndroid Build Coastguard Worker 				flip_nonblocking(display, pipe[child], atomic, &fb_info[child], (void *)child);
1196*d83cc019SAndroid Build Coastguard Worker 			} else {
1197*d83cc019SAndroid Build Coastguard Worker 				igt_assert_lte(vbl.sequence, vblank_start[child] + 5 * vrefresh[child] / 8);
1198*d83cc019SAndroid Build Coastguard Worker 
1199*d83cc019SAndroid Build Coastguard Worker 				shared[child] = 1;
1200*d83cc019SAndroid Build Coastguard Worker 			}
1201*d83cc019SAndroid Build Coastguard Worker 		}
1202*d83cc019SAndroid Build Coastguard Worker 
1203*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(done[0], vrefresh[0] / 2);
1204*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(done[1], vrefresh[1] / 2);
1205*d83cc019SAndroid Build Coastguard Worker 
1206*d83cc019SAndroid Build Coastguard Worker 		igt_waitchildren();
1207*d83cc019SAndroid Build Coastguard Worker 		for (int child = 0; child < 2; child++)
1208*d83cc019SAndroid Build Coastguard Worker 			igt_assert_f(shared[child] > vrefresh[child]*target[child] / 2,
1209*d83cc019SAndroid Build Coastguard Worker 				    "completed %lu cursor updated in a period of %lu flips, "
1210*d83cc019SAndroid Build Coastguard Worker 				    "we expect to complete approximately %lu updates, "
1211*d83cc019SAndroid Build Coastguard Worker 				    "with the threshold set at %lu\n",
1212*d83cc019SAndroid Build Coastguard Worker 				    shared[child], vrefresh[child] / 2,
1213*d83cc019SAndroid Build Coastguard Worker 				    vrefresh[child]*target[child], vrefresh[child]*target[child] / 2);
1214*d83cc019SAndroid Build Coastguard Worker 	}
1215*d83cc019SAndroid Build Coastguard Worker 
1216*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info[0]);
1217*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info[1]);
1218*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
1219*d83cc019SAndroid Build Coastguard Worker 	munmap((void *)shared, PAGE_SIZE);
1220*d83cc019SAndroid Build Coastguard Worker }
1221*d83cc019SAndroid Build Coastguard Worker 
flip_vs_cursor_crc(igt_display_t * display,bool atomic)1222*d83cc019SAndroid Build Coastguard Worker static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
1223*d83cc019SAndroid Build Coastguard Worker {
1224*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
1225*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
1226*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info, cursor_fb;
1227*d83cc019SAndroid Build Coastguard Worker 	unsigned vblank_start;
1228*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
1229*d83cc019SAndroid Build Coastguard Worker 	igt_crc_t crcs[3];
1230*d83cc019SAndroid Build Coastguard Worker 
1231*d83cc019SAndroid Build Coastguard Worker 	if (atomic)
1232*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
1233*d83cc019SAndroid Build Coastguard Worker 
1234*d83cc019SAndroid Build Coastguard Worker 	igt_require(set_fb_on_crtc(display, pipe, &fb_info));
1235*d83cc019SAndroid Build Coastguard Worker 
1236*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1237*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
1238*d83cc019SAndroid Build Coastguard Worker 
1239*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1240*d83cc019SAndroid Build Coastguard Worker 
1241*d83cc019SAndroid Build Coastguard Worker 	pipe_crc = igt_pipe_crc_new(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
1242*d83cc019SAndroid Build Coastguard Worker 
1243*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
1244*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, COMMIT_UNIVERSAL);
1245*d83cc019SAndroid Build Coastguard Worker 
1246*d83cc019SAndroid Build Coastguard Worker 	/* Collect reference crcs, crcs[0] last. */
1247*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[1]);
1248*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
1249*d83cc019SAndroid Build Coastguard Worker 
1250*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
1251*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1252*d83cc019SAndroid Build Coastguard Worker 
1253*d83cc019SAndroid Build Coastguard Worker 	/* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1254*d83cc019SAndroid Build Coastguard Worker 	for (int i = 1; i >= 0; i--) {
1255*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1256*d83cc019SAndroid Build Coastguard Worker 
1257*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe, atomic, &fb_info, NULL);
1258*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1259*d83cc019SAndroid Build Coastguard Worker 
1260*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1261*d83cc019SAndroid Build Coastguard Worker 
1262*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
1263*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1264*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
1265*d83cc019SAndroid Build Coastguard Worker 
1266*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start + 1);
1267*d83cc019SAndroid Build Coastguard Worker 
1268*d83cc019SAndroid Build Coastguard Worker 		igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
1269*d83cc019SAndroid Build Coastguard Worker 
1270*d83cc019SAndroid Build Coastguard Worker 		igt_assert_crc_equal(&crcs[i], &crcs[2]);
1271*d83cc019SAndroid Build Coastguard Worker 	}
1272*d83cc019SAndroid Build Coastguard Worker 
1273*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info);
1274*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
1275*d83cc019SAndroid Build Coastguard Worker }
1276*d83cc019SAndroid Build Coastguard Worker 
flip_vs_cursor_busy_crc(igt_display_t * display,bool atomic)1277*d83cc019SAndroid Build Coastguard Worker static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
1278*d83cc019SAndroid Build Coastguard Worker {
1279*d83cc019SAndroid Build Coastguard Worker 	struct drm_mode_cursor arg[2];
1280*d83cc019SAndroid Build Coastguard Worker 	struct drm_event_vblank vbl;
1281*d83cc019SAndroid Build Coastguard Worker 	struct igt_fb fb_info[2], cursor_fb;
1282*d83cc019SAndroid Build Coastguard Worker 	unsigned vblank_start;
1283*d83cc019SAndroid Build Coastguard Worker 	enum pipe pipe = find_connected_pipe(display, false);
1284*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_t *pipe_connected = &display->pipes[pipe];
1285*d83cc019SAndroid Build Coastguard Worker 	igt_plane_t *plane_primary = igt_pipe_get_plane_type(pipe_connected, DRM_PLANE_TYPE_PRIMARY);
1286*d83cc019SAndroid Build Coastguard Worker 	igt_crc_t crcs[2], test_crc;
1287*d83cc019SAndroid Build Coastguard Worker 
1288*d83cc019SAndroid Build Coastguard Worker 	if (atomic)
1289*d83cc019SAndroid Build Coastguard Worker 		igt_require(display->is_atomic);
1290*d83cc019SAndroid Build Coastguard Worker 
1291*d83cc019SAndroid Build Coastguard Worker 	igt_require(set_fb_on_crtc(display, pipe, &fb_info[0]));
1292*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_pattern_fb(display->drm_fd, fb_info[0].width, fb_info[0].height,
1293*d83cc019SAndroid Build Coastguard Worker 				    DRM_FORMAT_XRGB8888, LOCAL_I915_FORMAT_MOD_X_TILED, .1, .1, .1, &fb_info[1]);
1294*d83cc019SAndroid Build Coastguard Worker 
1295*d83cc019SAndroid Build Coastguard Worker 	igt_create_color_fb(display->drm_fd, 64, 64, DRM_FORMAT_ARGB8888, 0, 1., 1., 1., &cursor_fb);
1296*d83cc019SAndroid Build Coastguard Worker 	populate_cursor_args(display, pipe, arg, &cursor_fb);
1297*d83cc019SAndroid Build Coastguard Worker 
1298*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1299*d83cc019SAndroid Build Coastguard Worker 
1300*d83cc019SAndroid Build Coastguard Worker 	pipe_crc = igt_pipe_crc_new(display->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
1301*d83cc019SAndroid Build Coastguard Worker 
1302*d83cc019SAndroid Build Coastguard Worker 	set_cursor_on_pipe(display, pipe, &cursor_fb);
1303*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, COMMIT_UNIVERSAL);
1304*d83cc019SAndroid Build Coastguard Worker 
1305*d83cc019SAndroid Build Coastguard Worker 	/* Collect reference crcs, crc[0] last for the loop. */
1306*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[1]);
1307*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_crc_collect_crc(pipe_crc, &crcs[1]);
1308*d83cc019SAndroid Build Coastguard Worker 
1309*d83cc019SAndroid Build Coastguard Worker 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
1310*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_crc_collect_crc(pipe_crc, &crcs[0]);
1311*d83cc019SAndroid Build Coastguard Worker 
1312*d83cc019SAndroid Build Coastguard Worker 	/*
1313*d83cc019SAndroid Build Coastguard Worker 	  * Set fb 1 on primary at least once before flipping to force
1314*d83cc019SAndroid Build Coastguard Worker 	  * setting the correct cache level, else we get a stall in the
1315*d83cc019SAndroid Build Coastguard Worker 	  * page flip handler.
1316*d83cc019SAndroid Build Coastguard Worker 	  */
1317*d83cc019SAndroid Build Coastguard Worker 	igt_plane_set_fb(plane_primary, &fb_info[1]);
1318*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, COMMIT_UNIVERSAL);
1319*d83cc019SAndroid Build Coastguard Worker 
1320*d83cc019SAndroid Build Coastguard Worker 	igt_plane_set_fb(plane_primary, &fb_info[0]);
1321*d83cc019SAndroid Build Coastguard Worker 	igt_display_commit2(display, COMMIT_UNIVERSAL);
1322*d83cc019SAndroid Build Coastguard Worker 
1323*d83cc019SAndroid Build Coastguard Worker 	/*
1324*d83cc019SAndroid Build Coastguard Worker 	 * We must enable CRC collecting here since this may force
1325*d83cc019SAndroid Build Coastguard Worker 	 * a modeset, and this loop is timing sensitive.
1326*d83cc019SAndroid Build Coastguard Worker 	 */
1327*d83cc019SAndroid Build Coastguard Worker 	igt_pipe_crc_start(pipe_crc);
1328*d83cc019SAndroid Build Coastguard Worker 
1329*d83cc019SAndroid Build Coastguard Worker 	/* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
1330*d83cc019SAndroid Build Coastguard Worker 	for (int i = 1; i >= 0; i--) {
1331*d83cc019SAndroid Build Coastguard Worker 		igt_spin_t *spin;
1332*d83cc019SAndroid Build Coastguard Worker 
1333*d83cc019SAndroid Build Coastguard Worker 		spin = igt_spin_new(display->drm_fd,
1334*d83cc019SAndroid Build Coastguard Worker 				    .dependency = fb_info[1].gem_handle);
1335*d83cc019SAndroid Build Coastguard Worker 
1336*d83cc019SAndroid Build Coastguard Worker 		vblank_start = get_vblank(display->drm_fd, pipe, DRM_VBLANK_NEXTONMISS);
1337*d83cc019SAndroid Build Coastguard Worker 
1338*d83cc019SAndroid Build Coastguard Worker 		flip_nonblocking(display, pipe, atomic, &fb_info[1], NULL);
1339*d83cc019SAndroid Build Coastguard Worker 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
1340*d83cc019SAndroid Build Coastguard Worker 
1341*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(get_vblank(display->drm_fd, pipe, 0), vblank_start);
1342*d83cc019SAndroid Build Coastguard Worker 
1343*d83cc019SAndroid Build Coastguard Worker 		igt_pipe_crc_get_current(display->drm_fd, pipe_crc, &test_crc);
1344*d83cc019SAndroid Build Coastguard Worker 
1345*d83cc019SAndroid Build Coastguard Worker 		igt_spin_free(display->drm_fd, spin);
1346*d83cc019SAndroid Build Coastguard Worker 
1347*d83cc019SAndroid Build Coastguard Worker 		igt_set_timeout(1, "Stuck page flip");
1348*d83cc019SAndroid Build Coastguard Worker 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
1349*d83cc019SAndroid Build Coastguard Worker 		igt_reset_timeout();
1350*d83cc019SAndroid Build Coastguard Worker 
1351*d83cc019SAndroid Build Coastguard Worker 		igt_assert_lte(vblank_start + 1, get_vblank(display->drm_fd, pipe, 0));
1352*d83cc019SAndroid Build Coastguard Worker 
1353*d83cc019SAndroid Build Coastguard Worker 		igt_plane_set_fb(plane_primary, &fb_info[0]);
1354*d83cc019SAndroid Build Coastguard Worker 		igt_display_commit2(display, COMMIT_UNIVERSAL);
1355*d83cc019SAndroid Build Coastguard Worker 
1356*d83cc019SAndroid Build Coastguard Worker 		igt_assert_crc_equal(&crcs[i], &test_crc);
1357*d83cc019SAndroid Build Coastguard Worker 	}
1358*d83cc019SAndroid Build Coastguard Worker 
1359*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info[1]);
1360*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &fb_info[0]);
1361*d83cc019SAndroid Build Coastguard Worker 	igt_remove_fb(display->drm_fd, &cursor_fb);
1362*d83cc019SAndroid Build Coastguard Worker }
1363*d83cc019SAndroid Build Coastguard Worker 
1364*d83cc019SAndroid Build Coastguard Worker igt_main
1365*d83cc019SAndroid Build Coastguard Worker {
1366*d83cc019SAndroid Build Coastguard Worker 	const int ncpus = sysconf(_SC_NPROCESSORS_ONLN);
1367*d83cc019SAndroid Build Coastguard Worker 	igt_display_t display = { .drm_fd = -1 };
1368*d83cc019SAndroid Build Coastguard Worker 	int i;
1369*d83cc019SAndroid Build Coastguard Worker 
1370*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
1371*d83cc019SAndroid Build Coastguard Worker 		display.drm_fd = drm_open_driver_master(DRIVER_ANY);
1372*d83cc019SAndroid Build Coastguard Worker 		kmstest_set_vt_graphics_mode();
1373*d83cc019SAndroid Build Coastguard Worker 
1374*d83cc019SAndroid Build Coastguard Worker 		igt_display_require(&display, display.drm_fd);
1375*d83cc019SAndroid Build Coastguard Worker 	}
1376*d83cc019SAndroid Build Coastguard Worker 
1377*d83cc019SAndroid Build Coastguard Worker 	igt_subtest_group {
1378*d83cc019SAndroid Build Coastguard Worker 		enum pipe n;
for_each_pipe_static(n)1379*d83cc019SAndroid Build Coastguard Worker 		for_each_pipe_static(n) {
1380*d83cc019SAndroid Build Coastguard Worker 			errno = 0;
1381*d83cc019SAndroid Build Coastguard Worker 
1382*d83cc019SAndroid Build Coastguard Worker 			igt_fixture {
1383*d83cc019SAndroid Build Coastguard Worker 				igt_skip_on(n >= display.n_pipes);
1384*d83cc019SAndroid Build Coastguard Worker 			}
1385*d83cc019SAndroid Build Coastguard Worker 
1386*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-single-bo", kmstest_pipe_name(n))
1387*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, 1, DRM_MODE_CURSOR_BO, 20);
1388*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-single-move", kmstest_pipe_name(n))
1389*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, 1, DRM_MODE_CURSOR_MOVE, 20);
1390*d83cc019SAndroid Build Coastguard Worker 
1391*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-forked-bo", kmstest_pipe_name(n))
1392*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, ncpus, DRM_MODE_CURSOR_BO, 20);
1393*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-forked-move", kmstest_pipe_name(n))
1394*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, ncpus, DRM_MODE_CURSOR_MOVE, 20);
1395*d83cc019SAndroid Build Coastguard Worker 
1396*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-torture-bo", kmstest_pipe_name(n))
1397*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, -ncpus, DRM_MODE_CURSOR_BO, 20);
1398*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("pipe-%s-torture-move", kmstest_pipe_name(n))
1399*d83cc019SAndroid Build Coastguard Worker 				stress(&display, n, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
1400*d83cc019SAndroid Build Coastguard Worker 		}
1401*d83cc019SAndroid Build Coastguard Worker 	}
1402*d83cc019SAndroid Build Coastguard Worker 
1403*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-single-bo")
1404*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, 1, DRM_MODE_CURSOR_BO, 20);
1405*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-single-move")
1406*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, 1, DRM_MODE_CURSOR_MOVE, 20);
1407*d83cc019SAndroid Build Coastguard Worker 
1408*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-forked-bo")
1409*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, ncpus, DRM_MODE_CURSOR_BO, 20);
1410*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-forked-move")
1411*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, ncpus, DRM_MODE_CURSOR_MOVE, 20);
1412*d83cc019SAndroid Build Coastguard Worker 
1413*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-torture-bo")
1414*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, -ncpus, DRM_MODE_CURSOR_BO, 20);
1415*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("all-pipes-torture-move")
1416*d83cc019SAndroid Build Coastguard Worker 		stress(&display, -1, -ncpus, DRM_MODE_CURSOR_MOVE, 20);
1417*d83cc019SAndroid Build Coastguard Worker 
1418*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("nonblocking-modeset-vs-cursor-atomic")
1419*d83cc019SAndroid Build Coastguard Worker 		nonblocking_modeset_vs_cursor(&display, 1);
1420*d83cc019SAndroid Build Coastguard Worker 
1421*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("long-nonblocking-modeset-vs-cursor-atomic")
1422*d83cc019SAndroid Build Coastguard Worker 		nonblocking_modeset_vs_cursor(&display, 16);
1423*d83cc019SAndroid Build Coastguard Worker 
1424*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-flip-vs-cursor-legacy")
1425*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 8, false, false);
1426*d83cc019SAndroid Build Coastguard Worker 
1427*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-flip-vs-cursor-atomic")
1428*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 8, false, true);
1429*d83cc019SAndroid Build Coastguard Worker 
1430*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-cursor-vs-flip-legacy")
1431*d83cc019SAndroid Build Coastguard Worker 		two_screens_cursor_vs_flip(&display, 8, false);
1432*d83cc019SAndroid Build Coastguard Worker 
1433*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-long-flip-vs-cursor-legacy")
1434*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 150, false, false);
1435*d83cc019SAndroid Build Coastguard Worker 
1436*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-long-flip-vs-cursor-atomic")
1437*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 150, false, true);
1438*d83cc019SAndroid Build Coastguard Worker 
1439*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-long-cursor-vs-flip-legacy")
1440*d83cc019SAndroid Build Coastguard Worker 		two_screens_cursor_vs_flip(&display, 50, false);
1441*d83cc019SAndroid Build Coastguard Worker 
1442*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-nonblocking-modeset-vs-cursor-atomic")
1443*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 4, true, true);
1444*d83cc019SAndroid Build Coastguard Worker 
1445*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-cursor-vs-flip-atomic")
1446*d83cc019SAndroid Build Coastguard Worker 		two_screens_cursor_vs_flip(&display, 8, true);
1447*d83cc019SAndroid Build Coastguard Worker 
1448*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-long-nonblocking-modeset-vs-cursor-atomic")
1449*d83cc019SAndroid Build Coastguard Worker 		two_screens_flip_vs_cursor(&display, 15, true, true);
1450*d83cc019SAndroid Build Coastguard Worker 
1451*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("2x-long-cursor-vs-flip-atomic")
1452*d83cc019SAndroid Build Coastguard Worker 		two_screens_cursor_vs_flip(&display, 50, true);
1453*d83cc019SAndroid Build Coastguard Worker 
1454*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("flip-vs-cursor-crc-legacy")
1455*d83cc019SAndroid Build Coastguard Worker 		flip_vs_cursor_crc(&display, false);
1456*d83cc019SAndroid Build Coastguard Worker 
1457*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("flip-vs-cursor-crc-atomic")
1458*d83cc019SAndroid Build Coastguard Worker 		flip_vs_cursor_crc(&display, true);
1459*d83cc019SAndroid Build Coastguard Worker 
1460*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("flip-vs-cursor-busy-crc-legacy")
1461*d83cc019SAndroid Build Coastguard Worker 		flip_vs_cursor_busy_crc(&display, false);
1462*d83cc019SAndroid Build Coastguard Worker 
1463*d83cc019SAndroid Build Coastguard Worker 	igt_subtest("flip-vs-cursor-busy-crc-atomic")
1464*d83cc019SAndroid Build Coastguard Worker 		flip_vs_cursor_busy_crc(&display, true);
1465*d83cc019SAndroid Build Coastguard Worker 
1466*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i <= flip_test_last; i++) {
1467*d83cc019SAndroid Build Coastguard Worker 		const char *modes[flip_test_last+1] = {
1468*d83cc019SAndroid Build Coastguard Worker 			"legacy",
1469*d83cc019SAndroid Build Coastguard Worker 			"varying-size",
1470*d83cc019SAndroid Build Coastguard Worker 			"toggle",
1471*d83cc019SAndroid Build Coastguard Worker 			"atomic",
1472*d83cc019SAndroid Build Coastguard Worker 			"atomic-transitions",
1473*d83cc019SAndroid Build Coastguard Worker 			"atomic-transitions-varying-size"
1474*d83cc019SAndroid Build Coastguard Worker 		};
1475*d83cc019SAndroid Build Coastguard Worker 		const char *prefix = "short-";
1476*d83cc019SAndroid Build Coastguard Worker 
1477*d83cc019SAndroid Build Coastguard Worker 		switch (i) {
1478*d83cc019SAndroid Build Coastguard Worker 		case flip_test_legacy:
1479*d83cc019SAndroid Build Coastguard Worker 		case flip_test_varying_size:
1480*d83cc019SAndroid Build Coastguard Worker 		case flip_test_atomic:
1481*d83cc019SAndroid Build Coastguard Worker 			prefix = "basic-";
1482*d83cc019SAndroid Build Coastguard Worker 			break;
1483*d83cc019SAndroid Build Coastguard Worker 		default: break;
1484*d83cc019SAndroid Build Coastguard Worker 		}
1485*d83cc019SAndroid Build Coastguard Worker 
1486*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("%sflip-before-cursor-%s", prefix, modes[i])
1487*d83cc019SAndroid Build Coastguard Worker 			basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR, 0);
1488*d83cc019SAndroid Build Coastguard Worker 
1489*d83cc019SAndroid Build Coastguard Worker 		if (!cursor_slowpath(i)) {
1490*d83cc019SAndroid Build Coastguard Worker 			igt_subtest_f("%sbusy-flip-before-cursor-%s", prefix, modes[i]) {
1491*d83cc019SAndroid Build Coastguard Worker 				igt_require_gem(display.drm_fd);
1492*d83cc019SAndroid Build Coastguard Worker 				basic_flip_cursor(&display, i, FLIP_BEFORE_CURSOR,
1493*d83cc019SAndroid Build Coastguard Worker 						  BASIC_BUSY);
1494*d83cc019SAndroid Build Coastguard Worker 			}
1495*d83cc019SAndroid Build Coastguard Worker 		}
1496*d83cc019SAndroid Build Coastguard Worker 
1497*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("%sflip-after-cursor-%s", prefix, modes[i])
1498*d83cc019SAndroid Build Coastguard Worker 			basic_flip_cursor(&display, i, FLIP_AFTER_CURSOR, 0);
1499*d83cc019SAndroid Build Coastguard Worker 
1500*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("flip-vs-cursor-%s", modes[i])
1501*d83cc019SAndroid Build Coastguard Worker 			flip_vs_cursor(&display, i, 150);
1502*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cursor-vs-flip-%s", modes[i])
1503*d83cc019SAndroid Build Coastguard Worker 			cursor_vs_flip(&display, i, 50);
1504*d83cc019SAndroid Build Coastguard Worker 
1505*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cursorA-vs-flipA-%s", modes[i])
1506*d83cc019SAndroid Build Coastguard Worker 			flip(&display, 0, 0, 10, i);
1507*d83cc019SAndroid Build Coastguard Worker 
1508*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cursorA-vs-flipB-%s", modes[i])
1509*d83cc019SAndroid Build Coastguard Worker 			flip(&display, 0, 1, 10, i);
1510*d83cc019SAndroid Build Coastguard Worker 
1511*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cursorB-vs-flipA-%s", modes[i])
1512*d83cc019SAndroid Build Coastguard Worker 			flip(&display, 1, 0, 10, i);
1513*d83cc019SAndroid Build Coastguard Worker 
1514*d83cc019SAndroid Build Coastguard Worker 		igt_subtest_f("cursorB-vs-flipB-%s", modes[i])
1515*d83cc019SAndroid Build Coastguard Worker 			flip(&display, 1, 1, 10, i);
1516*d83cc019SAndroid Build Coastguard Worker 	}
1517*d83cc019SAndroid Build Coastguard Worker 
1518*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
1519*d83cc019SAndroid Build Coastguard Worker 		igt_display_fini(&display);
1520*d83cc019SAndroid Build Coastguard Worker 	}
1521*d83cc019SAndroid Build Coastguard Worker }
1522