blob: 00a65c171f426c216b3b2866ac6417ce2686bece [file] [log] [blame]
Sonika Jindale3611392014-06-18 14:27:27 +05301/*
Damien Lespiau9cf7e8d2014-07-08 12:08:20 +01002 * Copyright © 2013,2014 Intel Corporation
Sonika Jindale3611392014-06-18 14:27:27 +05303 *
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
Thomas Wood804e11f2015-08-17 17:57:43 +010025#include "igt.h"
Damien Lespiau92b29b12014-07-08 12:49:03 +010026#include <math.h>
Sonika Jindale3611392014-06-18 14:27:27 +053027
Sonika Jindale3611392014-06-18 14:27:27 +053028
Sonika Jindale3611392014-06-18 14:27:27 +053029typedef struct {
30 int gfx_fd;
31 igt_display_t display;
Sonika Jindale3611392014-06-18 14:27:27 +053032 struct igt_fb fb;
Tvrtko Ursulind9011062015-04-22 16:46:43 +010033 struct igt_fb fb_modeset;
Damien Lespiau19743a12014-07-08 12:59:03 +010034 igt_crc_t ref_crc;
Sonika Jindale3611392014-06-18 14:27:27 +053035 igt_pipe_crc_t *pipe_crc;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +053036 igt_rotation_t rotation;
37 int pos_x;
38 int pos_y;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010039 unsigned int w, h;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +010040 uint32_t override_fmt;
41 uint64_t override_tiling;
Sonika Jindale3611392014-06-18 14:27:27 +053042} data_t;
43
Damien Lespiau92b29b12014-07-08 12:49:03 +010044static void
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010045paint_squares(data_t *data, drmModeModeInfo *mode, igt_rotation_t rotation,
46 igt_plane_t *plane)
Damien Lespiau92b29b12014-07-08 12:49:03 +010047{
48 cairo_t *cr;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010049 unsigned int w = data->w;
50 unsigned int h = data->h;
Damien Lespiau92b29b12014-07-08 12:49:03 +010051
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010052 cr = igt_get_cairo_ctx(data->gfx_fd, &data->fb);
Damien Lespiau92b29b12014-07-08 12:49:03 +010053
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010054 if (rotation == IGT_ROTATION_180) {
55 cairo_translate(cr, w, h);
56 cairo_rotate(cr, M_PI);
Damien Lespiau92b29b12014-07-08 12:49:03 +010057 }
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010058
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010059 if (rotation == IGT_ROTATION_90) {
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010060 /* Paint 4 squares with width == height in Green, White,
61 Blue, Red Clockwise order to look like 270 degree rotated*/
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010062 igt_paint_color(cr, 0, 0, w / 2, h / 2, 0.0, 1.0, 0.0);
63 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 1.0, 1.0, 1.0);
64 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 1.0, 0.0, 0.0);
65 igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, 0.0, 0.0, 1.0);
Tvrtko Ursulinf2a58962015-05-22 11:00:45 +010066 } else if (rotation == IGT_ROTATION_270) {
67 /* Paint 4 squares with width == height in Blue, Red,
68 Green, White Clockwise order to look like 90 degree rotated*/
69 igt_paint_color(cr, 0, 0, w / 2, h / 2, 0.0, 0.0, 1.0);
70 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 1.0, 0.0, 0.0);
71 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 1.0, 1.0, 1.0);
72 igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, 0.0, 1.0, 0.0);
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010073 } else {
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010074 /* Paint with 4 squares of Red, Green, White, Blue Clockwise */
75 igt_paint_color(cr, 0, 0, w / 2, h / 2, 1.0, 0.0, 0.0);
76 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 0.0, 1.0, 0.0);
77 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 0.0, 0.0, 1.0);
78 igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, 1.0, 1.0, 1.0);
79 }
80
Damien Lespiau92b29b12014-07-08 12:49:03 +010081 cairo_destroy(cr);
82}
83
Tvrtko Ursulin637f0452015-04-27 12:29:11 +010084static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
85{
86 igt_display_t *display = &data->display;
87 enum igt_commit_style commit = COMMIT_LEGACY;
88 igt_plane_t *primary;
89
90 /*
91 * With igt_display_commit2 and COMMIT_UNIVERSAL, we call just the
92 * setplane without a modeset. So, to be able to call
93 * igt_display_commit and ultimately setcrtc to do the first modeset,
94 * we create an fb covering the crtc and call commit
95 */
96
97 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
98 igt_plane_set_fb(primary, &data->fb_modeset);
99 igt_display_commit(display);
100
101 igt_plane_set_fb(plane, &data->fb);
102
103 if (!plane->is_cursor)
104 igt_plane_set_position(plane, data->pos_x, data->pos_y);
105
106 if (plane->is_primary || plane->is_cursor) {
107 igt_require(data->display.has_universal_planes);
108 commit = COMMIT_UNIVERSAL;
109 }
110
111 igt_display_commit2(display, commit);
112}
113
Daniel Vetter57259d72014-11-24 16:08:32 +0100114static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
Damien Lespiau05f90b02014-07-08 18:51:25 +0100115 igt_plane_t *plane)
Sonika Jindale3611392014-06-18 14:27:27 +0530116{
117 drmModeModeInfo *mode;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100118 int fb_id, fb_modeset_id;
119 unsigned int w, h;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100120 uint64_t tiling = data->override_tiling ?
121 data->override_tiling : LOCAL_DRM_FORMAT_MOD_NONE;
122 uint32_t pixel_format = data->override_fmt ?
123 data->override_fmt : DRM_FORMAT_XRGB8888;
Sonika Jindale3611392014-06-18 14:27:27 +0530124
Damien Lespiau8facccf2014-07-08 18:28:53 +0100125 igt_output_set_pipe(output, pipe);
Sonika Jindale3611392014-06-18 14:27:27 +0530126
127 /* create the pipe_crc object for this pipe */
Damien Lespiau2eaa50f2014-07-08 18:56:15 +0100128 igt_pipe_crc_free(data->pipe_crc);
Damien Lespiau8facccf2014-07-08 18:28:53 +0100129 data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
Sonika Jindale3611392014-06-18 14:27:27 +0530130
Damien Lespiau19743a12014-07-08 12:59:03 +0100131 mode = igt_output_get_mode(output);
Sonika Jindale3611392014-06-18 14:27:27 +0530132
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530133 w = mode->hdisplay;
134 h = mode->vdisplay;
135
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100136 fb_modeset_id = igt_create_fb(data->gfx_fd,
137 w, h,
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100138 pixel_format,
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100139 tiling,
140 &data->fb_modeset);
141 igt_assert(fb_modeset_id);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530142
143 /*
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530144 * For 90/270, we will use create smaller fb so that the rotated
145 * frame can fit in
146 */
147 if (data->rotation == IGT_ROTATION_90 ||
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100148 data->rotation == IGT_ROTATION_270) {
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100149 tiling = data->override_tiling ?
150 data->override_tiling : LOCAL_I915_FORMAT_MOD_Y_TILED;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530151 w = h = mode->vdisplay;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100152 } else if (plane->is_cursor) {
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100153 pixel_format = data->override_fmt ?
154 data->override_fmt : DRM_FORMAT_ARGB8888;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100155 w = h = 128;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530156 }
157
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100158 data->w = w;
159 data->h = h;
Sonika Jindale3611392014-06-18 14:27:27 +0530160
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100161 fb_id = igt_create_fb(data->gfx_fd,
162 w, h,
163 pixel_format,
164 tiling,
165 &data->fb);
166 igt_assert(fb_id);
Damien Lespiau282f5602014-07-10 17:44:28 +0100167
Sonika Jindal47246982014-10-23 08:48:50 -0700168 /* Step 1: create a reference CRC for a software-rotated fb */
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100169 paint_squares(data, mode, data->rotation, plane);
Tvrtko Ursulin637f0452015-04-27 12:29:11 +0100170 commit_crtc(data, output, plane);
Damien Lespiau19743a12014-07-08 12:59:03 +0100171 igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
Sonika Jindale3611392014-06-18 14:27:27 +0530172
Damien Lespiau282f5602014-07-10 17:44:28 +0100173 /*
174 * Step 2: prepare the plane with an non-rotated fb let the hw
175 * rotate it.
176 */
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100177 paint_squares(data, mode, IGT_ROTATION_0, plane);
178 igt_plane_set_fb(plane, &data->fb);
Sonika Jindale3611392014-06-18 14:27:27 +0530179}
180
Damien Lespiau05f90b02014-07-08 18:51:25 +0100181static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
Sonika Jindale3611392014-06-18 14:27:27 +0530182{
183 igt_display_t *display = &data->display;
Sonika Jindale3611392014-06-18 14:27:27 +0530184
185 igt_pipe_crc_free(data->pipe_crc);
186 data->pipe_crc = NULL;
187
188 igt_remove_fb(data->gfx_fd, &data->fb);
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100189 igt_remove_fb(data->gfx_fd, &data->fb_modeset);
Damien Lespiau1a754392014-07-09 14:00:59 +0100190
191 /* XXX: see the note in prepare_crtc() */
192 if (!plane->is_primary) {
193 igt_plane_t *primary;
194
195 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
196 igt_plane_set_fb(primary, NULL);
197 }
198
Damien Lespiau05f90b02014-07-08 18:51:25 +0100199 igt_plane_set_fb(plane, NULL);
Sonika Jindale3611392014-06-18 14:27:27 +0530200 igt_output_set_pipe(output, PIPE_ANY);
Damien Lespiaueb81a922014-07-08 18:20:51 +0100201
Sonika Jindale3611392014-06-18 14:27:27 +0530202 igt_display_commit(display);
203}
204
Damien Lespiau05f90b02014-07-08 18:51:25 +0100205static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
Sonika Jindale3611392014-06-18 14:27:27 +0530206{
207 igt_display_t *display = &data->display;
208 igt_output_t *output;
Damien Lespiauaef475b2014-07-08 18:43:44 +0100209 enum pipe pipe;
Sonika Jindale3611392014-06-18 14:27:27 +0530210 int valid_tests = 0;
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100211 igt_crc_t crc_output, crc_unrotated;
Damien Lespiauc4564e02014-07-08 19:24:24 +0100212 enum igt_commit_style commit = COMMIT_LEGACY;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100213 int ret;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100214
Sonika Jindal47246982014-10-23 08:48:50 -0700215 if (plane_type == IGT_PLANE_PRIMARY || plane_type == IGT_PLANE_CURSOR) {
Damien Lespiau13e979c2014-07-08 18:13:47 +0100216 igt_require(data->display.has_universal_planes);
Damien Lespiauc4564e02014-07-08 19:24:24 +0100217 commit = COMMIT_UNIVERSAL;
218 }
Sonika Jindale3611392014-06-18 14:27:27 +0530219
220 for_each_connected_output(display, output) {
Damien Lespiauaef475b2014-07-08 18:43:44 +0100221 for_each_pipe(display, pipe) {
Damien Lespiau05f90b02014-07-08 18:51:25 +0100222 igt_plane_t *plane;
223
224 igt_output_set_pipe(output, pipe);
225
226 plane = igt_output_get_plane(output, plane_type);
227 igt_require(igt_plane_supports_rotation(plane));
228
Daniel Vetter57259d72014-11-24 16:08:32 +0100229 prepare_crtc(data, output, pipe, plane);
230
Sonika Jindal44281512014-08-19 12:01:25 +0530231 igt_display_commit2(display, commit);
Sonika Jindale3611392014-06-18 14:27:27 +0530232
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100233 /* collect unrotated CRC */
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100234 igt_pipe_crc_collect_crc(data->pipe_crc, &crc_unrotated);
235
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530236 igt_plane_set_rotation(plane, data->rotation);
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100237 ret = igt_display_try_commit2(display, commit);
238 if (data->override_fmt || data->override_tiling) {
239 igt_assert(ret == -EINVAL);
240 } else {
241 igt_assert(ret == 0);
242 igt_pipe_crc_collect_crc(data->pipe_crc,
243 &crc_output);
244 igt_assert_crc_equal(&data->ref_crc,
245 &crc_output);
246 }
Damien Lespiau39abe772014-07-08 18:36:32 +0100247
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530248 /*
249 * check the rotation state has been reset when the VT
250 * mode is restored
251 */
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100252 kmstest_restore_vt_mode();
253 kmstest_set_vt_graphics_mode();
Tvrtko Ursulin637f0452015-04-27 12:29:11 +0100254
255 commit_crtc(data, output, plane);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530256
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100257 igt_pipe_crc_collect_crc(data->pipe_crc, &crc_output);
Daniel Vettere588f6d2015-02-27 20:37:29 +0100258 igt_assert_crc_equal(&crc_unrotated, &crc_output);
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100259
Sonika Jindale3611392014-06-18 14:27:27 +0530260 valid_tests++;
Damien Lespiau05f90b02014-07-08 18:51:25 +0100261 cleanup_crtc(data, output, plane);
Sonika Jindale3611392014-06-18 14:27:27 +0530262 }
263 }
264 igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
265}
266
267igt_main
268{
269 data_t data = {};
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530270 int gen = 0;
Sonika Jindale3611392014-06-18 14:27:27 +0530271
272 igt_skip_on_simulation();
273
274 igt_fixture {
Imre Deakc256af52014-09-18 18:31:29 +0300275 data.gfx_fd = drm_open_any_master();
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530276 gen = intel_gen(intel_get_drm_devid(data.gfx_fd));
Sonika Jindale3611392014-06-18 14:27:27 +0530277
Daniel Vetter33f08842014-08-12 11:23:09 +0200278 kmstest_set_vt_graphics_mode();
Sonika Jindale3611392014-06-18 14:27:27 +0530279
280 igt_require_pipe_crc();
281
282 igt_display_init(&data.display, data.gfx_fd);
283 }
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530284 igt_subtest_f("primary-rotation-180") {
285 data.rotation = IGT_ROTATION_180;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100286 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530287 }
Sonika Jindale3611392014-06-18 14:27:27 +0530288
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530289 igt_subtest_f("sprite-rotation-180") {
290 data.rotation = IGT_ROTATION_180;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100291 test_plane_rotation(&data, IGT_PLANE_2);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530292 }
Sonika Jindale3611392014-06-18 14:27:27 +0530293
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530294 igt_subtest_f("cursor-rotation-180") {
295 data.rotation = IGT_ROTATION_180;
Sonika Jindal47246982014-10-23 08:48:50 -0700296 test_plane_rotation(&data, IGT_PLANE_CURSOR);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530297 }
298
299 igt_subtest_f("primary-rotation-90") {
300 igt_require(gen >= 9);
301 data.rotation = IGT_ROTATION_90;
302 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
303 }
304
305 igt_subtest_f("primary-rotation-270") {
306 igt_require(gen >= 9);
307 data.rotation = IGT_ROTATION_270;
308 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
309 }
310
311 igt_subtest_f("sprite-rotation-90") {
312 igt_require(gen >= 9);
313 data.rotation = IGT_ROTATION_90;
314 test_plane_rotation(&data, IGT_PLANE_2);
315 }
316
317 igt_subtest_f("sprite-rotation-270") {
318 igt_require(gen >= 9);
319 data.rotation = IGT_ROTATION_270;
320 test_plane_rotation(&data, IGT_PLANE_2);
321 }
322
323 igt_subtest_f("sprite-rotation-90-pos-100-0") {
324 igt_require(gen >= 9);
325 data.rotation = IGT_ROTATION_90;
326 data.pos_x = 100,
327 data.pos_y = 0;
328 test_plane_rotation(&data, IGT_PLANE_2);
329 }
330
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100331 igt_subtest_f("bad-pixel-format") {
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530332 igt_require(gen >= 9);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530333 data.pos_x = 0,
334 data.pos_y = 0;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100335 data.rotation = IGT_ROTATION_90;
336 data.override_fmt = DRM_FORMAT_RGB565;
337 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
338 }
339
340 igt_subtest_f("bad-tiling") {
341 igt_require(gen >= 9);
342 data.override_fmt = 0;
343 data.rotation = IGT_ROTATION_90;
344 data.override_tiling = LOCAL_DRM_FORMAT_MOD_NONE;
345 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530346 }
Sonika Jindal47246982014-10-23 08:48:50 -0700347
Sonika Jindale3611392014-06-18 14:27:27 +0530348 igt_fixture {
349 igt_display_fini(&data.display);
350 }
351}