kms_plane: Make the gathering of reference CRCs test agnostic
[platform/upstream/intel-gpu-tools.git] / tests / kms_plane.c
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  *   Damien Lespiau <damien.lespiau@intel.com>
25  */
26
27 #include <errno.h>
28 #include <stdbool.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "drmtest.h"
33 #include "igt_debugfs.h"
34 #include "igt_kms.h"
35
36 typedef struct {
37         float red;
38         float green;
39         float blue;
40 } color_t;
41
42 typedef struct {
43         int drm_fd;
44         igt_display_t display;
45         igt_pipe_crc_t *pipe_crc;
46 } data_t;
47
48 static color_t green = { 0.0f, 1.0f, 0.0f };
49
50 /*
51  * Common code across all tests, acting on data_t
52  */
53 static void test_init(data_t *data, enum pipe pipe)
54 {
55         data->pipe_crc = igt_pipe_crc_new(pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
56 }
57
58 static void test_fini(data_t *data)
59 {
60         igt_pipe_crc_free(data->pipe_crc);
61 }
62
63 static void
64 test_grab_crc(data_t *data, igt_output_t *output, color_t *fb_color,
65               igt_crc_t *crc /* out */)
66 {
67         struct igt_fb fb;
68         drmModeModeInfo *mode;
69         igt_plane_t *primary;
70
71         primary = igt_output_get_plane(output, 0);
72
73         mode = igt_output_get_mode(output);
74         igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
75                             DRM_FORMAT_XRGB8888,
76                             false, /* tiled */
77                             fb_color->red, fb_color->green, fb_color->blue,
78                             &fb);
79         igt_plane_set_fb(primary, &fb);
80
81         igt_display_commit(&data->display);
82
83         igt_pipe_crc_collect_crc(data->pipe_crc, crc);
84
85         igt_plane_set_fb(primary, NULL);
86         igt_display_commit(&data->display);
87
88         igt_remove_fb(data->drm_fd, &fb);
89 }
90
91 /*
92  * Plane position test.
93  *   - We start by grabbing a reference CRC of a full green fb being scanned
94  *     out on the primary plane
95  *   - Then we scannout 2 planes:
96  *      - the primary plane uses a green fb with a black rectangle
97  *      - a plane, on top of the primary plane, with a green fb that is set-up
98  *        to cover the black rectangle of the primary plane fb
99  *     The resulting CRC should be identical to the reference CRC
100  */
101
102 typedef struct {
103         data_t *data;
104         igt_crc_t reference_crc;
105 } test_position_t;
106
107 /*
108  * create a green fb with a black rectangle at (rect_x,rect_y) and of size
109  * (rect_w,rect_h)
110  */
111 static void
112 create_fb_for_mode__position(data_t *data, drmModeModeInfo *mode,
113                              double rect_x, double rect_y,
114                              double rect_w, double rect_h,
115                              struct igt_fb *fb /* out */)
116 {
117         unsigned int fb_id;
118         cairo_t *cr;
119
120         fb_id = igt_create_fb(data->drm_fd,
121                                   mode->hdisplay, mode->vdisplay,
122                                   DRM_FORMAT_XRGB8888,
123                                   false /* tiling */,
124                                   fb);
125         igt_assert(fb_id);
126
127         cr = igt_get_cairo_ctx(data->drm_fd, fb);
128         igt_paint_color(cr, 0, 0, mode->hdisplay, mode->vdisplay,
129                             0.0, 1.0, 0.0);
130         igt_paint_color(cr, rect_x, rect_y, rect_w, rect_h, 0.0, 0.0, 0.0);
131         igt_assert(cairo_status(cr) == 0);
132         cairo_destroy(cr);
133 }
134
135 enum {
136         TEST_POSITION_FULLY_COVERED = 1 << 0,
137 };
138
139 static void
140 test_plane_position_with_output(data_t *data,
141                                 enum pipe pipe,
142                                 enum igt_plane plane,
143                                 igt_output_t *output,
144                                 unsigned int flags)
145 {
146         test_position_t test = { .data = data };
147         igt_plane_t *primary, *sprite;
148         struct igt_fb primary_fb, sprite_fb;
149         drmModeModeInfo *mode;
150         igt_crc_t crc;
151
152         igt_info("Testing connector %s using pipe %c plane %d\n",
153                  igt_output_name(output), pipe_name(pipe), plane);
154
155         test_init(data, pipe);
156
157         test_grab_crc(data, output, &green, &test.reference_crc);
158
159         igt_output_set_pipe(output, pipe);
160
161         mode = igt_output_get_mode(output);
162         primary = igt_output_get_plane(output, 0);
163         sprite = igt_output_get_plane(output, plane);
164
165         create_fb_for_mode__position(data, mode, 100, 100, 64, 64,
166                                      &primary_fb);
167         igt_plane_set_fb(primary, &primary_fb);
168
169         igt_create_color_fb(data->drm_fd,
170                                 64, 64, /* width, height */
171                                 DRM_FORMAT_XRGB8888,
172                                 false, /* tiled */
173                                 0.0, 1.0, 0.0,
174                                 &sprite_fb);
175         igt_plane_set_fb(sprite, &sprite_fb);
176
177         if (flags & TEST_POSITION_FULLY_COVERED)
178                 igt_plane_set_position(sprite, 100, 100);
179         else
180                 igt_plane_set_position(sprite, 132, 132);
181
182         igt_display_commit(&data->display);
183
184         igt_pipe_crc_collect_crc(data->pipe_crc, &crc);
185
186         if (flags & TEST_POSITION_FULLY_COVERED)
187                 igt_assert(igt_crc_equal(&test.reference_crc, &crc));
188         else
189                 igt_assert(!igt_crc_equal(&test.reference_crc, &crc));
190
191         igt_plane_set_fb(primary, NULL);
192         igt_plane_set_fb(sprite, NULL);
193
194         /* reset the constraint on the pipe */
195         igt_output_set_pipe(output, PIPE_ANY);
196
197         test_fini(data);
198 }
199
200 static void
201 test_plane_position(data_t *data, enum pipe pipe, enum igt_plane plane,
202                     unsigned int flags)
203 {
204         igt_output_t *output;
205
206         igt_skip_on(pipe >= data->display.n_pipes);
207         igt_skip_on(plane >= data->display.pipes[pipe].n_planes);
208
209         for_each_connected_output(&data->display, output)
210                 test_plane_position_with_output(data, pipe, plane, output,
211                                                 flags);
212 }
213
214 static void
215 run_tests_for_pipe_plane(data_t *data, enum pipe pipe, enum igt_plane plane)
216 {
217         igt_subtest_f("plane-position-covered-pipe-%c-plane-%d",
218                       pipe_name(pipe), plane)
219                 test_plane_position(data, pipe, plane,
220                                     TEST_POSITION_FULLY_COVERED);
221
222         igt_subtest_f("plane-position-hole-pipe-%c-plane-%d",
223                       pipe_name(pipe), plane)
224                 test_plane_position(data, pipe, plane, 0);
225 }
226
227 static void
228 run_tests_for_pipe(data_t *data, enum pipe pipe)
229 {
230         int plane;
231
232         for (plane = 1; plane < IGT_MAX_PLANES; plane++)
233                 run_tests_for_pipe_plane(data, pipe, plane);
234 }
235
236 static data_t data;
237
238 igt_main
239 {
240
241         igt_skip_on_simulation();
242
243         igt_fixture {
244                 data.drm_fd = drm_open_any();
245
246                 igt_set_vt_graphics_mode();
247
248                 igt_require_pipe_crc();
249                 igt_display_init(&data.display, data.drm_fd);
250         }
251
252         for (int pipe = 0; pipe < 3; pipe++)
253                 run_tests_for_pipe(&data, pipe);
254
255         igt_fixture {
256                 igt_display_fini(&data.display);
257         }
258 }