blob: 1fc47dca8733d0c3cf502e03499a6b787de3d946 [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
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030029static void disable_psr()
Zach Reizner7d849892016-02-24 17:30:27 -080030{
Zach Reizner299fab72015-04-28 16:56:14 -070031 const char psr_path[] = "/sys/module/i915/parameters/enable_psr";
32 int psr_fd = open(psr_path, O_WRONLY);
33
34 if (psr_fd < 0)
35 return;
36
37 if (write(psr_fd, "0", 1) == -1) {
Zach Reizner7d849892016-02-24 17:30:27 -080038 bs_debug_error("failed to disable psr");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030039 } else {
Zach Reizner7d849892016-02-24 17:30:27 -080040 printf("disabled psr");
Zach Reizner299fab72015-04-28 16:56:14 -070041 }
42
43 close(psr_fd);
44}
45
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030046static void do_fixes()
Zach Reizner7d849892016-02-24 17:30:27 -080047{
Zach Reizner299fab72015-04-28 16:56:14 -070048 disable_psr();
49}
50
Zach Reiznerc09812f2015-01-12 16:49:49 -080051#define STEP_SKIP 0
52#define STEP_MMAP 1
53#define STEP_FAULT 2
54#define STEP_FLIP 3
55#define STEP_DRAW 4
56
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030057static void show_sequence(const int *sequence)
Zach Reiznerc09812f2015-01-12 16:49:49 -080058{
59 int sequence_subindex;
Zach Reizner7d849892016-02-24 17:30:27 -080060 printf("starting sequence: ");
Zach Reiznerc09812f2015-01-12 16:49:49 -080061 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
62 switch (sequence[sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -080063 case STEP_SKIP:
64 break;
65 case STEP_MMAP:
66 printf("mmap ");
67 break;
68 case STEP_FAULT:
69 printf("fault ");
70 break;
71 case STEP_FLIP:
72 printf("flip ");
73 break;
74 case STEP_DRAW:
75 printf("draw ");
76 break;
77 default:
78 bs_debug_error("<unknown step %d> (aborting!)",
79 sequence[sequence_subindex]);
80 abort();
81 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -080082 }
83 }
Zach Reizner7d849892016-02-24 17:30:27 -080084 printf("\n");
Zach Reiznerc09812f2015-01-12 16:49:49 -080085}
86
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030087static void draw(struct context *ctx)
Zach Reiznerc09812f2015-01-12 16:49:49 -080088{
Zach Reiznerc09812f2015-01-12 16:49:49 -080089 // Run the drawing routine with the key driver events in different
90 // sequences.
91 const int sequences[4][4] = {
92 { STEP_MMAP, STEP_FAULT, STEP_FLIP, STEP_DRAW },
Zach Reizner7d849892016-02-24 17:30:27 -080093 { STEP_MMAP, STEP_FLIP, STEP_DRAW, STEP_SKIP },
94 { STEP_MMAP, STEP_DRAW, STEP_FLIP, STEP_SKIP },
95 { STEP_FLIP, STEP_MMAP, STEP_DRAW, STEP_SKIP },
Zach Reiznerc09812f2015-01-12 16:49:49 -080096 };
97
98 int sequence_index = 0;
99 int sequence_subindex = 0;
100
101 int fb_idx = 1;
102
103 for (sequence_index = 0; sequence_index < 4; sequence_index++) {
104 show_sequence(sequences[sequence_index]);
Stéphane Marchesinf6fe9b72018-04-02 14:57:55 -0700105 for (int frame_index = 0; frame_index < NUM_FRAMES; frame_index += 2) {
Zach Reizner7d849892016-02-24 17:30:27 -0800106 struct framebuffer *fb = &ctx->fbs[fb_idx];
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700107 size_t bo_stride = gbm_bo_get_plane_stride(fb->bo, 0);
108 size_t bo_size = gbm_bo_get_plane_size(fb->bo, 0);
Gurchetan Singh3c382702017-04-10 18:22:10 -0700109 const uint32_t width = gbm_bo_get_width(fb->bo);
110 const uint32_t height = gbm_bo_get_height(fb->bo);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800111 uint32_t *bo_ptr;
112 volatile uint32_t *ptr;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700113 void *map_data;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800114
115 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
116 switch (sequences[sequence_index][sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -0800117 case STEP_MMAP:
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700118 bo_ptr = bs_mapper_map(ctx->mapper, fb->bo, 0,
119 &map_data);
120 if (bo_ptr == MAP_FAILED)
121 bs_debug_error("failed to mmap gbm bo");
122
Zach Reizner7d849892016-02-24 17:30:27 -0800123 ptr = bo_ptr;
124 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800125
Zach Reizner7d849892016-02-24 17:30:27 -0800126 case STEP_FAULT:
127 *ptr = 1234567;
128 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800129
Zach Reizner7d849892016-02-24 17:30:27 -0800130 case STEP_FLIP:
131 drmModePageFlip(ctx->display_fd, ctx->crtc_id,
132 ctx->fbs[fb_idx].id, 0, NULL);
133 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800134
Zach Reizner7d849892016-02-24 17:30:27 -0800135 case STEP_DRAW:
136 for (ptr = bo_ptr;
137 ptr < bo_ptr + (bo_size / sizeof(*bo_ptr));
138 ptr++) {
139 int y = ((void *)ptr - (void *)bo_ptr) /
140 bo_stride;
141 int x = ((void *)ptr - (void *)bo_ptr -
142 bo_stride * y) /
143 sizeof(*ptr);
Gurchetan Singh3c382702017-04-10 18:22:10 -0700144 x -= frame_index * (width / NUM_FRAMES);
145 y -= frame_index * (height / NUM_FRAMES);
Zach Reizner7d849892016-02-24 17:30:27 -0800146 *ptr = 0xff000000;
147 if (x * x + y * y <
148 frame_index * frame_index)
149 *ptr |= (frame_index % 0x100) << 8;
150 else
151 *ptr |= 0xff |
152 (sequence_index * 64 << 16);
153 }
154 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800155
Zach Reizner7d849892016-02-24 17:30:27 -0800156 case STEP_SKIP:
157 default:
158 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800159 }
160 }
161
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700162 bs_mapper_unmap(ctx->mapper, fb->bo, map_data);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800163
164 usleep(1e6 / 120); /* 120 Hz */
165
166 fb_idx = fb_idx ^ 1;
167 }
168 }
169}
170
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300171static const struct option longopts[] = {
172 { "help", no_argument, NULL, 'h' },
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700173 { "dma-buf", no_argument, NULL, 'b' },
174 { "gem", no_argument, NULL, 'g' },
175 { "dumb", no_argument, NULL, 'd' },
176 { "vgem", no_argument, NULL, 'v' },
177 { "scanout", no_argument, NULL, 's' },
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300178 { 0, 0, 0, 0 },
179};
180
181static void print_help(const char *argv0)
182{
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700183 printf("Usage: %s [OPTIONS]\n", argv0);
184 printf(" -h, --help Print help.\n");
185 printf(" -b, --dma-buf Use dma-buf mmap (by default).\n");
186 printf(" -g, --gem Use GEM map.\n");
187 printf(" -d, --dumb Use dump map.\n");
188 printf(" -v, --vgem Use vgem dump map.\n");
189 printf(" -s, --scanout Use buffer optimized for scanout.\n");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300190}
191
Zach Reiznerc09812f2015-01-12 16:49:49 -0800192int main(int argc, char **argv)
193{
Zach Reizner7d849892016-02-24 17:30:27 -0800194 struct context ctx = { 0 };
Zach Reiznerc09812f2015-01-12 16:49:49 -0800195
Zach Reizner299fab72015-04-28 16:56:14 -0700196 do_fixes();
197
Zach Reizner7d849892016-02-24 17:30:27 -0800198 ctx.display_fd = bs_drm_open_main_display();
199 if (ctx.display_fd < 0) {
200 bs_debug_error("failed to open card for display");
201 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800202 }
203
Zach Reizner7d849892016-02-24 17:30:27 -0800204 struct gbm_device *gbm = gbm_create_device(ctx.display_fd);
205 if (!gbm) {
206 bs_debug_error("failed to create gbm device");
207 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800208 }
209
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700210 int c;
Gurchetan Singh18a05992017-11-08 15:43:57 -0800211 uint32_t flags = GBM_BO_USE_SCANOUT;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700212 while ((c = getopt_long(argc, argv, "bgdvsh", longopts, NULL)) != -1) {
213 switch (c) {
214 case 'b':
215 ctx.mapper = bs_mapper_dma_buf_new();
Gurchetan Singh18a05992017-11-08 15:43:57 -0800216 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700217 printf("started dma-buf mmap.\n");
218 break;
219 case 'g':
220 ctx.mapper = bs_mapper_gem_new();
Gurchetan Singh18a05992017-11-08 15:43:57 -0800221 flags |= GBM_BO_USE_SW_READ_OFTEN | GBM_BO_USE_SW_WRITE_OFTEN;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700222 printf("started GEM map.\n");
223 break;
224 case 'd':
225 ctx.mapper = bs_mapper_dumb_new(gbm_device_get_fd(gbm));
Gurchetan Singh18a05992017-11-08 15:43:57 -0800226 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700227 printf("started dumb map.\n");
228 break;
229 case 'v':
230 ctx.vgem_device_fd = bs_drm_open_vgem();
231 ctx.mapper = bs_mapper_dumb_new(ctx.vgem_device_fd);
232 printf("started vgem map.\n");
233 break;
234 case 's':
235 flags = GBM_BO_USE_SCANOUT;
236 break;
237 case 'h':
238 default:
239 print_help(argv[0]);
240 return 1;
241 }
242 }
243
244 // Use dma-buf mmap by default, in case any arguments aren't selected.
245 if (!ctx.mapper) {
246 ctx.mapper = bs_mapper_dma_buf_new();
Deepak Sharma8df6d932018-01-30 17:13:35 -0800247 flags |= GBM_BO_USE_LINEAR;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700248 printf("started dma-buf mmap.\n");
249 }
250
251 if (ctx.mapper == NULL) {
252 bs_debug_error("failed to create mapper object");
253 return 1;
254 }
255
Zach Reizner7d849892016-02-24 17:30:27 -0800256 struct bs_drm_pipe pipe = { 0 };
257 if (!bs_drm_pipe_make(ctx.display_fd, &pipe)) {
258 bs_debug_error("failed to make pipe");
259 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800260 }
261
Zach Reizner7d849892016-02-24 17:30:27 -0800262 drmModeConnector *connector = drmModeGetConnector(ctx.display_fd, pipe.connector_id);
263 drmModeModeInfo *mode = &connector->modes[0];
264 ctx.crtc_id = pipe.crtc_id;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800265
Zach Reizner7d849892016-02-24 17:30:27 -0800266 printf("display size: %ux%u\n", mode->hdisplay, mode->vdisplay);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800267
Zach Reizner7d849892016-02-24 17:30:27 -0800268 for (size_t fb_index = 0; fb_index < BUFFERS; ++fb_index) {
269 struct framebuffer *fb = &ctx.fbs[fb_index];
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700270 fb->bo =
271 gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888, flags);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800272
Zach Reizner7d849892016-02-24 17:30:27 -0800273 if (!fb->bo) {
274 bs_debug_error("failed to create buffer object");
275 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800276 }
277
Zach Reizner7d849892016-02-24 17:30:27 -0800278 fb->id = bs_drm_fb_create_gbm(fb->bo);
279 if (fb->id == 0) {
280 bs_debug_error("failed to create fb");
281 return 1;
282 }
Zach Reiznerc09812f2015-01-12 16:49:49 -0800283 }
284
Zach Reizner7d849892016-02-24 17:30:27 -0800285 if (drmModeSetCrtc(ctx.display_fd, pipe.crtc_id, ctx.fbs[0].id, 0, 0, &pipe.connector_id, 1,
286 mode)) {
287 bs_debug_error("failed to set CRTC");
288 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800289 }
290
291 draw(&ctx);
292
Zach Reizner7d849892016-02-24 17:30:27 -0800293 return 0;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800294}