blob: 57912d1e8b05eb0e3564cfbdac4e71e8ae053d29 [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;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700119#if defined(RECOVERY_ABGR)
Tao Bao76be34c2017-02-07 13:30:19 -0800120 format = DRM_FORMAT_RGBA8888;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700121#elif defined(RECOVERY_BGRA)
Tao Bao76be34c2017-02-07 13:30:19 -0800122 format = DRM_FORMAT_ARGB8888;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700123#elif defined(RECOVERY_RGBX)
Tao Bao76be34c2017-02-07 13:30:19 -0800124 format = DRM_FORMAT_XBGR8888;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700125#else
Tao Bao76be34c2017-02-07 13:30:19 -0800126 format = DRM_FORMAT_RGB565;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700127#endif
128
Tao Bao76be34c2017-02-07 13:30:19 -0800129 drm_mode_create_dumb create_dumb = {};
130 create_dumb.height = height;
131 create_dumb.width = width;
132 create_dumb.bpp = drm_format_to_bpp(format);
133 create_dumb.flags = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700134
Tao Bao76be34c2017-02-07 13:30:19 -0800135 int ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
136 if (ret) {
137 printf("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800138 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800139 return nullptr;
140 }
141 surface->handle = create_dumb.handle;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700142
Tao Bao76be34c2017-02-07 13:30:19 -0800143 uint32_t handles[4], pitches[4], offsets[4];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700144
Tao Bao76be34c2017-02-07 13:30:19 -0800145 handles[0] = surface->handle;
146 pitches[0] = create_dumb.pitch;
147 offsets[0] = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700148
Tao Bao76be34c2017-02-07 13:30:19 -0800149 ret =
150 drmModeAddFB2(drm_fd, width, height, format, handles, pitches, offsets, &(surface->fb_id), 0);
151 if (ret) {
152 printf("drmModeAddFB2 failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800153 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800154 return nullptr;
155 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700156
Tao Bao76be34c2017-02-07 13:30:19 -0800157 drm_mode_map_dumb map_dumb = {};
158 map_dumb.handle = create_dumb.handle;
159 ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
160 if (ret) {
161 printf("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800162 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800163 return nullptr;
164 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700165
Tao Bao557fa1f2017-02-07 12:51:00 -0800166 surface->height = height;
167 surface->width = width;
168 surface->row_bytes = create_dumb.pitch;
169 surface->pixel_bytes = create_dumb.bpp / 8;
170 surface->data = static_cast<unsigned char*>(mmap(nullptr, surface->height * surface->row_bytes,
171 PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
172 map_dumb.offset));
173 if (surface->data == MAP_FAILED) {
Tao Bao76be34c2017-02-07 13:30:19 -0800174 perror("mmap() failed");
Tao Bao557fa1f2017-02-07 12:51:00 -0800175 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800176 return nullptr;
177 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700178
Tao Bao76be34c2017-02-07 13:30:19 -0800179 return surface;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700180}
181
Tao Bao76be34c2017-02-07 13:30:19 -0800182static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources,
183 drmModeConnector* connector) {
184 // Find the encoder. If we already have one, just use it.
185 drmModeEncoder* encoder;
186 if (connector->encoder_id) {
187 encoder = drmModeGetEncoder(fd, connector->encoder_id);
188 } else {
189 encoder = nullptr;
190 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700191
Tao Bao76be34c2017-02-07 13:30:19 -0800192 int32_t crtc;
193 if (encoder && encoder->crtc_id) {
194 crtc = encoder->crtc_id;
195 drmModeFreeEncoder(encoder);
196 return drmModeGetCrtc(fd, crtc);
197 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700198
Tao Bao76be34c2017-02-07 13:30:19 -0800199 // Didn't find anything, try to find a crtc and encoder combo.
200 crtc = -1;
201 for (int i = 0; i < connector->count_encoders; i++) {
202 encoder = drmModeGetEncoder(fd, connector->encoders[i]);
203
204 if (encoder) {
205 for (int j = 0; j < resources->count_crtcs; j++) {
206 if (!(encoder->possible_crtcs & (1 << j))) continue;
207 crtc = resources->crtcs[j];
208 break;
209 }
210 if (crtc >= 0) {
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700211 drmModeFreeEncoder(encoder);
212 return drmModeGetCrtc(fd, crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800213 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700214 }
Tao Bao76be34c2017-02-07 13:30:19 -0800215 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700216
Tao Bao76be34c2017-02-07 13:30:19 -0800217 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700218}
219
Tao Bao76be34c2017-02-07 13:30:19 -0800220static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) {
221 for (int i = 0; i < resources->count_connectors; i++) {
222 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
223 if (connector) {
224 if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) &&
225 (connector->count_modes > 0)) {
226 return connector;
227 }
228 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700229 }
Tao Bao76be34c2017-02-07 13:30:19 -0800230 }
231 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700232}
233
Tao Bao76be34c2017-02-07 13:30:19 -0800234static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) {
235 for (int i = 0; i < resources->count_connectors; i++) {
236 drmModeConnector* connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700237
Tao Bao76be34c2017-02-07 13:30:19 -0800238 connector = drmModeGetConnector(fd, resources->connectors[i]);
239 if (connector) {
240 if ((connector->count_modes > 0) && (connector->connection == DRM_MODE_CONNECTED))
241 return connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700242
Tao Bao76be34c2017-02-07 13:30:19 -0800243 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700244 }
Tao Bao76be34c2017-02-07 13:30:19 -0800245 }
246 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700247}
248
Tao Bao557fa1f2017-02-07 12:51:00 -0800249drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources,
250 uint32_t* mode_index) {
Tao Bao76be34c2017-02-07 13:30:19 -0800251 /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
252 static constexpr unsigned kConnectorPriority[] = {
253 DRM_MODE_CONNECTOR_LVDS,
254 DRM_MODE_CONNECTOR_eDP,
255 DRM_MODE_CONNECTOR_DSI,
256 };
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700257
Tao Bao76be34c2017-02-07 13:30:19 -0800258 drmModeConnector* main_monitor_connector = nullptr;
259 unsigned i = 0;
260 do {
261 main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
262 i++;
263 } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority));
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700264
Tao Bao76be34c2017-02-07 13:30:19 -0800265 /* If we didn't find a connector, grab the first one that is connected. */
266 if (!main_monitor_connector) {
267 main_monitor_connector = find_first_connected_connector(fd, resources);
268 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700269
Tao Bao76be34c2017-02-07 13:30:19 -0800270 /* If we still didn't find a connector, give up and return. */
271 if (!main_monitor_connector) return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700272
Tao Bao76be34c2017-02-07 13:30:19 -0800273 *mode_index = 0;
274 for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
275 if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
276 *mode_index = modes;
277 break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700278 }
Tao Bao76be34c2017-02-07 13:30:19 -0800279 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700280
Tao Bao76be34c2017-02-07 13:30:19 -0800281 return main_monitor_connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700282}
283
Tao Bao557fa1f2017-02-07 12:51:00 -0800284void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
Tao Bao76be34c2017-02-07 13:30:19 -0800285 for (int i = 0; i < resources->count_connectors; i++) {
286 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
287 drmModeCrtc* crtc = find_crtc_for_connector(fd, resources, connector);
288 if (crtc->crtc_id != main_crtc->crtc_id) {
Tao Bao557fa1f2017-02-07 12:51:00 -0800289 DrmDisableCrtc(fd, crtc);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700290 }
Tao Bao76be34c2017-02-07 13:30:19 -0800291 drmModeFreeCrtc(crtc);
292 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700293}
294
Tao Bao557fa1f2017-02-07 12:51:00 -0800295GRSurface* MinuiBackendDrm::Init() {
Tao Bao76be34c2017-02-07 13:30:19 -0800296 drmModeRes* res = nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700297
Tao Bao76be34c2017-02-07 13:30:19 -0800298 /* Consider DRM devices in order. */
299 for (int i = 0; i < DRM_MAX_MINOR; i++) {
300 char* dev_name;
301 int ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
302 if (ret < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700303
Tao Bao76be34c2017-02-07 13:30:19 -0800304 drm_fd = open(dev_name, O_RDWR, 0);
305 free(dev_name);
306 if (drm_fd < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700307
Tao Bao76be34c2017-02-07 13:30:19 -0800308 uint64_t cap = 0;
309 /* We need dumb buffers. */
310 ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
311 if (ret || cap == 0) {
312 close(drm_fd);
313 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700314 }
315
Tao Bao76be34c2017-02-07 13:30:19 -0800316 res = drmModeGetResources(drm_fd);
317 if (!res) {
318 close(drm_fd);
319 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700320 }
321
Tao Bao76be34c2017-02-07 13:30:19 -0800322 /* Use this device if it has at least one connected monitor. */
323 if (res->count_crtcs > 0 && res->count_connectors > 0) {
324 if (find_first_connected_connector(drm_fd, res)) break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700325 }
326
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700327 drmModeFreeResources(res);
Tao Bao76be34c2017-02-07 13:30:19 -0800328 close(drm_fd);
329 res = nullptr;
330 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700331
Tao Bao76be34c2017-02-07 13:30:19 -0800332 if (drm_fd < 0 || res == nullptr) {
333 perror("cannot find/open a drm device");
334 return nullptr;
335 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700336
Tao Bao76be34c2017-02-07 13:30:19 -0800337 uint32_t selected_mode;
Tao Bao557fa1f2017-02-07 12:51:00 -0800338 main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700339
Tao Bao76be34c2017-02-07 13:30:19 -0800340 if (!main_monitor_connector) {
341 printf("main_monitor_connector not found\n");
342 drmModeFreeResources(res);
343 close(drm_fd);
344 return nullptr;
345 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700346
Tao Bao76be34c2017-02-07 13:30:19 -0800347 main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
348
349 if (!main_monitor_crtc) {
350 printf("main_monitor_crtc not found\n");
351 drmModeFreeResources(res);
352 close(drm_fd);
353 return nullptr;
354 }
355
Tao Bao557fa1f2017-02-07 12:51:00 -0800356 DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800357
358 main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
359
360 int width = main_monitor_crtc->mode.hdisplay;
361 int height = main_monitor_crtc->mode.vdisplay;
362
363 drmModeFreeResources(res);
364
Tao Bao557fa1f2017-02-07 12:51:00 -0800365 GRSurfaceDrms[0] = DrmCreateSurface(width, height);
366 GRSurfaceDrms[1] = DrmCreateSurface(width, height);
367 if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
368 // GRSurfaceDrms and drm_fd should be freed in d'tor.
Tao Bao76be34c2017-02-07 13:30:19 -0800369 return nullptr;
370 }
371
372 current_buffer = 0;
373
Tianjie Xuccf00a22018-06-05 17:10:23 -0700374 // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
375 if (DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1]) != 0) {
376 return nullptr;
377 }
Tao Bao76be34c2017-02-07 13:30:19 -0800378
Tao Bao557fa1f2017-02-07 12:51:00 -0800379 return GRSurfaceDrms[0];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700380}
381
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700382static void page_flip_complete(__unused int fd,
383 __unused unsigned int sequence,
384 __unused unsigned int tv_sec,
385 __unused unsigned int tv_usec,
386 void *user_data) {
387 *static_cast<bool*>(user_data) = false;
388}
389
Tao Bao557fa1f2017-02-07 12:51:00 -0800390GRSurface* MinuiBackendDrm::Flip() {
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700391 bool ongoing_flip = true;
392
Tao Bao557fa1f2017-02-07 12:51:00 -0800393 int ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id,
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700394 GRSurfaceDrms[current_buffer]->fb_id,
395 DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip);
Tao Bao76be34c2017-02-07 13:30:19 -0800396 if (ret < 0) {
397 printf("drmModePageFlip failed ret=%d\n", ret);
398 return nullptr;
399 }
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700400
401 while (ongoing_flip) {
402 struct pollfd fds = {
403 .fd = drm_fd,
404 .events = POLLIN
405 };
406
407 ret = poll(&fds, 1, -1);
408 if (ret == -1 || !(fds.revents & POLLIN)) {
409 printf("poll() failed on drm fd\n");
410 break;
411 }
412
413 drmEventContext evctx = {
414 .version = DRM_EVENT_CONTEXT_VERSION,
415 .page_flip_handler = page_flip_complete
416 };
417
418 ret = drmHandleEvent(drm_fd, &evctx);
419 if (ret != 0) {
420 printf("drmHandleEvent failed ret=%d\n", ret);
421 break;
422 }
423 }
424
Tao Bao76be34c2017-02-07 13:30:19 -0800425 current_buffer = 1 - current_buffer;
Tao Bao557fa1f2017-02-07 12:51:00 -0800426 return GRSurfaceDrms[current_buffer];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700427}
428
Tao Bao557fa1f2017-02-07 12:51:00 -0800429MinuiBackendDrm::~MinuiBackendDrm() {
430 DrmDisableCrtc(drm_fd, main_monitor_crtc);
431 DrmDestroySurface(GRSurfaceDrms[0]);
432 DrmDestroySurface(GRSurfaceDrms[1]);
Tao Bao76be34c2017-02-07 13:30:19 -0800433 drmModeFreeCrtc(main_monitor_crtc);
434 drmModeFreeConnector(main_monitor_connector);
435 close(drm_fd);
436 drm_fd = -1;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700437}