1 /*
2  * Copyright © 2015 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors: Paulo Zanoni <paulo.r.zanoni@intel.com>
24  *
25  */
26 
27 #include "igt.h"
28 #include "igt_sysfs.h"
29 #include "igt_psr.h"
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <poll.h>
34 #include <pthread.h>
35 
36 
37 IGT_TEST_DESCRIPTION("Test the Kernel's frontbuffer tracking mechanism and "
38 		     "its related features: FBC, PSR and DRRS");
39 
40 /*
41  * One of the aspects of this test is that, for every subtest, we try different
42  * combinations of the parameters defined by the struct below. Because of this,
43  * a single addition of a new parameter or subtest function can lead to hundreds
44  * of new subtests.
45  *
46  * In order to reduce the number combinations we cut the cases that don't make
47  * sense, such as writing on the secondary screen when there is only a single
48  * pipe, or flipping when the target is the offscreen buffer. We also hide some
49  * combinations that are somewhat redundant and don't add much value to the
50  * test. For example, since we already do the offscreen testing with a single
51  * pipe enabled, there's no much value in doing it again with dual pipes. If you
52  * still want to try these redundant tests, you need to use the --show-hidden
53  * option.
54  *
55  * The most important hidden thing is the FEATURE_NONE set of tests. Whenever
56  * you get a failure on any test, it is important to check whether the same test
57  * fails with FEATURE_NONE - replace the feature name for "nop". If the nop test
58  * also fails, then it's likely the problem will be on the IGT side instead of
59  * the Kernel side. We don't expose this set of tests by default because (i)
60  * they take a long time to test; and (ii) if the feature tests work, then it's
61  * very likely that the nop tests will also work.
62  */
63 struct test_mode {
64 	/* Are we going to enable just one monitor, or are we going to setup a
65 	 * dual screen environment for the test? */
66 	enum {
67 		PIPE_SINGLE = 0,
68 		PIPE_DUAL,
69 		PIPE_COUNT,
70 	} pipes;
71 
72 	/* The primary screen is the one that's supposed to have the "feature"
73 	 * enabled on, but we have the option to draw on the secondary screen or
74 	 * on some offscreen buffer. We also only theck the CRC of the primary
75 	 * screen. */
76 	enum {
77 		SCREEN_PRIM = 0,
78 		SCREEN_SCND,
79 		SCREEN_OFFSCREEN,
80 		SCREEN_COUNT,
81 	} screen;
82 
83 	/* When we draw, we can draw directly on the primary plane, on the
84 	 * cursor or on the sprite plane. */
85 	enum {
86 		PLANE_PRI = 0,
87 		PLANE_CUR,
88 		PLANE_SPR,
89 		PLANE_COUNT,
90 	} plane;
91 
92 	/* We can organize the screens in a way that each screen has its own
93 	 * framebuffer, or in a way that all screens point to the same
94 	 * framebuffer, but on different places. This includes the offscreen
95 	 * screen. */
96 	enum {
97 		FBS_INDIVIDUAL = 0,
98 		FBS_SHARED,
99 		FBS_COUNT,
100 	} fbs;
101 
102 	/* Which features are we going to test now? This is a mask!
103 	 * FEATURE_DEFAULT is a special value which instruct the test to just
104 	 * keep what's already enabled by default in the Kernel. */
105 	enum {
106 		FEATURE_NONE  = 0,
107 		FEATURE_FBC   = 1,
108 		FEATURE_PSR   = 2,
109 		FEATURE_DRRS  = 4,
110 		FEATURE_COUNT = 8,
111 		FEATURE_DEFAULT = 8,
112 	} feature;
113 
114 	/* Possible pixel formats. We just use FORMAT_DEFAULT for most tests and
115 	 * only test a few things on the other formats. */
116 	enum pixel_format {
117 		FORMAT_RGB888 = 0,
118 		FORMAT_RGB565,
119 		FORMAT_RGB101010,
120 		FORMAT_COUNT,
121 		FORMAT_DEFAULT = FORMAT_RGB888,
122 	} format;
123 
124 	/* There are multiple APIs where we can do the equivalent of a page flip
125 	 * and they exercise slightly different codepaths inside the Kernel. */
126 	enum flip_type {
127 		FLIP_PAGEFLIP,
128 		FLIP_MODESET,
129 		FLIP_PLANES,
130 		FLIP_COUNT,
131 	} flip;
132 
133 	enum igt_draw_method method;
134 };
135 
136 enum color {
137 	COLOR_RED,
138 	COLOR_GREEN,
139 	COLOR_BLUE,
140 	COLOR_MAGENTA,
141 	COLOR_CYAN,
142 	COLOR_SCND_BG,
143 	COLOR_PRIM_BG = COLOR_BLUE,
144 	COLOR_OFFSCREEN_BG = COLOR_SCND_BG,
145 };
146 
147 struct rect {
148 	int x;
149 	int y;
150 	int w;
151 	int h;
152 	uint32_t color;
153 };
154 
155 struct {
156 	int fd;
157 	int debugfs;
158 	igt_display_t display;
159 
160 	drm_intel_bufmgr *bufmgr;
161 } drm;
162 
163 struct {
164 	bool can_test;
165 
166 	bool supports_last_action;
167 
168 	struct timespec last_action;
169 } fbc = {
170 	.can_test = false,
171 	.supports_last_action = false,
172 };
173 
174 struct {
175 	bool can_test;
176 } psr = {
177 	.can_test = false,
178 };
179 
180 #define MAX_DRRS_STATUS_BUF_LEN 256
181 
182 struct {
183 	bool can_test;
184 } drrs = {
185 	.can_test = false,
186 };
187 
188 igt_pipe_crc_t *pipe_crc;
189 igt_crc_t *wanted_crc;
190 struct {
191 	bool initialized;
192 	igt_crc_t crc;
193 } blue_crcs[FORMAT_COUNT];
194 
195 /* The goal of this structure is to easily allow us to deal with cases where we
196  * have a big framebuffer and the CRTC is just displaying a subregion of this
197  * big FB. */
198 struct fb_region {
199 	igt_plane_t *plane;
200 	struct igt_fb *fb;
201 	int x;
202 	int y;
203 	int w;
204 	int h;
205 };
206 
207 struct draw_pattern_info {
208 	bool frames_stack;
209 	int n_rects;
210 	struct rect (*get_rect)(struct fb_region *fb, int r);
211 
212 	bool initialized[FORMAT_COUNT];
213 	igt_crc_t *crcs[FORMAT_COUNT];
214 };
215 
216 /* Draw big rectangles on the screen. */
217 struct draw_pattern_info pattern1;
218 /* 64x64 rectangles at x:0,y:0, just so we can draw on the cursor and sprite. */
219 struct draw_pattern_info pattern2;
220 /* 64x64 rectangles at different positions, same color, for the move test. */
221 struct draw_pattern_info pattern3;
222 /* Just a fullscreen green square. */
223 struct draw_pattern_info pattern4;
224 
225 /* Command line parameters. */
226 struct {
227 	bool check_status;
228 	bool check_crc;
229 	bool fbc_check_compression;
230 	bool fbc_check_last_action;
231 	bool no_edp;
232 	bool small_modes;
233 	bool show_hidden;
234 	int step;
235 	int only_pipes;
236 	int shared_fb_x_offset;
237 	int shared_fb_y_offset;
238 	uint64_t tiling;
239 } opt = {
240 	.check_status = true,
241 	.check_crc = true,
242 	.fbc_check_compression = true,
243 	.fbc_check_last_action = true,
244 	.no_edp = false,
245 	.small_modes = false,
246 	.show_hidden= false,
247 	.step = 0,
248 	.only_pipes = PIPE_COUNT,
249 	.shared_fb_x_offset = 248,
250 	.shared_fb_y_offset = 500,
251 	.tiling = LOCAL_I915_FORMAT_MOD_X_TILED,
252 };
253 
254 struct modeset_params {
255 	enum pipe pipe;
256 	igt_output_t *output;
257 	drmModeModeInfo mode_copy, *mode;
258 
259 	struct fb_region primary;
260 	struct fb_region cursor;
261 	struct fb_region sprite;
262 };
263 
264 struct modeset_params prim_mode_params;
265 struct modeset_params scnd_mode_params;
266 
267 struct fb_region offscreen_fb;
268 struct screen_fbs {
269 	bool initialized;
270 
271 	struct igt_fb prim_pri;
272 	struct igt_fb prim_cur;
273 	struct igt_fb prim_spr;
274 
275 	struct igt_fb scnd_pri;
276 	struct igt_fb scnd_cur;
277 	struct igt_fb scnd_spr;
278 
279 	struct igt_fb offscreen;
280 	struct igt_fb big;
281 } fbs[FORMAT_COUNT];
282 
283 struct {
284 	pthread_t thread;
285 	bool stop;
286 
287 	uint32_t handle;
288 	uint32_t size;
289 	uint32_t stride;
290 	int width;
291 	int height;
292 	uint32_t color;
293 	int bpp;
294 } busy_thread = {
295 	.stop = true,
296 };
297 
get_connector_smallest_mode(igt_output_t * output)298 static const drmModeModeInfo *get_connector_smallest_mode(igt_output_t *output)
299 {
300 	drmModeConnector *c = output->config.connector;
301 	const drmModeModeInfo *smallest = NULL;
302 	int i;
303 
304 	for (i = 0; i < c->count_modes; i++) {
305 		drmModeModeInfo *mode = &c->modes[i];
306 
307 		if (!smallest)
308 			smallest = mode;
309 
310 		if (mode->hdisplay * mode->vdisplay <
311 		    smallest->hdisplay * smallest->vdisplay)
312 			smallest = mode;
313 	}
314 
315 	if (c->connector_type == DRM_MODE_CONNECTOR_eDP)
316 		smallest = igt_std_1024_mode_get();
317 
318 	return smallest;
319 }
320 
connector_get_mode(igt_output_t * output)321 static const drmModeModeInfo *connector_get_mode(igt_output_t *output)
322 {
323 	const drmModeModeInfo *mode = NULL;
324 
325 	if (opt.small_modes)
326 		mode = get_connector_smallest_mode(output);
327 	else
328 		mode = &output->config.default_mode;
329 
330 	 /* On HSW the CRC WA is so awful that it makes you think everything is
331 	  * bugged. */
332 	if (IS_HASWELL(intel_get_drm_devid(drm.fd)) &&
333 	    output->config.connector->connector_type == DRM_MODE_CONNECTOR_eDP)
334 		mode = igt_std_1024_mode_get();
335 
336 	return mode;
337 }
338 
init_mode_params(struct modeset_params * params,igt_output_t * output,enum pipe pipe)339 static void init_mode_params(struct modeset_params *params,
340 			     igt_output_t *output, enum pipe pipe)
341 {
342 	const drmModeModeInfo *mode;
343 
344 	igt_output_override_mode(output, NULL);
345 	mode = connector_get_mode(output);
346 
347 	params->pipe = pipe;
348 	params->output = output;
349 	params->mode_copy = *mode;
350 	params->mode = &params->mode_copy;
351 
352 	params->primary.plane = igt_pipe_get_plane_type(&drm.display.pipes[pipe], DRM_PLANE_TYPE_PRIMARY);
353 	params->primary.fb = NULL;
354 	params->primary.x = 0;
355 	params->primary.y = 0;
356 	params->primary.w = mode->hdisplay;
357 	params->primary.h = mode->vdisplay;
358 
359 	params->cursor.plane = igt_pipe_get_plane_type(&drm.display.pipes[pipe], DRM_PLANE_TYPE_CURSOR);
360 	params->cursor.fb = NULL;
361 	params->cursor.x = 0;
362 	params->cursor.y = 0;
363 	params->cursor.w = 64;
364 	params->cursor.h = 64;
365 
366 	params->sprite.plane = igt_pipe_get_plane_type(&drm.display.pipes[pipe], DRM_PLANE_TYPE_OVERLAY);
367 	igt_require(params->sprite.plane);
368 	params->sprite.fb = NULL;
369 	params->sprite.x = 0;
370 	params->sprite.y = 0;
371 	params->sprite.w = 64;
372 	params->sprite.h = 64;
373 }
374 
find_connector(bool edp_only,bool pipe_a,igt_output_t * forbidden_output,enum pipe forbidden_pipe,igt_output_t ** ret_output,enum pipe * ret_pipe)375 static bool find_connector(bool edp_only, bool pipe_a,
376 			   igt_output_t *forbidden_output,
377 			   enum pipe forbidden_pipe,
378 			   igt_output_t **ret_output,
379 			   enum pipe *ret_pipe)
380 {
381 	igt_output_t *output;
382 	enum pipe pipe;
383 
384 	for_each_pipe_with_valid_output(&drm.display, pipe, output) {
385 		drmModeConnectorPtr c = output->config.connector;
386 
387 		if (edp_only && c->connector_type != DRM_MODE_CONNECTOR_eDP)
388 			continue;
389 
390 		if (pipe_a && pipe != PIPE_A)
391 			continue;
392 
393 		if (output == forbidden_output || pipe == forbidden_pipe)
394 			continue;
395 
396 		if (c->connector_type == DRM_MODE_CONNECTOR_eDP && opt.no_edp)
397 			continue;
398 
399 		*ret_output = output;
400 		*ret_pipe = pipe;
401 		return true;
402 	}
403 
404 	return false;
405 }
406 
init_modeset_cached_params(void)407 static bool init_modeset_cached_params(void)
408 {
409 	igt_output_t *prim_output = NULL, *scnd_output = NULL;
410 	enum pipe prim_pipe, scnd_pipe;
411 
412 	/*
413 	 * We have this problem where PSR is only present on eDP monitors and
414 	 * FBC is only present on pipe A for some platforms. So we search first
415 	 * for the ideal case of eDP supporting pipe A, and try the less optimal
416 	 * configs later, sacrificing  one of the features.
417 	 * TODO: refactor the code in a way that allows us to have different
418 	 * sets of prim/scnd structs for different features.
419 	 */
420 	find_connector(true, true, NULL, PIPE_NONE, &prim_output, &prim_pipe);
421 	if (!prim_output)
422 		find_connector(true, false, NULL, PIPE_NONE, &prim_output, &prim_pipe);
423 	if (!prim_output)
424 		find_connector(false, true, NULL, PIPE_NONE, &prim_output, &prim_pipe);
425 	if (!prim_output)
426 		find_connector(false, false, NULL, PIPE_NONE, &prim_output, &prim_pipe);
427 
428 	if (!prim_output)
429 		return false;
430 
431 	find_connector(false, false, prim_output, prim_pipe,
432 		       &scnd_output, &scnd_pipe);
433 
434 	init_mode_params(&prim_mode_params, prim_output, prim_pipe);
435 
436 	if (!scnd_output) {
437 		scnd_mode_params.pipe = PIPE_NONE;
438 		scnd_mode_params.output = NULL;
439 		return true;
440 	}
441 
442 	init_mode_params(&scnd_mode_params, scnd_output, scnd_pipe);
443 	return true;
444 }
445 
create_fb(enum pixel_format pformat,int width,int height,uint64_t tiling,int plane,struct igt_fb * fb)446 static void create_fb(enum pixel_format pformat, int width, int height,
447 		      uint64_t tiling, int plane, struct igt_fb *fb)
448 {
449 	uint32_t format;
450 	uint64_t size;
451 	unsigned int stride;
452 	uint64_t tiling_for_size;
453 
454 	switch (pformat) {
455 	case FORMAT_RGB888:
456 		if (plane == PLANE_CUR)
457 			format = DRM_FORMAT_ARGB8888;
458 		else
459 			format = DRM_FORMAT_XRGB8888;
460 		break;
461 	case FORMAT_RGB565:
462 		/* Only the primary plane supports 16bpp! */
463 		if (plane == PLANE_PRI)
464 			format = DRM_FORMAT_RGB565;
465 		else if (plane == PLANE_CUR)
466 			format = DRM_FORMAT_ARGB8888;
467 		else
468 			format = DRM_FORMAT_XRGB8888;
469 		break;
470 	case FORMAT_RGB101010:
471 		if (plane == PLANE_PRI)
472 			format = DRM_FORMAT_XRGB2101010;
473 		else if (plane == PLANE_CUR)
474 			format = DRM_FORMAT_ARGB8888;
475 		else
476 			format = DRM_FORMAT_XRGB8888;
477 		break;
478 	default:
479 		igt_assert(false);
480 	}
481 
482 	/* We want all frontbuffers with the same width/height/format to have
483 	 * the same size regardless of tiling since we want to properly exercise
484 	 * the Kernel's specific tiling-checking code paths without accidentally
485 	 * hitting size-checking ones first. */
486 	if (plane == PLANE_CUR)
487 		tiling_for_size = LOCAL_DRM_FORMAT_MOD_NONE;
488 	else
489 		tiling_for_size = opt.tiling;
490 
491 	igt_calc_fb_size(drm.fd, width, height, format, tiling_for_size, &size,
492 			 &stride);
493 
494 	igt_create_fb_with_bo_size(drm.fd, width, height, format, tiling,
495 				   IGT_COLOR_YCBCR_BT709,
496 				   IGT_COLOR_YCBCR_LIMITED_RANGE,
497 				   fb, size, stride);
498 }
499 
pick_color(struct igt_fb * fb,enum color ecolor)500 static uint32_t pick_color(struct igt_fb *fb, enum color ecolor)
501 {
502 	uint32_t color, r, g, b, b2, a;
503 	bool alpha = false;
504 
505 	switch (fb->drm_format) {
506 	case DRM_FORMAT_RGB565:
507 		a =  0x0;
508 		r =  0x1F << 11;
509 		g =  0x3F << 5;
510 		b =  0x1F;
511 		b2 = 0x10;
512 		break;
513 	case DRM_FORMAT_ARGB8888:
514 		alpha = true;
515 	case DRM_FORMAT_XRGB8888:
516 		a =  0xFF << 24;
517 		r =  0xFF << 16;
518 		g =  0xFF << 8;
519 		b =  0xFF;
520 		b2 = 0x80;
521 		break;
522 	case DRM_FORMAT_ARGB2101010:
523 		alpha = true;
524 	case DRM_FORMAT_XRGB2101010:
525 		a = 0x3 << 30;
526 		r = 0x3FF << 20;
527 		g = 0x3FF << 10;
528 		b = 0x3FF;
529 		b2 = 0x200;
530 		break;
531 	default:
532 		igt_assert(false);
533 	}
534 
535 	switch (ecolor) {
536 	case COLOR_RED:
537 		color = r;
538 		break;
539 	case COLOR_GREEN:
540 		color = g;
541 		break;
542 	case COLOR_BLUE:
543 		color = b;
544 		break;
545 	case COLOR_MAGENTA:
546 		color = r | b;
547 		break;
548 	case COLOR_CYAN:
549 		color = g | b;
550 		break;
551 	case COLOR_SCND_BG:
552 		color = b2;
553 		break;
554 	default:
555 		igt_assert(false);
556 	}
557 
558 	if (alpha)
559 		color |= a;
560 
561 	return color;
562 }
563 
fill_fb(struct igt_fb * fb,enum color ecolor)564 static void fill_fb(struct igt_fb *fb, enum color ecolor)
565 {
566 	igt_draw_fill_fb(drm.fd, fb, pick_color(fb, ecolor));
567 }
568 
569 /*
570  * This is how the prim, scnd and offscreen FBs should be positioned inside the
571  * shared FB. The prim buffer starts at the X and Y offsets defined by
572  * opt.shared_fb_{x,y}_offset, then scnd starts at the same X pixel offset,
573  * right after prim ends on the Y axis, then the offscreen fb starts after scnd
574  * ends. Just like the picture:
575  *
576  * +-------------------------+
577  * | shared fb               |
578  * |   +------------------+  |
579  * |   | prim             |  |
580  * |   |                  |  |
581  * |   |                  |  |
582  * |   |                  |  |
583  * |   +------------------+--+
584  * |   | scnd                |
585  * |   |                     |
586  * |   |                     |
587  * |   +---------------+-----+
588  * |   | offscreen     |     |
589  * |   |               |     |
590  * |   |               |     |
591  * +---+---------------+-----+
592  *
593  * We do it vertically instead of the more common horizontal case in order to
594  * avoid super huge strides not supported by FBC.
595  */
create_shared_fb(enum pixel_format format)596 static void create_shared_fb(enum pixel_format format)
597 {
598 	int prim_w, prim_h, scnd_w, scnd_h, offs_w, offs_h, big_w, big_h;
599 	struct screen_fbs *s = &fbs[format];
600 
601 	prim_w = prim_mode_params.mode->hdisplay;
602 	prim_h = prim_mode_params.mode->vdisplay;
603 
604 	if (scnd_mode_params.output) {
605 		scnd_w = scnd_mode_params.mode->hdisplay;
606 		scnd_h = scnd_mode_params.mode->vdisplay;
607 	} else {
608 		scnd_w = 0;
609 		scnd_h = 0;
610 	}
611 	offs_w = offscreen_fb.w;
612 	offs_h = offscreen_fb.h;
613 
614 	big_w = prim_w;
615 	if (scnd_w > big_w)
616 		big_w = scnd_w;
617 	if (offs_w > big_w)
618 		big_w = offs_w;
619 	big_w += opt.shared_fb_x_offset;
620 
621 	big_h = prim_h + scnd_h + offs_h + opt.shared_fb_y_offset;
622 
623 	create_fb(format, big_w, big_h, opt.tiling, PLANE_PRI, &s->big);
624 }
625 
destroy_fbs(enum pixel_format format)626 static void destroy_fbs(enum pixel_format format)
627 {
628 	struct screen_fbs *s = &fbs[format];
629 
630 	if (!s->initialized)
631 		return;
632 
633 	if (scnd_mode_params.output) {
634 		igt_remove_fb(drm.fd, &s->scnd_pri);
635 		igt_remove_fb(drm.fd, &s->scnd_cur);
636 		igt_remove_fb(drm.fd, &s->scnd_spr);
637 	}
638 	igt_remove_fb(drm.fd, &s->prim_pri);
639 	igt_remove_fb(drm.fd, &s->prim_cur);
640 	igt_remove_fb(drm.fd, &s->prim_spr);
641 	igt_remove_fb(drm.fd, &s->offscreen);
642 	igt_remove_fb(drm.fd, &s->big);
643 }
644 
create_fbs(enum pixel_format format)645 static void create_fbs(enum pixel_format format)
646 {
647 	struct screen_fbs *s = &fbs[format];
648 
649 	if (s->initialized)
650 		destroy_fbs(format);
651 
652 	s->initialized = true;
653 
654 	create_fb(format, prim_mode_params.mode->hdisplay,
655 		  prim_mode_params.mode->vdisplay, opt.tiling, PLANE_PRI,
656 		  &s->prim_pri);
657 	create_fb(format, prim_mode_params.cursor.w,
658 		  prim_mode_params.cursor.h, LOCAL_DRM_FORMAT_MOD_NONE,
659 		  PLANE_CUR, &s->prim_cur);
660 	create_fb(format, prim_mode_params.sprite.w,
661 		  prim_mode_params.sprite.h, opt.tiling, PLANE_SPR,
662 		  &s->prim_spr);
663 
664 	create_fb(format, offscreen_fb.w, offscreen_fb.h, opt.tiling, PLANE_PRI,
665 		  &s->offscreen);
666 
667 	create_shared_fb(format);
668 
669 	if (!scnd_mode_params.output)
670 		return;
671 
672 	create_fb(format, scnd_mode_params.mode->hdisplay,
673 		  scnd_mode_params.mode->vdisplay, opt.tiling, PLANE_PRI,
674 		  &s->scnd_pri);
675 	create_fb(format, scnd_mode_params.cursor.w, scnd_mode_params.cursor.h,
676 		  LOCAL_DRM_FORMAT_MOD_NONE, PLANE_CUR, &s->scnd_cur);
677 	create_fb(format, scnd_mode_params.sprite.w, scnd_mode_params.sprite.h,
678 		  opt.tiling, PLANE_SPR, &s->scnd_spr);
679 }
680 
__set_prim_plane_for_params(struct modeset_params * params)681 static void __set_prim_plane_for_params(struct modeset_params *params)
682 {
683 	igt_plane_set_fb(params->primary.plane, params->primary.fb);
684 	igt_plane_set_position(params->primary.plane, 0, 0);
685 	igt_plane_set_size(params->primary.plane, params->mode->hdisplay, params->mode->vdisplay);
686 	igt_fb_set_position(params->primary.fb, params->primary.plane,
687 			    params->primary.x, params->primary.y);
688 	igt_fb_set_size(params->primary.fb, params->primary.plane,
689 			params->mode->hdisplay, params->mode->vdisplay);
690 }
691 
__set_mode_for_params(struct modeset_params * params)692 static void __set_mode_for_params(struct modeset_params *params)
693 {
694 	igt_output_override_mode(params->output, params->mode);
695 	igt_output_set_pipe(params->output, params->pipe);
696 
697 	__set_prim_plane_for_params(params);
698 }
699 
set_mode_for_params(struct modeset_params * params)700 static void set_mode_for_params(struct modeset_params *params)
701 {
702 	__set_mode_for_params(params);
703 	igt_display_commit(&drm.display);
704 }
705 
__debugfs_read(const char * param,char * buf,int len)706 static void __debugfs_read(const char *param, char *buf, int len)
707 {
708 	len = igt_debugfs_simple_read(drm.debugfs, param, buf, len);
709 	if (len < 0)
710 		igt_assert_eq(len, -ENODEV);
711 }
712 
__debugfs_write(const char * param,char * buf,int len)713 static int __debugfs_write(const char *param, char *buf, int len)
714 {
715 	return igt_sysfs_write(drm.debugfs, param, buf, len - 1);
716 }
717 
718 #define debugfs_read(p, arr) __debugfs_read(p, arr, sizeof(arr))
719 #define debugfs_write(p, arr) __debugfs_write(p, arr, sizeof(arr))
720 
721 static char last_fbc_buf[128];
722 
fbc_is_enabled(int lvl)723 static bool fbc_is_enabled(int lvl)
724 {
725 	char buf[128];
726 	bool print = true;
727 
728 	debugfs_read("i915_fbc_status", buf);
729 	if (lvl != IGT_LOG_DEBUG)
730 		last_fbc_buf[0] = '\0';
731 	else if (strcmp(last_fbc_buf, buf))
732 		strcpy(last_fbc_buf, buf);
733 	else
734 		print = false;
735 
736 	if (print)
737 		igt_log(IGT_LOG_DOMAIN, lvl, "fbc_is_enabled()?\n%s", buf);
738 
739 	return strstr(buf, "FBC enabled\n");
740 }
741 
drrs_set(unsigned int val)742 static void drrs_set(unsigned int val)
743 {
744 	char buf[2];
745 	int ret;
746 
747 	igt_debug("Manually %sabling DRRS. %u\n", val ? "en" : "dis", val);
748 	snprintf(buf, sizeof(buf), "%d", val);
749 	ret = debugfs_write("i915_drrs_ctl", buf);
750 
751 	/*
752 	 * drrs_enable() is called on DRRS capable platform only,
753 	 * whereas drrs_disable() is called on all platforms.
754 	 * So handle the failure of debugfs_write only for drrs_enable().
755 	 */
756 	if (val)
757 		igt_assert_f(ret == (sizeof(buf) - 1), "debugfs_write failed");
758 }
759 
is_drrs_high(void)760 static bool is_drrs_high(void)
761 {
762 	char buf[MAX_DRRS_STATUS_BUF_LEN];
763 
764 	debugfs_read("i915_drrs_status", buf);
765 	return strstr(buf, "DRRS_HIGH_RR");
766 }
767 
is_drrs_low(void)768 static bool is_drrs_low(void)
769 {
770 	char buf[MAX_DRRS_STATUS_BUF_LEN];
771 
772 	debugfs_read("i915_drrs_status", buf);
773 	return strstr(buf, "DRRS_LOW_RR");
774 }
775 
is_drrs_supported(void)776 static bool is_drrs_supported(void)
777 {
778 	char buf[MAX_DRRS_STATUS_BUF_LEN];
779 
780 	debugfs_read("i915_drrs_status", buf);
781 	return strstr(buf, "DRRS Supported: Yes");
782 }
783 
is_drrs_inactive(void)784 static bool is_drrs_inactive(void)
785 {
786 	char buf[MAX_DRRS_STATUS_BUF_LEN];
787 
788 	debugfs_read("i915_drrs_status", buf);
789 
790 	if (strstr(buf, "DRRS_State: "))
791 		return false;
792 
793 	return true;
794 }
795 
drrs_print_status(void)796 static void drrs_print_status(void)
797 {
798 	char buf[MAX_DRRS_STATUS_BUF_LEN];
799 
800 	debugfs_read("i915_drrs_status", buf);
801 	igt_info("DRRS STATUS :\n%s\n", buf);
802 }
803 
fbc_get_last_action(void)804 static struct timespec fbc_get_last_action(void)
805 {
806 	struct timespec ret = { 0, 0 };
807 	char buf[128];
808 	char *action;
809 	ssize_t n_read;
810 
811 	debugfs_read("i915_fbc_status", buf);
812 
813 	action = strstr(buf, "\nLast action:");
814 	igt_assert(action);
815 
816 	n_read = sscanf(action, "Last action: %ld.%ld",
817 			&ret.tv_sec, &ret.tv_nsec);
818 	igt_assert(n_read == 2);
819 
820 	return ret;
821 }
822 
fbc_last_action_changed(void)823 static bool fbc_last_action_changed(void)
824 {
825 	struct timespec t_new, t_old;
826 
827 	t_old = fbc.last_action;
828 	t_new = fbc_get_last_action();
829 
830 	fbc.last_action = t_new;
831 
832 #if 0
833 	igt_info("old: %ld.%ld\n", t_old.tv_sec, t_old.tv_nsec);
834 	igt_info("new: %ld.%ld\n", t_new.tv_sec, t_new.tv_nsec);
835 #endif
836 
837 	return t_old.tv_sec != t_new.tv_sec ||
838 	       t_old.tv_nsec != t_new.tv_nsec;
839 }
840 
fbc_update_last_action(void)841 static void fbc_update_last_action(void)
842 {
843 	if (!fbc.supports_last_action)
844 		return;
845 
846 	fbc.last_action = fbc_get_last_action();
847 
848 #if 0
849 	igt_info("Last action: %ld.%ld\n",
850 		 fbc.last_action.tv_sec, fbc.last_action.tv_nsec);
851 #endif
852 }
853 
fbc_setup_last_action(void)854 static void fbc_setup_last_action(void)
855 {
856 	ssize_t n_read;
857 	char buf[128];
858 	char *action;
859 
860 	debugfs_read("i915_fbc_status", buf);
861 
862 	action = strstr(buf, "\nLast action:");
863 	if (!action) {
864 		igt_info("FBC last action not supported\n");
865 		return;
866 	}
867 
868 	fbc.supports_last_action = true;
869 
870 	n_read = sscanf(action, "Last action: %ld.%ld",
871 			&fbc.last_action.tv_sec, &fbc.last_action.tv_nsec);
872 	igt_assert(n_read == 2);
873 }
874 
fbc_is_compressing(void)875 static bool fbc_is_compressing(void)
876 {
877 	char buf[128];
878 
879 	debugfs_read("i915_fbc_status", buf);
880 	return strstr(buf, "\nCompressing: yes\n") != NULL;
881 }
882 
fbc_wait_for_compression(void)883 static bool fbc_wait_for_compression(void)
884 {
885 	return igt_wait(fbc_is_compressing(), 2000, 1);
886 }
887 
fbc_not_enough_stolen(void)888 static bool fbc_not_enough_stolen(void)
889 {
890 	char buf[128];
891 
892 	debugfs_read("i915_fbc_status", buf);
893 	return strstr(buf, "FBC disabled: not enough stolen memory\n");
894 }
895 
fbc_stride_not_supported(void)896 static bool fbc_stride_not_supported(void)
897 {
898 	char buf[128];
899 
900 	debugfs_read("i915_fbc_status", buf);
901 	return strstr(buf, "FBC disabled: framebuffer stride not supported\n");
902 }
903 
fbc_mode_too_large(void)904 static bool fbc_mode_too_large(void)
905 {
906 	char buf[128];
907 
908 	debugfs_read("i915_fbc_status", buf);
909 	return strstr(buf, "FBC disabled: mode too large for compression\n");
910 }
911 
fbc_wait_until_enabled(void)912 static bool fbc_wait_until_enabled(void)
913 {
914 	last_fbc_buf[0] = '\0';
915 
916 	return igt_wait(fbc_is_enabled(IGT_LOG_DEBUG), 2000, 1);
917 }
918 
drrs_wait_until_rr_switch_to_low(void)919 static bool drrs_wait_until_rr_switch_to_low(void)
920 {
921 	return igt_wait(is_drrs_low(), 5000, 1);
922 }
923 
924 #define fbc_enable() igt_set_module_param_int("enable_fbc", 1)
925 #define fbc_disable() igt_set_module_param_int("enable_fbc", 0)
926 #define drrs_enable()	drrs_set(1)
927 #define drrs_disable()	drrs_set(0)
928 
pat1_get_rect(struct fb_region * fb,int r)929 static struct rect pat1_get_rect(struct fb_region *fb, int r)
930 {
931 	struct rect rect;
932 
933 	switch (r) {
934 	case 0:
935 		rect.x = 0;
936 		rect.y = 0;
937 		rect.w = fb->w / 8;
938 		rect.h = fb->h / 8;
939 		rect.color = pick_color(fb->fb, COLOR_GREEN);
940 		break;
941 	case 1:
942 		rect.x = fb->w / 8 * 4;
943 		rect.y = fb->h / 8 * 4;
944 		rect.w = fb->w / 8 * 2;
945 		rect.h = fb->h / 8 * 2;
946 		rect.color = pick_color(fb->fb, COLOR_RED);
947 		break;
948 	case 2:
949 		rect.x = fb->w / 16 + 1;
950 		rect.y = fb->h / 16 + 1;
951 		rect.w = fb->w / 8 + 1;
952 		rect.h = fb->h / 8 + 1;
953 		rect.color = pick_color(fb->fb, COLOR_MAGENTA);
954 		break;
955 	case 3:
956 		rect.x = fb->w - 1;
957 		rect.y = fb->h - 1;
958 		rect.w = 1;
959 		rect.h = 1;
960 		rect.color = pick_color(fb->fb, COLOR_CYAN);
961 		break;
962 	default:
963 		igt_assert(false);
964 	}
965 
966 	return rect;
967 }
968 
pat2_get_rect(struct fb_region * fb,int r)969 static struct rect pat2_get_rect(struct fb_region *fb, int r)
970 {
971 	struct rect rect;
972 
973 	rect.x = 0;
974 	rect.y = 0;
975 	rect.w = 64;
976 	rect.h = 64;
977 
978 	switch (r) {
979 	case 0:
980 		rect.color = pick_color(fb->fb, COLOR_GREEN);
981 		break;
982 	case 1:
983 		rect.x = 31;
984 		rect.y = 31;
985 		rect.w = 31;
986 		rect.h = 31;
987 		rect.color = pick_color(fb->fb, COLOR_RED);
988 		break;
989 	case 2:
990 		rect.x = 16;
991 		rect.y = 16;
992 		rect.w = 32;
993 		rect.h = 32;
994 		rect.color = pick_color(fb->fb, COLOR_MAGENTA);
995 		break;
996 	case 3:
997 		rect.color = pick_color(fb->fb, COLOR_CYAN);
998 		break;
999 	default:
1000 		igt_assert(false);
1001 	}
1002 
1003 	return rect;
1004 }
1005 
pat3_get_rect(struct fb_region * fb,int r)1006 static struct rect pat3_get_rect(struct fb_region *fb, int r)
1007 {
1008 	struct rect rect;
1009 
1010 	rect.w = 64;
1011 	rect.h = 64;
1012 	rect.color = pick_color(fb->fb, COLOR_GREEN);
1013 
1014 	switch (r) {
1015 	case 0:
1016 		rect.x = 0;
1017 		rect.y = 0;
1018 		break;
1019 	case 1:
1020 		rect.x = 64;
1021 		rect.y = 64;
1022 		break;
1023 	case 2:
1024 		rect.x = 1;
1025 		rect.y = 1;
1026 		break;
1027 	case 3:
1028 		rect.x = fb->w - 64;
1029 		rect.y = fb->h - 64;
1030 		break;
1031 	case 4:
1032 		rect.x = fb->w / 2 - 32;
1033 		rect.y = fb->h / 2 - 32;
1034 		break;
1035 	default:
1036 		igt_assert(false);
1037 	}
1038 
1039 	return rect;
1040 }
1041 
pat4_get_rect(struct fb_region * fb,int r)1042 static struct rect pat4_get_rect(struct fb_region *fb, int r)
1043 {
1044 	struct rect rect;
1045 
1046 	igt_assert_eq(r, 0);
1047 
1048 	rect.x = 0;
1049 	rect.y = 0;
1050 	rect.w = fb->w;
1051 	rect.h = fb->h;
1052 	rect.color = pick_color(fb->fb, COLOR_GREEN);
1053 
1054 	return rect;
1055 }
1056 
fb_dirty_ioctl(struct fb_region * fb,struct rect * rect)1057 static void fb_dirty_ioctl(struct fb_region *fb, struct rect *rect)
1058 {
1059 	int rc;
1060 	drmModeClip clip = {
1061 		.x1 = rect->x,
1062 		.x2 = rect->x + rect->w,
1063 		.y1 = rect->y,
1064 		.y2 = rect->y + rect->h,
1065 	};
1066 
1067 	rc = drmModeDirtyFB(drm.fd, fb->fb->fb_id, &clip, 1);
1068 
1069 	igt_assert(rc == 0 || rc == -ENOSYS);
1070 }
1071 
draw_rect(struct draw_pattern_info * pattern,struct fb_region * fb,enum igt_draw_method method,int r)1072 static void draw_rect(struct draw_pattern_info *pattern, struct fb_region *fb,
1073 		      enum igt_draw_method method, int r)
1074 {
1075 	struct rect rect = pattern->get_rect(fb, r);
1076 
1077 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, fb->fb, method,
1078 			 fb->x + rect.x, fb->y + rect.y,
1079 			 rect.w, rect.h, rect.color);
1080 
1081 	fb_dirty_ioctl(fb, &rect);
1082 }
1083 
draw_rect_igt_fb(struct draw_pattern_info * pattern,struct igt_fb * fb,enum igt_draw_method method,int r)1084 static void draw_rect_igt_fb(struct draw_pattern_info *pattern,
1085 			     struct igt_fb *fb, enum igt_draw_method method,
1086 			     int r)
1087 {
1088 	struct fb_region region = {
1089 		.fb = fb,
1090 		.x = 0,
1091 		.y = 0,
1092 		.w = fb->width,
1093 		.h = fb->height,
1094 	};
1095 
1096 	draw_rect(pattern, &region, method, r);
1097 }
1098 
fill_fb_region(struct fb_region * region,enum color ecolor)1099 static void fill_fb_region(struct fb_region *region, enum color ecolor)
1100 {
1101 	uint32_t color = pick_color(region->fb, ecolor);
1102 
1103 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, region->fb, IGT_DRAW_BLT,
1104 			 region->x, region->y, region->w, region->h,
1105 			 color);
1106 }
1107 
unset_all_crtcs(void)1108 static void unset_all_crtcs(void)
1109 {
1110 	igt_display_reset(&drm.display);
1111 	igt_display_commit(&drm.display);
1112 }
1113 
disable_features(const struct test_mode * t)1114 static bool disable_features(const struct test_mode *t)
1115 {
1116 	if (t->feature == FEATURE_DEFAULT)
1117 		return false;
1118 
1119 	fbc_disable();
1120 	drrs_disable();
1121 	return psr.can_test ? psr_disable(drm.debugfs) : false;
1122 }
1123 
busy_thread_func(void * data)1124 static void *busy_thread_func(void *data)
1125 {
1126 	while (!busy_thread.stop)
1127 		igt_draw_rect(drm.fd, drm.bufmgr, NULL, busy_thread.handle,
1128 			      busy_thread.size, busy_thread.stride,
1129 			      IGT_DRAW_BLT, 0, 0, busy_thread.width,
1130 			      busy_thread.height, busy_thread.color,
1131 			      busy_thread.bpp);
1132 
1133 	pthread_exit(0);
1134 }
1135 
start_busy_thread(struct igt_fb * fb)1136 static void start_busy_thread(struct igt_fb *fb)
1137 {
1138 	int rc;
1139 
1140 	igt_assert(busy_thread.stop == true);
1141 	busy_thread.stop = false;
1142 	busy_thread.handle = fb->gem_handle;
1143 	busy_thread.size = fb->size;
1144 	busy_thread.stride = fb->strides[0];
1145 	busy_thread.width = fb->width;
1146 	busy_thread.height = fb->height;
1147 	busy_thread.color = pick_color(fb, COLOR_PRIM_BG);
1148 	busy_thread.bpp = igt_drm_format_to_bpp(fb->drm_format);
1149 
1150 	rc = pthread_create(&busy_thread.thread, NULL, busy_thread_func, NULL);
1151 	igt_assert_eq(rc, 0);
1152 }
1153 
stop_busy_thread(void)1154 static void stop_busy_thread(void)
1155 {
1156 	if (!busy_thread.stop) {
1157 		busy_thread.stop = true;
1158 		igt_assert(pthread_join(busy_thread.thread, NULL) == 0);
1159 	}
1160 }
1161 
print_crc(const char * str,igt_crc_t * crc)1162 static void print_crc(const char *str, igt_crc_t *crc)
1163 {
1164 	char *pipe_str;
1165 
1166 	pipe_str = igt_crc_to_string(crc);
1167 
1168 	igt_debug("%s pipe:[%s]\n", str, pipe_str);
1169 
1170 	free(pipe_str);
1171 }
1172 
collect_crc(igt_crc_t * crc)1173 static void collect_crc(igt_crc_t *crc)
1174 {
1175 	igt_pipe_crc_collect_crc(pipe_crc, crc);
1176 }
1177 
init_blue_crc(enum pixel_format format)1178 static void init_blue_crc(enum pixel_format format)
1179 {
1180 	struct igt_fb blue;
1181 
1182 	if (blue_crcs[format].initialized)
1183 		return;
1184 
1185 	create_fb(format, prim_mode_params.mode->hdisplay,
1186 		  prim_mode_params.mode->vdisplay, opt.tiling, PLANE_PRI,
1187 		  &blue);
1188 
1189 	fill_fb(&blue, COLOR_PRIM_BG);
1190 
1191 	igt_output_set_pipe(prim_mode_params.output, prim_mode_params.pipe);
1192 	igt_output_override_mode(prim_mode_params.output, prim_mode_params.mode);
1193 	igt_plane_set_fb(prim_mode_params.primary.plane, &blue);
1194 	igt_display_commit(&drm.display);
1195 
1196 	if (!pipe_crc) {
1197 		pipe_crc = igt_pipe_crc_new(drm.fd, prim_mode_params.pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
1198 		igt_assert(pipe_crc);
1199 	}
1200 
1201 	collect_crc(&blue_crcs[format].crc);
1202 
1203 	print_crc("Blue CRC:  ", &blue_crcs[format].crc);
1204 
1205 	igt_display_reset(&drm.display);
1206 
1207 	igt_remove_fb(drm.fd, &blue);
1208 
1209 	blue_crcs[format].initialized = true;
1210 }
1211 
init_crcs(enum pixel_format format,struct draw_pattern_info * pattern)1212 static void init_crcs(enum pixel_format format,
1213 		      struct draw_pattern_info *pattern)
1214 {
1215 	int r, r_;
1216 	struct igt_fb tmp_fbs[pattern->n_rects];
1217 
1218 	if (pattern->initialized[format])
1219 		return;
1220 
1221 	pattern->crcs[format] = calloc(pattern->n_rects,
1222 				       sizeof(*(pattern->crcs[format])));
1223 
1224 	for (r = 0; r < pattern->n_rects; r++)
1225 		create_fb(format, prim_mode_params.mode->hdisplay,
1226 			  prim_mode_params.mode->vdisplay, opt.tiling,
1227 			  PLANE_PRI, &tmp_fbs[r]);
1228 
1229 	for (r = 0; r < pattern->n_rects; r++)
1230 		fill_fb(&tmp_fbs[r], COLOR_PRIM_BG);
1231 
1232 	if (pattern->frames_stack) {
1233 		for (r = 0; r < pattern->n_rects; r++)
1234 			for (r_ = 0; r_ <= r; r_++)
1235 				draw_rect_igt_fb(pattern, &tmp_fbs[r],
1236 						 IGT_DRAW_PWRITE, r_);
1237 	} else {
1238 		for (r = 0; r < pattern->n_rects; r++)
1239 			draw_rect_igt_fb(pattern, &tmp_fbs[r], IGT_DRAW_PWRITE,
1240 					 r);
1241 	}
1242 
1243 	igt_output_set_pipe(prim_mode_params.output, prim_mode_params.pipe);
1244 	igt_output_override_mode(prim_mode_params.output, prim_mode_params.mode);
1245 	for (r = 0; r < pattern->n_rects; r++) {
1246 		igt_plane_set_fb(prim_mode_params.primary.plane, &tmp_fbs[r]);
1247 		igt_display_commit(&drm.display);
1248 
1249 		collect_crc(&pattern->crcs[format][r]);
1250 	}
1251 
1252 	for (r = 0; r < pattern->n_rects; r++) {
1253 		igt_debug("Rect %d CRC:", r);
1254 		print_crc("", &pattern->crcs[format][r]);
1255 	}
1256 
1257 	igt_display_reset(&drm.display);
1258 
1259 	for (r = 0; r < pattern->n_rects; r++)
1260 		igt_remove_fb(drm.fd, &tmp_fbs[r]);
1261 
1262 	pattern->initialized[format] = true;
1263 }
1264 
setup_drm(void)1265 static void setup_drm(void)
1266 {
1267 	drm.fd = drm_open_driver_master(DRIVER_INTEL);
1268 	drm.debugfs = igt_debugfs_dir(drm.fd);
1269 
1270 	kmstest_set_vt_graphics_mode();
1271 	igt_display_require(&drm.display, drm.fd);
1272 
1273 	drm.bufmgr = drm_intel_bufmgr_gem_init(drm.fd, 4096);
1274 	igt_assert(drm.bufmgr);
1275 	drm_intel_bufmgr_gem_enable_reuse(drm.bufmgr);
1276 }
1277 
teardown_drm(void)1278 static void teardown_drm(void)
1279 {
1280 	drm_intel_bufmgr_destroy(drm.bufmgr);
1281 	igt_display_fini(&drm.display);
1282 	close(drm.fd);
1283 }
1284 
setup_modeset(void)1285 static void setup_modeset(void)
1286 {
1287 	igt_require(init_modeset_cached_params());
1288 	offscreen_fb.fb = NULL;
1289 	offscreen_fb.w = 1024;
1290 	offscreen_fb.h = 1024;
1291 	create_fbs(FORMAT_DEFAULT);
1292 }
1293 
teardown_modeset(void)1294 static void teardown_modeset(void)
1295 {
1296 	enum pixel_format f;
1297 
1298 	for (f = 0; f < FORMAT_COUNT; f++)
1299 		destroy_fbs(f);
1300 }
1301 
setup_crcs(void)1302 static void setup_crcs(void)
1303 {
1304 	enum pixel_format f;
1305 
1306 	for (f = 0; f < FORMAT_COUNT; f++)
1307 		blue_crcs[f].initialized = false;
1308 
1309 	pattern1.frames_stack = true;
1310 	pattern1.n_rects = 4;
1311 	pattern1.get_rect = pat1_get_rect;
1312 	for (f = 0; f < FORMAT_COUNT; f++) {
1313 		pattern1.initialized[f] = false;
1314 		pattern1.crcs[f] = NULL;
1315 	}
1316 
1317 	pattern2.frames_stack = true;
1318 	pattern2.n_rects = 4;
1319 	pattern2.get_rect = pat2_get_rect;
1320 	for (f = 0; f < FORMAT_COUNT; f++) {
1321 		pattern2.initialized[f] = false;
1322 		pattern2.crcs[f] = NULL;
1323 	}
1324 
1325 	pattern3.frames_stack = false;
1326 	pattern3.n_rects = 5;
1327 	pattern3.get_rect = pat3_get_rect;
1328 	for (f = 0; f < FORMAT_COUNT; f++) {
1329 		pattern3.initialized[f] = false;
1330 		pattern3.crcs[f] = NULL;
1331 	}
1332 
1333 	pattern4.frames_stack = false;
1334 	pattern4.n_rects = 1;
1335 	pattern4.get_rect = pat4_get_rect;
1336 	for (f = 0; f < FORMAT_COUNT; f++) {
1337 		pattern4.initialized[f] = false;
1338 		pattern4.crcs[f] = NULL;
1339 	}
1340 }
1341 
teardown_crcs(void)1342 static void teardown_crcs(void)
1343 {
1344 	enum pixel_format f;
1345 
1346 	for (f = 0; f < FORMAT_COUNT; f++) {
1347 		if (pattern1.crcs[f])
1348 			free(pattern1.crcs[f]);
1349 		if (pattern2.crcs[f])
1350 			free(pattern2.crcs[f]);
1351 		if (pattern3.crcs[f])
1352 			free(pattern3.crcs[f]);
1353 		if (pattern4.crcs[f])
1354 			free(pattern4.crcs[f]);
1355 	}
1356 
1357 	igt_pipe_crc_free(pipe_crc);
1358 }
1359 
fbc_supported_on_chipset(void)1360 static bool fbc_supported_on_chipset(void)
1361 {
1362 	char buf[128];
1363 
1364 	debugfs_read("i915_fbc_status", buf);
1365 	if (*buf == '\0')
1366 		return false;
1367 
1368 	return !strstr(buf, "FBC unsupported on this chipset\n");
1369 }
1370 
setup_fbc(void)1371 static void setup_fbc(void)
1372 {
1373 	int devid = intel_get_drm_devid(drm.fd);
1374 
1375 	if (!fbc_supported_on_chipset()) {
1376 		igt_info("Can't test FBC: not supported on this chipset\n");
1377 		return;
1378 	}
1379 
1380 	/*
1381 	 * While some platforms do allow FBC on pipes B/C, this test suite
1382 	 * is not prepared for that yet.
1383 	 * TODO: solve this.
1384 	 */
1385 	if (prim_mode_params.pipe != PIPE_A) {
1386 		igt_info("Can't test FBC: primary connector doesn't support "
1387 			 "pipe A\n");
1388 		return;
1389 	}
1390 
1391 	/* Early Generations are not able to report compression status. */
1392 	if (!AT_LEAST_GEN(devid, 7))
1393 		opt.fbc_check_compression = false;
1394 
1395 	fbc.can_test = true;
1396 
1397 	fbc_setup_last_action();
1398 }
1399 
teardown_fbc(void)1400 static void teardown_fbc(void)
1401 {
1402 }
1403 
setup_psr(void)1404 static void setup_psr(void)
1405 {
1406 	if (prim_mode_params.output->config.connector->connector_type !=
1407 	    DRM_MODE_CONNECTOR_eDP) {
1408 		igt_info("Can't test PSR: no usable eDP screen.\n");
1409 		return;
1410 	}
1411 
1412 	if (!psr_sink_support(drm.debugfs, PSR_MODE_1)) {
1413 		igt_info("Can't test PSR: not supported by sink.\n");
1414 		return;
1415 	}
1416 	psr.can_test = true;
1417 }
1418 
teardown_psr(void)1419 static void teardown_psr(void)
1420 {
1421 }
1422 
setup_drrs(void)1423 static void setup_drrs(void)
1424 {
1425 	if (prim_mode_params.output->config.connector->connector_type !=
1426 	    DRM_MODE_CONNECTOR_eDP) {
1427 		igt_info("Can't test DRRS: no usable eDP screen.\n");
1428 		return;
1429 	}
1430 
1431 	if (!is_drrs_supported()) {
1432 		igt_info("Can't test DRRS: Not supported.\n");
1433 		return;
1434 	}
1435 
1436 	drrs.can_test = true;
1437 }
1438 
setup_environment(void)1439 static void setup_environment(void)
1440 {
1441 	setup_drm();
1442 	setup_modeset();
1443 
1444 	setup_fbc();
1445 	setup_psr();
1446 	setup_drrs();
1447 
1448 	setup_crcs();
1449 }
1450 
teardown_environment(void)1451 static void teardown_environment(void)
1452 {
1453 	stop_busy_thread();
1454 
1455 	teardown_crcs();
1456 	teardown_psr();
1457 	teardown_fbc();
1458 	teardown_modeset();
1459 	teardown_drm();
1460 }
1461 
wait_user(int step,const char * msg)1462 static void wait_user(int step, const char *msg)
1463 {
1464 	if (opt.step < step)
1465 		return;
1466 
1467 	igt_info("%s Press enter...\n", msg);
1468 	while (getchar() != '\n')
1469 		;
1470 }
1471 
pick_params(const struct test_mode * t)1472 static struct modeset_params *pick_params(const struct test_mode *t)
1473 {
1474 	switch (t->screen) {
1475 	case SCREEN_PRIM:
1476 		return &prim_mode_params;
1477 	case SCREEN_SCND:
1478 		return &scnd_mode_params;
1479 	case SCREEN_OFFSCREEN:
1480 		return NULL;
1481 	default:
1482 		igt_assert(false);
1483 	}
1484 }
1485 
pick_target(const struct test_mode * t,struct modeset_params * params)1486 static struct fb_region *pick_target(const struct test_mode *t,
1487 				     struct modeset_params *params)
1488 {
1489 	if (!params)
1490 		return &offscreen_fb;
1491 
1492 	switch (t->plane) {
1493 	case PLANE_PRI:
1494 		return &params->primary;
1495 	case PLANE_CUR:
1496 		return &params->cursor;
1497 	case PLANE_SPR:
1498 		return &params->sprite;
1499 	default:
1500 		igt_assert(false);
1501 	}
1502 }
1503 
do_flush(const struct test_mode * t)1504 static void do_flush(const struct test_mode *t)
1505 {
1506 	struct modeset_params *params = pick_params(t);
1507 	struct fb_region *target = pick_target(t, params);
1508 
1509 	gem_set_domain(drm.fd, target->fb->gem_handle, I915_GEM_DOMAIN_GTT, 0);
1510 }
1511 
1512 #define DONT_ASSERT_CRC			(1 << 0)
1513 #define DONT_ASSERT_FEATURE_STATUS	(1 << 1)
1514 #define DONT_ASSERT_FBC_STATUS		(1 << 12)
1515 
1516 #define FBC_ASSERT_FLAGS		(0xF << 2)
1517 #define ASSERT_FBC_ENABLED		(1 << 2)
1518 #define ASSERT_FBC_DISABLED		(1 << 3)
1519 #define ASSERT_LAST_ACTION_CHANGED	(1 << 4)
1520 #define ASSERT_NO_ACTION_CHANGE		(1 << 5)
1521 
1522 #define PSR_ASSERT_FLAGS		(3 << 6)
1523 #define ASSERT_PSR_ENABLED		(1 << 6)
1524 #define ASSERT_PSR_DISABLED		(1 << 7)
1525 
1526 #define DRRS_ASSERT_FLAGS		(7 << 8)
1527 #define ASSERT_DRRS_HIGH		(1 << 8)
1528 #define ASSERT_DRRS_LOW			(1 << 9)
1529 #define ASSERT_DRRS_INACTIVE		(1 << 10)
1530 
1531 #define ASSERT_NO_IDLE_GPU		(1 << 11)
1532 
adjust_assertion_flags(const struct test_mode * t,int flags)1533 static int adjust_assertion_flags(const struct test_mode *t, int flags)
1534 {
1535 	if (!(flags & DONT_ASSERT_FEATURE_STATUS)) {
1536 		if (!(flags & ASSERT_FBC_DISABLED))
1537 			flags |= ASSERT_FBC_ENABLED;
1538 		if (!(flags & ASSERT_PSR_DISABLED))
1539 			flags |= ASSERT_PSR_ENABLED;
1540 		if (!((flags & ASSERT_DRRS_LOW) ||
1541 		    (flags & ASSERT_DRRS_INACTIVE)))
1542 			flags |= ASSERT_DRRS_HIGH;
1543 	}
1544 
1545 	if ((t->feature & FEATURE_FBC) == 0 || (flags & DONT_ASSERT_FBC_STATUS))
1546 		flags &= ~FBC_ASSERT_FLAGS;
1547 	if ((t->feature & FEATURE_PSR) == 0)
1548 		flags &= ~PSR_ASSERT_FLAGS;
1549 	if ((t->feature & FEATURE_DRRS) == 0)
1550 		flags &= ~DRRS_ASSERT_FLAGS;
1551 
1552 	return flags;
1553 }
1554 
do_crc_assertions(int flags)1555 static void do_crc_assertions(int flags)
1556 {
1557 	igt_crc_t crc;
1558 
1559 	if (!opt.check_crc || (flags & DONT_ASSERT_CRC))
1560 		return;
1561 
1562 	collect_crc(&crc);
1563 	print_crc("Calculated CRC:", &crc);
1564 
1565 	igt_assert(wanted_crc);
1566 	igt_assert_crc_equal(&crc, wanted_crc);
1567 }
1568 
do_status_assertions(int flags)1569 static void do_status_assertions(int flags)
1570 {
1571 	if (!opt.check_status) {
1572 		/* Make sure we settle before continuing. */
1573 		sleep(1);
1574 		return;
1575 	}
1576 
1577 	if (flags & ASSERT_DRRS_HIGH) {
1578 		if (!is_drrs_high()) {
1579 			drrs_print_status();
1580 			igt_assert_f(false, "DRRS HIGH\n");
1581 		}
1582 	} else if (flags & ASSERT_DRRS_LOW) {
1583 		if (!drrs_wait_until_rr_switch_to_low()) {
1584 			drrs_print_status();
1585 			igt_assert_f(false, "DRRS LOW\n");
1586 		}
1587 	} else if (flags & ASSERT_DRRS_INACTIVE) {
1588 		if (!is_drrs_inactive()) {
1589 			drrs_print_status();
1590 			igt_assert_f(false, "DRRS INACTIVE\n");
1591 		}
1592 	}
1593 
1594 	if (flags & ASSERT_FBC_ENABLED) {
1595 		igt_require(!fbc_not_enough_stolen());
1596 		igt_require(!fbc_stride_not_supported());
1597 		igt_require(!fbc_mode_too_large());
1598 		if (!fbc_wait_until_enabled()) {
1599 			igt_assert_f(fbc_is_enabled(IGT_LOG_WARN),
1600 				     "FBC disabled\n");
1601 		}
1602 
1603 		if (opt.fbc_check_compression)
1604 			igt_assert(fbc_wait_for_compression());
1605 	} else if (flags & ASSERT_FBC_DISABLED) {
1606 		igt_assert(!fbc_wait_until_enabled());
1607 	}
1608 
1609 	if (flags & ASSERT_PSR_ENABLED)
1610 		igt_assert_f(psr_wait_entry(drm.debugfs, PSR_MODE_1),
1611 			     "PSR still disabled\n");
1612 	else if (flags & ASSERT_PSR_DISABLED)
1613 		igt_assert_f(psr_wait_update(drm.debugfs, PSR_MODE_1),
1614 			     "PSR still enabled\n");
1615 }
1616 
__do_assertions(const struct test_mode * t,int flags,int line)1617 static void __do_assertions(const struct test_mode *t, int flags,
1618 			    int line)
1619 {
1620 	flags = adjust_assertion_flags(t, flags);
1621 
1622 	/* Make sure any submitted rendering is now idle. */
1623 	if (!(flags & ASSERT_NO_IDLE_GPU))
1624 		gem_quiescent_gpu(drm.fd);
1625 
1626 	igt_debug("checking asserts in line %i\n", line);
1627 
1628 	wait_user(2, "Paused before assertions.");
1629 
1630 	/* Check the CRC to make sure the drawing operations work
1631 	 * immediately, independently of the features being enabled. */
1632 	do_crc_assertions(flags);
1633 
1634 	/* Now we can flush things to make the test faster. */
1635 	do_flush(t);
1636 
1637 	do_status_assertions(flags);
1638 
1639 	/* Check CRC again to make sure the compressed screen is ok,
1640 	 * except if we're not drawing on the primary screen. On this
1641 	 * case, the first check should be enough and a new CRC check
1642 	 * would only delay the test suite while adding no value to the
1643 	 * test suite. */
1644 	if (t->screen == SCREEN_PRIM)
1645 		do_crc_assertions(flags);
1646 
1647 	if (fbc.supports_last_action && opt.fbc_check_last_action) {
1648 		if (flags & ASSERT_LAST_ACTION_CHANGED)
1649 			igt_assert(fbc_last_action_changed());
1650 		else if (flags & ASSERT_NO_ACTION_CHANGE)
1651 			igt_assert(!fbc_last_action_changed());
1652 	}
1653 
1654 	wait_user(1, "Paused after assertions.");
1655 }
1656 
1657 #define do_assertions(__flags) __do_assertions(t, (__flags), __LINE__)
1658 
enable_prim_screen_and_wait(const struct test_mode * t)1659 static void enable_prim_screen_and_wait(const struct test_mode *t)
1660 {
1661 	fill_fb_region(&prim_mode_params.primary, COLOR_PRIM_BG);
1662 	set_mode_for_params(&prim_mode_params);
1663 
1664 	wanted_crc = &blue_crcs[t->format].crc;
1665 	fbc_update_last_action();
1666 
1667 	do_assertions(ASSERT_NO_ACTION_CHANGE);
1668 }
1669 
enable_both_screens_and_wait(const struct test_mode * t)1670 static void enable_both_screens_and_wait(const struct test_mode *t)
1671 {
1672 	fill_fb_region(&prim_mode_params.primary, COLOR_PRIM_BG);
1673 	fill_fb_region(&scnd_mode_params.primary, COLOR_SCND_BG);
1674 
1675 	__set_mode_for_params(&prim_mode_params);
1676 	__set_mode_for_params(&scnd_mode_params);
1677 
1678 	igt_display_commit2(&drm.display, drm.display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
1679 
1680 	wanted_crc = &blue_crcs[t->format].crc;
1681 	fbc_update_last_action();
1682 
1683 	do_assertions(ASSERT_NO_ACTION_CHANGE);
1684 }
1685 
set_region_for_test(const struct test_mode * t,struct fb_region * reg)1686 static void set_region_for_test(const struct test_mode *t,
1687 				struct fb_region *reg)
1688 {
1689 	fill_fb_region(reg, COLOR_PRIM_BG);
1690 
1691 	igt_plane_set_fb(reg->plane, reg->fb);
1692 	igt_plane_set_position(reg->plane, 0, 0);
1693 	igt_plane_set_size(reg->plane, reg->w, reg->h);
1694 	igt_fb_set_size(reg->fb, reg->plane, reg->w, reg->h);
1695 
1696 	igt_display_commit(&drm.display);
1697 	do_assertions(ASSERT_NO_ACTION_CHANGE);
1698 }
1699 
enable_features_for_test(const struct test_mode * t)1700 static bool enable_features_for_test(const struct test_mode *t)
1701 {
1702 	bool ret = false;
1703 
1704 	if (t->feature == FEATURE_DEFAULT)
1705 		return false;
1706 
1707 	if (t->feature & FEATURE_FBC)
1708 		fbc_enable();
1709 	if (t->feature & FEATURE_PSR)
1710 		ret = psr_enable(drm.debugfs, PSR_MODE_1);
1711 	if (t->feature & FEATURE_DRRS)
1712 		drrs_enable();
1713 
1714 	return ret;
1715 }
1716 
check_test_requirements(const struct test_mode * t)1717 static void check_test_requirements(const struct test_mode *t)
1718 {
1719 	if (t->pipes == PIPE_DUAL)
1720 		igt_require_f(scnd_mode_params.output,
1721 			    "Can't test dual pipes with the current outputs\n");
1722 
1723 	if (t->feature & FEATURE_FBC)
1724 		igt_require_f(fbc.can_test,
1725 			      "Can't test FBC with this chipset\n");
1726 
1727 	if (t->feature & FEATURE_PSR) {
1728 		igt_require_f(psr.can_test,
1729 			      "Can't test PSR with the current outputs\n");
1730 	}
1731 
1732 	if (t->feature & FEATURE_DRRS)
1733 		igt_require_f(drrs.can_test,
1734 			      "Can't test DRRS with the current outputs\n");
1735 
1736 	/*
1737 	 * In kernel, When PSR is enabled, DRRS will be disabled. So If a test
1738 	 * case needs DRRS + PSR enabled, that will be skipped.
1739 	 */
1740 	igt_require_f(!((t->feature & FEATURE_PSR) &&
1741 		      (t->feature & FEATURE_DRRS)),
1742 		      "Can't test PSR and DRRS together\n");
1743 
1744 	if (opt.only_pipes != PIPE_COUNT)
1745 		igt_require(t->pipes == opt.only_pipes);
1746 }
1747 
set_crtc_fbs(const struct test_mode * t)1748 static void set_crtc_fbs(const struct test_mode *t)
1749 {
1750 	struct screen_fbs *s = &fbs[t->format];
1751 
1752 	create_fbs(t->format);
1753 
1754 	switch (t->fbs) {
1755 	case FBS_INDIVIDUAL:
1756 		prim_mode_params.primary.fb = &s->prim_pri;
1757 		scnd_mode_params.primary.fb = &s->scnd_pri;
1758 		offscreen_fb.fb = &s->offscreen;
1759 
1760 		prim_mode_params.primary.x = 0;
1761 		scnd_mode_params.primary.x = 0;
1762 		offscreen_fb.x = 0;
1763 
1764 		prim_mode_params.primary.y = 0;
1765 		scnd_mode_params.primary.y = 0;
1766 		offscreen_fb.y = 0;
1767 		break;
1768 	case FBS_SHARED:
1769 		/* Please see the comment at the top of create_shared_fb(). */
1770 		prim_mode_params.primary.fb = &s->big;
1771 		scnd_mode_params.primary.fb = &s->big;
1772 		offscreen_fb.fb = &s->big;
1773 
1774 		prim_mode_params.primary.x = opt.shared_fb_x_offset;
1775 		scnd_mode_params.primary.x = opt.shared_fb_x_offset;
1776 		offscreen_fb.x = opt.shared_fb_x_offset;
1777 
1778 		prim_mode_params.primary.y = opt.shared_fb_y_offset;
1779 		scnd_mode_params.primary.y = prim_mode_params.primary.y +
1780 					prim_mode_params.primary.h;
1781 		offscreen_fb.y = scnd_mode_params.primary.y + scnd_mode_params.primary.h;
1782 		break;
1783 	default:
1784 		igt_assert(false);
1785 	}
1786 
1787 	prim_mode_params.cursor.fb = &s->prim_cur;
1788 	prim_mode_params.sprite.fb = &s->prim_spr;
1789 	scnd_mode_params.cursor.fb = &s->scnd_cur;
1790 	scnd_mode_params.sprite.fb = &s->scnd_spr;
1791 }
1792 
prepare_subtest_data(const struct test_mode * t,struct draw_pattern_info * pattern)1793 static void prepare_subtest_data(const struct test_mode *t,
1794 				 struct draw_pattern_info *pattern)
1795 {
1796 	bool need_modeset;
1797 
1798 	check_test_requirements(t);
1799 
1800 	stop_busy_thread();
1801 
1802 	need_modeset = disable_features(t);
1803 	set_crtc_fbs(t);
1804 
1805 	if (t->screen == SCREEN_OFFSCREEN)
1806 		fill_fb_region(&offscreen_fb, COLOR_OFFSCREEN_BG);
1807 
1808 	igt_display_reset(&drm.display);
1809 	if (need_modeset)
1810 		igt_display_commit(&drm.display);
1811 
1812 	init_blue_crc(t->format);
1813 	if (pattern)
1814 		init_crcs(t->format, pattern);
1815 
1816 	need_modeset = enable_features_for_test(t);
1817 	if (need_modeset)
1818 		igt_display_commit(&drm.display);
1819 }
1820 
prepare_subtest_screens(const struct test_mode * t)1821 static void prepare_subtest_screens(const struct test_mode *t)
1822 {
1823 	if (t->pipes == PIPE_DUAL)
1824 		enable_both_screens_and_wait(t);
1825 	else
1826 		enable_prim_screen_and_wait(t);
1827 
1828 	if (t->screen == SCREEN_PRIM) {
1829 		if (t->plane == PLANE_CUR)
1830 			set_region_for_test(t, &prim_mode_params.cursor);
1831 		if (t->plane == PLANE_SPR)
1832 			set_region_for_test(t, &prim_mode_params.sprite);
1833 	}
1834 
1835 	if (t->pipes == PIPE_DUAL && t->screen == SCREEN_SCND) {
1836 		if (t->plane == PLANE_CUR)
1837 			set_region_for_test(t, &scnd_mode_params.cursor);
1838 		if (t->plane == PLANE_SPR)
1839 			set_region_for_test(t, &scnd_mode_params.sprite);
1840 	}
1841 }
1842 
prepare_subtest(const struct test_mode * t,struct draw_pattern_info * pattern)1843 static void prepare_subtest(const struct test_mode *t,
1844 			    struct draw_pattern_info *pattern)
1845 {
1846 	prepare_subtest_data(t, pattern);
1847 	prepare_subtest_screens(t);
1848 }
1849 
1850 /*
1851  * rte - the basic sanity test
1852  *
1853  * METHOD
1854  *   Just disable all screens, assert everything is disabled, then enable all
1855  *   screens - including primary, cursor and sprite planes - and assert that
1856  *   the tested feature is enabled.
1857  *
1858  * EXPECTED RESULTS
1859  *   Blue screens and t->feature enabled.
1860  *
1861  * FAILURES
1862  *   A failure here means that every other subtest will probably fail too. It
1863  *   probably means that the Kernel is just not enabling the feature we want.
1864  */
rte_subtest(const struct test_mode * t)1865 static void rte_subtest(const struct test_mode *t)
1866 {
1867 	prepare_subtest_data(t, NULL);
1868 
1869 	unset_all_crtcs();
1870 	do_assertions(ASSERT_FBC_DISABLED | ASSERT_PSR_DISABLED |
1871 		      DONT_ASSERT_CRC | ASSERT_DRRS_INACTIVE);
1872 
1873 	if (t->pipes == PIPE_SINGLE)
1874 		enable_prim_screen_and_wait(t);
1875 	else
1876 		enable_both_screens_and_wait(t);
1877 
1878 	set_region_for_test(t, &prim_mode_params.cursor);
1879 	set_region_for_test(t, &prim_mode_params.sprite);
1880 
1881 	if (t->pipes == PIPE_DUAL) {
1882 		set_region_for_test(t, &scnd_mode_params.cursor);
1883 		set_region_for_test(t, &scnd_mode_params.sprite);
1884 	}
1885 }
1886 
update_wanted_crc(const struct test_mode * t,igt_crc_t * crc)1887 static void update_wanted_crc(const struct test_mode *t, igt_crc_t *crc)
1888 {
1889 	if (t->screen == SCREEN_PRIM)
1890 		wanted_crc = crc;
1891 }
1892 
op_disables_psr(const struct test_mode * t,enum igt_draw_method method)1893 static bool op_disables_psr(const struct test_mode *t,
1894 			    enum igt_draw_method method)
1895 {
1896 	if (method != IGT_DRAW_MMAP_GTT)
1897 		return false;
1898 	if (t->screen == SCREEN_PRIM)
1899 		return true;
1900 	/* On FBS_SHARED, even if the target is not the PSR screen
1901 	 * (SCREEN_PRIM), all primary planes share the same frontbuffer, so a
1902 	 * write to the second screen primary plane - or offscreen plane - will
1903 	 * touch the framebuffer that's also used by the primary screen. */
1904 	if (t->fbs == FBS_SHARED && t->plane == PLANE_PRI)
1905 		return true;
1906 
1907 	return false;
1908 }
1909 
1910 /*
1911  * draw - draw a set of rectangles on the screen using the provided method
1912  *
1913  * METHOD
1914  *   Just set the screens as appropriate and then start drawing a series of
1915  *   rectangles on the target screen. The important guy here is the drawing
1916  *   method used.
1917  *
1918  * EXPECTED RESULTS
1919  *   The feature either stays enabled or gets reenabled after the oprations. You
1920  *   will also see the rectangles on the target screen.
1921  *
1922  * FAILURES
1923  *   A failure here indicates a problem somewhere between the Kernel's
1924  *   frontbuffer tracking infrastructure or the feature itself. You need to pay
1925  *   attention to which drawing method is being used.
1926  */
draw_subtest(const struct test_mode * t)1927 static void draw_subtest(const struct test_mode *t)
1928 {
1929 	int r;
1930 	int assertions = 0;
1931 	struct draw_pattern_info *pattern;
1932 	struct modeset_params *params = pick_params(t);
1933 	struct fb_region *target;
1934 
1935 	switch (t->screen) {
1936 	case SCREEN_PRIM:
1937 		if (t->method != IGT_DRAW_MMAP_GTT && t->plane == PLANE_PRI)
1938 			assertions |= ASSERT_LAST_ACTION_CHANGED;
1939 		else
1940 			assertions |= ASSERT_NO_ACTION_CHANGE;
1941 		break;
1942 	case SCREEN_SCND:
1943 	case SCREEN_OFFSCREEN:
1944 		assertions |= ASSERT_NO_ACTION_CHANGE;
1945 		break;
1946 	default:
1947 		igt_assert(false);
1948 	}
1949 
1950 	switch (t->plane) {
1951 	case PLANE_PRI:
1952 		pattern = &pattern1;
1953 		break;
1954 	case PLANE_CUR:
1955 	case PLANE_SPR:
1956 		pattern = &pattern2;
1957 		break;
1958 	default:
1959 		igt_assert(false);
1960 	}
1961 
1962 	if (op_disables_psr(t, t->method))
1963 		assertions |= ASSERT_PSR_DISABLED;
1964 
1965 	/*
1966 	 * On FBS_INDIVIDUAL, write to offscreen plane will not touch the
1967 	 * current frambuffer. Hence assert for DRRS_LOW.
1968 	 */
1969 	if ((t->fbs == FBS_INDIVIDUAL) && (t->screen == SCREEN_OFFSCREEN))
1970 		assertions |= ASSERT_DRRS_LOW;
1971 
1972 	prepare_subtest(t, pattern);
1973 	target = pick_target(t, params);
1974 
1975 	for (r = 0; r < pattern->n_rects; r++) {
1976 		igt_debug("Drawing rect %d\n", r);
1977 		draw_rect(pattern, target, t->method, r);
1978 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
1979 		do_assertions(assertions);
1980 	}
1981 }
1982 
1983 /*
1984  * multidraw - draw a set of rectangles on the screen using alternated drawing
1985  *             methods
1986  *
1987  * METHOD
1988  *   This is just like the draw subtest, but now we keep alternating between two
1989  *   drawing methods. Each time we run multidraw_subtest we will test all the
1990  *   possible pairs of drawing methods.
1991  *
1992  * EXPECTED RESULTS
1993  *   The same as the draw subtest.
1994  *
1995  * FAILURES
1996  *   If you get a failure here, first you need to check whether you also get
1997  *   failures on the individual draw subtests. If yes, then go fix every single
1998  *   draw subtest first. If all the draw subtests pass but this one fails, then
1999  *   you have to study how one drawing method is stopping the other from
2000  *   properly working.
2001  */
multidraw_subtest(const struct test_mode * t)2002 static void multidraw_subtest(const struct test_mode *t)
2003 {
2004 	int r;
2005 	int assertions = 0;
2006 	struct draw_pattern_info *pattern;
2007 	struct modeset_params *params = pick_params(t);
2008 	struct fb_region *target;
2009 	enum igt_draw_method m1, m2, used_method;
2010 	bool wc_used = false;
2011 
2012 	switch (t->plane) {
2013 	case PLANE_PRI:
2014 		pattern = &pattern1;
2015 		break;
2016 	case PLANE_CUR:
2017 	case PLANE_SPR:
2018 		pattern = &pattern2;
2019 		break;
2020 	default:
2021 		igt_assert(false);
2022 	}
2023 
2024 	prepare_subtest(t, pattern);
2025 	target = pick_target(t, params);
2026 
2027 	for (m1 = 0; m1 < IGT_DRAW_METHOD_COUNT; m1++) {
2028 		for (m2 = m1 + 1; m2 < IGT_DRAW_METHOD_COUNT; m2++) {
2029 
2030 			igt_debug("Methods %s and %s\n",
2031 				  igt_draw_get_method_name(m1),
2032 				  igt_draw_get_method_name(m2));
2033 			for (r = 0; r < pattern->n_rects; r++) {
2034 				used_method = (r % 2 == 0) ? m1 : m2;
2035 
2036 				igt_debug("Used method %s\n",
2037 					igt_draw_get_method_name(used_method));
2038 
2039 				draw_rect(pattern, target, used_method, r);
2040 
2041 				if (used_method == IGT_DRAW_MMAP_WC ||
2042 				    used_method == IGT_DRAW_MMAP_GTT)
2043 					wc_used = true;
2044 
2045 				update_wanted_crc(t,
2046 						  &pattern->crcs[t->format][r]);
2047 
2048 				assertions = used_method != IGT_DRAW_MMAP_GTT ?
2049 					     ASSERT_LAST_ACTION_CHANGED :
2050 					     ASSERT_NO_ACTION_CHANGE;
2051 				if (op_disables_psr(t, used_method) &&
2052 				    !wc_used)
2053 					assertions |= ASSERT_PSR_DISABLED;
2054 
2055 				do_assertions(assertions);
2056 			}
2057 
2058 			fill_fb_region(target, COLOR_PRIM_BG);
2059 
2060 			update_wanted_crc(t, &blue_crcs[t->format].crc);
2061 			do_assertions(ASSERT_NO_ACTION_CHANGE);
2062 		}
2063 	}
2064 }
2065 
format_is_valid(int feature_flags,enum pixel_format format)2066 static bool format_is_valid(int feature_flags,
2067 			    enum pixel_format format)
2068 {
2069 	int devid = intel_get_drm_devid(drm.fd);
2070 
2071 	if (!(feature_flags & FEATURE_FBC))
2072 		return true;
2073 
2074 	switch (format) {
2075 	case FORMAT_RGB888:
2076 		return true;
2077 	case FORMAT_RGB565:
2078 		if (IS_GEN2(devid) || IS_G4X(devid))
2079 			return false;
2080 		return true;
2081 	case FORMAT_RGB101010:
2082 		return false;
2083 	default:
2084 		igt_assert(false);
2085 	}
2086 }
2087 
2088 /*
2089  * badformat - test pixel formats that are not supported by at least one feature
2090  *
2091  * METHOD
2092  *   We just do a modeset on a buffer with the given pixel format and check the
2093  *   status of the relevant features.
2094  *
2095  * EXPECTED RESULTS
2096  *   No assertion failures :)
2097  *
2098  * FAILURES
2099  *   If you get a feature enabled/disabled assertion failure, then you should
2100  *   probably check the Kernel code for the feature that checks the pixel
2101  *   formats. If you get a CRC assertion failure, then you should use the
2102  *   appropriate command line arguments that will allow you to look at the
2103  *   screen, then judge what to do based on what you see.
2104  */
badformat_subtest(const struct test_mode * t)2105 static void badformat_subtest(const struct test_mode *t)
2106 {
2107 	bool fbc_valid = format_is_valid(FEATURE_FBC, t->format);
2108 	bool psr_valid = format_is_valid(FEATURE_PSR, t->format);
2109 	int assertions = ASSERT_NO_ACTION_CHANGE;
2110 
2111 	prepare_subtest_data(t, NULL);
2112 
2113 	fill_fb_region(&prim_mode_params.primary, COLOR_PRIM_BG);
2114 	set_mode_for_params(&prim_mode_params);
2115 
2116 	wanted_crc = &blue_crcs[t->format].crc;
2117 
2118 	if (!fbc_valid)
2119 		assertions |= ASSERT_FBC_DISABLED;
2120 	if (!psr_valid)
2121 		assertions |= ASSERT_PSR_DISABLED;
2122 	do_assertions(assertions);
2123 }
2124 
2125 /*
2126  * format_draw - test pixel formats that are not FORMAT_DEFAULT
2127  *
2128  * METHOD
2129  *   The real subtest to be executed depends on whether the pixel format is
2130  *   supported by the features being tested or not. Check the documentation of
2131  *   each subtest.
2132  *
2133  * EXPECTED RESULTS
2134  *   See the documentation for each subtest.
2135  *
2136  * FAILURES
2137  *   See the documentation for each subtest.
2138  */
format_draw_subtest(const struct test_mode * t)2139 static void format_draw_subtest(const struct test_mode *t)
2140 {
2141 	if (format_is_valid(t->feature, t->format))
2142 		draw_subtest(t);
2143 	else
2144 		badformat_subtest(t);
2145 }
2146 
2147 /*
2148  * slow_draw - sleep a little bit between drawing operations
2149  *
2150  * METHOD
2151  *   This test is basically the same as the draw subtest, except that we sleep a
2152  *   little bit after each drawing operation. The goal is to detect problems
2153  *   that can happen in case a drawing operation is done while the machine is in
2154  *   some deep sleep states.
2155  *
2156  * EXPECTED RESULTS
2157  *   The pattern appears on the screen as expected.
2158  *
2159  * FAILURES
2160  *   I've seen this happen in a SKL machine and still haven't investigated it.
2161  *   My guess would be that preventing deep sleep states fixes the problem.
2162  */
slow_draw_subtest(const struct test_mode * t)2163 static void slow_draw_subtest(const struct test_mode *t)
2164 {
2165 	int r;
2166 	struct draw_pattern_info *pattern = &pattern1;
2167 	struct modeset_params *params = pick_params(t);
2168 	struct fb_region *target;
2169 
2170 	prepare_subtest(t, pattern);
2171 	sleep(2);
2172 	target = pick_target(t, params);
2173 
2174 	for (r = 0; r < pattern->n_rects; r++) {
2175 		sleep(2);
2176 		draw_rect(pattern, target, t->method, r);
2177 		sleep(2);
2178 
2179 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
2180 
2181 		if (t->feature & FEATURE_DRRS)
2182 			do_assertions(ASSERT_DRRS_LOW);
2183 		else
2184 			do_assertions(0);
2185 	}
2186 }
2187 
flip_handler(int fd,unsigned int sequence,unsigned int tv_sec,unsigned int tv_usec,void * data)2188 static void flip_handler(int fd, unsigned int sequence, unsigned int tv_sec,
2189 			 unsigned int tv_usec, void *data)
2190 {
2191 	igt_debug("Flip event received.\n");
2192 }
2193 
wait_flip_event(void)2194 static void wait_flip_event(void)
2195 {
2196 	int rc;
2197 	drmEventContext evctx;
2198 	struct pollfd pfd;
2199 
2200 	evctx.version = 2;
2201 	evctx.vblank_handler = NULL;
2202 	evctx.page_flip_handler = flip_handler;
2203 
2204 	pfd.fd = drm.fd;
2205 	pfd.events = POLLIN;
2206 	pfd.revents = 0;
2207 
2208 	rc = poll(&pfd, 1, 1000);
2209 	switch (rc) {
2210 	case 0:
2211 		igt_assert_f(false, "Poll timeout\n");
2212 		break;
2213 	case 1:
2214 		rc = drmHandleEvent(drm.fd, &evctx);
2215 		igt_assert_eq(rc, 0);
2216 		break;
2217 	default:
2218 		igt_assert_f(false, "Unexpected poll rc %d\n", rc);
2219 		break;
2220 	}
2221 }
2222 
set_prim_plane_for_params(struct modeset_params * params)2223 static void set_prim_plane_for_params(struct modeset_params *params)
2224 {
2225 	__set_prim_plane_for_params(params);
2226 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2227 }
2228 
page_flip_for_params(struct modeset_params * params,enum flip_type type)2229 static void page_flip_for_params(struct modeset_params *params,
2230 				 enum flip_type type)
2231 {
2232 	int rc;
2233 
2234 	switch (type) {
2235 	case FLIP_PAGEFLIP:
2236 		rc = drmModePageFlip(drm.fd, drm.display.pipes[params->pipe].crtc_id,
2237 				     params->primary.fb->fb_id,
2238 				     DRM_MODE_PAGE_FLIP_EVENT, NULL);
2239 		igt_assert_eq(rc, 0);
2240 		wait_flip_event();
2241 		break;
2242 	case FLIP_MODESET:
2243 		set_mode_for_params(params);
2244 		break;
2245 	case FLIP_PLANES:
2246 		set_prim_plane_for_params(params);
2247 		break;
2248 	default:
2249 		igt_assert(false);
2250 	}
2251 }
2252 
2253 /*
2254  * flip - just exercise page flips with the patterns we have
2255  *
2256  * METHOD
2257  *   We draw the pattern on a backbuffer using the provided method, then we
2258  *   flip, making this the frontbuffer. We can flip both using the dedicated
2259  *   pageflip IOCTL or the modeset IOCTL.
2260  *
2261  * EXPECTED RESULTS
2262  *   Everything works as expected, screen contents are properly updated.
2263  *
2264  * FAILURES
2265  *   On a failure here you need to go directly to the Kernel's flip code and see
2266  *   how it interacts with the feature being tested.
2267  */
flip_subtest(const struct test_mode * t)2268 static void flip_subtest(const struct test_mode *t)
2269 {
2270 	int r;
2271 	int assertions = 0;
2272 	struct igt_fb fb2, *orig_fb;
2273 	struct modeset_params *params = pick_params(t);
2274 	struct draw_pattern_info *pattern = &pattern1;
2275 	enum color bg_color;
2276 
2277 	switch (t->screen) {
2278 	case SCREEN_PRIM:
2279 		assertions |= ASSERT_LAST_ACTION_CHANGED;
2280 		bg_color = COLOR_PRIM_BG;
2281 		break;
2282 	case SCREEN_SCND:
2283 		assertions |= ASSERT_NO_ACTION_CHANGE;
2284 		bg_color = COLOR_SCND_BG;
2285 		break;
2286 	default:
2287 		igt_assert(false);
2288 	}
2289 
2290 	prepare_subtest(t, pattern);
2291 
2292 	create_fb(t->format, params->primary.fb->width, params->primary.fb->height,
2293 		  opt.tiling, t->plane, &fb2);
2294 	fill_fb(&fb2, bg_color);
2295 	orig_fb = params->primary.fb;
2296 
2297 	for (r = 0; r < pattern->n_rects; r++) {
2298 		params->primary.fb = (r % 2 == 0) ? &fb2 : orig_fb;
2299 
2300 		if (r != 0)
2301 			draw_rect(pattern, &params->primary, t->method, r - 1);
2302 		draw_rect(pattern, &params->primary, t->method, r);
2303 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
2304 
2305 		page_flip_for_params(params, t->flip);
2306 
2307 		do_assertions(assertions);
2308 	}
2309 
2310 	igt_remove_fb(drm.fd, &fb2);
2311 }
2312 
2313 /*
2314  * fliptrack - check if the hardware tracking works after page flips
2315  *
2316  * METHOD
2317  *   Flip to a new buffer, then draw on it using MMAP_GTT and check the CRC to
2318  *   make sure the hardware tracking detected the write.
2319  *
2320  * EXPECTED RESULTS
2321  *   Everything works as expected, screen contents are properly updated.
2322  *
2323  * FAILURES
2324  *   First you need to check if the draw and flip subtests pass. Only after both
2325  *   are passing this test can be useful. If we're failing only on this subtest,
2326  *   then maybe we are not properly updating the hardware tracking registers
2327  *   during the flip operations.
2328  */
fliptrack_subtest(const struct test_mode * t,enum flip_type type)2329 static void fliptrack_subtest(const struct test_mode *t, enum flip_type type)
2330 {
2331 	int r;
2332 	struct igt_fb fb2, *orig_fb;
2333 	struct modeset_params *params = pick_params(t);
2334 	struct draw_pattern_info *pattern = &pattern1;
2335 
2336 	prepare_subtest(t, pattern);
2337 
2338 	create_fb(t->format, params->primary.fb->width, params->primary.fb->height,
2339 		  opt.tiling, t->plane, &fb2);
2340 	fill_fb(&fb2, COLOR_PRIM_BG);
2341 	orig_fb = params->primary.fb;
2342 
2343 	for (r = 0; r < pattern->n_rects; r++) {
2344 		params->primary.fb = (r % 2 == 0) ? &fb2 : orig_fb;
2345 
2346 		if (r != 0)
2347 			draw_rect(pattern, &params->primary, t->method, r - 1);
2348 
2349 		page_flip_for_params(params, type);
2350 		do_assertions(0);
2351 
2352 		draw_rect(pattern, &params->primary, t->method, r);
2353 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
2354 
2355 		do_assertions(ASSERT_PSR_DISABLED);
2356 	}
2357 
2358 	igt_remove_fb(drm.fd, &fb2);
2359 }
2360 
2361 /*
2362  * move - just move the sprite or cursor around
2363  *
2364  * METHOD
2365  *   Move the surface around, following the defined pattern.
2366  *
2367  * EXPECTED RESULTS
2368  *   The move operations are properly detected by the Kernel, and the screen is
2369  *   properly updated every time.
2370  *
2371  * FAILURES
2372  *   If you get a failure here, check how the Kernel is enabling or disabling
2373  *   your feature when it moves the planes around.
2374  */
move_subtest(const struct test_mode * t)2375 static void move_subtest(const struct test_mode *t)
2376 {
2377 	int r;
2378 	int assertions = ASSERT_NO_ACTION_CHANGE;
2379 	struct modeset_params *params = pick_params(t);
2380 	struct draw_pattern_info *pattern = &pattern3;
2381 	struct fb_region *reg = pick_target(t, params);
2382 	bool repeat = false;
2383 
2384 	prepare_subtest(t, pattern);
2385 
2386 	/* Just paint the right color since we start at 0x0. */
2387 	draw_rect(pattern, reg, t->method, 0);
2388 	update_wanted_crc(t, &pattern->crcs[t->format][0]);
2389 
2390 	do_assertions(assertions);
2391 
2392 	for (r = 1; r < pattern->n_rects; r++) {
2393 		struct rect rect = pattern->get_rect(&params->primary, r);
2394 
2395 		igt_plane_set_fb(reg->plane, reg->fb);
2396 		igt_plane_set_position(reg->plane, rect.x, rect.y);
2397 		igt_plane_set_size(reg->plane, rect.w, rect.h);
2398 		igt_fb_set_size(reg->fb, reg->plane, rect.w, rect.h);
2399 		igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2400 
2401 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
2402 
2403 		do_assertions(assertions);
2404 
2405 		/* "Move" the last rect to the same position just to make sure
2406 		 * this works too. */
2407 		if (r+1 == pattern->n_rects && !repeat) {
2408 			repeat = true;
2409 			r--;
2410 		}
2411 	}
2412 }
2413 
2414 /*
2415  * onoff - just enable and disable the sprite or cursor plane a few times
2416  *
2417  * METHOD
2418  *   Just enable and disable the desired plane a few times.
2419  *
2420  * EXPECTED RESULTS
2421  *   Everything is properly detected by the Kernel and the screen contents are
2422  *   accurate.
2423  *
2424  * FAILURES
2425  *   As usual, if you get a failure here you need to check how the feature is
2426  *   being handled when the planes are enabled or disabled.
2427  */
onoff_subtest(const struct test_mode * t)2428 static void onoff_subtest(const struct test_mode *t)
2429 {
2430 	int r;
2431 	int assertions = ASSERT_NO_ACTION_CHANGE;
2432 	struct modeset_params *params = pick_params(t);
2433 	struct draw_pattern_info *pattern = &pattern3;
2434 
2435 	prepare_subtest(t, pattern);
2436 
2437 	/* Just paint the right color since we start at 0x0. */
2438 	draw_rect(pattern, pick_target(t, params), t->method, 0);
2439 	update_wanted_crc(t, &pattern->crcs[t->format][0]);
2440 	do_assertions(assertions);
2441 
2442 	for (r = 0; r < 4; r++) {
2443 		struct fb_region *reg = pick_target(t, params);
2444 
2445 		if (r % 2 == 0) {
2446 			igt_plane_set_fb(reg->plane, NULL);
2447 			igt_display_commit(&drm.display);
2448 
2449 			update_wanted_crc(t, &blue_crcs[t->format].crc);
2450 
2451 		} else {
2452 			igt_plane_set_fb(reg->plane, reg->fb);
2453 			igt_plane_set_size(reg->plane, reg->w, reg->h);
2454 			igt_fb_set_size(reg->fb, reg->plane, reg->w, reg->h);
2455 			igt_display_commit(&drm.display);
2456 
2457 			update_wanted_crc(t, &pattern->crcs[t->format][0]);
2458 		}
2459 
2460 		do_assertions(assertions);
2461 	}
2462 }
2463 
prim_plane_disabled(void)2464 static bool prim_plane_disabled(void)
2465 {
2466 	/*
2467 	 * Cannot use igt_plane_get_prop here to retrieve fb_id,
2468 	 * the testsuite doesn't require ATOMIC.
2469 	 */
2470 	return !prim_mode_params.primary.plane->values[IGT_PLANE_FB_ID];
2471 }
2472 
2473 /*
2474  * fullscreen_plane - put a fullscreen plane covering the whole screen
2475  *
2476  * METHOD
2477  *   As simple as the description above.
2478  *
2479  * EXPECTED RESULTS
2480  *   It depends on the feature being tested. FBC gets disabled, but PSR doesn't.
2481  *
2482  * FAILURES
2483  *   Again, if you get failures here you need to dig into the Kernel code, see
2484  *   how it is handling your feature on this specific case.
2485  */
fullscreen_plane_subtest(const struct test_mode * t)2486 static void fullscreen_plane_subtest(const struct test_mode *t)
2487 {
2488 	struct draw_pattern_info *pattern = &pattern4;
2489 	struct igt_fb fullscreen_fb;
2490 	struct rect rect;
2491 	struct modeset_params *params = pick_params(t);
2492 	int assertions;
2493 
2494 	prepare_subtest(t, pattern);
2495 
2496 	rect = pattern->get_rect(&params->primary, 0);
2497 	create_fb(t->format, rect.w, rect.h, opt.tiling, t->plane,
2498 		  &fullscreen_fb);
2499 	/* Call pick_color() again since PRI and SPR may not support the same
2500 	 * pixel formats. */
2501 	rect.color = pick_color(&fullscreen_fb, COLOR_GREEN);
2502 	igt_draw_fill_fb(drm.fd, &fullscreen_fb, rect.color);
2503 
2504 	igt_plane_set_fb(params->sprite.plane, &fullscreen_fb);
2505 	igt_display_commit(&drm.display);
2506 	update_wanted_crc(t, &pattern->crcs[t->format][0]);
2507 
2508 	switch (t->screen) {
2509 	case SCREEN_PRIM:
2510 		assertions = ASSERT_LAST_ACTION_CHANGED;
2511 
2512 		if (prim_plane_disabled())
2513 			assertions |= ASSERT_FBC_DISABLED;
2514 		break;
2515 	case SCREEN_SCND:
2516 		assertions = ASSERT_NO_ACTION_CHANGE;
2517 		break;
2518 	default:
2519 		igt_assert(false);
2520 	}
2521 	do_assertions(assertions);
2522 
2523 	igt_plane_set_fb(params->sprite.plane, NULL);
2524 	igt_display_commit(&drm.display);
2525 
2526 	if (t->screen == SCREEN_PRIM)
2527 		assertions = ASSERT_LAST_ACTION_CHANGED;
2528 	update_wanted_crc(t, &blue_crcs[t->format].crc);
2529 	do_assertions(assertions);
2530 
2531 	igt_remove_fb(drm.fd, &fullscreen_fb);
2532 }
2533 
2534 /*
2535  * scaledprimary - try different primary plane scaling strategies
2536  *
2537  * METHOD
2538  *    Enable the primary plane, use drmModeSetPlane to force scaling in
2539  *    different ways.
2540  *
2541  * EXPECTED RESULTS
2542  *   SKIP on platforms that don't support primary plane scaling. Success on all
2543  *   others.
2544  *
2545  * FAILURES
2546  *   TODO: although we're exercising the code here, we're not really doing
2547  *   assertions in order to check if things are working properly. The biggest
2548  *   issue this code would be able to find would be an incorrectly calculated
2549  *   CFB size, and today we don't have means to assert this. One day we might
2550  *   implement some sort of stolen memory checking mechanism, then we'll be able
2551  *   to force it to run after every drmModeSetPlane call here, so we'll be
2552  *   checking if the expected CFB size is actually what we think it is.
2553  */
scaledprimary_subtest(const struct test_mode * t)2554 static void scaledprimary_subtest(const struct test_mode *t)
2555 {
2556 	struct igt_fb new_fb, *old_fb;
2557 	struct modeset_params *params = pick_params(t);
2558 	struct fb_region *reg = &params->primary;
2559 	int gen = intel_gen(intel_get_drm_devid(drm.fd));
2560 	int src_y_upscale = ALIGN(reg->h / 4, 4);
2561 
2562 	igt_require_f(gen >= 9,
2563 		      "Can't test primary plane scaling before gen 9\n");
2564 
2565 	prepare_subtest(t, NULL);
2566 
2567 	old_fb = reg->fb;
2568 
2569 	create_fb(t->format, reg->fb->width, reg->fb->height,
2570 		  opt.tiling, t->plane, &new_fb);
2571 	fill_fb(&new_fb, COLOR_BLUE);
2572 
2573 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, &new_fb, t->method,
2574 			 reg->x, reg->y, reg->w / 2, reg->h / 2,
2575 			 pick_color(&new_fb, COLOR_GREEN));
2576 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, &new_fb, t->method,
2577 			 reg->x + reg->w / 2, reg->y + reg->h / 2,
2578 			 reg->w / 2, reg->h / 2,
2579 			 pick_color(&new_fb, COLOR_RED));
2580 	igt_draw_rect_fb(drm.fd, drm.bufmgr, NULL, &new_fb, t->method,
2581 			 reg->x + reg->w / 2, reg->y + reg->h / 2,
2582 			 reg->w / 4, reg->h / 4,
2583 			 pick_color(&new_fb, COLOR_MAGENTA));
2584 
2585 	/* No scaling. */
2586 	igt_plane_set_fb(reg->plane, &new_fb);
2587 	igt_fb_set_position(&new_fb, reg->plane, reg->x, reg->y);
2588 	igt_fb_set_size(&new_fb, reg->plane, reg->w, reg->h);
2589 	igt_plane_set_size(reg->plane, params->mode->hdisplay, params->mode->vdisplay);
2590 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2591 	do_assertions(DONT_ASSERT_CRC);
2592 
2593 	/* Source upscaling. */
2594 	igt_fb_set_size(&new_fb, reg->plane, reg->w / 2, reg->h / 2);
2595 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2596 	do_assertions(DONT_ASSERT_CRC);
2597 
2598 	/* Destination doesn't fill the entire CRTC, no scaling. */
2599 	igt_fb_set_size(&new_fb, reg->plane, reg->w / 2, reg->h / 2);
2600 	igt_plane_set_position(reg->plane,
2601 			       params->mode->hdisplay / 4,
2602 			       params->mode->vdisplay / 4);
2603 	igt_plane_set_size(reg->plane,
2604 			   params->mode->hdisplay / 2,
2605 			   params->mode->vdisplay / 2);
2606 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2607 	do_assertions(DONT_ASSERT_CRC);
2608 
2609 	/* Destination doesn't fill the entire CRTC, upscaling. */
2610 	igt_fb_set_position(&new_fb, reg->plane,
2611 			    reg->x + reg->w / 4, reg->y + src_y_upscale);
2612 	igt_fb_set_size(&new_fb, reg->plane, reg->w / 2, reg->h / 2);
2613 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2614 	do_assertions(DONT_ASSERT_CRC);
2615 
2616 	/*
2617 	 * On gen <= 10 HW, FBC is not enabled on a plane with a Y offset
2618 	 * that isn't divisible by 4, because it causes FIFO underruns.
2619 	 *
2620 	 * Check that FBC is disabled.
2621 	 */
2622 	igt_fb_set_position(&new_fb, reg->plane,
2623 			    reg->x + reg->w / 4, reg->y + src_y_upscale + 3);
2624 	igt_fb_set_size(&new_fb, reg->plane, reg->w / 2, reg->h / 2);
2625 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2626 	do_assertions(DONT_ASSERT_CRC | (gen <= 10 ? ASSERT_FBC_DISABLED : 0));
2627 
2628 	/* Back to the good and old blue fb. */
2629 	igt_plane_set_fb(reg->plane, old_fb);
2630 	igt_plane_set_position(params->primary.plane, 0, 0);
2631 	igt_plane_set_size(reg->plane, params->mode->hdisplay, params->mode->vdisplay);
2632 	igt_fb_set_position(reg->fb, reg->plane, reg->x, reg->y);
2633 	igt_fb_set_size(reg->fb, reg->plane, reg->w, reg->h);
2634 	igt_display_commit2(&drm.display, COMMIT_UNIVERSAL);
2635 	do_assertions(0);
2636 
2637 	igt_remove_fb(drm.fd, &new_fb);
2638 }
2639 /**
2640  * modesetfrombusy - modeset from a busy buffer to a non-busy buffer
2641  *
2642  * METHOD
2643  *   Set a mode, make the frontbuffer busy using BLT writes, do a modeset to a
2644  *   non-busy buffer, then check if the features are enabled. The goal of this
2645  *   test is to exercise a bug we had on the frontbuffer tracking infrastructure
2646  *   code.
2647  *
2648  * EXPECTED RESULTS
2649  *   No assertions fail.
2650  *
2651  * FAILURES
2652  *   If you're failing this test, then you probably need "drm/i915: Clear
2653  *   fb_tracking.busy_bits also for synchronous flips" or any other patch that
2654  *   properly updates dev_priv->fb_tracking.busy_bits when we're alternating
2655  *   between buffers with different busyness.
2656  */
modesetfrombusy_subtest(const struct test_mode * t)2657 static void modesetfrombusy_subtest(const struct test_mode *t)
2658 {
2659 	struct modeset_params *params = pick_params(t);
2660 	struct igt_fb fb2;
2661 
2662 	prepare_subtest(t, NULL);
2663 
2664 	create_fb(t->format, params->primary.fb->width, params->primary.fb->height,
2665 		  opt.tiling, t->plane, &fb2);
2666 	fill_fb(&fb2, COLOR_PRIM_BG);
2667 
2668 	start_busy_thread(params->primary.fb);
2669 	usleep(10000);
2670 
2671 	unset_all_crtcs();
2672 	params->primary.fb = &fb2;
2673 	set_mode_for_params(params);
2674 
2675 	do_assertions(ASSERT_NO_IDLE_GPU);
2676 
2677 	stop_busy_thread();
2678 
2679 	igt_remove_fb(drm.fd, &fb2);
2680 }
2681 
2682 /**
2683  * suspend - make sure suspend/resume keeps us on the same state
2684  *
2685  * METHOD
2686  *   Set a mode, assert FBC is there, suspend, resume, assert FBC is still
2687  *   there. Unset modes, assert FBC is disabled, resuspend, resume, assert FBC
2688  *   is still disabled.
2689  *
2690  * EXPECTED RESULTS
2691  *   Suspend/resume doesn't affect the FBC state.
2692  *
2693  * FAILURES
2694  *   A lot of different things could lead to a bug here, you'll have to check
2695  *   the Kernel code.
2696  */
suspend_subtest(const struct test_mode * t)2697 static void suspend_subtest(const struct test_mode *t)
2698 {
2699 	struct modeset_params *params = pick_params(t);
2700 
2701 	prepare_subtest(t, NULL);
2702 	igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE);
2703 	do_assertions(ASSERT_DRRS_LOW);
2704 
2705 	unset_all_crtcs();
2706 	igt_system_suspend_autoresume(SUSPEND_STATE_MEM, SUSPEND_TEST_NONE);
2707 	do_assertions(ASSERT_FBC_DISABLED | ASSERT_PSR_DISABLED |
2708 		      DONT_ASSERT_CRC | ASSERT_DRRS_INACTIVE);
2709 
2710 	set_mode_for_params(params);
2711 	do_assertions(0);
2712 }
2713 
2714 /**
2715  * farfromfence - test drawing as far from the fence start as possible
2716  *
2717  * METHOD
2718  *   One of the possible problems with FBC is that if the mode being displayed
2719  *   is very far away from the fence we might setup the hardware frontbuffer
2720  *   tracking in the wrong way. So this test tries to set a really tall FB,
2721  *   makes the CRTC point to the bottom of that FB, then it tries to exercise
2722  *   the hardware frontbuffer tracking through GTT mmap operations.
2723  *
2724  * EXPECTED RESULTS
2725  *   Everything succeeds.
2726  *
2727  * FAILURES
2728  *   If you're getting wrong CRC calulations, then the hardware tracking might
2729  *   be misconfigured and needs to be checked. If we're failing because FBC is
2730  *   disabled and the reason is that there's not enough stolen memory, then the
2731  *   Kernel might be calculating the amount of stolen memory needed based on the
2732  *   whole framebuffer size, and not just on the needed size: in this case, you
2733  *   need a newer Kernel.
2734  */
farfromfence_subtest(const struct test_mode * t)2735 static void farfromfence_subtest(const struct test_mode *t)
2736 {
2737 	int r;
2738 	struct igt_fb tall_fb;
2739 	struct modeset_params *params = pick_params(t);
2740 	struct draw_pattern_info *pattern = &pattern1;
2741 	struct fb_region *target;
2742 	int max_height, assertions = 0;
2743 	int gen = intel_gen(intel_get_drm_devid(drm.fd));
2744 
2745 	switch (gen) {
2746 	case 2:
2747 		max_height = 2048;
2748 		break;
2749 	case 3:
2750 		max_height = 4096;
2751 		break;
2752 	default:
2753 		max_height = 8192;
2754 		break;
2755 	}
2756 
2757 	/* Gen 9 doesn't do the same dspaddr_offset magic as the older
2758 	 * gens, so FBC may not be enabled there. */
2759 	if (gen >= 9)
2760 		assertions |= DONT_ASSERT_FEATURE_STATUS;
2761 
2762 	prepare_subtest(t, pattern);
2763 	target = pick_target(t, params);
2764 
2765 	create_fb(t->format, params->mode->hdisplay, max_height, opt.tiling,
2766 		  t->plane, &tall_fb);
2767 
2768 	fill_fb(&tall_fb, COLOR_PRIM_BG);
2769 
2770 	params->primary.fb = &tall_fb;
2771 	params->primary.x = 0;
2772 	params->primary.y = max_height - params->mode->vdisplay;
2773 	set_mode_for_params(params);
2774 	do_assertions(assertions);
2775 
2776 	for (r = 0; r < pattern->n_rects; r++) {
2777 		draw_rect(pattern, target, t->method, r);
2778 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
2779 
2780 		/* GTT draws disable PSR. */
2781 		do_assertions(assertions | ASSERT_PSR_DISABLED);
2782 	}
2783 
2784 	igt_remove_fb(drm.fd, &tall_fb);
2785 }
2786 
try_invalid_strides(void)2787 static void try_invalid_strides(void)
2788 {
2789 	uint32_t gem_handle;
2790 	int rc;
2791 
2792 	/* Sizes that the Kernel shouldn't even allow for tiled */
2793 	gem_handle = gem_create(drm.fd, 2048);
2794 
2795 	/* Smaller than 512, yet still 64-byte aligned. */
2796 	rc = __gem_set_tiling(drm.fd, gem_handle, I915_TILING_X, 448);
2797 	igt_assert_eq(rc, -EINVAL);
2798 
2799 	/* Bigger than 512, but not 64-byte aligned. */
2800 	rc = __gem_set_tiling(drm.fd, gem_handle, I915_TILING_X, 1022);
2801 	igt_assert_eq(rc, -EINVAL);
2802 
2803 	/* Just make sure something actually works. */
2804 	rc = __gem_set_tiling(drm.fd, gem_handle, I915_TILING_X, 1024);
2805 	igt_assert_eq(rc, 0);
2806 
2807 	gem_close(drm.fd, gem_handle);
2808 }
2809 
2810 /**
2811  * badstride - try to use buffers with strides that are not supported
2812  *
2813  * METHOD
2814  *   First we try to create buffers with strides that are not allowed for tiled
2815  *   surfaces and assert the Kernel rejects them. Then we create buffers with
2816  *   strides that are allowed by the Kernel, but that are incompatible with FBC
2817  *   and we assert that FBC stays disabled after we set a mode on those buffers.
2818  *
2819  * EXPECTED RESULTS
2820  *   The invalid strides are rejected, and the valid strides that are
2821  *   incompatible with FBC result in FBC disabled.
2822  *
2823  * FAILURES
2824  *   There are two possible places where the Kernel can be broken: either the
2825  *   code that checks valid strides for tiled buffers or the code that checks
2826  *   the valid strides for FBC.
2827  */
badstride_subtest(const struct test_mode * t)2828 static void badstride_subtest(const struct test_mode *t)
2829 {
2830 	struct igt_fb wide_fb, *old_fb;
2831 	struct modeset_params *params = pick_params(t);
2832 	int rc;
2833 
2834 	try_invalid_strides();
2835 
2836 	prepare_subtest(t, NULL);
2837 
2838 	old_fb = params->primary.fb;
2839 
2840 	create_fb(t->format, params->primary.fb->width + 4096, params->primary.fb->height,
2841 		  opt.tiling, t->plane, &wide_fb);
2842 	igt_assert(wide_fb.strides[0] > 16384);
2843 
2844 	fill_fb(&wide_fb, COLOR_PRIM_BG);
2845 
2846 	/* Try a simple modeset with the new fb. */
2847 	params->primary.fb = &wide_fb;
2848 	set_mode_for_params(params);
2849 	do_assertions(ASSERT_FBC_DISABLED);
2850 
2851 	/* Go back to the old fb so FBC works again. */
2852 	params->primary.fb = old_fb;
2853 	set_mode_for_params(params);
2854 	do_assertions(0);
2855 
2856 	/* We're doing the equivalent of a modeset, but with the planes API. */
2857 	params->primary.fb = &wide_fb;
2858 	set_prim_plane_for_params(params);
2859 	do_assertions(ASSERT_FBC_DISABLED);
2860 
2861 	params->primary.fb = old_fb;
2862 	set_mode_for_params(params);
2863 	do_assertions(0);
2864 
2865 	/*
2866 	 * We previously couldn't use the page flip IOCTL to flip to a buffer
2867 	 * with a different stride. With the atomic page flip helper we can,
2868 	 * so allow page flip to fail and succeed.
2869 	 */
2870 	rc = drmModePageFlip(drm.fd, drm.display.pipes[params->pipe].crtc_id, wide_fb.fb_id, 0, NULL);
2871 	igt_assert(rc == -EINVAL || rc == 0);
2872 	do_assertions(rc == 0 ? ASSERT_FBC_DISABLED : 0);
2873 
2874 	igt_remove_fb(drm.fd, &wide_fb);
2875 }
2876 
2877 /**
2878  * stridechange - change the frontbuffer stride by doing a modeset
2879  *
2880  * METHOD
2881  *   This test sets a mode on a CRTC, then creates a buffer with a different
2882  *   stride - still compatible with FBC -, and sets the mode on it. The Kernel
2883  *   currently shortcuts the modeset path for this case, so it won't trigger
2884  *   calls to xx_crtc_enable or xx_crtc_disable, and that could lead to
2885  *   problems, so test the case.
2886  *
2887  * EXPECTED RESULTS
2888  *   With the current Kernel, FBC may or may not remain enabled on this case,
2889  *   but we can still check the CRC values.
2890  *
2891  * FAILURES
2892  *   A bad Kernel may just not resize the CFB while keeping FBC enabled, and
2893  *   this can lead to underruns or stolen memory corruption. Underruns usually
2894  *   lead to CRC check errors, and stolen memory corruption can't be easily
2895  *   checked currently. A bad Kernel may also just throw some WARNs on dmesg.
2896  */
stridechange_subtest(const struct test_mode * t)2897 static void stridechange_subtest(const struct test_mode *t)
2898 {
2899 	struct igt_fb *new_fb, *old_fb;
2900 	struct modeset_params *params = pick_params(t);
2901 	int rc;
2902 
2903 	prepare_subtest(t, NULL);
2904 
2905 	old_fb = params->primary.fb;
2906 
2907 	/* We can't assert that FBC will be enabled since there may not be
2908 	 * enough space for the CFB, but we can check the CRC. */
2909 	new_fb = &fbs[t->format].big;
2910 	igt_assert(old_fb->strides[0] != new_fb->strides[0]);
2911 
2912 	params->primary.fb = new_fb;
2913 	fill_fb_region(&params->primary, COLOR_PRIM_BG);
2914 
2915 	set_mode_for_params(params);
2916 	do_assertions(DONT_ASSERT_FBC_STATUS);
2917 
2918 	/* Go back to the fb that can have FBC. */
2919 	params->primary.fb = old_fb;
2920 	set_mode_for_params(params);
2921 	do_assertions(0);
2922 
2923 	/* This operation is the same as above, but with the planes API. */
2924 	params->primary.fb = new_fb;
2925 	set_prim_plane_for_params(params);
2926 	do_assertions(DONT_ASSERT_FBC_STATUS);
2927 
2928 	params->primary.fb = old_fb;
2929 	set_prim_plane_for_params(params);
2930 	do_assertions(0);
2931 
2932 	/*
2933 	 * Try to set a new stride. with the page flip api. This is allowed
2934 	 * with the atomic page flip helper, but not with the legacy page flip.
2935 	 */
2936 	rc = drmModePageFlip(drm.fd, drm.display.pipes[params->pipe].crtc_id, new_fb->fb_id, 0, NULL);
2937 	igt_assert(rc == -EINVAL || rc == 0);
2938 	do_assertions(rc ? 0 : DONT_ASSERT_FBC_STATUS);
2939 }
2940 
2941 /**
2942  * tilingchange - alternate between tiled and untiled in multiple ways
2943  *
2944  * METHOD
2945  *   This test alternates between tiled and untiled frontbuffers of the same
2946  *   size and format through multiple different APIs: the page flip IOCTL,
2947  *   normal modesets and the plane APIs.
2948  *
2949  * EXPECTED RESULTS
2950  *   FBC gets properly disabled for the untiled FB and reenabled for the
2951  *   tiled FB.
2952  *
2953  * FAILURES
2954  *   Bad Kernels may somehow leave FBC enabled, which can cause FIFO underruns
2955  *   that lead to CRC assertion failures.
2956  */
tilingchange_subtest(const struct test_mode * t)2957 static void tilingchange_subtest(const struct test_mode *t)
2958 {
2959 	struct igt_fb new_fb, *old_fb;
2960 	struct modeset_params *params = pick_params(t);
2961 	enum flip_type flip_type;
2962 
2963 	prepare_subtest(t, NULL);
2964 
2965 	old_fb = params->primary.fb;
2966 
2967 	create_fb(t->format, params->primary.fb->width, params->primary.fb->height,
2968 		  LOCAL_DRM_FORMAT_MOD_NONE, t->plane, &new_fb);
2969 	fill_fb(&new_fb, COLOR_PRIM_BG);
2970 
2971 	for (flip_type = 0; flip_type < FLIP_COUNT; flip_type++) {
2972 		igt_debug("Flip type: %d\n", flip_type);
2973 
2974 		/* Set a buffer with no tiling. */
2975 		params->primary.fb = &new_fb;
2976 		page_flip_for_params(params, flip_type);
2977 		do_assertions(ASSERT_FBC_DISABLED);
2978 
2979 		/* Put FBC back in a working state. */
2980 		params->primary.fb = old_fb;
2981 		page_flip_for_params(params, flip_type);
2982 		do_assertions(0);
2983 	}
2984 
2985 	igt_remove_fb(drm.fd, &new_fb);
2986 }
2987 
2988 /*
2989  * basic - do some basic operations regardless of which features are enabled
2990  *
2991  * METHOD
2992  *   This subtest does page flips and draw operations and checks the CRCs of the
2993  *   results. The big difference between this and the others is that here we
2994  *   don't enable/disable any features such as FBC or PSR: we go with whatever
2995  *   the Kernel has enabled by default for us. This subtest only does things
2996  *   that are exercised by the other subtests and in a less exhaustive way: it's
2997  *   completely redundant. On the other hand, it is very quick and was created
2998  *   with the CI system in mind: it's a quick way to detect regressions, so if
2999  *   it fails, then we can run the other subtests to find out why.
3000  *
3001  * EXPECTED RESULTS
3002  *   Passed CRC assertions.
3003  *
3004  * FAILURES
3005  *   If you get a failure here, you should run the more specific draw and flip
3006  *   subtests of each feature in order to discover what exactly is failing and
3007  *   why.
3008  */
basic_subtest(const struct test_mode * t)3009 static void basic_subtest(const struct test_mode *t)
3010 {
3011 	struct draw_pattern_info *pattern = &pattern1;
3012 	struct modeset_params *params = pick_params(t);
3013 	enum igt_draw_method method;
3014 	struct igt_fb *fb1, fb2;
3015 	int r;
3016 	int assertions = DONT_ASSERT_FEATURE_STATUS;
3017 
3018 	prepare_subtest(t, pattern);
3019 
3020 	create_fb(t->format, params->primary.fb->width, params->primary.fb->height,
3021 		  opt.tiling, t->plane, &fb2);
3022 	fb1 = params->primary.fb;
3023 
3024 	for (r = 0, method = 0; method < IGT_DRAW_METHOD_COUNT; method++, r++) {
3025 		if (r == pattern->n_rects) {
3026 			params->primary.fb = (params->primary.fb == fb1) ? &fb2 : fb1;
3027 
3028 			fill_fb_region(&params->primary, COLOR_PRIM_BG);
3029 			update_wanted_crc(t, &blue_crcs[t->format].crc);
3030 
3031 			page_flip_for_params(params, t->flip);
3032 			do_assertions(assertions);
3033 
3034 			r = 0;
3035 		}
3036 
3037 		draw_rect(pattern, &params->primary, method, r);
3038 		update_wanted_crc(t, &pattern->crcs[t->format][r]);
3039 		do_assertions(assertions);
3040 	}
3041 
3042 	igt_remove_fb(drm.fd, &fb2);
3043 }
3044 
opt_handler(int option,int option_index,void * data)3045 static int opt_handler(int option, int option_index, void *data)
3046 {
3047 	switch (option) {
3048 	case 's':
3049 		opt.check_status = false;
3050 		break;
3051 	case 'c':
3052 		opt.check_crc = false;
3053 		break;
3054 	case 'o':
3055 		opt.fbc_check_compression = false;
3056 		break;
3057 	case 'a':
3058 		opt.fbc_check_last_action = false;
3059 		break;
3060 	case 'e':
3061 		opt.no_edp = true;
3062 		break;
3063 	case 'm':
3064 		opt.small_modes = true;
3065 		break;
3066 	case 'i':
3067 		opt.show_hidden = true;
3068 		break;
3069 	case 't':
3070 		opt.step++;
3071 		break;
3072 	case 'x':
3073 		errno = 0;
3074 		opt.shared_fb_x_offset = strtol(optarg, NULL, 0);
3075 		if (errno != 0)
3076 			return IGT_OPT_HANDLER_ERROR;
3077 		break;
3078 	case 'y':
3079 		errno = 0;
3080 		opt.shared_fb_y_offset = strtol(optarg, NULL, 0);
3081 		if (errno != 0)
3082 			return IGT_OPT_HANDLER_ERROR;
3083 		break;
3084 	case '1':
3085 		if (opt.only_pipes != PIPE_COUNT)
3086 			return IGT_OPT_HANDLER_ERROR;
3087 		opt.only_pipes = PIPE_SINGLE;
3088 		break;
3089 	case '2':
3090 		if (opt.only_pipes != PIPE_COUNT)
3091 			return IGT_OPT_HANDLER_ERROR;
3092 		opt.only_pipes = PIPE_DUAL;
3093 		break;
3094 	case 'l':
3095 		if (!strcmp(optarg, "x"))
3096 			opt.tiling = LOCAL_I915_FORMAT_MOD_X_TILED;
3097 		else if (!strcmp(optarg, "y"))
3098 			opt.tiling = LOCAL_I915_FORMAT_MOD_Y_TILED;
3099 		else {
3100 			igt_warn("Bad tiling value: %s\n", optarg);
3101 			return IGT_OPT_HANDLER_ERROR;
3102 		}
3103 		break;
3104 	default:
3105 		return IGT_OPT_HANDLER_ERROR;
3106 	}
3107 
3108 	return IGT_OPT_HANDLER_SUCCESS;
3109 }
3110 
3111 const char *help_str =
3112 "  --no-status-check           Don't check for enable/disable status\n"
3113 "  --no-crc-check              Don't check for CRC values\n"
3114 "  --no-fbc-compression-check  Don't check for the FBC compression status\n"
3115 "  --no-fbc-action-check       Don't check for the FBC last action\n"
3116 "  --no-edp                    Don't use eDP monitors\n"
3117 "  --use-small-modes           Use smaller resolutions for the modes\n"
3118 "  --show-hidden               Show hidden subtests\n"
3119 "  --step                      Stop on each step so you can check the screen\n"
3120 "  --shared-fb-x offset        Use 'offset' as the X offset for the shared FB\n"
3121 "  --shared-fb-y offset        Use 'offset' as the Y offset for the shared FB\n"
3122 "  --1p-only                   Only run subtests that use 1 pipe\n"
3123 "  --2p-only                   Only run subtests that use 2 pipes\n"
3124 "  --tiling tiling             Use 'tiling' as the tiling mode, which can be\n"
3125 "                              either 'x' (default) or 'y'\n";
3126 
pipes_str(int pipes)3127 static const char *pipes_str(int pipes)
3128 {
3129 	switch (pipes) {
3130 	case PIPE_SINGLE:
3131 		return "1p";
3132 	case PIPE_DUAL:
3133 		return "2p";
3134 	default:
3135 		igt_assert(false);
3136 	}
3137 }
3138 
screen_str(int screen)3139 static const char *screen_str(int screen)
3140 {
3141 	switch (screen) {
3142 	case SCREEN_PRIM:
3143 		return "primscrn";
3144 	case SCREEN_SCND:
3145 		return "scndscrn";
3146 	case SCREEN_OFFSCREEN:
3147 		return "offscren";
3148 	default:
3149 		igt_assert(false);
3150 	}
3151 }
3152 
plane_str(int plane)3153 static const char *plane_str(int plane)
3154 {
3155 	switch (plane) {
3156 	case PLANE_PRI:
3157 		return "pri";
3158 	case PLANE_CUR:
3159 		return "cur";
3160 	case PLANE_SPR:
3161 		return "spr";
3162 	default:
3163 		igt_assert(false);
3164 	}
3165 }
3166 
fbs_str(int fb)3167 static const char *fbs_str(int fb)
3168 {
3169 	switch (fb) {
3170 	case FBS_INDIVIDUAL:
3171 		return "indfb";
3172 	case FBS_SHARED:
3173 		return "shrfb";
3174 	default:
3175 		igt_assert(false);
3176 	}
3177 }
3178 
feature_str(int feature)3179 static const char *feature_str(int feature)
3180 {
3181 	switch (feature) {
3182 	case FEATURE_NONE:
3183 		return "nop";
3184 	case FEATURE_FBC:
3185 		return "fbc";
3186 	case FEATURE_PSR:
3187 		return "psr";
3188 	case FEATURE_FBC | FEATURE_PSR:
3189 		return "fbcpsr";
3190 	case FEATURE_DRRS:
3191 		return "drrs";
3192 	case FEATURE_FBC | FEATURE_DRRS:
3193 		return "fbcdrrs";
3194 	case FEATURE_PSR | FEATURE_DRRS:
3195 		return "psrdrrs";
3196 	case FEATURE_FBC | FEATURE_PSR | FEATURE_DRRS:
3197 		return "fbcpsrdrrs";
3198 	default:
3199 		igt_assert(false);
3200 	}
3201 }
3202 
format_str(enum pixel_format format)3203 static const char *format_str(enum pixel_format format)
3204 {
3205 	switch (format) {
3206 	case FORMAT_RGB888:
3207 		return "rgb888";
3208 	case FORMAT_RGB565:
3209 		return "rgb565";
3210 	case FORMAT_RGB101010:
3211 		return "rgb101010";
3212 	default:
3213 		igt_assert(false);
3214 	}
3215 }
3216 
flip_str(enum flip_type flip)3217 static const char *flip_str(enum flip_type flip)
3218 {
3219 	switch (flip) {
3220 	case FLIP_PAGEFLIP:
3221 		return "pg";
3222 	case FLIP_MODESET:
3223 		return "ms";
3224 	case FLIP_PLANES:
3225 		return "pl";
3226 	default:
3227 		igt_assert(false);
3228 	}
3229 }
3230 
3231 #define TEST_MODE_ITER_BEGIN(t) \
3232 	t.format = FORMAT_DEFAULT;					   \
3233 	t.flip = FLIP_PAGEFLIP;						   \
3234 	for (t.feature = 0; t.feature < FEATURE_COUNT; t.feature++) {	   \
3235 	for (t.pipes = 0; t.pipes < PIPE_COUNT; t.pipes++) {		   \
3236 	for (t.screen = 0; t.screen < SCREEN_COUNT; t.screen++) {	   \
3237 	for (t.plane = 0; t.plane < PLANE_COUNT; t.plane++) {		   \
3238 	for (t.fbs = 0; t.fbs < FBS_COUNT; t.fbs++) {			   \
3239 	for (t.method = 0; t.method < IGT_DRAW_METHOD_COUNT; t.method++) { \
3240 		if (t.pipes == PIPE_SINGLE && t.screen == SCREEN_SCND)	   \
3241 			continue;					   \
3242 		if (t.screen == SCREEN_OFFSCREEN && t.plane != PLANE_PRI)  \
3243 			continue;					   \
3244 		if (!opt.show_hidden && t.pipes == PIPE_DUAL &&		   \
3245 		    t.screen == SCREEN_OFFSCREEN)			   \
3246 			continue;					   \
3247 		if (!opt.show_hidden && t.feature == FEATURE_NONE)	   \
3248 			continue;					   \
3249 		if (!opt.show_hidden && t.fbs == FBS_SHARED &&		   \
3250 		    (t.plane == PLANE_CUR || t.plane == PLANE_SPR))	   \
3251 			continue;
3252 
3253 
3254 #define TEST_MODE_ITER_END } } } } } }
3255 
3256 struct option long_options[] = {
3257 	{ "no-status-check",          0, 0, 's'},
3258 	{ "no-crc-check",             0, 0, 'c'},
3259 	{ "no-fbc-compression-check", 0, 0, 'o'},
3260 	{ "no-fbc-action-check",      0, 0, 'a'},
3261 	{ "no-edp",                   0, 0, 'e'},
3262 	{ "use-small-modes",          0, 0, 'm'},
3263 	{ "show-hidden",              0, 0, 'i'},
3264 	{ "step",                     0, 0, 't'},
3265 	{ "shared-fb-x",              1, 0, 'x'},
3266 	{ "shared-fb-y",              1, 0, 'y'},
3267 	{ "1p-only",                  0, 0, '1'},
3268 	{ "2p-only",                  0, 0, '2'},
3269 	{ "tiling",                   1, 0, 'l'},
3270 	{ 0, 0, 0, 0 }
3271 };
3272 
3273 igt_main_args("", long_options, help_str, opt_handler, NULL)
3274 {
3275 	struct test_mode t;
3276 
3277 	igt_fixture
3278 		setup_environment();
3279 
3280 	for (t.feature = 0; t.feature < FEATURE_COUNT; t.feature++) {
3281 		if (!opt.show_hidden && t.feature == FEATURE_NONE)
3282 			continue;
3283 		for (t.pipes = 0; t.pipes < PIPE_COUNT; t.pipes++) {
3284 			t.screen = SCREEN_PRIM;
3285 			t.plane = PLANE_PRI;
3286 			t.fbs = FBS_INDIVIDUAL;
3287 			t.format = FORMAT_DEFAULT;
3288 			/* Make sure nothing is using these values. */
3289 			t.flip = -1;
3290 			t.method = -1;
3291 
3292 			igt_subtest_f("%s-%s-rte",
3293 				      feature_str(t.feature),
3294 				      pipes_str(t.pipes))
3295 				rte_subtest(&t);
3296 		}
3297 	}
3298 
3299 	TEST_MODE_ITER_BEGIN(t)
3300 		igt_subtest_f("%s-%s-%s-%s-%s-draw-%s",
3301 			      feature_str(t.feature),
3302 			      pipes_str(t.pipes),
3303 			      screen_str(t.screen),
3304 			      plane_str(t.plane),
3305 			      fbs_str(t.fbs),
3306 			      igt_draw_get_method_name(t.method))
3307 			draw_subtest(&t);
3308 	TEST_MODE_ITER_END
3309 
3310 	TEST_MODE_ITER_BEGIN(t)
3311 		if (t.plane != PLANE_PRI ||
3312 		    t.screen == SCREEN_OFFSCREEN ||
3313 		    (!opt.show_hidden && t.method != IGT_DRAW_BLT))
3314 			continue;
3315 
3316 		for (t.flip = 0; t.flip < FLIP_COUNT; t.flip++)
3317 			igt_subtest_f("%s-%s-%s-%s-%sflip-%s",
3318 				      feature_str(t.feature),
3319 				      pipes_str(t.pipes),
3320 				      screen_str(t.screen),
3321 				      fbs_str(t.fbs),
3322 				      flip_str(t.flip),
3323 				      igt_draw_get_method_name(t.method))
3324 				flip_subtest(&t);
3325 	TEST_MODE_ITER_END
3326 
3327 	TEST_MODE_ITER_BEGIN(t)
3328 		if (t.plane != PLANE_PRI ||
3329 		    t.screen != SCREEN_PRIM ||
3330 		    t.method != IGT_DRAW_MMAP_GTT ||
3331 		    (t.feature & FEATURE_FBC) == 0)
3332 			continue;
3333 
3334 		igt_subtest_f("%s-%s-%s-fliptrack",
3335 			      feature_str(t.feature),
3336 			      pipes_str(t.pipes),
3337 			      fbs_str(t.fbs))
3338 			fliptrack_subtest(&t, FLIP_PAGEFLIP);
3339 	TEST_MODE_ITER_END
3340 
3341 	TEST_MODE_ITER_BEGIN(t)
3342 		if (t.screen == SCREEN_OFFSCREEN ||
3343 		    t.method != IGT_DRAW_BLT ||
3344 		    t.plane == PLANE_PRI)
3345 			continue;
3346 
3347 		igt_subtest_f("%s-%s-%s-%s-%s-move",
3348 			      feature_str(t.feature),
3349 			      pipes_str(t.pipes),
3350 			      screen_str(t.screen),
3351 			      plane_str(t.plane),
3352 			      fbs_str(t.fbs))
3353 			move_subtest(&t);
3354 
3355 		igt_subtest_f("%s-%s-%s-%s-%s-onoff",
3356 			      feature_str(t.feature),
3357 			      pipes_str(t.pipes),
3358 			      screen_str(t.screen),
3359 			      plane_str(t.plane),
3360 			      fbs_str(t.fbs))
3361 			onoff_subtest(&t);
3362 	TEST_MODE_ITER_END
3363 
3364 	TEST_MODE_ITER_BEGIN(t)
3365 		if (t.screen == SCREEN_OFFSCREEN ||
3366 		    t.method != IGT_DRAW_BLT ||
3367 		    t.plane != PLANE_SPR)
3368 			continue;
3369 
3370 		igt_subtest_f("%s-%s-%s-%s-%s-fullscreen",
3371 			      feature_str(t.feature),
3372 			      pipes_str(t.pipes),
3373 			      screen_str(t.screen),
3374 			      plane_str(t.plane),
3375 			      fbs_str(t.fbs))
3376 			fullscreen_plane_subtest(&t);
3377 	TEST_MODE_ITER_END
3378 
3379 	TEST_MODE_ITER_BEGIN(t)
3380 		if (t.screen != SCREEN_PRIM ||
3381 		    t.method != IGT_DRAW_BLT ||
3382 		    (!opt.show_hidden && t.plane != PLANE_PRI) ||
3383 		    (!opt.show_hidden && t.fbs != FBS_INDIVIDUAL))
3384 			continue;
3385 
3386 		igt_subtest_f("%s-%s-%s-%s-multidraw",
3387 			      feature_str(t.feature),
3388 			      pipes_str(t.pipes),
3389 			      plane_str(t.plane),
3390 			      fbs_str(t.fbs))
3391 			multidraw_subtest(&t);
3392 	TEST_MODE_ITER_END
3393 
3394 	TEST_MODE_ITER_BEGIN(t)
3395 		if (t.pipes != PIPE_SINGLE ||
3396 		    t.screen != SCREEN_PRIM ||
3397 		    t.plane != PLANE_PRI ||
3398 		    t.fbs != FBS_INDIVIDUAL ||
3399 		    t.method != IGT_DRAW_MMAP_GTT)
3400 			continue;
3401 
3402 		igt_subtest_f("%s-farfromfence", feature_str(t.feature))
3403 			farfromfence_subtest(&t);
3404 	TEST_MODE_ITER_END
3405 
3406 	TEST_MODE_ITER_BEGIN(t)
3407 		if (t.pipes != PIPE_SINGLE ||
3408 		    t.screen != SCREEN_PRIM ||
3409 		    t.plane != PLANE_PRI ||
3410 		    t.fbs != FBS_INDIVIDUAL)
3411 			continue;
3412 
3413 		for (t.format = 0; t.format < FORMAT_COUNT; t.format++) {
3414 			/* Skip what we already tested. */
3415 			if (t.format == FORMAT_DEFAULT)
3416 				continue;
3417 
3418 			igt_subtest_f("%s-%s-draw-%s",
3419 				      feature_str(t.feature),
3420 				      format_str(t.format),
3421 				      igt_draw_get_method_name(t.method))
3422 				format_draw_subtest(&t);
3423 		}
3424 	TEST_MODE_ITER_END
3425 
3426 	TEST_MODE_ITER_BEGIN(t)
3427 		if (t.pipes != PIPE_SINGLE ||
3428 		    t.screen != SCREEN_PRIM ||
3429 		    t.plane != PLANE_PRI ||
3430 		    t.method != IGT_DRAW_BLT)
3431 			continue;
3432 		igt_subtest_f("%s-%s-scaledprimary",
3433 			      feature_str(t.feature),
3434 			      fbs_str(t.fbs))
3435 			scaledprimary_subtest(&t);
3436 	TEST_MODE_ITER_END
3437 
3438 	TEST_MODE_ITER_BEGIN(t)
3439 		if (t.pipes != PIPE_SINGLE ||
3440 		    t.screen != SCREEN_PRIM ||
3441 		    t.plane != PLANE_PRI ||
3442 		    t.fbs != FBS_INDIVIDUAL ||
3443 		    t.method != IGT_DRAW_BLT)
3444 			continue;
3445 
3446 		igt_subtest_f("%s-modesetfrombusy", feature_str(t.feature))
3447 			modesetfrombusy_subtest(&t);
3448 
3449 		if (t.feature & FEATURE_FBC) {
3450 			igt_subtest_f("%s-badstride", feature_str(t.feature))
3451 				badstride_subtest(&t);
3452 
3453 			igt_subtest_f("%s-stridechange", feature_str(t.feature))
3454 				stridechange_subtest(&t);
3455 
3456 			igt_subtest_f("%s-tilingchange", feature_str(t.feature))
3457 				tilingchange_subtest(&t);
3458 		}
3459 
3460 		if ((t.feature & FEATURE_PSR) || (t.feature & FEATURE_DRRS))
3461 			igt_subtest_f("%s-slowdraw", feature_str(t.feature))
3462 				slow_draw_subtest(&t);
3463 
3464 		igt_subtest_f("%s-suspend", feature_str(t.feature))
3465 			suspend_subtest(&t);
3466 	TEST_MODE_ITER_END
3467 
3468 	t.pipes = PIPE_SINGLE;
3469 	t.screen = SCREEN_PRIM;
3470 	t.plane = PLANE_PRI;
3471 	t.fbs = FBS_INDIVIDUAL;
3472 	t.feature = FEATURE_DEFAULT;
3473 	t.format = FORMAT_DEFAULT;
3474 	t.flip = FLIP_PAGEFLIP;
3475 	igt_subtest("basic") {
3476 		igt_require_gem(drm.fd);
3477 		basic_subtest(&t);
3478 	}
3479 
3480 	igt_fixture
3481 		teardown_environment();
3482 }
3483