blob: 3fd77c42b80324d31aef6a69e4d2105105bb3398 [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
Damien Lespiau92b29b12014-07-08 12:49:03 +010025#include <math.h>
Sonika Jindale3611392014-06-18 14:27:27 +053026
27#include "drmtest.h"
28#include "igt_debugfs.h"
29#include "igt_kms.h"
30#include "igt_core.h"
Sonika Jindale1ce5ea2015-04-22 16:44:05 +053031#include "intel_chipset.h"
Sonika Jindale3611392014-06-18 14:27:27 +053032
Sonika Jindale3611392014-06-18 14:27:27 +053033typedef struct {
34 int gfx_fd;
35 igt_display_t display;
Sonika Jindale3611392014-06-18 14:27:27 +053036 struct igt_fb fb;
Tvrtko Ursulind9011062015-04-22 16:46:43 +010037 struct igt_fb fb_modeset;
Damien Lespiau19743a12014-07-08 12:59:03 +010038 igt_crc_t ref_crc;
Sonika Jindale3611392014-06-18 14:27:27 +053039 igt_pipe_crc_t *pipe_crc;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +053040 igt_rotation_t rotation;
41 int pos_x;
42 int pos_y;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010043 unsigned int w, h;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +010044 uint32_t override_fmt;
45 uint64_t override_tiling;
Sonika Jindale3611392014-06-18 14:27:27 +053046} data_t;
47
Damien Lespiau92b29b12014-07-08 12:49:03 +010048static void
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010049paint_squares(data_t *data, drmModeModeInfo *mode, igt_rotation_t rotation,
50 igt_plane_t *plane)
Damien Lespiau92b29b12014-07-08 12:49:03 +010051{
52 cairo_t *cr;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010053 unsigned int w = data->w;
54 unsigned int h = data->h;
Damien Lespiau92b29b12014-07-08 12:49:03 +010055
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010056 cr = igt_get_cairo_ctx(data->gfx_fd, &data->fb);
Damien Lespiau92b29b12014-07-08 12:49:03 +010057
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010058 if (rotation == IGT_ROTATION_180) {
59 cairo_translate(cr, w, h);
60 cairo_rotate(cr, M_PI);
Damien Lespiau92b29b12014-07-08 12:49:03 +010061 }
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010062
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010063 if (rotation == IGT_ROTATION_90) {
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010064 /* Paint 4 squares with width == height in Green, White,
65 Blue, Red Clockwise order to look like 270 degree rotated*/
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010066 igt_paint_color(cr, 0, 0, w / 2, h / 2, 0.0, 1.0, 0.0);
67 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 1.0, 1.0, 1.0);
68 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 1.0, 0.0, 0.0);
69 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 +010070 } else if (rotation == IGT_ROTATION_270) {
71 /* Paint 4 squares with width == height in Blue, Red,
72 Green, White Clockwise order to look like 90 degree rotated*/
73 igt_paint_color(cr, 0, 0, w / 2, h / 2, 0.0, 0.0, 1.0);
74 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 1.0, 0.0, 0.0);
75 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 1.0, 1.0, 1.0);
76 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 +010077 } else {
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +010078 /* Paint with 4 squares of Red, Green, White, Blue Clockwise */
79 igt_paint_color(cr, 0, 0, w / 2, h / 2, 1.0, 0.0, 0.0);
80 igt_paint_color(cr, w / 2, 0, w / 2, h / 2, 0.0, 1.0, 0.0);
81 igt_paint_color(cr, 0, h / 2, w / 2, h / 2, 0.0, 0.0, 1.0);
82 igt_paint_color(cr, w / 2, h / 2, w / 2, h / 2, 1.0, 1.0, 1.0);
83 }
84
Damien Lespiau92b29b12014-07-08 12:49:03 +010085 cairo_destroy(cr);
86}
87
Tvrtko Ursulin637f0452015-04-27 12:29:11 +010088static void commit_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
89{
90 igt_display_t *display = &data->display;
91 enum igt_commit_style commit = COMMIT_LEGACY;
92 igt_plane_t *primary;
93
94 /*
95 * With igt_display_commit2 and COMMIT_UNIVERSAL, we call just the
96 * setplane without a modeset. So, to be able to call
97 * igt_display_commit and ultimately setcrtc to do the first modeset,
98 * we create an fb covering the crtc and call commit
99 */
100
101 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
102 igt_plane_set_fb(primary, &data->fb_modeset);
103 igt_display_commit(display);
104
105 igt_plane_set_fb(plane, &data->fb);
106
107 if (!plane->is_cursor)
108 igt_plane_set_position(plane, data->pos_x, data->pos_y);
109
110 if (plane->is_primary || plane->is_cursor) {
111 igt_require(data->display.has_universal_planes);
112 commit = COMMIT_UNIVERSAL;
113 }
114
115 igt_display_commit2(display, commit);
116}
117
Daniel Vetter57259d72014-11-24 16:08:32 +0100118static void prepare_crtc(data_t *data, igt_output_t *output, enum pipe pipe,
Damien Lespiau05f90b02014-07-08 18:51:25 +0100119 igt_plane_t *plane)
Sonika Jindale3611392014-06-18 14:27:27 +0530120{
121 drmModeModeInfo *mode;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100122 int fb_id, fb_modeset_id;
123 unsigned int w, h;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100124 uint64_t tiling = data->override_tiling ?
125 data->override_tiling : LOCAL_DRM_FORMAT_MOD_NONE;
126 uint32_t pixel_format = data->override_fmt ?
127 data->override_fmt : DRM_FORMAT_XRGB8888;
Sonika Jindale3611392014-06-18 14:27:27 +0530128
Damien Lespiau8facccf2014-07-08 18:28:53 +0100129 igt_output_set_pipe(output, pipe);
Sonika Jindale3611392014-06-18 14:27:27 +0530130
131 /* create the pipe_crc object for this pipe */
Damien Lespiau2eaa50f2014-07-08 18:56:15 +0100132 igt_pipe_crc_free(data->pipe_crc);
Damien Lespiau8facccf2014-07-08 18:28:53 +0100133 data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
Sonika Jindale3611392014-06-18 14:27:27 +0530134
Damien Lespiau19743a12014-07-08 12:59:03 +0100135 mode = igt_output_get_mode(output);
Sonika Jindale3611392014-06-18 14:27:27 +0530136
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530137 w = mode->hdisplay;
138 h = mode->vdisplay;
139
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100140 fb_modeset_id = igt_create_fb(data->gfx_fd,
141 w, h,
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100142 pixel_format,
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100143 tiling,
144 &data->fb_modeset);
145 igt_assert(fb_modeset_id);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530146
147 /*
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530148 * For 90/270, we will use create smaller fb so that the rotated
149 * frame can fit in
150 */
151 if (data->rotation == IGT_ROTATION_90 ||
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100152 data->rotation == IGT_ROTATION_270) {
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100153 tiling = data->override_tiling ?
154 data->override_tiling : LOCAL_I915_FORMAT_MOD_Y_TILED;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530155 w = h = mode->vdisplay;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100156 } else if (plane->is_cursor) {
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100157 pixel_format = data->override_fmt ?
158 data->override_fmt : DRM_FORMAT_ARGB8888;
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100159 w = h = 128;
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530160 }
161
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100162 data->w = w;
163 data->h = h;
Sonika Jindale3611392014-06-18 14:27:27 +0530164
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100165 fb_id = igt_create_fb(data->gfx_fd,
166 w, h,
167 pixel_format,
168 tiling,
169 &data->fb);
170 igt_assert(fb_id);
Damien Lespiau282f5602014-07-10 17:44:28 +0100171
Sonika Jindal47246982014-10-23 08:48:50 -0700172 /* Step 1: create a reference CRC for a software-rotated fb */
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100173 paint_squares(data, mode, data->rotation, plane);
Tvrtko Ursulin637f0452015-04-27 12:29:11 +0100174 commit_crtc(data, output, plane);
Damien Lespiau19743a12014-07-08 12:59:03 +0100175 igt_pipe_crc_collect_crc(data->pipe_crc, &data->ref_crc);
Sonika Jindale3611392014-06-18 14:27:27 +0530176
Damien Lespiau282f5602014-07-10 17:44:28 +0100177 /*
178 * Step 2: prepare the plane with an non-rotated fb let the hw
179 * rotate it.
180 */
Tvrtko Ursulinb769a7c2015-04-22 16:46:46 +0100181 paint_squares(data, mode, IGT_ROTATION_0, plane);
182 igt_plane_set_fb(plane, &data->fb);
Sonika Jindale3611392014-06-18 14:27:27 +0530183}
184
Damien Lespiau05f90b02014-07-08 18:51:25 +0100185static void cleanup_crtc(data_t *data, igt_output_t *output, igt_plane_t *plane)
Sonika Jindale3611392014-06-18 14:27:27 +0530186{
187 igt_display_t *display = &data->display;
Sonika Jindale3611392014-06-18 14:27:27 +0530188
189 igt_pipe_crc_free(data->pipe_crc);
190 data->pipe_crc = NULL;
191
192 igt_remove_fb(data->gfx_fd, &data->fb);
Tvrtko Ursulind9011062015-04-22 16:46:43 +0100193 igt_remove_fb(data->gfx_fd, &data->fb_modeset);
Damien Lespiau1a754392014-07-09 14:00:59 +0100194
195 /* XXX: see the note in prepare_crtc() */
196 if (!plane->is_primary) {
197 igt_plane_t *primary;
198
199 primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
200 igt_plane_set_fb(primary, NULL);
201 }
202
Damien Lespiau05f90b02014-07-08 18:51:25 +0100203 igt_plane_set_fb(plane, NULL);
Sonika Jindale3611392014-06-18 14:27:27 +0530204 igt_output_set_pipe(output, PIPE_ANY);
Damien Lespiaueb81a922014-07-08 18:20:51 +0100205
Sonika Jindale3611392014-06-18 14:27:27 +0530206 igt_display_commit(display);
207}
208
Damien Lespiau05f90b02014-07-08 18:51:25 +0100209static void test_plane_rotation(data_t *data, enum igt_plane plane_type)
Sonika Jindale3611392014-06-18 14:27:27 +0530210{
211 igt_display_t *display = &data->display;
212 igt_output_t *output;
Damien Lespiauaef475b2014-07-08 18:43:44 +0100213 enum pipe pipe;
Sonika Jindale3611392014-06-18 14:27:27 +0530214 int valid_tests = 0;
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100215 igt_crc_t crc_output, crc_unrotated;
Damien Lespiauc4564e02014-07-08 19:24:24 +0100216 enum igt_commit_style commit = COMMIT_LEGACY;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100217 int ret;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100218
Sonika Jindal47246982014-10-23 08:48:50 -0700219 if (plane_type == IGT_PLANE_PRIMARY || plane_type == IGT_PLANE_CURSOR) {
Damien Lespiau13e979c2014-07-08 18:13:47 +0100220 igt_require(data->display.has_universal_planes);
Damien Lespiauc4564e02014-07-08 19:24:24 +0100221 commit = COMMIT_UNIVERSAL;
222 }
Sonika Jindale3611392014-06-18 14:27:27 +0530223
224 for_each_connected_output(display, output) {
Damien Lespiauaef475b2014-07-08 18:43:44 +0100225 for_each_pipe(display, pipe) {
Damien Lespiau05f90b02014-07-08 18:51:25 +0100226 igt_plane_t *plane;
227
228 igt_output_set_pipe(output, pipe);
229
230 plane = igt_output_get_plane(output, plane_type);
231 igt_require(igt_plane_supports_rotation(plane));
232
Daniel Vetter57259d72014-11-24 16:08:32 +0100233 prepare_crtc(data, output, pipe, plane);
234
Sonika Jindal44281512014-08-19 12:01:25 +0530235 igt_display_commit2(display, commit);
Sonika Jindale3611392014-06-18 14:27:27 +0530236
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100237 /* collect unrotated CRC */
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100238 igt_pipe_crc_collect_crc(data->pipe_crc, &crc_unrotated);
239
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530240 igt_plane_set_rotation(plane, data->rotation);
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100241 ret = igt_display_try_commit2(display, commit);
242 if (data->override_fmt || data->override_tiling) {
243 igt_assert(ret == -EINVAL);
244 } else {
245 igt_assert(ret == 0);
246 igt_pipe_crc_collect_crc(data->pipe_crc,
247 &crc_output);
248 igt_assert_crc_equal(&data->ref_crc,
249 &crc_output);
250 }
Damien Lespiau39abe772014-07-08 18:36:32 +0100251
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530252 /*
253 * check the rotation state has been reset when the VT
254 * mode is restored
255 */
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100256 kmstest_restore_vt_mode();
257 kmstest_set_vt_graphics_mode();
Tvrtko Ursulin637f0452015-04-27 12:29:11 +0100258
259 commit_crtc(data, output, plane);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530260
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100261 igt_pipe_crc_collect_crc(data->pipe_crc, &crc_output);
Daniel Vettere588f6d2015-02-27 20:37:29 +0100262 igt_assert_crc_equal(&crc_unrotated, &crc_output);
Thomas Wood1bec6cb2014-08-14 14:06:37 +0100263
Sonika Jindale3611392014-06-18 14:27:27 +0530264 valid_tests++;
Damien Lespiau05f90b02014-07-08 18:51:25 +0100265 cleanup_crtc(data, output, plane);
Sonika Jindale3611392014-06-18 14:27:27 +0530266 }
267 }
268 igt_require_f(valid_tests, "no valid crtc/connector combinations found\n");
269}
270
271igt_main
272{
273 data_t data = {};
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530274 int gen = 0;
Sonika Jindale3611392014-06-18 14:27:27 +0530275
276 igt_skip_on_simulation();
277
278 igt_fixture {
Imre Deakc256af52014-09-18 18:31:29 +0300279 data.gfx_fd = drm_open_any_master();
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530280 gen = intel_gen(intel_get_drm_devid(data.gfx_fd));
Sonika Jindale3611392014-06-18 14:27:27 +0530281
Daniel Vetter33f08842014-08-12 11:23:09 +0200282 kmstest_set_vt_graphics_mode();
Sonika Jindale3611392014-06-18 14:27:27 +0530283
284 igt_require_pipe_crc();
285
286 igt_display_init(&data.display, data.gfx_fd);
287 }
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530288 igt_subtest_f("primary-rotation-180") {
289 data.rotation = IGT_ROTATION_180;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100290 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530291 }
Sonika Jindale3611392014-06-18 14:27:27 +0530292
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530293 igt_subtest_f("sprite-rotation-180") {
294 data.rotation = IGT_ROTATION_180;
Damien Lespiau13e979c2014-07-08 18:13:47 +0100295 test_plane_rotation(&data, IGT_PLANE_2);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530296 }
Sonika Jindale3611392014-06-18 14:27:27 +0530297
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530298 igt_subtest_f("cursor-rotation-180") {
299 data.rotation = IGT_ROTATION_180;
Sonika Jindal47246982014-10-23 08:48:50 -0700300 test_plane_rotation(&data, IGT_PLANE_CURSOR);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530301 }
302
303 igt_subtest_f("primary-rotation-90") {
304 igt_require(gen >= 9);
305 data.rotation = IGT_ROTATION_90;
306 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
307 }
308
309 igt_subtest_f("primary-rotation-270") {
310 igt_require(gen >= 9);
311 data.rotation = IGT_ROTATION_270;
312 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
313 }
314
315 igt_subtest_f("sprite-rotation-90") {
316 igt_require(gen >= 9);
317 data.rotation = IGT_ROTATION_90;
318 test_plane_rotation(&data, IGT_PLANE_2);
319 }
320
321 igt_subtest_f("sprite-rotation-270") {
322 igt_require(gen >= 9);
323 data.rotation = IGT_ROTATION_270;
324 test_plane_rotation(&data, IGT_PLANE_2);
325 }
326
327 igt_subtest_f("sprite-rotation-90-pos-100-0") {
328 igt_require(gen >= 9);
329 data.rotation = IGT_ROTATION_90;
330 data.pos_x = 100,
331 data.pos_y = 0;
332 test_plane_rotation(&data, IGT_PLANE_2);
333 }
334
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100335 igt_subtest_f("bad-pixel-format") {
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530336 igt_require(gen >= 9);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530337 data.pos_x = 0,
338 data.pos_y = 0;
Tvrtko Ursulindbf64682015-04-22 16:46:48 +0100339 data.rotation = IGT_ROTATION_90;
340 data.override_fmt = DRM_FORMAT_RGB565;
341 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
342 }
343
344 igt_subtest_f("bad-tiling") {
345 igt_require(gen >= 9);
346 data.override_fmt = 0;
347 data.rotation = IGT_ROTATION_90;
348 data.override_tiling = LOCAL_DRM_FORMAT_MOD_NONE;
349 test_plane_rotation(&data, IGT_PLANE_PRIMARY);
Sonika Jindale1ce5ea2015-04-22 16:44:05 +0530350 }
Sonika Jindal47246982014-10-23 08:48:50 -0700351
Sonika Jindale3611392014-06-18 14:27:27 +0530352 igt_fixture {
353 igt_display_fini(&data.display);
354 }
355}