1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker * Copyright © 2019 Google LLC
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 /** @file kms_throughput.c
25*d83cc019SAndroid Build Coastguard Worker */
26*d83cc019SAndroid Build Coastguard Worker
27*d83cc019SAndroid Build Coastguard Worker #include <drm.h>
28*d83cc019SAndroid Build Coastguard Worker #include <sys/time.h>
29*d83cc019SAndroid Build Coastguard Worker #include <xf86drm.h>
30*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
31*d83cc019SAndroid Build Coastguard Worker #include "igt.h"
32*d83cc019SAndroid Build Coastguard Worker #include "ion.h"
33*d83cc019SAndroid Build Coastguard Worker
make_display(igt_display_t * display)34*d83cc019SAndroid Build Coastguard Worker static void make_display(igt_display_t *display)
35*d83cc019SAndroid Build Coastguard Worker {
36*d83cc019SAndroid Build Coastguard Worker display->drm_fd = drm_open_driver_master(DRIVER_ANY);
37*d83cc019SAndroid Build Coastguard Worker igt_display_require(display, display->drm_fd);
38*d83cc019SAndroid Build Coastguard Worker igt_require(display->is_atomic);
39*d83cc019SAndroid Build Coastguard Worker igt_display_require_output(display);
40*d83cc019SAndroid Build Coastguard Worker }
41*d83cc019SAndroid Build Coastguard Worker
get_output(igt_display_t * display,enum pipe * pipe,igt_output_t ** output)42*d83cc019SAndroid Build Coastguard Worker static bool get_output(igt_display_t *display,
43*d83cc019SAndroid Build Coastguard Worker enum pipe *pipe, igt_output_t **output)
44*d83cc019SAndroid Build Coastguard Worker {
45*d83cc019SAndroid Build Coastguard Worker igt_info("Display %p has %d pipes\n", display, display->n_pipes);
46*d83cc019SAndroid Build Coastguard Worker for (int i = 0; i < display->n_pipes; ++i)
47*d83cc019SAndroid Build Coastguard Worker {
48*d83cc019SAndroid Build Coastguard Worker igt_info("Pipe %d (crtc %u) has %d planes\n",
49*d83cc019SAndroid Build Coastguard Worker i, display->pipes[i].crtc_id,
50*d83cc019SAndroid Build Coastguard Worker display->pipes[i].n_planes);
51*d83cc019SAndroid Build Coastguard Worker }
52*d83cc019SAndroid Build Coastguard Worker
53*d83cc019SAndroid Build Coastguard Worker for_each_pipe_with_valid_output(display, *pipe, *output)
54*d83cc019SAndroid Build Coastguard Worker {
55*d83cc019SAndroid Build Coastguard Worker /* we are happy with the first one */
56*d83cc019SAndroid Build Coastguard Worker return true;
57*d83cc019SAndroid Build Coastguard Worker }
58*d83cc019SAndroid Build Coastguard Worker
59*d83cc019SAndroid Build Coastguard Worker return false;
60*d83cc019SAndroid Build Coastguard Worker }
61*d83cc019SAndroid Build Coastguard Worker
get_pipe(igt_display_t * display,igt_pipe_t ** p,igt_output_t ** output)62*d83cc019SAndroid Build Coastguard Worker static void get_pipe(igt_display_t *display,
63*d83cc019SAndroid Build Coastguard Worker igt_pipe_t **p, igt_output_t **output)
64*d83cc019SAndroid Build Coastguard Worker {
65*d83cc019SAndroid Build Coastguard Worker enum pipe pipe_idx = PIPE_NONE;
66*d83cc019SAndroid Build Coastguard Worker *output = NULL;
67*d83cc019SAndroid Build Coastguard Worker igt_require(get_output(display, &pipe_idx, output));
68*d83cc019SAndroid Build Coastguard Worker igt_info("Using output id %u, name %s\n",
69*d83cc019SAndroid Build Coastguard Worker (*output)->id, (*output)->name);
70*d83cc019SAndroid Build Coastguard Worker
71*d83cc019SAndroid Build Coastguard Worker /* I'd love to call this 'pipe' but pipe(2) is in the way */
72*d83cc019SAndroid Build Coastguard Worker *p = &display->pipes[pipe_idx];
73*d83cc019SAndroid Build Coastguard Worker igt_require(*p);
74*d83cc019SAndroid Build Coastguard Worker
75*d83cc019SAndroid Build Coastguard Worker igt_info("Chosen pipe (crtc %u) has %d planes\n",
76*d83cc019SAndroid Build Coastguard Worker (*p)->crtc_id, (*p)->n_planes);
77*d83cc019SAndroid Build Coastguard Worker }
78*d83cc019SAndroid Build Coastguard Worker
prepare(igt_display_t * display,igt_pipe_t * p,igt_output_t * output)79*d83cc019SAndroid Build Coastguard Worker static void prepare(igt_display_t *display, igt_pipe_t *p, igt_output_t *output)
80*d83cc019SAndroid Build Coastguard Worker {
81*d83cc019SAndroid Build Coastguard Worker igt_display_reset(display);
82*d83cc019SAndroid Build Coastguard Worker igt_output_set_pipe(output, p->pipe);
83*d83cc019SAndroid Build Coastguard Worker }
84*d83cc019SAndroid Build Coastguard Worker
plane_for_index(igt_pipe_t * p,size_t index)85*d83cc019SAndroid Build Coastguard Worker static igt_plane_t *plane_for_index(igt_pipe_t *p, size_t index)
86*d83cc019SAndroid Build Coastguard Worker {
87*d83cc019SAndroid Build Coastguard Worker return &p->planes[index];
88*d83cc019SAndroid Build Coastguard Worker }
89*d83cc019SAndroid Build Coastguard Worker
90*d83cc019SAndroid Build Coastguard Worker struct histogram
91*d83cc019SAndroid Build Coastguard Worker {
92*d83cc019SAndroid Build Coastguard Worker struct timeval last_commit;
93*d83cc019SAndroid Build Coastguard Worker size_t num_buckets;
94*d83cc019SAndroid Build Coastguard Worker size_t *buckets;
95*d83cc019SAndroid Build Coastguard Worker };
96*d83cc019SAndroid Build Coastguard Worker
histogram_init(struct histogram * h)97*d83cc019SAndroid Build Coastguard Worker static void histogram_init(struct histogram *h)
98*d83cc019SAndroid Build Coastguard Worker {
99*d83cc019SAndroid Build Coastguard Worker gettimeofday(&h->last_commit, NULL);
100*d83cc019SAndroid Build Coastguard Worker h->num_buckets = 100;
101*d83cc019SAndroid Build Coastguard Worker h->buckets = calloc(h->num_buckets, sizeof(*h->buckets));
102*d83cc019SAndroid Build Coastguard Worker }
103*d83cc019SAndroid Build Coastguard Worker
histogram_update(struct histogram * h)104*d83cc019SAndroid Build Coastguard Worker static void histogram_update(struct histogram *h)
105*d83cc019SAndroid Build Coastguard Worker {
106*d83cc019SAndroid Build Coastguard Worker struct timeval this_commit;
107*d83cc019SAndroid Build Coastguard Worker gettimeofday(&this_commit, NULL);
108*d83cc019SAndroid Build Coastguard Worker
109*d83cc019SAndroid Build Coastguard Worker struct timeval diff;
110*d83cc019SAndroid Build Coastguard Worker timersub(&this_commit, &h->last_commit, &diff);
111*d83cc019SAndroid Build Coastguard Worker const size_t ms = (diff.tv_sec * 1000) + (diff.tv_usec / 1000);
112*d83cc019SAndroid Build Coastguard Worker size_t bucket = ms;
113*d83cc019SAndroid Build Coastguard Worker if (bucket >= h->num_buckets)
114*d83cc019SAndroid Build Coastguard Worker {
115*d83cc019SAndroid Build Coastguard Worker // the last bucket is a catch-all
116*d83cc019SAndroid Build Coastguard Worker bucket = h->num_buckets - 1;
117*d83cc019SAndroid Build Coastguard Worker }
118*d83cc019SAndroid Build Coastguard Worker h->buckets[bucket]++;
119*d83cc019SAndroid Build Coastguard Worker
120*d83cc019SAndroid Build Coastguard Worker memcpy(&h->last_commit, &this_commit, sizeof(this_commit));
121*d83cc019SAndroid Build Coastguard Worker }
122*d83cc019SAndroid Build Coastguard Worker
histogram_print(struct histogram * h)123*d83cc019SAndroid Build Coastguard Worker static void histogram_print(struct histogram *h)
124*d83cc019SAndroid Build Coastguard Worker {
125*d83cc019SAndroid Build Coastguard Worker igt_info("Histogram buckets with 1 or more entries:\n");
126*d83cc019SAndroid Build Coastguard Worker
127*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < h->num_buckets; ++i)
128*d83cc019SAndroid Build Coastguard Worker {
129*d83cc019SAndroid Build Coastguard Worker size_t value = h->buckets[i];
130*d83cc019SAndroid Build Coastguard Worker
131*d83cc019SAndroid Build Coastguard Worker if (value)
132*d83cc019SAndroid Build Coastguard Worker {
133*d83cc019SAndroid Build Coastguard Worker if (i == h->num_buckets - 1)
134*d83cc019SAndroid Build Coastguard Worker {
135*d83cc019SAndroid Build Coastguard Worker igt_info("%zu+ ms: %zu\n", i, value);
136*d83cc019SAndroid Build Coastguard Worker }
137*d83cc019SAndroid Build Coastguard Worker else
138*d83cc019SAndroid Build Coastguard Worker {
139*d83cc019SAndroid Build Coastguard Worker igt_info("%zu ms: %zu\n", i, value);
140*d83cc019SAndroid Build Coastguard Worker }
141*d83cc019SAndroid Build Coastguard Worker }
142*d83cc019SAndroid Build Coastguard Worker }
143*d83cc019SAndroid Build Coastguard Worker }
144*d83cc019SAndroid Build Coastguard Worker
histogram_cleanup(struct histogram * h)145*d83cc019SAndroid Build Coastguard Worker static void histogram_cleanup(struct histogram *h)
146*d83cc019SAndroid Build Coastguard Worker {
147*d83cc019SAndroid Build Coastguard Worker free(h->buckets);
148*d83cc019SAndroid Build Coastguard Worker }
149*d83cc019SAndroid Build Coastguard Worker
150*d83cc019SAndroid Build Coastguard Worker static const size_t max_num_fbs = 32;
151*d83cc019SAndroid Build Coastguard Worker
152*d83cc019SAndroid Build Coastguard Worker struct tuning
153*d83cc019SAndroid Build Coastguard Worker {
154*d83cc019SAndroid Build Coastguard Worker drmModeModeInfoPtr mode;
155*d83cc019SAndroid Build Coastguard Worker size_t num_iterations;
156*d83cc019SAndroid Build Coastguard Worker size_t num_fb_sets;
157*d83cc019SAndroid Build Coastguard Worker size_t num_fbs;
158*d83cc019SAndroid Build Coastguard Worker struct fbgeom {
159*d83cc019SAndroid Build Coastguard Worker size_t width;
160*d83cc019SAndroid Build Coastguard Worker size_t height;
161*d83cc019SAndroid Build Coastguard Worker } fb_geom[max_num_fbs];
162*d83cc019SAndroid Build Coastguard Worker };
163*d83cc019SAndroid Build Coastguard Worker
info_timestamp(const char * text)164*d83cc019SAndroid Build Coastguard Worker static void info_timestamp(const char *text)
165*d83cc019SAndroid Build Coastguard Worker {
166*d83cc019SAndroid Build Coastguard Worker struct timeval ts;
167*d83cc019SAndroid Build Coastguard Worker gettimeofday(&ts, NULL);
168*d83cc019SAndroid Build Coastguard Worker igt_debug("%ld: %s\n", ts.tv_usec, text);
169*d83cc019SAndroid Build Coastguard Worker }
170*d83cc019SAndroid Build Coastguard Worker
flip_overlays(igt_pipe_t * p,struct igt_fb ** fb_sets,const struct tuning * tuning,size_t iter)171*d83cc019SAndroid Build Coastguard Worker static void flip_overlays(igt_pipe_t *p, struct igt_fb **fb_sets,
172*d83cc019SAndroid Build Coastguard Worker const struct tuning *tuning,
173*d83cc019SAndroid Build Coastguard Worker size_t iter)
174*d83cc019SAndroid Build Coastguard Worker {
175*d83cc019SAndroid Build Coastguard Worker size_t fb_set = iter % tuning->num_fb_sets;
176*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fbs = fb_sets[fb_set];
177*d83cc019SAndroid Build Coastguard Worker
178*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < tuning->num_fbs; ++i)
179*d83cc019SAndroid Build Coastguard Worker {
180*d83cc019SAndroid Build Coastguard Worker igt_plane_t *plane = plane_for_index(p, i);
181*d83cc019SAndroid Build Coastguard Worker igt_plane_set_prop_value(plane, IGT_PLANE_ZPOS, i);
182*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, &fbs[i]);
183*d83cc019SAndroid Build Coastguard Worker }
184*d83cc019SAndroid Build Coastguard Worker
185*d83cc019SAndroid Build Coastguard Worker igt_pipe_obj_set_prop_value(p, IGT_CRTC_ACTIVE, 1);
186*d83cc019SAndroid Build Coastguard Worker
187*d83cc019SAndroid Build Coastguard Worker info_timestamp("start commit");
188*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(p->display, COMMIT_ATOMIC);
189*d83cc019SAndroid Build Coastguard Worker info_timestamp("end commit");
190*d83cc019SAndroid Build Coastguard Worker }
191*d83cc019SAndroid Build Coastguard Worker
repeat_flip(igt_pipe_t * p,struct igt_fb ** fb_sets,const struct tuning * tuning)192*d83cc019SAndroid Build Coastguard Worker static void repeat_flip(igt_pipe_t *p, struct igt_fb **fb_sets,
193*d83cc019SAndroid Build Coastguard Worker const struct tuning *tuning)
194*d83cc019SAndroid Build Coastguard Worker {
195*d83cc019SAndroid Build Coastguard Worker struct histogram h;
196*d83cc019SAndroid Build Coastguard Worker histogram_init(&h);
197*d83cc019SAndroid Build Coastguard Worker
198*d83cc019SAndroid Build Coastguard Worker for (size_t iter = 0; iter < tuning->num_iterations; ++iter)
199*d83cc019SAndroid Build Coastguard Worker {
200*d83cc019SAndroid Build Coastguard Worker igt_debug("Iteration %zu\n", iter);
201*d83cc019SAndroid Build Coastguard Worker flip_overlays(p, fb_sets, tuning, iter);
202*d83cc019SAndroid Build Coastguard Worker histogram_update(&h);
203*d83cc019SAndroid Build Coastguard Worker }
204*d83cc019SAndroid Build Coastguard Worker
205*d83cc019SAndroid Build Coastguard Worker igt_debug("About to clear fbs\n");
206*d83cc019SAndroid Build Coastguard Worker
207*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < tuning->num_fbs; ++i)
208*d83cc019SAndroid Build Coastguard Worker {
209*d83cc019SAndroid Build Coastguard Worker igt_plane_t *plane = plane_for_index(p, i);
210*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, NULL);
211*d83cc019SAndroid Build Coastguard Worker }
212*d83cc019SAndroid Build Coastguard Worker
213*d83cc019SAndroid Build Coastguard Worker igt_debug("About to flip with no fbs\n");
214*d83cc019SAndroid Build Coastguard Worker
215*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(p->display, COMMIT_ATOMIC);
216*d83cc019SAndroid Build Coastguard Worker igt_wait_for_vblank(p->display->drm_fd, p->pipe);
217*d83cc019SAndroid Build Coastguard Worker
218*d83cc019SAndroid Build Coastguard Worker igt_debug("About to deactivate the crtc\n");
219*d83cc019SAndroid Build Coastguard Worker
220*d83cc019SAndroid Build Coastguard Worker igt_pipe_obj_set_prop_value(p, IGT_CRTC_ACTIVE, 0);
221*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(p->display, COMMIT_ATOMIC);
222*d83cc019SAndroid Build Coastguard Worker
223*d83cc019SAndroid Build Coastguard Worker histogram_print(&h);
224*d83cc019SAndroid Build Coastguard Worker histogram_cleanup(&h);
225*d83cc019SAndroid Build Coastguard Worker }
226*d83cc019SAndroid Build Coastguard Worker
create_dumb_fb(igt_display_t * display,size_t width,size_t height,struct igt_fb * fb)227*d83cc019SAndroid Build Coastguard Worker static void create_dumb_fb(igt_display_t *display,
228*d83cc019SAndroid Build Coastguard Worker size_t width, size_t height,
229*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fb)
230*d83cc019SAndroid Build Coastguard Worker {
231*d83cc019SAndroid Build Coastguard Worker igt_create_fb(display->drm_fd,
232*d83cc019SAndroid Build Coastguard Worker width, height,
233*d83cc019SAndroid Build Coastguard Worker DRM_FORMAT_ARGB8888, LOCAL_DRM_FORMAT_MOD_NONE, fb);
234*d83cc019SAndroid Build Coastguard Worker }
235*d83cc019SAndroid Build Coastguard Worker
236*d83cc019SAndroid Build Coastguard Worker
get_num_planes(igt_display_t * display)237*d83cc019SAndroid Build Coastguard Worker static int get_num_planes(igt_display_t *display)
238*d83cc019SAndroid Build Coastguard Worker {
239*d83cc019SAndroid Build Coastguard Worker const int drm_fd = display->drm_fd;
240*d83cc019SAndroid Build Coastguard Worker int ret;
241*d83cc019SAndroid Build Coastguard Worker
242*d83cc019SAndroid Build Coastguard Worker drmModePlaneRes *const plane_resources =
243*d83cc019SAndroid Build Coastguard Worker drmModeGetPlaneResources(drm_fd);
244*d83cc019SAndroid Build Coastguard Worker
245*d83cc019SAndroid Build Coastguard Worker ret = plane_resources->count_planes;
246*d83cc019SAndroid Build Coastguard Worker
247*d83cc019SAndroid Build Coastguard Worker drmModeFreePlaneResources(plane_resources);
248*d83cc019SAndroid Build Coastguard Worker
249*d83cc019SAndroid Build Coastguard Worker return ret;
250*d83cc019SAndroid Build Coastguard Worker }
251*d83cc019SAndroid Build Coastguard Worker
get_max_zpos(igt_display_t * display,igt_pipe_t * p)252*d83cc019SAndroid Build Coastguard Worker static int get_max_zpos(igt_display_t *display, igt_pipe_t *p)
253*d83cc019SAndroid Build Coastguard Worker {
254*d83cc019SAndroid Build Coastguard Worker igt_plane_t *primary = plane_for_index(p, 0);
255*d83cc019SAndroid Build Coastguard Worker
256*d83cc019SAndroid Build Coastguard Worker drmModePropertyPtr zpos_prop = NULL;
257*d83cc019SAndroid Build Coastguard Worker
258*d83cc019SAndroid Build Coastguard Worker if (kmstest_get_property(display->drm_fd,
259*d83cc019SAndroid Build Coastguard Worker primary->drm_plane->plane_id,
260*d83cc019SAndroid Build Coastguard Worker DRM_MODE_OBJECT_PLANE,
261*d83cc019SAndroid Build Coastguard Worker "zpos", NULL, NULL,
262*d83cc019SAndroid Build Coastguard Worker &zpos_prop) &&
263*d83cc019SAndroid Build Coastguard Worker zpos_prop &&
264*d83cc019SAndroid Build Coastguard Worker zpos_prop->flags & DRM_MODE_PROP_RANGE)
265*d83cc019SAndroid Build Coastguard Worker {
266*d83cc019SAndroid Build Coastguard Worker return zpos_prop->values[1];
267*d83cc019SAndroid Build Coastguard Worker }
268*d83cc019SAndroid Build Coastguard Worker else
269*d83cc019SAndroid Build Coastguard Worker {
270*d83cc019SAndroid Build Coastguard Worker return -1;
271*d83cc019SAndroid Build Coastguard Worker }
272*d83cc019SAndroid Build Coastguard Worker }
273*d83cc019SAndroid Build Coastguard Worker
get_num_fbs(igt_display_t * display,igt_pipe_t * p)274*d83cc019SAndroid Build Coastguard Worker size_t get_num_fbs(igt_display_t *display, igt_pipe_t *p)
275*d83cc019SAndroid Build Coastguard Worker {
276*d83cc019SAndroid Build Coastguard Worker const char *NUM_FBS = getenv("NUM_FBS");
277*d83cc019SAndroid Build Coastguard Worker
278*d83cc019SAndroid Build Coastguard Worker if (NUM_FBS)
279*d83cc019SAndroid Build Coastguard Worker {
280*d83cc019SAndroid Build Coastguard Worker return (size_t)atoi(NUM_FBS);
281*d83cc019SAndroid Build Coastguard Worker }
282*d83cc019SAndroid Build Coastguard Worker else
283*d83cc019SAndroid Build Coastguard Worker {
284*d83cc019SAndroid Build Coastguard Worker const int num_planes = get_num_planes(display);
285*d83cc019SAndroid Build Coastguard Worker const int max_zpos = get_max_zpos(display, p);
286*d83cc019SAndroid Build Coastguard Worker
287*d83cc019SAndroid Build Coastguard Worker if (max_zpos >= 0 && max_zpos + 1 < num_planes)
288*d83cc019SAndroid Build Coastguard Worker {
289*d83cc019SAndroid Build Coastguard Worker return (size_t)max_zpos + 1;
290*d83cc019SAndroid Build Coastguard Worker }
291*d83cc019SAndroid Build Coastguard Worker else
292*d83cc019SAndroid Build Coastguard Worker {
293*d83cc019SAndroid Build Coastguard Worker return (size_t)num_planes;
294*d83cc019SAndroid Build Coastguard Worker }
295*d83cc019SAndroid Build Coastguard Worker }
296*d83cc019SAndroid Build Coastguard Worker }
297*d83cc019SAndroid Build Coastguard Worker
calculate_complexity(const drmModeModeInfoPtr mode)298*d83cc019SAndroid Build Coastguard Worker size_t calculate_complexity(const drmModeModeInfoPtr mode)
299*d83cc019SAndroid Build Coastguard Worker {
300*d83cc019SAndroid Build Coastguard Worker return (size_t)mode->hdisplay * (size_t)mode->vdisplay * (size_t)mode->vrefresh;
301*d83cc019SAndroid Build Coastguard Worker }
302*d83cc019SAndroid Build Coastguard Worker
get_peak_mode(igt_output_t * output)303*d83cc019SAndroid Build Coastguard Worker drmModeModeInfoPtr get_peak_mode(igt_output_t *output)
304*d83cc019SAndroid Build Coastguard Worker {
305*d83cc019SAndroid Build Coastguard Worker drmModeConnector *const connector = output->config.connector;
306*d83cc019SAndroid Build Coastguard Worker if (!connector || connector->count_modes == 0)
307*d83cc019SAndroid Build Coastguard Worker {
308*d83cc019SAndroid Build Coastguard Worker return NULL;
309*d83cc019SAndroid Build Coastguard Worker }
310*d83cc019SAndroid Build Coastguard Worker
311*d83cc019SAndroid Build Coastguard Worker drmModeModeInfoPtr peak_mode = &connector->modes[0];
312*d83cc019SAndroid Build Coastguard Worker size_t peak_complexity = calculate_complexity(peak_mode);
313*d83cc019SAndroid Build Coastguard Worker
314*d83cc019SAndroid Build Coastguard Worker for (drmModeModeInfoPtr mode = &connector->modes[0];
315*d83cc019SAndroid Build Coastguard Worker mode < &connector->modes[connector->count_modes]; ++mode)
316*d83cc019SAndroid Build Coastguard Worker {
317*d83cc019SAndroid Build Coastguard Worker const size_t complexity = calculate_complexity(mode);
318*d83cc019SAndroid Build Coastguard Worker igt_debug("Mode %zu is %hux%hu@%u\n",
319*d83cc019SAndroid Build Coastguard Worker (size_t)(mode - connector->modes),
320*d83cc019SAndroid Build Coastguard Worker mode->hdisplay, mode->vdisplay, mode->vrefresh);
321*d83cc019SAndroid Build Coastguard Worker if (complexity > peak_complexity)
322*d83cc019SAndroid Build Coastguard Worker {
323*d83cc019SAndroid Build Coastguard Worker peak_mode = mode;
324*d83cc019SAndroid Build Coastguard Worker peak_complexity = complexity;
325*d83cc019SAndroid Build Coastguard Worker }
326*d83cc019SAndroid Build Coastguard Worker }
327*d83cc019SAndroid Build Coastguard Worker
328*d83cc019SAndroid Build Coastguard Worker return peak_mode;
329*d83cc019SAndroid Build Coastguard Worker }
330*d83cc019SAndroid Build Coastguard Worker
get_tuning(struct tuning * tuning,igt_display_t * display,igt_pipe_t * p,igt_output_t * output)331*d83cc019SAndroid Build Coastguard Worker void get_tuning(struct tuning *tuning,
332*d83cc019SAndroid Build Coastguard Worker igt_display_t *display, igt_pipe_t *p,
333*d83cc019SAndroid Build Coastguard Worker igt_output_t *output)
334*d83cc019SAndroid Build Coastguard Worker {
335*d83cc019SAndroid Build Coastguard Worker tuning->mode = get_peak_mode(output);
336*d83cc019SAndroid Build Coastguard Worker igt_require(tuning->mode);
337*d83cc019SAndroid Build Coastguard Worker
338*d83cc019SAndroid Build Coastguard Worker if (igt_output_get_mode(output) != tuning->mode)
339*d83cc019SAndroid Build Coastguard Worker {
340*d83cc019SAndroid Build Coastguard Worker igt_output_override_mode(output, tuning->mode);
341*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(p->display, COMMIT_ATOMIC);
342*d83cc019SAndroid Build Coastguard Worker }
343*d83cc019SAndroid Build Coastguard Worker
344*d83cc019SAndroid Build Coastguard Worker igt_info("Chosen mode:\n");
345*d83cc019SAndroid Build Coastguard Worker kmstest_dump_mode(tuning->mode);
346*d83cc019SAndroid Build Coastguard Worker
347*d83cc019SAndroid Build Coastguard Worker tuning->num_iterations = 1000;
348*d83cc019SAndroid Build Coastguard Worker tuning->num_fb_sets = 2;
349*d83cc019SAndroid Build Coastguard Worker
350*d83cc019SAndroid Build Coastguard Worker tuning->num_fbs = get_num_fbs(display, p);
351*d83cc019SAndroid Build Coastguard Worker igt_require(tuning->num_fbs <= max_num_fbs);
352*d83cc019SAndroid Build Coastguard Worker
353*d83cc019SAndroid Build Coastguard Worker drmModeModeInfo *mode = igt_output_get_mode(output);
354*d83cc019SAndroid Build Coastguard Worker const char *FB_WIDTH = getenv("FB_WIDTH");
355*d83cc019SAndroid Build Coastguard Worker const char *FB_HEIGHT = getenv("FB_HEIGHT");
356*d83cc019SAndroid Build Coastguard Worker
357*d83cc019SAndroid Build Coastguard Worker const size_t requested_fb_width = FB_WIDTH ?
358*d83cc019SAndroid Build Coastguard Worker (size_t)atoi(FB_WIDTH) :
359*d83cc019SAndroid Build Coastguard Worker mode->hdisplay;
360*d83cc019SAndroid Build Coastguard Worker
361*d83cc019SAndroid Build Coastguard Worker const size_t requested_fb_height = FB_HEIGHT ?
362*d83cc019SAndroid Build Coastguard Worker (size_t)atoi(FB_HEIGHT) :
363*d83cc019SAndroid Build Coastguard Worker mode->vdisplay;
364*d83cc019SAndroid Build Coastguard Worker
365*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(p->display, COMMIT_ATOMIC);
366*d83cc019SAndroid Build Coastguard Worker
367*d83cc019SAndroid Build Coastguard Worker struct igt_fb fb;
368*d83cc019SAndroid Build Coastguard Worker create_dumb_fb(p->display, requested_fb_width, requested_fb_height, &fb);
369*d83cc019SAndroid Build Coastguard Worker
370*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < tuning->num_fbs; ++i)
371*d83cc019SAndroid Build Coastguard Worker {
372*d83cc019SAndroid Build Coastguard Worker igt_plane_t *const plane = plane_for_index(p, i);
373*d83cc019SAndroid Build Coastguard Worker igt_plane_set_prop_value(plane, IGT_PLANE_ZPOS, i);
374*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, &fb);
375*d83cc019SAndroid Build Coastguard Worker
376*d83cc019SAndroid Build Coastguard Worker int ret = igt_display_try_commit_atomic(p->display,
377*d83cc019SAndroid Build Coastguard Worker DRM_MODE_ATOMIC_TEST_ONLY,
378*d83cc019SAndroid Build Coastguard Worker NULL);
379*d83cc019SAndroid Build Coastguard Worker
380*d83cc019SAndroid Build Coastguard Worker if (ret)
381*d83cc019SAndroid Build Coastguard Worker {
382*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].width = mode->hdisplay;
383*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].height = mode->vdisplay;
384*d83cc019SAndroid Build Coastguard Worker }
385*d83cc019SAndroid Build Coastguard Worker else
386*d83cc019SAndroid Build Coastguard Worker {
387*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].width = requested_fb_width;
388*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].height = requested_fb_height;
389*d83cc019SAndroid Build Coastguard Worker }
390*d83cc019SAndroid Build Coastguard Worker
391*d83cc019SAndroid Build Coastguard Worker igt_info("Plane %zu is %zux%zu\n", i,
392*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].width,
393*d83cc019SAndroid Build Coastguard Worker tuning->fb_geom[i].height);
394*d83cc019SAndroid Build Coastguard Worker
395*d83cc019SAndroid Build Coastguard Worker igt_plane_set_fb(plane, NULL);
396*d83cc019SAndroid Build Coastguard Worker }
397*d83cc019SAndroid Build Coastguard Worker
398*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(p->display->drm_fd, &fb);
399*d83cc019SAndroid Build Coastguard Worker }
400*d83cc019SAndroid Build Coastguard Worker
401*d83cc019SAndroid Build Coastguard Worker igt_main
402*d83cc019SAndroid Build Coastguard Worker {
403*d83cc019SAndroid Build Coastguard Worker igt_display_t display = {};
404*d83cc019SAndroid Build Coastguard Worker make_display(&display);
405*d83cc019SAndroid Build Coastguard Worker
406*d83cc019SAndroid Build Coastguard Worker igt_pipe_t *p = NULL;
407*d83cc019SAndroid Build Coastguard Worker igt_output_t *output = NULL;
408*d83cc019SAndroid Build Coastguard Worker get_pipe(&display, &p, &output);
409*d83cc019SAndroid Build Coastguard Worker
410*d83cc019SAndroid Build Coastguard Worker do_or_die(drmSetClientCap(
411*d83cc019SAndroid Build Coastguard Worker display.drm_fd,
412*d83cc019SAndroid Build Coastguard Worker DRM_CLIENT_CAP_ATOMIC,
413*d83cc019SAndroid Build Coastguard Worker 1));
414*d83cc019SAndroid Build Coastguard Worker
415*d83cc019SAndroid Build Coastguard Worker do_or_die(drmSetClientCap(
416*d83cc019SAndroid Build Coastguard Worker display.drm_fd,
417*d83cc019SAndroid Build Coastguard Worker DRM_CLIENT_CAP_UNIVERSAL_PLANES,
418*d83cc019SAndroid Build Coastguard Worker 1));
419*d83cc019SAndroid Build Coastguard Worker
420*d83cc019SAndroid Build Coastguard Worker igt_pipe_refresh(&display, p->pipe, true);
421*d83cc019SAndroid Build Coastguard Worker
422*d83cc019SAndroid Build Coastguard Worker prepare(&display, p, output);
423*d83cc019SAndroid Build Coastguard Worker
424*d83cc019SAndroid Build Coastguard Worker drmModeModeInfoPtr orig_mode = igt_output_get_mode(output);
425*d83cc019SAndroid Build Coastguard Worker
426*d83cc019SAndroid Build Coastguard Worker struct tuning tuning;
427*d83cc019SAndroid Build Coastguard Worker get_tuning(&tuning, &display, p, output);
428*d83cc019SAndroid Build Coastguard Worker
429*d83cc019SAndroid Build Coastguard Worker {
430*d83cc019SAndroid Build Coastguard Worker struct igt_fb **fb_sets =
431*d83cc019SAndroid Build Coastguard Worker malloc(sizeof(struct igt_fb*[tuning.num_fb_sets]));
432*d83cc019SAndroid Build Coastguard Worker
433*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < tuning.num_fb_sets; ++i)
434*d83cc019SAndroid Build Coastguard Worker {
435*d83cc019SAndroid Build Coastguard Worker fb_sets[i] = malloc(sizeof(struct igt_fb[tuning.num_fbs]));
436*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fbs = fb_sets[i];
437*d83cc019SAndroid Build Coastguard Worker for (size_t j = 0; j < tuning.num_fbs; ++j)
438*d83cc019SAndroid Build Coastguard Worker {
439*d83cc019SAndroid Build Coastguard Worker create_dumb_fb(&display,
440*d83cc019SAndroid Build Coastguard Worker tuning.fb_geom[j].width,
441*d83cc019SAndroid Build Coastguard Worker tuning.fb_geom[j].height,
442*d83cc019SAndroid Build Coastguard Worker &fbs[j]);
443*d83cc019SAndroid Build Coastguard Worker };
444*d83cc019SAndroid Build Coastguard Worker }
445*d83cc019SAndroid Build Coastguard Worker
446*d83cc019SAndroid Build Coastguard Worker
447*d83cc019SAndroid Build Coastguard Worker repeat_flip(p, fb_sets, &tuning);
448*d83cc019SAndroid Build Coastguard Worker
449*d83cc019SAndroid Build Coastguard Worker for (size_t i = 0; i < tuning.num_fb_sets; ++i)
450*d83cc019SAndroid Build Coastguard Worker {
451*d83cc019SAndroid Build Coastguard Worker struct igt_fb *fbs = fb_sets[i];
452*d83cc019SAndroid Build Coastguard Worker for (size_t j = 0; j < tuning.num_fbs; ++j)
453*d83cc019SAndroid Build Coastguard Worker {
454*d83cc019SAndroid Build Coastguard Worker igt_remove_fb(display.drm_fd, &fbs[j]);
455*d83cc019SAndroid Build Coastguard Worker };
456*d83cc019SAndroid Build Coastguard Worker free(fbs);
457*d83cc019SAndroid Build Coastguard Worker }
458*d83cc019SAndroid Build Coastguard Worker free(fb_sets);
459*d83cc019SAndroid Build Coastguard Worker }
460*d83cc019SAndroid Build Coastguard Worker
461*d83cc019SAndroid Build Coastguard Worker if (orig_mode != tuning.mode)
462*d83cc019SAndroid Build Coastguard Worker {
463*d83cc019SAndroid Build Coastguard Worker igt_output_override_mode(output, orig_mode);
464*d83cc019SAndroid Build Coastguard Worker igt_display_commit2(&display, COMMIT_ATOMIC);
465*d83cc019SAndroid Build Coastguard Worker }
466*d83cc019SAndroid Build Coastguard Worker
467*d83cc019SAndroid Build Coastguard Worker igt_info("Success\n");
468*d83cc019SAndroid Build Coastguard Worker }
469