blob: 7ac1ffbd3a8e29f3b52af8f34a6113f2a0f0e4d8 [file] [log] [blame]
Zach Reiznerc09812f2015-01-12 16:49:49 -08001/*
Dongseong Hwang59ff9f92016-04-22 17:39:32 +03002 * Copyright 2017 The Chromium OS Authors. All rights reserved.
Zach Reiznerc09812f2015-01-12 16:49:49 -08003 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
Dongseong Hwang59ff9f92016-04-22 17:39:32 +03007#include <getopt.h>
8
Zach Reizner7d849892016-02-24 17:30:27 -08009#include "bs_drm.h"
Zach Reiznerc09812f2015-01-12 16:49:49 -080010
11#define BUFFERS 2
Gurchetan Singh68da5c02017-11-17 17:47:27 -080012#define NUM_FRAMES 0x40
Zach Reiznerc09812f2015-01-12 16:49:49 -080013
Zach Reizner7d849892016-02-24 17:30:27 -080014struct framebuffer {
15 struct gbm_bo *bo;
Zach Reizner7d849892016-02-24 17:30:27 -080016 uint32_t id;
Zach Reiznerc09812f2015-01-12 16:49:49 -080017};
18
Zach Reizner7d849892016-02-24 17:30:27 -080019struct context {
20 int display_fd;
Zach Reizner7d849892016-02-24 17:30:27 -080021 uint32_t crtc_id;
22
23 struct framebuffer fbs[BUFFERS];
Dongseong Hwang9093afe2017-03-20 19:16:28 -070024 struct bs_mapper *mapper;
25
26 int vgem_device_fd;
Zach Reizner7d849892016-02-24 17:30:27 -080027};
28
Casey Bowman6b2da632018-09-24 15:06:55 -070029struct disabled_features {
30 char psr_prev_val[1];
31};
32
33const char psr_path[] = "/sys/module/i915/parameters/enable_psr";
34
35static void disable_psr(struct disabled_features *dis_feat)
Zach Reizner7d849892016-02-24 17:30:27 -080036{
Casey Bowman6b2da632018-09-24 15:06:55 -070037 int psr_fd = open(psr_path, O_RDWR);
Zach Reizner299fab72015-04-28 16:56:14 -070038
39 if (psr_fd < 0)
40 return;
41
Casey Bowman6b2da632018-09-24 15:06:55 -070042 if (read(psr_fd, dis_feat->psr_prev_val, 1) == -1) {
43 bs_debug_error("failed to read psr value");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030044 } else {
Casey Bowman6b2da632018-09-24 15:06:55 -070045 printf("previous enable_psr value: %c\n", dis_feat->psr_prev_val[0]);
46 }
47 if (strncmp(dis_feat->psr_prev_val, "1", 1) == 0) {
48 if (write(psr_fd, "0", 1) == -1) {
49 bs_debug_error("failed to disable psr");
50 } else {
51 printf("disabled psr\n");
52 }
Zach Reizner299fab72015-04-28 16:56:14 -070053 }
54
55 close(psr_fd);
56}
57
Casey Bowman6b2da632018-09-24 15:06:55 -070058static void restore_psr(struct disabled_features *dis_feat)
Zach Reizner7d849892016-02-24 17:30:27 -080059{
Casey Bowman6b2da632018-09-24 15:06:55 -070060 if (strncmp(dis_feat->psr_prev_val, "1", 1) == 0) {
61 int psr_fd = open(psr_path, O_WRONLY);
62
63 if (psr_fd < 0)
64 return;
65
66 if (write(psr_fd, "1", 1) == -1) {
67 bs_debug_error("failed to re-enable psr");
68 } else {
69 printf("re-enabled psr\n");
70 }
71
72 close(psr_fd);
73 }
74}
75
76static void do_fixes(struct disabled_features *dis_feat)
77{
78 disable_psr(dis_feat);
79}
80
81static void restore_features(struct disabled_features *dis_feat)
82{
83 restore_psr(dis_feat);
Zach Reizner299fab72015-04-28 16:56:14 -070084}
85
Zach Reiznerc09812f2015-01-12 16:49:49 -080086#define STEP_SKIP 0
87#define STEP_MMAP 1
88#define STEP_FAULT 2
89#define STEP_FLIP 3
90#define STEP_DRAW 4
91
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030092static void show_sequence(const int *sequence)
Zach Reiznerc09812f2015-01-12 16:49:49 -080093{
94 int sequence_subindex;
Zach Reizner7d849892016-02-24 17:30:27 -080095 printf("starting sequence: ");
Zach Reiznerc09812f2015-01-12 16:49:49 -080096 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
97 switch (sequence[sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -080098 case STEP_SKIP:
99 break;
100 case STEP_MMAP:
101 printf("mmap ");
102 break;
103 case STEP_FAULT:
104 printf("fault ");
105 break;
106 case STEP_FLIP:
107 printf("flip ");
108 break;
109 case STEP_DRAW:
110 printf("draw ");
111 break;
112 default:
113 bs_debug_error("<unknown step %d> (aborting!)",
114 sequence[sequence_subindex]);
115 abort();
116 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800117 }
118 }
Zach Reizner7d849892016-02-24 17:30:27 -0800119 printf("\n");
Zach Reiznerc09812f2015-01-12 16:49:49 -0800120}
121
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300122static void draw(struct context *ctx)
Zach Reiznerc09812f2015-01-12 16:49:49 -0800123{
Zach Reiznerc09812f2015-01-12 16:49:49 -0800124 // Run the drawing routine with the key driver events in different
125 // sequences.
126 const int sequences[4][4] = {
127 { STEP_MMAP, STEP_FAULT, STEP_FLIP, STEP_DRAW },
Zach Reizner7d849892016-02-24 17:30:27 -0800128 { STEP_MMAP, STEP_FLIP, STEP_DRAW, STEP_SKIP },
129 { STEP_MMAP, STEP_DRAW, STEP_FLIP, STEP_SKIP },
130 { STEP_FLIP, STEP_MMAP, STEP_DRAW, STEP_SKIP },
Zach Reiznerc09812f2015-01-12 16:49:49 -0800131 };
132
133 int sequence_index = 0;
134 int sequence_subindex = 0;
135
136 int fb_idx = 1;
137
138 for (sequence_index = 0; sequence_index < 4; sequence_index++) {
139 show_sequence(sequences[sequence_index]);
Stéphane Marchesinf6fe9b72018-04-02 14:57:55 -0700140 for (int frame_index = 0; frame_index < NUM_FRAMES; frame_index += 2) {
Zach Reizner7d849892016-02-24 17:30:27 -0800141 struct framebuffer *fb = &ctx->fbs[fb_idx];
Satyajit Sahub7e47dd2018-05-07 12:35:50 +0530142 uint32_t bo_stride;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700143 size_t bo_size = gbm_bo_get_plane_size(fb->bo, 0);
Gurchetan Singh3c382702017-04-10 18:22:10 -0700144 const uint32_t width = gbm_bo_get_width(fb->bo);
145 const uint32_t height = gbm_bo_get_height(fb->bo);
Gurchetan Singh7fb6e962020-08-24 10:51:23 -0700146 uint32_t *bo_ptr = NULL;
147 volatile uint32_t *ptr = NULL;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700148 void *map_data;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800149
150 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
151 switch (sequences[sequence_index][sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -0800152 case STEP_MMAP:
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700153 bo_ptr = bs_mapper_map(ctx->mapper, fb->bo, 0,
Satyajit Sahub7e47dd2018-05-07 12:35:50 +0530154 &map_data, &bo_stride);
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700155 if (bo_ptr == MAP_FAILED)
156 bs_debug_error("failed to mmap gbm bo");
157
Zach Reizner7d849892016-02-24 17:30:27 -0800158 ptr = bo_ptr;
159 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800160
Zach Reizner7d849892016-02-24 17:30:27 -0800161 case STEP_FAULT:
162 *ptr = 1234567;
163 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800164
Zach Reizner7d849892016-02-24 17:30:27 -0800165 case STEP_FLIP:
166 drmModePageFlip(ctx->display_fd, ctx->crtc_id,
167 ctx->fbs[fb_idx].id, 0, NULL);
168 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800169
Zach Reizner7d849892016-02-24 17:30:27 -0800170 case STEP_DRAW:
171 for (ptr = bo_ptr;
172 ptr < bo_ptr + (bo_size / sizeof(*bo_ptr));
173 ptr++) {
174 int y = ((void *)ptr - (void *)bo_ptr) /
175 bo_stride;
176 int x = ((void *)ptr - (void *)bo_ptr -
177 bo_stride * y) /
178 sizeof(*ptr);
Gurchetan Singh3c382702017-04-10 18:22:10 -0700179 x -= frame_index * (width / NUM_FRAMES);
180 y -= frame_index * (height / NUM_FRAMES);
Zach Reizner7d849892016-02-24 17:30:27 -0800181 *ptr = 0xff000000;
182 if (x * x + y * y <
183 frame_index * frame_index)
184 *ptr |= (frame_index % 0x100) << 8;
185 else
186 *ptr |= 0xff |
187 (sequence_index * 64 << 16);
188 }
189 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800190
Zach Reizner7d849892016-02-24 17:30:27 -0800191 case STEP_SKIP:
192 default:
193 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800194 }
195 }
196
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700197 bs_mapper_unmap(ctx->mapper, fb->bo, map_data);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800198
199 usleep(1e6 / 120); /* 120 Hz */
200
201 fb_idx = fb_idx ^ 1;
202 }
203 }
204}
205
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300206static const struct option longopts[] = {
207 { "help", no_argument, NULL, 'h' },
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700208 { "dma-buf", no_argument, NULL, 'b' },
209 { "gem", no_argument, NULL, 'g' },
210 { "dumb", no_argument, NULL, 'd' },
211 { "vgem", no_argument, NULL, 'v' },
212 { "scanout", no_argument, NULL, 's' },
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300213 { 0, 0, 0, 0 },
214};
215
216static void print_help(const char *argv0)
217{
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700218 printf("Usage: %s [OPTIONS]\n", argv0);
219 printf(" -h, --help Print help.\n");
220 printf(" -b, --dma-buf Use dma-buf mmap (by default).\n");
221 printf(" -g, --gem Use GEM map.\n");
222 printf(" -d, --dumb Use dump map.\n");
223 printf(" -v, --vgem Use vgem dump map.\n");
224 printf(" -s, --scanout Use buffer optimized for scanout.\n");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300225}
226
Zach Reiznerc09812f2015-01-12 16:49:49 -0800227int main(int argc, char **argv)
228{
Zach Reizner7d849892016-02-24 17:30:27 -0800229 struct context ctx = { 0 };
Casey Bowman6b2da632018-09-24 15:06:55 -0700230 struct disabled_features dis_feat = { 0 };
Zach Reiznerc09812f2015-01-12 16:49:49 -0800231
Casey Bowman6b2da632018-09-24 15:06:55 -0700232 do_fixes(&dis_feat);
Zach Reizner299fab72015-04-28 16:56:14 -0700233
Zach Reizner7d849892016-02-24 17:30:27 -0800234 ctx.display_fd = bs_drm_open_main_display();
235 if (ctx.display_fd < 0) {
236 bs_debug_error("failed to open card for display");
237 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800238 }
239
Zach Reizner7d849892016-02-24 17:30:27 -0800240 struct gbm_device *gbm = gbm_create_device(ctx.display_fd);
241 if (!gbm) {
242 bs_debug_error("failed to create gbm device");
243 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800244 }
245
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700246 int c;
Gurchetan Singh18a05992017-11-08 15:43:57 -0800247 uint32_t flags = GBM_BO_USE_SCANOUT;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700248 while ((c = getopt_long(argc, argv, "bgdvsh", longopts, NULL)) != -1) {
249 switch (c) {
250 case 'b':
251 ctx.mapper = bs_mapper_dma_buf_new();
Gurchetan Singh18a05992017-11-08 15:43:57 -0800252 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700253 printf("started dma-buf mmap.\n");
254 break;
255 case 'g':
256 ctx.mapper = bs_mapper_gem_new();
Gurchetan Singh18a05992017-11-08 15:43:57 -0800257 flags |= GBM_BO_USE_SW_READ_OFTEN | GBM_BO_USE_SW_WRITE_OFTEN;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700258 printf("started GEM map.\n");
259 break;
260 case 'd':
261 ctx.mapper = bs_mapper_dumb_new(gbm_device_get_fd(gbm));
Gurchetan Singh18a05992017-11-08 15:43:57 -0800262 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700263 printf("started dumb map.\n");
264 break;
265 case 'v':
266 ctx.vgem_device_fd = bs_drm_open_vgem();
267 ctx.mapper = bs_mapper_dumb_new(ctx.vgem_device_fd);
268 printf("started vgem map.\n");
269 break;
270 case 's':
271 flags = GBM_BO_USE_SCANOUT;
272 break;
273 case 'h':
274 default:
275 print_help(argv[0]);
276 return 1;
277 }
278 }
279
280 // Use dma-buf mmap by default, in case any arguments aren't selected.
281 if (!ctx.mapper) {
282 ctx.mapper = bs_mapper_dma_buf_new();
Deepak Sharma8df6d932018-01-30 17:13:35 -0800283 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700284 printf("started dma-buf mmap.\n");
285 }
286
287 if (ctx.mapper == NULL) {
288 bs_debug_error("failed to create mapper object");
289 return 1;
290 }
291
Zach Reizner7d849892016-02-24 17:30:27 -0800292 struct bs_drm_pipe pipe = { 0 };
293 if (!bs_drm_pipe_make(ctx.display_fd, &pipe)) {
294 bs_debug_error("failed to make pipe");
295 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800296 }
297
Zach Reizner7d849892016-02-24 17:30:27 -0800298 drmModeConnector *connector = drmModeGetConnector(ctx.display_fd, pipe.connector_id);
299 drmModeModeInfo *mode = &connector->modes[0];
300 ctx.crtc_id = pipe.crtc_id;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800301
Zach Reizner7d849892016-02-24 17:30:27 -0800302 printf("display size: %ux%u\n", mode->hdisplay, mode->vdisplay);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800303
Zach Reizner7d849892016-02-24 17:30:27 -0800304 for (size_t fb_index = 0; fb_index < BUFFERS; ++fb_index) {
305 struct framebuffer *fb = &ctx.fbs[fb_index];
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700306 fb->bo =
307 gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888, flags);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800308
Zach Reizner7d849892016-02-24 17:30:27 -0800309 if (!fb->bo) {
310 bs_debug_error("failed to create buffer object");
311 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800312 }
313
Zach Reizner7d849892016-02-24 17:30:27 -0800314 fb->id = bs_drm_fb_create_gbm(fb->bo);
315 if (fb->id == 0) {
316 bs_debug_error("failed to create fb");
317 return 1;
318 }
Zach Reiznerc09812f2015-01-12 16:49:49 -0800319 }
320
Zach Reizner7d849892016-02-24 17:30:27 -0800321 if (drmModeSetCrtc(ctx.display_fd, pipe.crtc_id, ctx.fbs[0].id, 0, 0, &pipe.connector_id, 1,
322 mode)) {
323 bs_debug_error("failed to set CRTC");
324 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800325 }
326
327 draw(&ctx);
328
Casey Bowman6b2da632018-09-24 15:06:55 -0700329 restore_features(&dis_feat);
330
Zach Reizner7d849892016-02-24 17:30:27 -0800331 return 0;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800332}