Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 1 | /* |
Dongseong Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 2 | * Copyright 2017 The Chromium OS Authors. All rights reserved. |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 3 | * Use of this source code is governed by a BSD-style license that can be |
| 4 | * found in the LICENSE file. |
| 5 | */ |
| 6 | |
Dongseong Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 7 | #include <getopt.h> |
| 8 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 9 | #include "bs_drm.h" |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 10 | |
| 11 | #define BUFFERS 2 |
Gurchetan Singh | 68da5c0 | 2017-11-17 17:47:27 -0800 | [diff] [blame] | 12 | #define NUM_FRAMES 0x40 |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 13 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 14 | struct framebuffer { |
| 15 | struct gbm_bo *bo; |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 16 | uint32_t id; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 17 | }; |
| 18 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 19 | struct context { |
| 20 | int display_fd; |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 21 | uint32_t crtc_id; |
| 22 | |
| 23 | struct framebuffer fbs[BUFFERS]; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 24 | struct bs_mapper *mapper; |
| 25 | |
| 26 | int vgem_device_fd; |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 27 | }; |
| 28 | |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 29 | struct disabled_features { |
| 30 | char psr_prev_val[1]; |
| 31 | }; |
| 32 | |
| 33 | const char psr_path[] = "/sys/module/i915/parameters/enable_psr"; |
| 34 | |
| 35 | static void disable_psr(struct disabled_features *dis_feat) |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 36 | { |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 37 | int psr_fd = open(psr_path, O_RDWR); |
Zach Reizner | 299fab7 | 2015-04-28 16:56:14 -0700 | [diff] [blame] | 38 | |
| 39 | if (psr_fd < 0) |
| 40 | return; |
| 41 | |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 42 | if (read(psr_fd, dis_feat->psr_prev_val, 1) == -1) { |
| 43 | bs_debug_error("failed to read psr value"); |
Dongseong Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 44 | } else { |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 45 | 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 Reizner | 299fab7 | 2015-04-28 16:56:14 -0700 | [diff] [blame] | 53 | } |
| 54 | |
| 55 | close(psr_fd); |
| 56 | } |
| 57 | |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 58 | static void restore_psr(struct disabled_features *dis_feat) |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 59 | { |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 60 | 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 | |
| 76 | static void do_fixes(struct disabled_features *dis_feat) |
| 77 | { |
| 78 | disable_psr(dis_feat); |
| 79 | } |
| 80 | |
| 81 | static void restore_features(struct disabled_features *dis_feat) |
| 82 | { |
| 83 | restore_psr(dis_feat); |
Zach Reizner | 299fab7 | 2015-04-28 16:56:14 -0700 | [diff] [blame] | 84 | } |
| 85 | |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 86 | #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 Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 92 | static void show_sequence(const int *sequence) |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 93 | { |
| 94 | int sequence_subindex; |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 95 | printf("starting sequence: "); |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 96 | for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) { |
| 97 | switch (sequence[sequence_subindex]) { |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 98 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 117 | } |
| 118 | } |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 119 | printf("\n"); |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 120 | } |
| 121 | |
Dongseong Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 122 | static void draw(struct context *ctx) |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 123 | { |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 124 | // 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 Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 128 | { 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 131 | }; |
| 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 Marchesin | f6fe9b7 | 2018-04-02 14:57:55 -0700 | [diff] [blame] | 140 | for (int frame_index = 0; frame_index < NUM_FRAMES; frame_index += 2) { |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 141 | struct framebuffer *fb = &ctx->fbs[fb_idx]; |
Satyajit Sahu | b7e47dd | 2018-05-07 12:35:50 +0530 | [diff] [blame] | 142 | uint32_t bo_stride; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 143 | size_t bo_size = gbm_bo_get_plane_size(fb->bo, 0); |
Gurchetan Singh | 3c38270 | 2017-04-10 18:22:10 -0700 | [diff] [blame] | 144 | const uint32_t width = gbm_bo_get_width(fb->bo); |
| 145 | const uint32_t height = gbm_bo_get_height(fb->bo); |
Gurchetan Singh | 7fb6e96 | 2020-08-24 10:51:23 -0700 | [diff] [blame] | 146 | uint32_t *bo_ptr = NULL; |
| 147 | volatile uint32_t *ptr = NULL; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 148 | void *map_data; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 149 | |
| 150 | for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) { |
| 151 | switch (sequences[sequence_index][sequence_subindex]) { |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 152 | case STEP_MMAP: |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 153 | bo_ptr = bs_mapper_map(ctx->mapper, fb->bo, 0, |
Satyajit Sahu | b7e47dd | 2018-05-07 12:35:50 +0530 | [diff] [blame] | 154 | &map_data, &bo_stride); |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 155 | if (bo_ptr == MAP_FAILED) |
| 156 | bs_debug_error("failed to mmap gbm bo"); |
| 157 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 158 | ptr = bo_ptr; |
| 159 | break; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 160 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 161 | case STEP_FAULT: |
| 162 | *ptr = 1234567; |
| 163 | break; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 164 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 165 | case STEP_FLIP: |
| 166 | drmModePageFlip(ctx->display_fd, ctx->crtc_id, |
| 167 | ctx->fbs[fb_idx].id, 0, NULL); |
| 168 | break; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 169 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 170 | 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 Singh | 3c38270 | 2017-04-10 18:22:10 -0700 | [diff] [blame] | 179 | x -= frame_index * (width / NUM_FRAMES); |
| 180 | y -= frame_index * (height / NUM_FRAMES); |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 181 | *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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 190 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 191 | case STEP_SKIP: |
| 192 | default: |
| 193 | break; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 194 | } |
| 195 | } |
| 196 | |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 197 | bs_mapper_unmap(ctx->mapper, fb->bo, map_data); |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 198 | |
| 199 | usleep(1e6 / 120); /* 120 Hz */ |
| 200 | |
| 201 | fb_idx = fb_idx ^ 1; |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | |
Dongseong Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 206 | static const struct option longopts[] = { |
| 207 | { "help", no_argument, NULL, 'h' }, |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 208 | { "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 Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 213 | { 0, 0, 0, 0 }, |
| 214 | }; |
| 215 | |
| 216 | static void print_help(const char *argv0) |
| 217 | { |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 218 | 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 Hwang | 59ff9f9 | 2016-04-22 17:39:32 +0300 | [diff] [blame] | 225 | } |
| 226 | |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 227 | int main(int argc, char **argv) |
| 228 | { |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 229 | struct context ctx = { 0 }; |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 230 | struct disabled_features dis_feat = { 0 }; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 231 | |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 232 | do_fixes(&dis_feat); |
Zach Reizner | 299fab7 | 2015-04-28 16:56:14 -0700 | [diff] [blame] | 233 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 234 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 238 | } |
| 239 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 240 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 244 | } |
| 245 | |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 246 | int c; |
Gurchetan Singh | 18a0599 | 2017-11-08 15:43:57 -0800 | [diff] [blame] | 247 | uint32_t flags = GBM_BO_USE_SCANOUT; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 248 | 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 Singh | 18a0599 | 2017-11-08 15:43:57 -0800 | [diff] [blame] | 252 | flags |= GBM_BO_USE_LINEAR; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 253 | printf("started dma-buf mmap.\n"); |
| 254 | break; |
| 255 | case 'g': |
| 256 | ctx.mapper = bs_mapper_gem_new(); |
Gurchetan Singh | 18a0599 | 2017-11-08 15:43:57 -0800 | [diff] [blame] | 257 | flags |= GBM_BO_USE_SW_READ_OFTEN | GBM_BO_USE_SW_WRITE_OFTEN; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 258 | printf("started GEM map.\n"); |
| 259 | break; |
| 260 | case 'd': |
| 261 | ctx.mapper = bs_mapper_dumb_new(gbm_device_get_fd(gbm)); |
Gurchetan Singh | 18a0599 | 2017-11-08 15:43:57 -0800 | [diff] [blame] | 262 | flags |= GBM_BO_USE_LINEAR; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 263 | 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 Sharma | 8df6d93 | 2018-01-30 17:13:35 -0800 | [diff] [blame] | 283 | flags |= GBM_BO_USE_LINEAR; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 284 | 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 Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 292 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 296 | } |
| 297 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 298 | drmModeConnector *connector = drmModeGetConnector(ctx.display_fd, pipe.connector_id); |
| 299 | drmModeModeInfo *mode = &connector->modes[0]; |
| 300 | ctx.crtc_id = pipe.crtc_id; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 301 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 302 | printf("display size: %ux%u\n", mode->hdisplay, mode->vdisplay); |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 303 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 304 | for (size_t fb_index = 0; fb_index < BUFFERS; ++fb_index) { |
| 305 | struct framebuffer *fb = &ctx.fbs[fb_index]; |
Dongseong Hwang | 9093afe | 2017-03-20 19:16:28 -0700 | [diff] [blame] | 306 | fb->bo = |
| 307 | gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888, flags); |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 308 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 309 | if (!fb->bo) { |
| 310 | bs_debug_error("failed to create buffer object"); |
| 311 | return 1; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 312 | } |
| 313 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 314 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 319 | } |
| 320 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 321 | 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 Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 325 | } |
| 326 | |
| 327 | draw(&ctx); |
| 328 | |
Casey Bowman | 6b2da63 | 2018-09-24 15:06:55 -0700 | [diff] [blame] | 329 | restore_features(&dis_feat); |
| 330 | |
Zach Reizner | 7d84989 | 2016-02-24 17:30:27 -0800 | [diff] [blame] | 331 | return 0; |
Zach Reizner | c09812f | 2015-01-12 16:49:49 -0800 | [diff] [blame] | 332 | } |