xref: /aosp_15_r20/external/igt-gpu-tools/tests/kms_plane_lowres.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2016 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  */
24 
25 #include "igt.h"
26 #include "drmtest.h"
27 #include <errno.h>
28 #include <stdbool.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <time.h>
32 
33 IGT_TEST_DESCRIPTION("Test atomic mode setting with a plane by switching between high and low resolutions");
34 
35 #define MAX_CRCS          1
36 #define SIZE            256
37 #define LOOP_FOREVER     -1
38 
39 typedef struct {
40 	int drm_fd;
41 	igt_display_t display;
42 	struct igt_fb fb_primary;
43 	struct igt_fb fb_plane;
44 } data_t;
45 
46 static drmModeModeInfo
get_lowres_mode(int drmfd,igt_output_t * output,drmModeModeInfo * mode_default)47 get_lowres_mode(int drmfd, igt_output_t *output, drmModeModeInfo *mode_default)
48 {
49 	drmModeModeInfo mode;
50 	bool found = false;
51 	int limit = mode_default->vdisplay - SIZE;
52 	int j;
53 
54 	for (j = 0; j < output->config.connector->count_modes; j++) {
55 		mode = output->config.connector->modes[j];
56 		if (mode.vdisplay < limit) {
57 			found = true;
58 			break;
59 		}
60 	}
61 
62 	if (!found)
63 		return *igt_std_1024_mode_get();
64 
65 	return mode;
66 }
67 
68 static void
check_mode(drmModeModeInfo * mode1,drmModeModeInfo * mode2)69 check_mode(drmModeModeInfo *mode1, drmModeModeInfo *mode2)
70 {
71 	igt_assert_eq(mode1->hdisplay, mode2->hdisplay);
72 	igt_assert_eq(mode1->vdisplay, mode2->vdisplay);
73 	igt_assert_eq(mode1->vrefresh, mode2->vrefresh);
74 }
75 
76 /*
77  * Return false if test on this plane should be skipped
78  */
79 static bool
setup_plane(data_t * data,igt_plane_t * plane,drmModeModeInfo * mode,uint64_t modifier)80 setup_plane(data_t *data, igt_plane_t *plane, drmModeModeInfo *mode,
81 	    uint64_t modifier)
82 {
83 	uint64_t plane_modifier;
84 	uint32_t plane_format;
85 	int size, x, y;
86 
87 	if (plane->type == DRM_PLANE_TYPE_PRIMARY)
88 		return false;
89 
90 	if (plane->type == DRM_PLANE_TYPE_CURSOR)
91 		size = 64;
92 	else
93 		size = SIZE;
94 
95 	x = 0;
96 	y = mode->vdisplay - size;
97 
98 	if (plane->type == DRM_PLANE_TYPE_CURSOR) {
99 		plane_format = DRM_FORMAT_ARGB8888;
100 		plane_modifier = LOCAL_DRM_FORMAT_MOD_NONE;
101 	} else {
102 		plane_format = DRM_FORMAT_XRGB8888;
103 		plane_modifier = modifier;
104 	}
105 
106 	if (!igt_plane_has_format_mod(plane, plane_format, plane_modifier))
107 		return false;
108 
109 	igt_create_color_fb(data->drm_fd, size, size, plane_format,
110 			    plane_modifier, 1.0, 1.0, 0.0, &data->fb_plane);
111 	igt_plane_set_position(plane, x, y);
112 	igt_plane_set_fb(plane, &data->fb_plane);
113 
114 	return true;
115 }
116 
117 static igt_plane_t *
primary_plane_get(igt_display_t * display,enum pipe pipe)118 primary_plane_get(igt_display_t *display, enum pipe pipe)
119 {
120 	unsigned plane_primary_id = display->pipes[pipe].plane_primary;
121 	return &display->pipes[pipe].planes[plane_primary_id];
122 }
123 
124 static unsigned
test_planes_on_pipe_with_output(data_t * data,enum pipe pipe,igt_output_t * output,uint64_t modifier)125 test_planes_on_pipe_with_output(data_t *data, enum pipe pipe,
126 				igt_output_t *output, uint64_t modifier)
127 {
128 	drmModeModeInfo *mode, mode_lowres;
129 	igt_pipe_crc_t *pipe_crc;
130 	unsigned tested = 0;
131 	igt_plane_t *plane;
132 
133 	igt_info("Testing connector %s using pipe %s\n",
134 		 igt_output_name(output), kmstest_pipe_name(pipe));
135 
136 	igt_output_set_pipe(output, pipe);
137 	mode = igt_output_get_mode(output);
138 	mode_lowres = get_lowres_mode(data->drm_fd, output, mode);
139 
140 	igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
141 			    DRM_FORMAT_XRGB8888, modifier, 0.0, 0.0, 1.0,
142 			    &data->fb_primary);
143 	igt_plane_set_fb(primary_plane_get(&data->display, pipe),
144 			 &data->fb_primary);
145 
146 	pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe,
147 				    INTEL_PIPE_CRC_SOURCE_AUTO);
148 
149 	/* yellow sprite plane in lower left corner */
150 	for_each_plane_on_pipe(&data->display, pipe, plane) {
151 		igt_crc_t crc_hires1, crc_hires2;
152 		int r;
153 
154 		if (!setup_plane(data, plane, mode, modifier))
155 			continue;
156 
157 		r = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
158 		if (r) {
159 			igt_debug("Commit failed %i", r);
160 			continue;
161 		}
162 
163 		igt_pipe_crc_start(pipe_crc);
164 		igt_pipe_crc_get_single(pipe_crc, &crc_hires1);
165 
166 		igt_assert_plane_visible(data->drm_fd, pipe, plane->index,
167 					 true);
168 
169 		/* switch to lower resolution */
170 		igt_output_override_mode(output, &mode_lowres);
171 		igt_output_set_pipe(output, pipe);
172 		check_mode(&mode_lowres, igt_output_get_mode(output));
173 
174 		igt_display_commit2(&data->display, COMMIT_ATOMIC);
175 
176 		igt_assert_plane_visible(data->drm_fd, pipe, plane->index,
177 					 false);
178 
179 		/* switch back to higher resolution */
180 		igt_output_override_mode(output, NULL);
181 		igt_output_set_pipe(output, pipe);
182 		check_mode(mode, igt_output_get_mode(output));
183 
184 		igt_display_commit2(&data->display, COMMIT_ATOMIC);
185 
186 		igt_pipe_crc_get_current(data->drm_fd, pipe_crc, &crc_hires2);
187 
188 		igt_assert_plane_visible(data->drm_fd, pipe, plane->index,
189 					 true);
190 
191 		igt_assert_crc_equal(&crc_hires1, &crc_hires2);
192 
193 		igt_pipe_crc_stop(pipe_crc);
194 
195 		igt_plane_set_fb(plane, NULL);
196 		igt_remove_fb(data->drm_fd, &data->fb_plane);
197 		tested++;
198 	}
199 
200 	igt_pipe_crc_free(pipe_crc);
201 
202 	igt_plane_set_fb(primary_plane_get(&data->display, pipe), NULL);
203 	igt_remove_fb(data->drm_fd, &data->fb_primary);
204 	igt_output_set_pipe(output, PIPE_NONE);
205 
206 	return tested;
207 }
208 
209 static void
test_planes_on_pipe(data_t * data,enum pipe pipe,uint64_t modifier)210 test_planes_on_pipe(data_t *data, enum pipe pipe, uint64_t modifier)
211 {
212 	igt_output_t *output;
213 	unsigned tested = 0;
214 
215 	igt_skip_on(pipe >= data->display.n_pipes);
216 	igt_display_require_output_on_pipe(&data->display, pipe);
217 	igt_skip_on(!igt_display_has_format_mod(&data->display,
218 						DRM_FORMAT_XRGB8888, modifier));
219 
220 	for_each_valid_output_on_pipe(&data->display, pipe, output)
221 		tested += test_planes_on_pipe_with_output(data, pipe, output,
222 							  modifier);
223 
224 	igt_assert(tested > 0);
225 }
226 
227 igt_main
228 {
229 	data_t data = {};
230 	enum pipe pipe;
231 
232 	igt_skip_on_simulation();
233 
234 	igt_fixture {
235 		data.drm_fd = drm_open_driver_master(DRIVER_ANY);
236 
237 		kmstest_set_vt_graphics_mode();
238 
239 		igt_require_pipe_crc(data.drm_fd);
240 		igt_display_require(&data.display, data.drm_fd);
241 		igt_require(data.display.is_atomic);
242 	}
243 
for_each_pipe_static(pipe)244 	for_each_pipe_static(pipe) {
245 		igt_subtest_f("pipe-%s-tiling-none", kmstest_pipe_name(pipe))
246 			test_planes_on_pipe(&data, pipe,
247 					    LOCAL_DRM_FORMAT_MOD_NONE);
248 
249 		igt_subtest_f("pipe-%s-tiling-x", kmstest_pipe_name(pipe))
250 			test_planes_on_pipe(&data, pipe,
251 					    LOCAL_I915_FORMAT_MOD_X_TILED);
252 
253 		igt_subtest_f("pipe-%s-tiling-y", kmstest_pipe_name(pipe))
254 			test_planes_on_pipe(&data, pipe,
255 					    LOCAL_I915_FORMAT_MOD_Y_TILED);
256 
257 		igt_subtest_f("pipe-%s-tiling-yf", kmstest_pipe_name(pipe))
258 			test_planes_on_pipe(&data, pipe,
259 					    LOCAL_I915_FORMAT_MOD_Yf_TILED);
260 	}
261 
262 	igt_fixture {
263 		igt_display_fini(&data.display);
264 	}
265 }
266