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