blob: 0ea121fe733e2ec343cd97aa7f58121b44e686d2 [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
12
Zach Reizner7d849892016-02-24 17:30:27 -080013struct framebuffer {
14 struct gbm_bo *bo;
Zach Reizner7d849892016-02-24 17:30:27 -080015 uint32_t id;
Zach Reiznerc09812f2015-01-12 16:49:49 -080016};
17
Zach Reizner7d849892016-02-24 17:30:27 -080018struct context {
19 int display_fd;
Zach Reizner7d849892016-02-24 17:30:27 -080020 uint32_t crtc_id;
21
22 struct framebuffer fbs[BUFFERS];
Dongseong Hwang9093afe2017-03-20 19:16:28 -070023 struct bs_mapper *mapper;
24
25 int vgem_device_fd;
Zach Reizner7d849892016-02-24 17:30:27 -080026};
27
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030028static void disable_psr()
Zach Reizner7d849892016-02-24 17:30:27 -080029{
Zach Reizner299fab72015-04-28 16:56:14 -070030 const char psr_path[] = "/sys/module/i915/parameters/enable_psr";
31 int psr_fd = open(psr_path, O_WRONLY);
32
33 if (psr_fd < 0)
34 return;
35
36 if (write(psr_fd, "0", 1) == -1) {
Zach Reizner7d849892016-02-24 17:30:27 -080037 bs_debug_error("failed to disable psr");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030038 } else {
Zach Reizner7d849892016-02-24 17:30:27 -080039 printf("disabled psr");
Zach Reizner299fab72015-04-28 16:56:14 -070040 }
41
42 close(psr_fd);
43}
44
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030045static void do_fixes()
Zach Reizner7d849892016-02-24 17:30:27 -080046{
Zach Reizner299fab72015-04-28 16:56:14 -070047 disable_psr();
48}
49
Zach Reiznerc09812f2015-01-12 16:49:49 -080050#define STEP_SKIP 0
51#define STEP_MMAP 1
52#define STEP_FAULT 2
53#define STEP_FLIP 3
54#define STEP_DRAW 4
55
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030056static void show_sequence(const int *sequence)
Zach Reiznerc09812f2015-01-12 16:49:49 -080057{
58 int sequence_subindex;
Zach Reizner7d849892016-02-24 17:30:27 -080059 printf("starting sequence: ");
Zach Reiznerc09812f2015-01-12 16:49:49 -080060 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
61 switch (sequence[sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -080062 case STEP_SKIP:
63 break;
64 case STEP_MMAP:
65 printf("mmap ");
66 break;
67 case STEP_FAULT:
68 printf("fault ");
69 break;
70 case STEP_FLIP:
71 printf("flip ");
72 break;
73 case STEP_DRAW:
74 printf("draw ");
75 break;
76 default:
77 bs_debug_error("<unknown step %d> (aborting!)",
78 sequence[sequence_subindex]);
79 abort();
80 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -080081 }
82 }
Zach Reizner7d849892016-02-24 17:30:27 -080083 printf("\n");
Zach Reiznerc09812f2015-01-12 16:49:49 -080084}
85
Dongseong Hwang59ff9f92016-04-22 17:39:32 +030086static void draw(struct context *ctx)
Zach Reiznerc09812f2015-01-12 16:49:49 -080087{
Zach Reiznerc09812f2015-01-12 16:49:49 -080088 // Run the drawing routine with the key driver events in different
89 // sequences.
90 const int sequences[4][4] = {
91 { STEP_MMAP, STEP_FAULT, STEP_FLIP, STEP_DRAW },
Zach Reizner7d849892016-02-24 17:30:27 -080092 { STEP_MMAP, STEP_FLIP, STEP_DRAW, STEP_SKIP },
93 { STEP_MMAP, STEP_DRAW, STEP_FLIP, STEP_SKIP },
94 { STEP_FLIP, STEP_MMAP, STEP_DRAW, STEP_SKIP },
Zach Reiznerc09812f2015-01-12 16:49:49 -080095 };
96
97 int sequence_index = 0;
98 int sequence_subindex = 0;
99
100 int fb_idx = 1;
101
102 for (sequence_index = 0; sequence_index < 4; sequence_index++) {
103 show_sequence(sequences[sequence_index]);
Zach Reizner7d849892016-02-24 17:30:27 -0800104 for (int frame_index = 0; frame_index < 0x100; frame_index++) {
105 struct framebuffer *fb = &ctx->fbs[fb_idx];
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700106 size_t bo_stride = gbm_bo_get_plane_stride(fb->bo, 0);
107 size_t bo_size = gbm_bo_get_plane_size(fb->bo, 0);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800108 uint32_t *bo_ptr;
109 volatile uint32_t *ptr;
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700110 void *map_data;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800111
112 for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
113 switch (sequences[sequence_index][sequence_subindex]) {
Zach Reizner7d849892016-02-24 17:30:27 -0800114 case STEP_MMAP:
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700115 bo_ptr = bs_mapper_map(ctx->mapper, fb->bo, 0,
116 &map_data);
117 if (bo_ptr == MAP_FAILED)
118 bs_debug_error("failed to mmap gbm bo");
119
Zach Reizner7d849892016-02-24 17:30:27 -0800120 ptr = bo_ptr;
121 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800122
Zach Reizner7d849892016-02-24 17:30:27 -0800123 case STEP_FAULT:
124 *ptr = 1234567;
125 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800126
Zach Reizner7d849892016-02-24 17:30:27 -0800127 case STEP_FLIP:
128 drmModePageFlip(ctx->display_fd, ctx->crtc_id,
129 ctx->fbs[fb_idx].id, 0, NULL);
130 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800131
Zach Reizner7d849892016-02-24 17:30:27 -0800132 case STEP_DRAW:
133 for (ptr = bo_ptr;
134 ptr < bo_ptr + (bo_size / sizeof(*bo_ptr));
135 ptr++) {
136 int y = ((void *)ptr - (void *)bo_ptr) /
137 bo_stride;
138 int x = ((void *)ptr - (void *)bo_ptr -
139 bo_stride * y) /
140 sizeof(*ptr);
141 x -= 100;
142 y -= 100;
143 *ptr = 0xff000000;
144 if (x * x + y * y <
145 frame_index * frame_index)
146 *ptr |= (frame_index % 0x100) << 8;
147 else
148 *ptr |= 0xff |
149 (sequence_index * 64 << 16);
150 }
151 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800152
Zach Reizner7d849892016-02-24 17:30:27 -0800153 case STEP_SKIP:
154 default:
155 break;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800156 }
157 }
158
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700159 bs_mapper_unmap(ctx->mapper, fb->bo, map_data);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800160
161 usleep(1e6 / 120); /* 120 Hz */
162
163 fb_idx = fb_idx ^ 1;
164 }
165 }
166}
167
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300168static const struct option longopts[] = {
169 { "help", no_argument, NULL, 'h' },
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700170 { "dma-buf", no_argument, NULL, 'b' },
171 { "gem", no_argument, NULL, 'g' },
172 { "dumb", no_argument, NULL, 'd' },
173 { "vgem", no_argument, NULL, 'v' },
174 { "scanout", no_argument, NULL, 's' },
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300175 { 0, 0, 0, 0 },
176};
177
178static void print_help(const char *argv0)
179{
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700180 printf("Usage: %s [OPTIONS]\n", argv0);
181 printf(" -h, --help Print help.\n");
182 printf(" -b, --dma-buf Use dma-buf mmap (by default).\n");
183 printf(" -g, --gem Use GEM map.\n");
184 printf(" -d, --dumb Use dump map.\n");
185 printf(" -v, --vgem Use vgem dump map.\n");
186 printf(" -s, --scanout Use buffer optimized for scanout.\n");
Dongseong Hwang59ff9f92016-04-22 17:39:32 +0300187}
188
Zach Reiznerc09812f2015-01-12 16:49:49 -0800189int main(int argc, char **argv)
190{
Zach Reizner7d849892016-02-24 17:30:27 -0800191 struct context ctx = { 0 };
Zach Reiznerc09812f2015-01-12 16:49:49 -0800192
Zach Reizner299fab72015-04-28 16:56:14 -0700193 do_fixes();
194
Zach Reizner7d849892016-02-24 17:30:27 -0800195 ctx.display_fd = bs_drm_open_main_display();
196 if (ctx.display_fd < 0) {
197 bs_debug_error("failed to open card for display");
198 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800199 }
200
Zach Reizner7d849892016-02-24 17:30:27 -0800201 struct gbm_device *gbm = gbm_create_device(ctx.display_fd);
202 if (!gbm) {
203 bs_debug_error("failed to create gbm device");
204 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800205 }
206
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700207 int c;
208 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR;
209 while ((c = getopt_long(argc, argv, "bgdvsh", longopts, NULL)) != -1) {
210 switch (c) {
211 case 'b':
212 ctx.mapper = bs_mapper_dma_buf_new();
213 printf("started dma-buf mmap.\n");
214 break;
215 case 'g':
216 ctx.mapper = bs_mapper_gem_new();
217 printf("started GEM map.\n");
218 break;
219 case 'd':
220 ctx.mapper = bs_mapper_dumb_new(gbm_device_get_fd(gbm));
221 printf("started dumb map.\n");
222 break;
223 case 'v':
224 ctx.vgem_device_fd = bs_drm_open_vgem();
225 ctx.mapper = bs_mapper_dumb_new(ctx.vgem_device_fd);
226 printf("started vgem map.\n");
227 break;
228 case 's':
229 flags = GBM_BO_USE_SCANOUT;
230 break;
231 case 'h':
232 default:
233 print_help(argv[0]);
234 return 1;
235 }
236 }
237
238 // Use dma-buf mmap by default, in case any arguments aren't selected.
239 if (!ctx.mapper) {
240 ctx.mapper = bs_mapper_dma_buf_new();
241 printf("started dma-buf mmap.\n");
242 }
243
244 if (ctx.mapper == NULL) {
245 bs_debug_error("failed to create mapper object");
246 return 1;
247 }
248
Zach Reizner7d849892016-02-24 17:30:27 -0800249 struct bs_drm_pipe pipe = { 0 };
250 if (!bs_drm_pipe_make(ctx.display_fd, &pipe)) {
251 bs_debug_error("failed to make pipe");
252 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800253 }
254
Zach Reizner7d849892016-02-24 17:30:27 -0800255 drmModeConnector *connector = drmModeGetConnector(ctx.display_fd, pipe.connector_id);
256 drmModeModeInfo *mode = &connector->modes[0];
257 ctx.crtc_id = pipe.crtc_id;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800258
Zach Reizner7d849892016-02-24 17:30:27 -0800259 printf("display size: %ux%u\n", mode->hdisplay, mode->vdisplay);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800260
Zach Reizner7d849892016-02-24 17:30:27 -0800261 for (size_t fb_index = 0; fb_index < BUFFERS; ++fb_index) {
262 struct framebuffer *fb = &ctx.fbs[fb_index];
Dongseong Hwang9093afe2017-03-20 19:16:28 -0700263 fb->bo =
264 gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888, flags);
Zach Reiznerc09812f2015-01-12 16:49:49 -0800265
Zach Reizner7d849892016-02-24 17:30:27 -0800266 if (!fb->bo) {
267 bs_debug_error("failed to create buffer object");
268 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800269 }
270
Zach Reizner7d849892016-02-24 17:30:27 -0800271 fb->id = bs_drm_fb_create_gbm(fb->bo);
272 if (fb->id == 0) {
273 bs_debug_error("failed to create fb");
274 return 1;
275 }
Zach Reiznerc09812f2015-01-12 16:49:49 -0800276 }
277
Zach Reizner7d849892016-02-24 17:30:27 -0800278 if (drmModeSetCrtc(ctx.display_fd, pipe.crtc_id, ctx.fbs[0].id, 0, 0, &pipe.connector_id, 1,
279 mode)) {
280 bs_debug_error("failed to set CRTC");
281 return 1;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800282 }
283
284 draw(&ctx);
285
Zach Reizner7d849892016-02-24 17:30:27 -0800286 return 0;
Zach Reiznerc09812f2015-01-12 16:49:49 -0800287}