1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2016 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker *
4*d83cc019SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker *
11*d83cc019SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker * Software.
14*d83cc019SAndroid Build Coastguard Worker *
15*d83cc019SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker *
23*d83cc019SAndroid Build Coastguard Worker */
24*d83cc019SAndroid Build Coastguard Worker
25*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
26*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
27*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
28*d83cc019SAndroid Build Coastguard Worker #include <stdbool.h>
29*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
30*d83cc019SAndroid Build Coastguard Worker #include <string.h>
31*d83cc019SAndroid Build Coastguard Worker #include <time.h>
32*d83cc019SAndroid Build Coastguard Worker
33*d83cc019SAndroid Build Coastguard Worker IGT_TEST_DESCRIPTION("Test atomic mode setting with multiple planes.");
34*d83cc019SAndroid Build Coastguard Worker
35*d83cc019SAndroid Build Coastguard Worker #define SIZE_PLANE 256
36*d83cc019SAndroid Build Coastguard Worker #define SIZE_CURSOR 128
37*d83cc019SAndroid Build Coastguard Worker #define LOOP_FOREVER -1
38*d83cc019SAndroid Build Coastguard Worker
39*d83cc019SAndroid Build Coastguard Worker typedef struct {
40*d83cc019SAndroid Build Coastguard Worker float red;
41*d83cc019SAndroid Build Coastguard Worker float green;
42*d83cc019SAndroid Build Coastguard Worker float blue;
43*d83cc019SAndroid Build Coastguard Worker } color_t;
44*d83cc019SAndroid Build Coastguard Worker
45*d83cc019SAndroid Build Coastguard Worker typedef struct {
46*d83cc019SAndroid Build Coastguard Worker int drm_fd;
47*d83cc019SAndroid Build Coastguard Worker igt_display_t display;
48*d83cc019SAndroid Build Coastguard Worker igt_crc_t ref_crc;
49*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_t *pipe_crc;
50*d83cc019SAndroid Build Coastguard Worker igt_plane_t **plane;
51*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fb;
52*d83cc019SAndroid Build Coastguard Worker } data_t;
53*d83cc019SAndroid Build Coastguard Worker
54*d83cc019SAndroid Build Coastguard Worker /* Command line parameters. */
55*d83cc019SAndroid Build Coastguard Worker struct {
56*d83cc019SAndroid Build Coastguard Worker int iterations;
57*d83cc019SAndroid Build Coastguard Worker bool user_seed;
58*d83cc019SAndroid Build Coastguard Worker int seed;
59*d83cc019SAndroid Build Coastguard Worker } opt = {
60*d83cc019SAndroid Build Coastguard Worker .iterations = 1,
61*d83cc019SAndroid Build Coastguard Worker .user_seed = false,
62*d83cc019SAndroid Build Coastguard Worker .seed = 1,
63*d83cc019SAndroid Build Coastguard Worker };
64*d83cc019SAndroid Build Coastguard Worker
65*d83cc019SAndroid Build Coastguard Worker /*
66*d83cc019SAndroid Build Coastguard Worker * Common code across all tests, acting on data_t
67*d83cc019SAndroid Build Coastguard Worker */
test_init(data_t * data,enum pipe pipe,int n_planes)68*d83cc019SAndroid Build Coastguard Worker static void test_init(data_t *data, enum pipe pipe, int n_planes)
69*d83cc019SAndroid Build Coastguard Worker {
70*d83cc019SAndroid Build Coastguard Worker data->pipe_crc = igt_pipe_crc_new(data->drm_fd, pipe, INTEL_PIPE_CRC_SOURCE_AUTO);
71*d83cc019SAndroid Build Coastguard Worker
72*d83cc019SAndroid Build Coastguard Worker data->plane = calloc(n_planes, sizeof(*data->plane));
73*d83cc019SAndroid Build Coastguard Worker igt_assert_f(data->plane != NULL, "Failed to allocate memory for planes\n");
74*d83cc019SAndroid Build Coastguard Worker
75*d83cc019SAndroid Build Coastguard Worker data->fb = calloc(n_planes, sizeof(struct igt_fb));
76*d83cc019SAndroid Build Coastguard Worker igt_assert_f(data->fb != NULL, "Failed to allocate memory for FBs\n");
77*d83cc019SAndroid Build Coastguard Worker }
78*d83cc019SAndroid Build Coastguard Worker
test_fini(data_t * data,igt_output_t * output,int n_planes)79*d83cc019SAndroid Build Coastguard Worker static void test_fini(data_t *data, igt_output_t *output, int n_planes)
80*d83cc019SAndroid Build Coastguard Worker {
81*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_stop(data->pipe_crc);
82*d83cc019SAndroid Build Coastguard Worker
83*d83cc019SAndroid Build Coastguard Worker /* reset the constraint on the pipe */
84*d83cc019SAndroid Build Coastguard Worker igt_output_set_pipe(output, PIPE_ANY);
85*d83cc019SAndroid Build Coastguard Worker
86*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_free(data->pipe_crc);
87*d83cc019SAndroid Build Coastguard Worker data->pipe_crc = NULL;
88*d83cc019SAndroid Build Coastguard Worker
89*d83cc019SAndroid Build Coastguard Worker free(data->plane);
90*d83cc019SAndroid Build Coastguard Worker data->plane = NULL;
91*d83cc019SAndroid Build Coastguard Worker
92*d83cc019SAndroid Build Coastguard Worker free(data->fb);
93*d83cc019SAndroid Build Coastguard Worker data->fb = NULL;
94*d83cc019SAndroid Build Coastguard Worker
95*d83cc019SAndroid Build Coastguard Worker igt_display_reset(&data->display);
96*d83cc019SAndroid Build Coastguard Worker }
97*d83cc019SAndroid Build Coastguard Worker
98*d83cc019SAndroid Build Coastguard Worker static void
get_reference_crc(data_t * data,igt_output_t * output,enum pipe pipe,color_t * color,uint64_t tiling)99*d83cc019SAndroid Build Coastguard Worker get_reference_crc(data_t *data, igt_output_t *output, enum pipe pipe,
100*d83cc019SAndroid Build Coastguard Worker color_t *color, uint64_t tiling)
101*d83cc019SAndroid Build Coastguard Worker {
102*d83cc019SAndroid Build Coastguard Worker drmModeModeInfo *mode;
103*d83cc019SAndroid Build Coastguard Worker igt_plane_t *primary;
104*d83cc019SAndroid Build Coastguard Worker int ret;
105*d83cc019SAndroid Build Coastguard Worker
106*d83cc019SAndroid Build Coastguard Worker igt_output_set_pipe(output, pipe);
107*d83cc019SAndroid Build Coastguard Worker
108*d83cc019SAndroid Build Coastguard Worker primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
109*d83cc019SAndroid Build Coastguard Worker data->plane[primary->index] = primary;
110*d83cc019SAndroid Build Coastguard Worker
111*d83cc019SAndroid Build Coastguard Worker mode = igt_output_get_mode(output);
112*d83cc019SAndroid Build Coastguard Worker
113*d83cc019SAndroid Build Coastguard Worker igt_create_color_fb(data->drm_fd, mode->hdisplay, mode->vdisplay,
114*d83cc019SAndroid Build Coastguard Worker DRM_FORMAT_XRGB8888,
115*d83cc019SAndroid Build Coastguard Worker LOCAL_DRM_FORMAT_MOD_NONE,
116*d83cc019SAndroid Build Coastguard Worker color->red, color->green, color->blue,
117*d83cc019SAndroid Build Coastguard Worker &data->fb[primary->index]);
118*d83cc019SAndroid Build Coastguard Worker
119*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(data->plane[primary->index], &data->fb[primary->index]);
120*d83cc019SAndroid Build Coastguard Worker
121*d83cc019SAndroid Build Coastguard Worker ret = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
122*d83cc019SAndroid Build Coastguard Worker igt_skip_on(ret != 0);
123*d83cc019SAndroid Build Coastguard Worker
124*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_start(data->pipe_crc);
125*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_get_single(data->pipe_crc, &data->ref_crc);
126*d83cc019SAndroid Build Coastguard Worker }
127*d83cc019SAndroid Build Coastguard Worker
128*d83cc019SAndroid Build Coastguard Worker static void
create_fb_for_mode_position(data_t * data,igt_output_t * output,drmModeModeInfo * mode,color_t * color,int * rect_x,int * rect_y,int * rect_w,int * rect_h,uint64_t tiling,int max_planes)129*d83cc019SAndroid Build Coastguard Worker create_fb_for_mode_position(data_t *data, igt_output_t *output, drmModeModeInfo *mode,
130*d83cc019SAndroid Build Coastguard Worker color_t *color, int *rect_x, int *rect_y,
131*d83cc019SAndroid Build Coastguard Worker int *rect_w, int *rect_h, uint64_t tiling,
132*d83cc019SAndroid Build Coastguard Worker int max_planes)
133*d83cc019SAndroid Build Coastguard Worker {
134*d83cc019SAndroid Build Coastguard Worker unsigned int fb_id;
135*d83cc019SAndroid Build Coastguard Worker cairo_t *cr;
136*d83cc019SAndroid Build Coastguard Worker igt_plane_t *primary;
137*d83cc019SAndroid Build Coastguard Worker
138*d83cc019SAndroid Build Coastguard Worker primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
139*d83cc019SAndroid Build Coastguard Worker
140*d83cc019SAndroid Build Coastguard Worker igt_skip_on(!igt_display_has_format_mod(&data->display,
141*d83cc019SAndroid Build Coastguard Worker DRM_FORMAT_XRGB8888,
142*d83cc019SAndroid Build Coastguard Worker tiling));
143*d83cc019SAndroid Build Coastguard Worker
144*d83cc019SAndroid Build Coastguard Worker fb_id = igt_create_fb(data->drm_fd,
145*d83cc019SAndroid Build Coastguard Worker mode->hdisplay, mode->vdisplay,
146*d83cc019SAndroid Build Coastguard Worker DRM_FORMAT_XRGB8888,
147*d83cc019SAndroid Build Coastguard Worker tiling,
148*d83cc019SAndroid Build Coastguard Worker &data->fb[primary->index]);
149*d83cc019SAndroid Build Coastguard Worker igt_assert(fb_id);
150*d83cc019SAndroid Build Coastguard Worker
151*d83cc019SAndroid Build Coastguard Worker cr = igt_get_cairo_ctx(data->drm_fd, &data->fb[primary->index]);
152*d83cc019SAndroid Build Coastguard Worker igt_paint_color(cr, rect_x[0], rect_y[0],
153*d83cc019SAndroid Build Coastguard Worker mode->hdisplay, mode->vdisplay,
154*d83cc019SAndroid Build Coastguard Worker color->red, color->green, color->blue);
155*d83cc019SAndroid Build Coastguard Worker
156*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i < max_planes; i++) {
157*d83cc019SAndroid Build Coastguard Worker if (data->plane[i]->type == DRM_PLANE_TYPE_PRIMARY)
158*d83cc019SAndroid Build Coastguard Worker continue;
159*d83cc019SAndroid Build Coastguard Worker igt_paint_color(cr, rect_x[i], rect_y[i],
160*d83cc019SAndroid Build Coastguard Worker rect_w[i], rect_h[i], 0.0, 0.0, 0.0);
161*d83cc019SAndroid Build Coastguard Worker }
162*d83cc019SAndroid Build Coastguard Worker
163*d83cc019SAndroid Build Coastguard Worker igt_put_cairo_ctx(data->drm_fd, &data->fb[primary->index], cr);
164*d83cc019SAndroid Build Coastguard Worker }
165*d83cc019SAndroid Build Coastguard Worker
166*d83cc019SAndroid Build Coastguard Worker
167*d83cc019SAndroid Build Coastguard Worker static void
prepare_planes(data_t * data,enum pipe pipe_id,color_t * color,uint64_t tiling,int max_planes,igt_output_t * output)168*d83cc019SAndroid Build Coastguard Worker prepare_planes(data_t *data, enum pipe pipe_id, color_t *color,
169*d83cc019SAndroid Build Coastguard Worker uint64_t tiling, int max_planes, igt_output_t *output)
170*d83cc019SAndroid Build Coastguard Worker {
171*d83cc019SAndroid Build Coastguard Worker drmModeModeInfo *mode;
172*d83cc019SAndroid Build Coastguard Worker igt_pipe_t *pipe;
173*d83cc019SAndroid Build Coastguard Worker igt_plane_t *primary;
174*d83cc019SAndroid Build Coastguard Worker int *x;
175*d83cc019SAndroid Build Coastguard Worker int *y;
176*d83cc019SAndroid Build Coastguard Worker int *size;
177*d83cc019SAndroid Build Coastguard Worker int i;
178*d83cc019SAndroid Build Coastguard Worker int* suffle;
179*d83cc019SAndroid Build Coastguard Worker
180*d83cc019SAndroid Build Coastguard Worker igt_output_set_pipe(output, pipe_id);
181*d83cc019SAndroid Build Coastguard Worker primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
182*d83cc019SAndroid Build Coastguard Worker pipe = primary->pipe;
183*d83cc019SAndroid Build Coastguard Worker
184*d83cc019SAndroid Build Coastguard Worker x = malloc(pipe->n_planes * sizeof(*x));
185*d83cc019SAndroid Build Coastguard Worker igt_assert_f(x, "Failed to allocate %ld bytes for variable x\n", (long int) (pipe->n_planes * sizeof(*x)));
186*d83cc019SAndroid Build Coastguard Worker y = malloc(pipe->n_planes * sizeof(*y));
187*d83cc019SAndroid Build Coastguard Worker igt_assert_f(y, "Failed to allocate %ld bytes for variable y\n", (long int) (pipe->n_planes * sizeof(*y)));
188*d83cc019SAndroid Build Coastguard Worker size = malloc(pipe->n_planes * sizeof(*size));
189*d83cc019SAndroid Build Coastguard Worker igt_assert_f(size, "Failed to allocate %ld bytes for variable size\n", (long int) (pipe->n_planes * sizeof(*size)));
190*d83cc019SAndroid Build Coastguard Worker suffle = malloc(pipe->n_planes * sizeof(*suffle));
191*d83cc019SAndroid Build Coastguard Worker igt_assert_f(suffle, "Failed to allocate %ld bytes for variable size\n", (long int) (pipe->n_planes * sizeof(*suffle)));
192*d83cc019SAndroid Build Coastguard Worker
193*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < pipe->n_planes; i++)
194*d83cc019SAndroid Build Coastguard Worker suffle[i] = i;
195*d83cc019SAndroid Build Coastguard Worker
196*d83cc019SAndroid Build Coastguard Worker /*
197*d83cc019SAndroid Build Coastguard Worker * suffle table for planes. using rand() should keep it
198*d83cc019SAndroid Build Coastguard Worker * 'randomized in expected way'
199*d83cc019SAndroid Build Coastguard Worker */
200*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < 256; i++) {
201*d83cc019SAndroid Build Coastguard Worker int n, m;
202*d83cc019SAndroid Build Coastguard Worker int a, b;
203*d83cc019SAndroid Build Coastguard Worker
204*d83cc019SAndroid Build Coastguard Worker n = rand() % (pipe->n_planes-1);
205*d83cc019SAndroid Build Coastguard Worker m = rand() % (pipe->n_planes-1);
206*d83cc019SAndroid Build Coastguard Worker
207*d83cc019SAndroid Build Coastguard Worker /*
208*d83cc019SAndroid Build Coastguard Worker * keep primary plane at its place for test's sake.
209*d83cc019SAndroid Build Coastguard Worker */
210*d83cc019SAndroid Build Coastguard Worker if(n == primary->index || m == primary->index)
211*d83cc019SAndroid Build Coastguard Worker continue;
212*d83cc019SAndroid Build Coastguard Worker
213*d83cc019SAndroid Build Coastguard Worker a = suffle[n];
214*d83cc019SAndroid Build Coastguard Worker b = suffle[m];
215*d83cc019SAndroid Build Coastguard Worker suffle[n] = b;
216*d83cc019SAndroid Build Coastguard Worker suffle[m] = a;
217*d83cc019SAndroid Build Coastguard Worker }
218*d83cc019SAndroid Build Coastguard Worker
219*d83cc019SAndroid Build Coastguard Worker mode = igt_output_get_mode(output);
220*d83cc019SAndroid Build Coastguard Worker
221*d83cc019SAndroid Build Coastguard Worker /* planes with random positions */
222*d83cc019SAndroid Build Coastguard Worker x[primary->index] = 0;
223*d83cc019SAndroid Build Coastguard Worker y[primary->index] = 0;
224*d83cc019SAndroid Build Coastguard Worker for (i = 0; i < max_planes; i++) {
225*d83cc019SAndroid Build Coastguard Worker /*
226*d83cc019SAndroid Build Coastguard Worker * Here is made assumption primary plane will have
227*d83cc019SAndroid Build Coastguard Worker * index zero.
228*d83cc019SAndroid Build Coastguard Worker */
229*d83cc019SAndroid Build Coastguard Worker igt_plane_t *plane = igt_output_get_plane(output, suffle[i]);
230*d83cc019SAndroid Build Coastguard Worker uint32_t plane_format;
231*d83cc019SAndroid Build Coastguard Worker uint64_t plane_tiling;
232*d83cc019SAndroid Build Coastguard Worker
233*d83cc019SAndroid Build Coastguard Worker if (plane->type == DRM_PLANE_TYPE_PRIMARY)
234*d83cc019SAndroid Build Coastguard Worker continue;
235*d83cc019SAndroid Build Coastguard Worker else if (plane->type == DRM_PLANE_TYPE_CURSOR)
236*d83cc019SAndroid Build Coastguard Worker size[i] = SIZE_CURSOR;
237*d83cc019SAndroid Build Coastguard Worker else
238*d83cc019SAndroid Build Coastguard Worker size[i] = SIZE_PLANE;
239*d83cc019SAndroid Build Coastguard Worker
240*d83cc019SAndroid Build Coastguard Worker x[i] = rand() % (mode->hdisplay - size[i]);
241*d83cc019SAndroid Build Coastguard Worker y[i] = rand() % (mode->vdisplay - size[i]);
242*d83cc019SAndroid Build Coastguard Worker
243*d83cc019SAndroid Build Coastguard Worker data->plane[i] = plane;
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker plane_format = data->plane[i]->type == DRM_PLANE_TYPE_CURSOR ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
246*d83cc019SAndroid Build Coastguard Worker plane_tiling = data->plane[i]->type == DRM_PLANE_TYPE_CURSOR ? LOCAL_DRM_FORMAT_MOD_NONE : tiling;
247*d83cc019SAndroid Build Coastguard Worker
248*d83cc019SAndroid Build Coastguard Worker igt_skip_on(!igt_plane_has_format_mod(plane, plane_format,
249*d83cc019SAndroid Build Coastguard Worker plane_tiling));
250*d83cc019SAndroid Build Coastguard Worker
251*d83cc019SAndroid Build Coastguard Worker igt_create_color_fb(data->drm_fd,
252*d83cc019SAndroid Build Coastguard Worker size[i], size[i],
253*d83cc019SAndroid Build Coastguard Worker plane_format,
254*d83cc019SAndroid Build Coastguard Worker plane_tiling,
255*d83cc019SAndroid Build Coastguard Worker color->red, color->green, color->blue,
256*d83cc019SAndroid Build Coastguard Worker &data->fb[i]);
257*d83cc019SAndroid Build Coastguard Worker
258*d83cc019SAndroid Build Coastguard Worker igt_plane_set_position(data->plane[i], x[i], y[i]);
259*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(data->plane[i], &data->fb[i]);
260*d83cc019SAndroid Build Coastguard Worker }
261*d83cc019SAndroid Build Coastguard Worker
262*d83cc019SAndroid Build Coastguard Worker /* primary plane */
263*d83cc019SAndroid Build Coastguard Worker data->plane[primary->index] = primary;
264*d83cc019SAndroid Build Coastguard Worker create_fb_for_mode_position(data, output, mode, color, x, y,
265*d83cc019SAndroid Build Coastguard Worker size, size, tiling, max_planes);
266*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(data->plane[primary->index], &data->fb[primary->index]);
267*d83cc019SAndroid Build Coastguard Worker free((void*)x);
268*d83cc019SAndroid Build Coastguard Worker free((void*)y);
269*d83cc019SAndroid Build Coastguard Worker free((void*)size);
270*d83cc019SAndroid Build Coastguard Worker free((void*)suffle);
271*d83cc019SAndroid Build Coastguard Worker }
272*d83cc019SAndroid Build Coastguard Worker
273*d83cc019SAndroid Build Coastguard Worker /*
274*d83cc019SAndroid Build Coastguard Worker * Multiple plane position test.
275*d83cc019SAndroid Build Coastguard Worker * - We start by grabbing a reference CRC of a full blue fb being scanned
276*d83cc019SAndroid Build Coastguard Worker * out on the primary plane
277*d83cc019SAndroid Build Coastguard Worker * - Then we scannout number of planes:
278*d83cc019SAndroid Build Coastguard Worker * * the primary plane uses a blue fb with a black rectangle holes
279*d83cc019SAndroid Build Coastguard Worker * * planes, on top of the primary plane, with a blue fb that is set-up
280*d83cc019SAndroid Build Coastguard Worker * to cover the black rectangles of the primary plane
281*d83cc019SAndroid Build Coastguard Worker * The resulting CRC should be identical to the reference CRC
282*d83cc019SAndroid Build Coastguard Worker */
283*d83cc019SAndroid Build Coastguard Worker
284*d83cc019SAndroid Build Coastguard Worker static void
test_plane_position_with_output(data_t * data,enum pipe pipe,igt_output_t * output,int n_planes,uint64_t tiling)285*d83cc019SAndroid Build Coastguard Worker test_plane_position_with_output(data_t *data, enum pipe pipe,
286*d83cc019SAndroid Build Coastguard Worker igt_output_t *output, int n_planes,
287*d83cc019SAndroid Build Coastguard Worker uint64_t tiling)
288*d83cc019SAndroid Build Coastguard Worker {
289*d83cc019SAndroid Build Coastguard Worker color_t blue = { 0.0f, 0.0f, 1.0f };
290*d83cc019SAndroid Build Coastguard Worker igt_crc_t crc;
291*d83cc019SAndroid Build Coastguard Worker igt_plane_t *plane;
292*d83cc019SAndroid Build Coastguard Worker int i;
293*d83cc019SAndroid Build Coastguard Worker int err, c = 0;
294*d83cc019SAndroid Build Coastguard Worker int iterations = opt.iterations < 1 ? 1 : opt.iterations;
295*d83cc019SAndroid Build Coastguard Worker bool loop_forever;
296*d83cc019SAndroid Build Coastguard Worker char info[256];
297*d83cc019SAndroid Build Coastguard Worker
298*d83cc019SAndroid Build Coastguard Worker if (opt.iterations == LOOP_FOREVER) {
299*d83cc019SAndroid Build Coastguard Worker loop_forever = true;
300*d83cc019SAndroid Build Coastguard Worker sprintf(info, "forever");
301*d83cc019SAndroid Build Coastguard Worker } else {
302*d83cc019SAndroid Build Coastguard Worker loop_forever = false;
303*d83cc019SAndroid Build Coastguard Worker sprintf(info, "for %d %s",
304*d83cc019SAndroid Build Coastguard Worker iterations, iterations > 1 ? "iterations" : "iteration");
305*d83cc019SAndroid Build Coastguard Worker }
306*d83cc019SAndroid Build Coastguard Worker
307*d83cc019SAndroid Build Coastguard Worker test_init(data, pipe, n_planes);
308*d83cc019SAndroid Build Coastguard Worker
309*d83cc019SAndroid Build Coastguard Worker get_reference_crc(data, output, pipe, &blue, tiling);
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker /* Find out how many planes are allowed simultaneously */
312*d83cc019SAndroid Build Coastguard Worker do {
313*d83cc019SAndroid Build Coastguard Worker c++;
314*d83cc019SAndroid Build Coastguard Worker prepare_planes(data, pipe, &blue, tiling, c, output);
315*d83cc019SAndroid Build Coastguard Worker err = igt_display_try_commit2(&data->display, COMMIT_ATOMIC);
316*d83cc019SAndroid Build Coastguard Worker
317*d83cc019SAndroid Build Coastguard Worker for_each_plane_on_pipe(&data->display, pipe, plane)
318*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, NULL);
319*d83cc019SAndroid Build Coastguard Worker
320*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(&data->display, COMMIT_ATOMIC);
321*d83cc019SAndroid Build Coastguard Worker
322*d83cc019SAndroid Build Coastguard Worker for (int x = 0; x < c; x++)
323*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(data->drm_fd, &data->fb[x]);
324*d83cc019SAndroid Build Coastguard Worker } while (!err && c < n_planes);
325*d83cc019SAndroid Build Coastguard Worker
326*d83cc019SAndroid Build Coastguard Worker if (err)
327*d83cc019SAndroid Build Coastguard Worker c--;
328*d83cc019SAndroid Build Coastguard Worker
329*d83cc019SAndroid Build Coastguard Worker igt_info("Testing connector %s using pipe %s with %d planes %s with seed %d\n",
330*d83cc019SAndroid Build Coastguard Worker igt_output_name(output), kmstest_pipe_name(pipe), c,
331*d83cc019SAndroid Build Coastguard Worker info, opt.seed);
332*d83cc019SAndroid Build Coastguard Worker
333*d83cc019SAndroid Build Coastguard Worker i = 0;
334*d83cc019SAndroid Build Coastguard Worker while (i < iterations || loop_forever) {
335*d83cc019SAndroid Build Coastguard Worker /* randomize planes and set up the holes */
336*d83cc019SAndroid Build Coastguard Worker prepare_planes(data, pipe, &blue, tiling, c, output);
337*d83cc019SAndroid Build Coastguard Worker
338*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(&data->display, COMMIT_ATOMIC);
339*d83cc019SAndroid Build Coastguard Worker
340*d83cc019SAndroid Build Coastguard Worker igt_pipe_crc_get_current(data->display.drm_fd, data->pipe_crc, &crc);
341*d83cc019SAndroid Build Coastguard Worker
342*d83cc019SAndroid Build Coastguard Worker for_each_plane_on_pipe(&data->display, pipe, plane)
343*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, NULL);
344*d83cc019SAndroid Build Coastguard Worker
345*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(&data->display, COMMIT_ATOMIC);
346*d83cc019SAndroid Build Coastguard Worker
347*d83cc019SAndroid Build Coastguard Worker for (int x = 0; x < c; x++)
348*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(data->drm_fd, &data->fb[x]);
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker igt_assert_crc_equal(&data->ref_crc, &crc);
351*d83cc019SAndroid Build Coastguard Worker
352*d83cc019SAndroid Build Coastguard Worker i++;
353*d83cc019SAndroid Build Coastguard Worker }
354*d83cc019SAndroid Build Coastguard Worker
355*d83cc019SAndroid Build Coastguard Worker test_fini(data, output, n_planes);
356*d83cc019SAndroid Build Coastguard Worker }
357*d83cc019SAndroid Build Coastguard Worker
358*d83cc019SAndroid Build Coastguard Worker static void
test_plane_position(data_t * data,enum pipe pipe,uint64_t tiling)359*d83cc019SAndroid Build Coastguard Worker test_plane_position(data_t *data, enum pipe pipe, uint64_t tiling)
360*d83cc019SAndroid Build Coastguard Worker {
361*d83cc019SAndroid Build Coastguard Worker igt_output_t *output;
362*d83cc019SAndroid Build Coastguard Worker int n_planes = data->display.pipes[pipe].n_planes;
363*d83cc019SAndroid Build Coastguard Worker
364*d83cc019SAndroid Build Coastguard Worker output = igt_get_single_output_for_pipe(&data->display, pipe);
365*d83cc019SAndroid Build Coastguard Worker igt_require(output);
366*d83cc019SAndroid Build Coastguard Worker
367*d83cc019SAndroid Build Coastguard Worker if (!opt.user_seed)
368*d83cc019SAndroid Build Coastguard Worker opt.seed = time(NULL);
369*d83cc019SAndroid Build Coastguard Worker
370*d83cc019SAndroid Build Coastguard Worker srand(opt.seed);
371*d83cc019SAndroid Build Coastguard Worker
372*d83cc019SAndroid Build Coastguard Worker test_plane_position_with_output(data, pipe, output,
373*d83cc019SAndroid Build Coastguard Worker n_planes, tiling);
374*d83cc019SAndroid Build Coastguard Worker }
375*d83cc019SAndroid Build Coastguard Worker
376*d83cc019SAndroid Build Coastguard Worker static void
run_tests_for_pipe(data_t * data,enum pipe pipe)377*d83cc019SAndroid Build Coastguard Worker run_tests_for_pipe(data_t *data, enum pipe pipe)
378*d83cc019SAndroid Build Coastguard Worker {
379*d83cc019SAndroid Build Coastguard Worker igt_fixture {
380*d83cc019SAndroid Build Coastguard Worker igt_skip_on(pipe >= data->display.n_pipes);
381*d83cc019SAndroid Build Coastguard Worker igt_require(data->display.pipes[pipe].n_planes > 0);
382*d83cc019SAndroid Build Coastguard Worker }
383*d83cc019SAndroid Build Coastguard Worker
384*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("atomic-pipe-%s-tiling-x", kmstest_pipe_name(pipe))
385*d83cc019SAndroid Build Coastguard Worker test_plane_position(data, pipe, LOCAL_I915_FORMAT_MOD_X_TILED);
386*d83cc019SAndroid Build Coastguard Worker
387*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("atomic-pipe-%s-tiling-y", kmstest_pipe_name(pipe))
388*d83cc019SAndroid Build Coastguard Worker test_plane_position(data, pipe, LOCAL_I915_FORMAT_MOD_Y_TILED);
389*d83cc019SAndroid Build Coastguard Worker
390*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("atomic-pipe-%s-tiling-yf", kmstest_pipe_name(pipe))
391*d83cc019SAndroid Build Coastguard Worker test_plane_position(data, pipe, LOCAL_I915_FORMAT_MOD_Yf_TILED);
392*d83cc019SAndroid Build Coastguard Worker
393*d83cc019SAndroid Build Coastguard Worker igt_subtest_f("atomic-pipe-%s-tiling-none", kmstest_pipe_name(pipe))
394*d83cc019SAndroid Build Coastguard Worker test_plane_position(data, pipe, LOCAL_DRM_FORMAT_MOD_NONE);
395*d83cc019SAndroid Build Coastguard Worker }
396*d83cc019SAndroid Build Coastguard Worker
397*d83cc019SAndroid Build Coastguard Worker static data_t data;
398*d83cc019SAndroid Build Coastguard Worker
opt_handler(int option,int option_index,void * input)399*d83cc019SAndroid Build Coastguard Worker static int opt_handler(int option, int option_index, void *input)
400*d83cc019SAndroid Build Coastguard Worker {
401*d83cc019SAndroid Build Coastguard Worker switch (option) {
402*d83cc019SAndroid Build Coastguard Worker case 'i':
403*d83cc019SAndroid Build Coastguard Worker opt.iterations = strtol(optarg, NULL, 0);
404*d83cc019SAndroid Build Coastguard Worker
405*d83cc019SAndroid Build Coastguard Worker if (opt.iterations < LOOP_FOREVER || opt.iterations == 0) {
406*d83cc019SAndroid Build Coastguard Worker igt_info("incorrect number of iterations: %d\n", opt.iterations);
407*d83cc019SAndroid Build Coastguard Worker return IGT_OPT_HANDLER_ERROR;
408*d83cc019SAndroid Build Coastguard Worker }
409*d83cc019SAndroid Build Coastguard Worker
410*d83cc019SAndroid Build Coastguard Worker break;
411*d83cc019SAndroid Build Coastguard Worker case 's':
412*d83cc019SAndroid Build Coastguard Worker opt.user_seed = true;
413*d83cc019SAndroid Build Coastguard Worker opt.seed = strtol(optarg, NULL, 0);
414*d83cc019SAndroid Build Coastguard Worker break;
415*d83cc019SAndroid Build Coastguard Worker default:
416*d83cc019SAndroid Build Coastguard Worker return IGT_OPT_HANDLER_ERROR;
417*d83cc019SAndroid Build Coastguard Worker }
418*d83cc019SAndroid Build Coastguard Worker
419*d83cc019SAndroid Build Coastguard Worker return IGT_OPT_HANDLER_SUCCESS;
420*d83cc019SAndroid Build Coastguard Worker }
421*d83cc019SAndroid Build Coastguard Worker
422*d83cc019SAndroid Build Coastguard Worker const char *help_str =
423*d83cc019SAndroid Build Coastguard Worker " --iterations Number of iterations for test coverage. -1 loop forever, default 64 iterations\n"
424*d83cc019SAndroid Build Coastguard Worker " --seed Seed for random number generator\n";
425*d83cc019SAndroid Build Coastguard Worker
426*d83cc019SAndroid Build Coastguard Worker struct option long_options[] = {
427*d83cc019SAndroid Build Coastguard Worker { "iterations", required_argument, NULL, 'i'},
428*d83cc019SAndroid Build Coastguard Worker { "seed", required_argument, NULL, 's'},
429*d83cc019SAndroid Build Coastguard Worker { 0, 0, 0, 0 }
430*d83cc019SAndroid Build Coastguard Worker };
431*d83cc019SAndroid Build Coastguard Worker
432*d83cc019SAndroid Build Coastguard Worker igt_main_args("", long_options, help_str, opt_handler, NULL)
433*d83cc019SAndroid Build Coastguard Worker {
434*d83cc019SAndroid Build Coastguard Worker enum pipe pipe;
435*d83cc019SAndroid Build Coastguard Worker
436*d83cc019SAndroid Build Coastguard Worker igt_skip_on_simulation();
437*d83cc019SAndroid Build Coastguard Worker
438*d83cc019SAndroid Build Coastguard Worker igt_fixture {
439*d83cc019SAndroid Build Coastguard Worker data.drm_fd = drm_open_driver_master(DRIVER_INTEL | DRIVER_AMDGPU);
440*d83cc019SAndroid Build Coastguard Worker kmstest_set_vt_graphics_mode();
441*d83cc019SAndroid Build Coastguard Worker igt_require_pipe_crc(data.drm_fd);
442*d83cc019SAndroid Build Coastguard Worker igt_display_require(&data.display, data.drm_fd);
443*d83cc019SAndroid Build Coastguard Worker igt_require(data.display.is_atomic);
444*d83cc019SAndroid Build Coastguard Worker }
445*d83cc019SAndroid Build Coastguard Worker
for_each_pipe_static(pipe)446*d83cc019SAndroid Build Coastguard Worker for_each_pipe_static(pipe) {
447*d83cc019SAndroid Build Coastguard Worker igt_describe("Check that the kernel handles atomic updates of "
448*d83cc019SAndroid Build Coastguard Worker "multiple planes correctly by changing their "
449*d83cc019SAndroid Build Coastguard Worker "geometry and making sure the changes are "
450*d83cc019SAndroid Build Coastguard Worker "reflected immediately after each commit.");
451*d83cc019SAndroid Build Coastguard Worker igt_subtest_group
452*d83cc019SAndroid Build Coastguard Worker run_tests_for_pipe(&data, pipe);
453*d83cc019SAndroid Build Coastguard Worker }
454*d83cc019SAndroid Build Coastguard Worker
455*d83cc019SAndroid Build Coastguard Worker igt_fixture {
456*d83cc019SAndroid Build Coastguard Worker igt_display_fini(&data.display);
457*d83cc019SAndroid Build Coastguard Worker }
458*d83cc019SAndroid Build Coastguard Worker }
459