blob: 9336a1e6300a77ba41434c2497ead0805dbb183f [file] [log] [blame]
Stéphane Marchesin1a92c442015-06-29 20:05:48 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tao Bao557fa1f2017-02-07 12:51:00 -080017#include "graphics_drm.h"
18
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070019#include <fcntl.h>
Jeremy Compostella955da1e2018-06-07 10:51:33 -070020#include <poll.h>
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070021#include <stdio.h>
22#include <stdlib.h>
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070023#include <sys/mman.h>
24#include <sys/types.h>
25#include <unistd.h>
Tao Bao76be34c2017-02-07 13:30:19 -080026
27#include <drm_fourcc.h>
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070028#include <xf86drm.h>
29#include <xf86drmMode.h>
30
Tao Bao0ecbd762017-01-16 21:16:58 -080031#include "minui/minui.h"
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070032
33#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A)))
34
Tao Bao557fa1f2017-02-07 12:51:00 -080035MinuiBackendDrm::MinuiBackendDrm()
36 : GRSurfaceDrms(), main_monitor_crtc(nullptr), main_monitor_connector(nullptr), drm_fd(-1) {}
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070037
Tao Bao557fa1f2017-02-07 12:51:00 -080038void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) {
Tao Bao76be34c2017-02-07 13:30:19 -080039 if (crtc) {
40 drmModeSetCrtc(drm_fd, crtc->crtc_id,
41 0, // fb_id
42 0, 0, // x,y
43 nullptr, // connectors
44 0, // connector_count
45 nullptr); // mode
46 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070047}
48
Tianjie Xuccf00a22018-06-05 17:10:23 -070049int MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, GRSurfaceDrm* surface) {
50 int ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y
51 &main_monitor_connector->connector_id,
52 1, // connector_count
53 &main_monitor_crtc->mode);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070054
Tao Bao76be34c2017-02-07 13:30:19 -080055 if (ret) {
56 printf("drmModeSetCrtc failed ret=%d\n", ret);
57 }
Tianjie Xuccf00a22018-06-05 17:10:23 -070058
59 return ret;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070060}
61
Tao Bao557fa1f2017-02-07 12:51:00 -080062void MinuiBackendDrm::Blank(bool blank) {
Tao Bao76be34c2017-02-07 13:30:19 -080063 if (blank) {
Tao Bao557fa1f2017-02-07 12:51:00 -080064 DrmDisableCrtc(drm_fd, main_monitor_crtc);
Tao Bao76be34c2017-02-07 13:30:19 -080065 } else {
Tao Bao557fa1f2017-02-07 12:51:00 -080066 DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[current_buffer]);
Tao Bao76be34c2017-02-07 13:30:19 -080067 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070068}
69
Tao Bao557fa1f2017-02-07 12:51:00 -080070void MinuiBackendDrm::DrmDestroySurface(GRSurfaceDrm* surface) {
Tao Bao76be34c2017-02-07 13:30:19 -080071 if (!surface) return;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070072
Tao Bao557fa1f2017-02-07 12:51:00 -080073 if (surface->data) {
74 munmap(surface->data, surface->row_bytes * surface->height);
Tao Bao76be34c2017-02-07 13:30:19 -080075 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070076
Tao Bao76be34c2017-02-07 13:30:19 -080077 if (surface->fb_id) {
78 int ret = drmModeRmFB(drm_fd, surface->fb_id);
79 if (ret) {
80 printf("drmModeRmFB failed ret=%d\n", ret);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070081 }
Tao Bao76be34c2017-02-07 13:30:19 -080082 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070083
Tao Bao76be34c2017-02-07 13:30:19 -080084 if (surface->handle) {
85 drm_gem_close gem_close = {};
86 gem_close.handle = surface->handle;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070087
Tao Bao76be34c2017-02-07 13:30:19 -080088 int ret = drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
89 if (ret) {
90 printf("DRM_IOCTL_GEM_CLOSE failed ret=%d\n", ret);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070091 }
Tao Bao76be34c2017-02-07 13:30:19 -080092 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070093
Tao Bao557fa1f2017-02-07 12:51:00 -080094 delete surface;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -070095}
96
97static int drm_format_to_bpp(uint32_t format) {
Tao Bao76be34c2017-02-07 13:30:19 -080098 switch (format) {
99 case DRM_FORMAT_ABGR8888:
100 case DRM_FORMAT_BGRA8888:
101 case DRM_FORMAT_RGBX8888:
102 case DRM_FORMAT_BGRX8888:
103 case DRM_FORMAT_XBGR8888:
104 case DRM_FORMAT_XRGB8888:
105 return 32;
106 case DRM_FORMAT_RGB565:
107 return 16;
108 default:
109 printf("Unknown format %d\n", format);
110 return 32;
111 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700112}
113
Tao Bao557fa1f2017-02-07 12:51:00 -0800114GRSurfaceDrm* MinuiBackendDrm::DrmCreateSurface(int width, int height) {
115 GRSurfaceDrm* surface = new GRSurfaceDrm;
116 *surface = {};
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700117
Tao Bao76be34c2017-02-07 13:30:19 -0800118 uint32_t format;
Tao Baoed876a72018-07-31 21:32:50 -0700119 PixelFormat pixel_format = gr_pixel_format();
120 if (pixel_format == PixelFormat::ABGR) {
121 format = DRM_FORMAT_ABGR8888;
122 } else if (pixel_format == PixelFormat::BGRA) {
123 format = DRM_FORMAT_BGRA8888;
124 } else if (pixel_format == PixelFormat::RGBX) {
125 format = DRM_FORMAT_RGBX8888;
126 } else {
127 format = DRM_FORMAT_RGB565;
128 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700129
Tao Bao76be34c2017-02-07 13:30:19 -0800130 drm_mode_create_dumb create_dumb = {};
131 create_dumb.height = height;
132 create_dumb.width = width;
133 create_dumb.bpp = drm_format_to_bpp(format);
134 create_dumb.flags = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700135
Tao Bao76be34c2017-02-07 13:30:19 -0800136 int ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
137 if (ret) {
138 printf("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800139 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800140 return nullptr;
141 }
142 surface->handle = create_dumb.handle;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700143
Tao Bao76be34c2017-02-07 13:30:19 -0800144 uint32_t handles[4], pitches[4], offsets[4];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700145
Tao Bao76be34c2017-02-07 13:30:19 -0800146 handles[0] = surface->handle;
147 pitches[0] = create_dumb.pitch;
148 offsets[0] = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700149
Tao Bao76be34c2017-02-07 13:30:19 -0800150 ret =
151 drmModeAddFB2(drm_fd, width, height, format, handles, pitches, offsets, &(surface->fb_id), 0);
152 if (ret) {
153 printf("drmModeAddFB2 failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800154 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800155 return nullptr;
156 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700157
Tao Bao76be34c2017-02-07 13:30:19 -0800158 drm_mode_map_dumb map_dumb = {};
159 map_dumb.handle = create_dumb.handle;
160 ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
161 if (ret) {
162 printf("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800163 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800164 return nullptr;
165 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700166
Tao Bao557fa1f2017-02-07 12:51:00 -0800167 surface->height = height;
168 surface->width = width;
169 surface->row_bytes = create_dumb.pitch;
170 surface->pixel_bytes = create_dumb.bpp / 8;
171 surface->data = static_cast<unsigned char*>(mmap(nullptr, surface->height * surface->row_bytes,
172 PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
173 map_dumb.offset));
174 if (surface->data == MAP_FAILED) {
Tao Bao76be34c2017-02-07 13:30:19 -0800175 perror("mmap() failed");
Tao Bao557fa1f2017-02-07 12:51:00 -0800176 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800177 return nullptr;
178 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700179
Tao Bao76be34c2017-02-07 13:30:19 -0800180 return surface;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700181}
182
Tao Bao76be34c2017-02-07 13:30:19 -0800183static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources,
184 drmModeConnector* connector) {
185 // Find the encoder. If we already have one, just use it.
186 drmModeEncoder* encoder;
187 if (connector->encoder_id) {
188 encoder = drmModeGetEncoder(fd, connector->encoder_id);
189 } else {
190 encoder = nullptr;
191 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700192
Tao Bao76be34c2017-02-07 13:30:19 -0800193 int32_t crtc;
194 if (encoder && encoder->crtc_id) {
195 crtc = encoder->crtc_id;
196 drmModeFreeEncoder(encoder);
197 return drmModeGetCrtc(fd, crtc);
198 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700199
Tao Bao76be34c2017-02-07 13:30:19 -0800200 // Didn't find anything, try to find a crtc and encoder combo.
201 crtc = -1;
202 for (int i = 0; i < connector->count_encoders; i++) {
203 encoder = drmModeGetEncoder(fd, connector->encoders[i]);
204
205 if (encoder) {
206 for (int j = 0; j < resources->count_crtcs; j++) {
207 if (!(encoder->possible_crtcs & (1 << j))) continue;
208 crtc = resources->crtcs[j];
209 break;
210 }
211 if (crtc >= 0) {
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700212 drmModeFreeEncoder(encoder);
213 return drmModeGetCrtc(fd, crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800214 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700215 }
Tao Bao76be34c2017-02-07 13:30:19 -0800216 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700217
Tao Bao76be34c2017-02-07 13:30:19 -0800218 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700219}
220
Tao Bao76be34c2017-02-07 13:30:19 -0800221static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) {
222 for (int i = 0; i < resources->count_connectors; i++) {
223 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
224 if (connector) {
225 if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) &&
226 (connector->count_modes > 0)) {
227 return connector;
228 }
229 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700230 }
Tao Bao76be34c2017-02-07 13:30:19 -0800231 }
232 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700233}
234
Tao Bao76be34c2017-02-07 13:30:19 -0800235static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) {
236 for (int i = 0; i < resources->count_connectors; i++) {
237 drmModeConnector* connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700238
Tao Bao76be34c2017-02-07 13:30:19 -0800239 connector = drmModeGetConnector(fd, resources->connectors[i]);
240 if (connector) {
241 if ((connector->count_modes > 0) && (connector->connection == DRM_MODE_CONNECTED))
242 return connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700243
Tao Bao76be34c2017-02-07 13:30:19 -0800244 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700245 }
Tao Bao76be34c2017-02-07 13:30:19 -0800246 }
247 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700248}
249
Tao Bao557fa1f2017-02-07 12:51:00 -0800250drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources,
251 uint32_t* mode_index) {
Tao Bao76be34c2017-02-07 13:30:19 -0800252 /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
253 static constexpr unsigned kConnectorPriority[] = {
254 DRM_MODE_CONNECTOR_LVDS,
255 DRM_MODE_CONNECTOR_eDP,
256 DRM_MODE_CONNECTOR_DSI,
257 };
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700258
Tao Bao76be34c2017-02-07 13:30:19 -0800259 drmModeConnector* main_monitor_connector = nullptr;
260 unsigned i = 0;
261 do {
262 main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
263 i++;
264 } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority));
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700265
Tao Bao76be34c2017-02-07 13:30:19 -0800266 /* If we didn't find a connector, grab the first one that is connected. */
267 if (!main_monitor_connector) {
268 main_monitor_connector = find_first_connected_connector(fd, resources);
269 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700270
Tao Bao76be34c2017-02-07 13:30:19 -0800271 /* If we still didn't find a connector, give up and return. */
272 if (!main_monitor_connector) return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700273
Tao Bao76be34c2017-02-07 13:30:19 -0800274 *mode_index = 0;
275 for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
276 if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
277 *mode_index = modes;
278 break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700279 }
Tao Bao76be34c2017-02-07 13:30:19 -0800280 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700281
Tao Bao76be34c2017-02-07 13:30:19 -0800282 return main_monitor_connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700283}
284
Tao Bao557fa1f2017-02-07 12:51:00 -0800285void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
Tao Bao76be34c2017-02-07 13:30:19 -0800286 for (int i = 0; i < resources->count_connectors; i++) {
287 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
288 drmModeCrtc* crtc = find_crtc_for_connector(fd, resources, connector);
289 if (crtc->crtc_id != main_crtc->crtc_id) {
Tao Bao557fa1f2017-02-07 12:51:00 -0800290 DrmDisableCrtc(fd, crtc);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700291 }
Tao Bao76be34c2017-02-07 13:30:19 -0800292 drmModeFreeCrtc(crtc);
293 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700294}
295
Tao Bao557fa1f2017-02-07 12:51:00 -0800296GRSurface* MinuiBackendDrm::Init() {
Tao Bao76be34c2017-02-07 13:30:19 -0800297 drmModeRes* res = nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700298
Tao Bao76be34c2017-02-07 13:30:19 -0800299 /* Consider DRM devices in order. */
300 for (int i = 0; i < DRM_MAX_MINOR; i++) {
301 char* dev_name;
302 int ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
303 if (ret < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700304
Tao Bao76be34c2017-02-07 13:30:19 -0800305 drm_fd = open(dev_name, O_RDWR, 0);
306 free(dev_name);
307 if (drm_fd < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700308
Tao Bao76be34c2017-02-07 13:30:19 -0800309 uint64_t cap = 0;
310 /* We need dumb buffers. */
311 ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
312 if (ret || cap == 0) {
313 close(drm_fd);
314 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700315 }
316
Tao Bao76be34c2017-02-07 13:30:19 -0800317 res = drmModeGetResources(drm_fd);
318 if (!res) {
319 close(drm_fd);
320 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700321 }
322
Tao Bao76be34c2017-02-07 13:30:19 -0800323 /* Use this device if it has at least one connected monitor. */
324 if (res->count_crtcs > 0 && res->count_connectors > 0) {
325 if (find_first_connected_connector(drm_fd, res)) break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700326 }
327
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700328 drmModeFreeResources(res);
Tao Bao76be34c2017-02-07 13:30:19 -0800329 close(drm_fd);
330 res = nullptr;
331 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700332
Tao Bao76be34c2017-02-07 13:30:19 -0800333 if (drm_fd < 0 || res == nullptr) {
334 perror("cannot find/open a drm device");
335 return nullptr;
336 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700337
Tao Bao76be34c2017-02-07 13:30:19 -0800338 uint32_t selected_mode;
Tao Bao557fa1f2017-02-07 12:51:00 -0800339 main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700340
Tao Bao76be34c2017-02-07 13:30:19 -0800341 if (!main_monitor_connector) {
342 printf("main_monitor_connector not found\n");
343 drmModeFreeResources(res);
344 close(drm_fd);
345 return nullptr;
346 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700347
Tao Bao76be34c2017-02-07 13:30:19 -0800348 main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
349
350 if (!main_monitor_crtc) {
351 printf("main_monitor_crtc not found\n");
352 drmModeFreeResources(res);
353 close(drm_fd);
354 return nullptr;
355 }
356
Tao Bao557fa1f2017-02-07 12:51:00 -0800357 DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800358
359 main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
360
361 int width = main_monitor_crtc->mode.hdisplay;
362 int height = main_monitor_crtc->mode.vdisplay;
363
364 drmModeFreeResources(res);
365
Tao Bao557fa1f2017-02-07 12:51:00 -0800366 GRSurfaceDrms[0] = DrmCreateSurface(width, height);
367 GRSurfaceDrms[1] = DrmCreateSurface(width, height);
368 if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
369 // GRSurfaceDrms and drm_fd should be freed in d'tor.
Tao Bao76be34c2017-02-07 13:30:19 -0800370 return nullptr;
371 }
372
373 current_buffer = 0;
374
Tianjie Xuccf00a22018-06-05 17:10:23 -0700375 // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
376 if (DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1]) != 0) {
377 return nullptr;
378 }
Tao Bao76be34c2017-02-07 13:30:19 -0800379
Tao Bao557fa1f2017-02-07 12:51:00 -0800380 return GRSurfaceDrms[0];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700381}
382
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700383static void page_flip_complete(__unused int fd,
384 __unused unsigned int sequence,
385 __unused unsigned int tv_sec,
386 __unused unsigned int tv_usec,
387 void *user_data) {
388 *static_cast<bool*>(user_data) = false;
389}
390
Tao Bao557fa1f2017-02-07 12:51:00 -0800391GRSurface* MinuiBackendDrm::Flip() {
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700392 bool ongoing_flip = true;
393
Tao Bao557fa1f2017-02-07 12:51:00 -0800394 int ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id,
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700395 GRSurfaceDrms[current_buffer]->fb_id,
396 DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip);
Tao Bao76be34c2017-02-07 13:30:19 -0800397 if (ret < 0) {
398 printf("drmModePageFlip failed ret=%d\n", ret);
399 return nullptr;
400 }
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700401
402 while (ongoing_flip) {
403 struct pollfd fds = {
404 .fd = drm_fd,
405 .events = POLLIN
406 };
407
408 ret = poll(&fds, 1, -1);
409 if (ret == -1 || !(fds.revents & POLLIN)) {
410 printf("poll() failed on drm fd\n");
411 break;
412 }
413
414 drmEventContext evctx = {
415 .version = DRM_EVENT_CONTEXT_VERSION,
416 .page_flip_handler = page_flip_complete
417 };
418
419 ret = drmHandleEvent(drm_fd, &evctx);
420 if (ret != 0) {
421 printf("drmHandleEvent failed ret=%d\n", ret);
422 break;
423 }
424 }
425
Tao Bao76be34c2017-02-07 13:30:19 -0800426 current_buffer = 1 - current_buffer;
Tao Bao557fa1f2017-02-07 12:51:00 -0800427 return GRSurfaceDrms[current_buffer];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700428}
429
Tao Bao557fa1f2017-02-07 12:51:00 -0800430MinuiBackendDrm::~MinuiBackendDrm() {
431 DrmDisableCrtc(drm_fd, main_monitor_crtc);
432 DrmDestroySurface(GRSurfaceDrms[0]);
433 DrmDestroySurface(GRSurfaceDrms[1]);
Tao Bao76be34c2017-02-07 13:30:19 -0800434 drmModeFreeCrtc(main_monitor_crtc);
435 drmModeFreeConnector(main_monitor_connector);
436 close(drm_fd);
437 drm_fd = -1;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700438}