xref: /aosp_15_r20/external/igt-gpu-tools/tests/kms_flip_tiling.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2014 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:
24  *   Ander Conselvan de Oliveira <[email protected]>
25  */
26 
27 #include "igt.h"
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include <string.h>
32 
33 IGT_TEST_DESCRIPTION("Test page flips and tiling scenarios");
34 
35 typedef struct {
36 	int drm_fd;
37 	igt_display_t display;
38 	int gen;
39 } data_t;
40 
41 static igt_pipe_crc_t *_pipe_crc;
42 
pipe_crc_new(data_t * data,int pipe)43 static igt_pipe_crc_t *pipe_crc_new(data_t *data, int pipe)
44 {
45 	if (_pipe_crc) {
46 		igt_pipe_crc_free(_pipe_crc);
47 		_pipe_crc = NULL;
48 	}
49 
50 	_pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
51 	igt_assert(_pipe_crc);
52 
53 	return _pipe_crc;
54 }
55 
pipe_crc_free(void)56 static void pipe_crc_free(void)
57 {
58 	if (_pipe_crc) {
59 		igt_pipe_crc_free(_pipe_crc);
60 		_pipe_crc = NULL;
61 	}
62 }
63 
64 static void
test_flip_tiling(data_t * data,enum pipe pipe,igt_output_t * output,uint64_t tiling[2])65 test_flip_tiling(data_t *data, enum pipe pipe, igt_output_t *output, uint64_t tiling[2])
66 {
67 	drmModeModeInfo *mode;
68 	igt_plane_t *primary;
69 	struct igt_fb fb[2];
70 	igt_pipe_crc_t *pipe_crc;
71 	igt_crc_t reference_crc, crc;
72 	int fb_id, ret, width;
73 
74 	pipe_crc = pipe_crc_new(data, pipe);
75 	igt_output_set_pipe(output, pipe);
76 
77 	mode = igt_output_get_mode(output);
78 
79 	/* Interlaced modes don't support Y/Yf tiling */
80 	if (tiling[0] == LOCAL_I915_FORMAT_MOD_Y_TILED ||
81 	    tiling[0] == LOCAL_I915_FORMAT_MOD_Yf_TILED ||
82 	    tiling[1] == LOCAL_I915_FORMAT_MOD_Y_TILED ||
83 	    tiling[1] == LOCAL_I915_FORMAT_MOD_Yf_TILED)
84 		igt_require(!(mode->flags & DRM_MODE_FLAG_INTERLACE));
85 
86 	primary = igt_output_get_plane(output, 0);
87 
88 	width = mode->hdisplay;
89 
90 	if (tiling[0] != tiling[1] &&
91 	    (tiling[0] != LOCAL_DRM_FORMAT_MOD_NONE ||
92 	     tiling[1] != LOCAL_DRM_FORMAT_MOD_NONE)) {
93 		/*
94 		 * Since a page flip to a buffer with different stride
95 		 * doesn't work, choose width so that the stride of both
96 		 * buffers is the same.
97 		 */
98 		width = 512;
99 		while (width < mode->hdisplay)
100 			width *= 2;
101 	}
102 
103 	fb_id = igt_create_pattern_fb(data->drm_fd, width, mode->vdisplay,
104 				      DRM_FORMAT_XRGB8888, tiling[0],
105 				      &fb[0]);
106 	igt_assert(fb_id);
107 
108 	/* Second fb has different background so CRC does not match. */
109 	fb_id = igt_create_color_pattern_fb(data->drm_fd, width, mode->vdisplay,
110 				      DRM_FORMAT_XRGB8888, tiling[1],
111 				      0.5, 0.5, 0.5, &fb[1]);
112 	igt_assert(fb_id);
113 
114 	/* Set the crtc and generate a reference CRC. */
115 	igt_plane_set_fb(primary, &fb[1]);
116 	igt_display_commit(&data->display);
117 	igt_pipe_crc_collect_crc(pipe_crc, &reference_crc);
118 
119 	/* Commit the first fb. */
120 	igt_plane_set_fb(primary, &fb[0]);
121 	igt_display_commit(&data->display);
122 
123 	/* Flip to the second fb. */
124 	ret = drmModePageFlip(data->drm_fd, output->config.crtc->crtc_id,
125 			      fb[1].fb_id, DRM_MODE_PAGE_FLIP_EVENT, NULL);
126 	/*
127 	 * Page flip should work but some transitions may be temporarily
128 	 * on some kernels.
129 	 */
130 	igt_require(ret == 0);
131 
132 	kmstest_wait_for_pageflip(data->drm_fd);
133 
134 	/* Get a crc and compare with the reference. */
135 	igt_pipe_crc_collect_crc(pipe_crc, &crc);
136 	igt_assert_crc_equal(&reference_crc, &crc);
137 
138 	/* Clean up. */
139 	igt_plane_set_fb(primary, NULL);
140 	pipe_crc_free();
141 	igt_output_set_pipe(output, PIPE_ANY);
142 	igt_display_commit(&data->display);
143 
144 	igt_remove_fb(data->drm_fd, &fb[0]);
145 	igt_remove_fb(data->drm_fd, &fb[1]);
146 }
147 
148 static data_t data;
149 igt_output_t *output;
150 
151 igt_main
152 {
153 	igt_skip_on_simulation();
154 
155 	igt_fixture {
156 		data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
157 		data.gen = intel_gen(intel_get_drm_devid(data.drm_fd));
158 
159 		kmstest_set_vt_graphics_mode();
160 
161 		igt_require_pipe_crc(data.drm_fd);
162 		igt_display_require(&data.display, data.drm_fd);
163 	}
164 
165 	/*
166 	 * Test that a page flip from a tiled buffer to a linear one works
167 	 * correctly. First, it sets the crtc with the linear buffer and
168 	 * generates a reference crc for the pipe. Then, the crtc is set with
169 	 * the tiled one and page flip to the linear one issued. A new crc is
170 	 * generated and compared to the reference one.
171 	 */
172 
173 	igt_subtest_f("flip-changes-tiling") {
174 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED,
175 				       LOCAL_DRM_FORMAT_MOD_NONE };
176 		enum pipe pipe;
177 
178 		for_each_pipe_with_valid_output(&data.display, pipe, output)
179 			test_flip_tiling(&data, pipe, output, tiling);
180 	}
181 
182 	igt_subtest_f("flip-changes-tiling-Y") {
183 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED,
184 				       LOCAL_DRM_FORMAT_MOD_NONE };
185 		enum pipe pipe;
186 
187 		igt_require_fb_modifiers(data.drm_fd);
188 		igt_require(data.gen >= 9);
189 
190 		for_each_pipe_with_valid_output(&data.display, pipe, output)
191 			test_flip_tiling(&data, pipe, output, tiling);
192 	}
193 
194 	igt_subtest_f("flip-changes-tiling-Yf") {
195 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED,
196 				       LOCAL_DRM_FORMAT_MOD_NONE };
197 		enum pipe pipe;
198 
199 		igt_require_fb_modifiers(data.drm_fd);
200 		igt_require(data.gen >= 9);
201 
202 		for_each_pipe_with_valid_output(&data.display, pipe, output)
203 			test_flip_tiling(&data, pipe, output, tiling);
204 	}
205 
206 	/*
207 	 * Test that a page flip from a tiled buffer to another tiled one works
208 	 * correctly. First, it sets the crtc with the tiled buffer and
209 	 * generates a reference crc for the pipe. Then a page flip to second
210 	 * tiled buffer is issued. A new crc is generated and compared to the
211 	 * reference one.
212 	 */
213 
214 	igt_subtest_f("flip-X-tiled") {
215 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_X_TILED,
216 				       LOCAL_I915_FORMAT_MOD_X_TILED };
217 		enum pipe pipe;
218 
219 		for_each_pipe_with_valid_output(&data.display, pipe, output)
220 			test_flip_tiling(&data, pipe, output, tiling);
221 	}
222 
223 	igt_subtest_f("flip-Y-tiled") {
224 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Y_TILED,
225 				       LOCAL_I915_FORMAT_MOD_Y_TILED };
226 		enum pipe pipe;
227 
228 		igt_require_fb_modifiers(data.drm_fd);
229 		igt_require(data.gen >= 9);
230 
231 		for_each_pipe_with_valid_output(&data.display, pipe, output)
232 			test_flip_tiling(&data, pipe, output, tiling);
233 	}
234 
235 	igt_subtest_f("flip-Yf-tiled") {
236 		uint64_t tiling[2] = { LOCAL_I915_FORMAT_MOD_Yf_TILED,
237 				       LOCAL_I915_FORMAT_MOD_Yf_TILED };
238 		enum pipe pipe;
239 
240 		igt_require_fb_modifiers(data.drm_fd);
241 		igt_require(data.gen >= 9);
242 
243 		for_each_pipe_with_valid_output(&data.display, pipe, output)
244 			test_flip_tiling(&data, pipe, output, tiling);
245 	}
246 
247 	/*
248 	 * Test that a page flip from a linear buffer to a tiled one works
249 	 * correctly. First, it sets the crtc with the linear buffer and
250 	 * generates a reference crc for the pipe. Then a page flip to a tiled
251 	 * buffer is issued. A new crc is generated and compared to the
252 	 * reference one.
253 	 */
254 
255 	igt_subtest_f("flip-to-X-tiled") {
256 		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
257 				       LOCAL_I915_FORMAT_MOD_X_TILED };
258 		enum pipe pipe;
259 
260 		for_each_pipe_with_valid_output(&data.display, pipe, output)
261 			test_flip_tiling(&data, pipe, output, tiling);
262 	}
263 
264 	igt_subtest_f("flip-to-Y-tiled") {
265 		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
266 				       LOCAL_I915_FORMAT_MOD_Y_TILED };
267 		enum pipe pipe;
268 
269 		igt_require_fb_modifiers(data.drm_fd);
270 		igt_require(data.gen >= 9);
271 
272 		for_each_pipe_with_valid_output(&data.display, pipe, output)
273 			test_flip_tiling(&data, pipe, output, tiling);
274 	}
275 
276 	igt_subtest_f("flip-to-Yf-tiled") {
277 		uint64_t tiling[2] = { LOCAL_DRM_FORMAT_MOD_NONE,
278 				       LOCAL_I915_FORMAT_MOD_Yf_TILED };
279 		enum pipe pipe;
280 
281 		igt_require_fb_modifiers(data.drm_fd);
282 		igt_require(data.gen >= 9);
283 
284 		for_each_pipe_with_valid_output(&data.display, pipe, output)
285 			test_flip_tiling(&data, pipe, output, tiling);
286 	}
287 
288 	igt_fixture {
289 		igt_display_fini(&data.display);
290 	}
291 }
292