blob: 81b49fd95f6cbbd43bd3338287a5418dc0ac24c7 [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 Bao92bdb5a2018-10-21 12:12:37 -070073 if (surface->mmapped_buffer_) {
74 munmap(surface->mmapped_buffer_, 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();
tangrobin13bec762018-08-07 17:23:31 +0800120 // PixelFormat comes in byte order, whereas DRM_FORMAT_* uses little-endian
121 // (external/libdrm/include/drm/drm_fourcc.h). Note that although drm_fourcc.h also defines a
122 // macro of DRM_FORMAT_BIG_ENDIAN, it doesn't seem to be actually supported (see the discussion
123 // in https://lists.freedesktop.org/archives/amd-gfx/2017-May/008560.html).
Tao Baoed876a72018-07-31 21:32:50 -0700124 if (pixel_format == PixelFormat::ABGR) {
tangrobin13bec762018-08-07 17:23:31 +0800125 format = DRM_FORMAT_RGBA8888;
Tao Baoed876a72018-07-31 21:32:50 -0700126 } else if (pixel_format == PixelFormat::BGRA) {
tangrobin13bec762018-08-07 17:23:31 +0800127 format = DRM_FORMAT_ARGB8888;
Tao Baoed876a72018-07-31 21:32:50 -0700128 } else if (pixel_format == PixelFormat::RGBX) {
tangrobin13bec762018-08-07 17:23:31 +0800129 format = DRM_FORMAT_XBGR8888;
Tao Baoed876a72018-07-31 21:32:50 -0700130 } else {
131 format = DRM_FORMAT_RGB565;
132 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700133
Tao Bao76be34c2017-02-07 13:30:19 -0800134 drm_mode_create_dumb create_dumb = {};
135 create_dumb.height = height;
136 create_dumb.width = width;
137 create_dumb.bpp = drm_format_to_bpp(format);
138 create_dumb.flags = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700139
Tao Bao76be34c2017-02-07 13:30:19 -0800140 int ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
141 if (ret) {
142 printf("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800143 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800144 return nullptr;
145 }
146 surface->handle = create_dumb.handle;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700147
Tao Bao76be34c2017-02-07 13:30:19 -0800148 uint32_t handles[4], pitches[4], offsets[4];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700149
Tao Bao76be34c2017-02-07 13:30:19 -0800150 handles[0] = surface->handle;
151 pitches[0] = create_dumb.pitch;
152 offsets[0] = 0;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700153
Tao Bao76be34c2017-02-07 13:30:19 -0800154 ret =
155 drmModeAddFB2(drm_fd, width, height, format, handles, pitches, offsets, &(surface->fb_id), 0);
156 if (ret) {
157 printf("drmModeAddFB2 failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800158 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800159 return nullptr;
160 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700161
Tao Bao76be34c2017-02-07 13:30:19 -0800162 drm_mode_map_dumb map_dumb = {};
163 map_dumb.handle = create_dumb.handle;
164 ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
165 if (ret) {
166 printf("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n", ret);
Tao Bao557fa1f2017-02-07 12:51:00 -0800167 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800168 return nullptr;
169 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700170
Tao Bao557fa1f2017-02-07 12:51:00 -0800171 surface->height = height;
172 surface->width = width;
173 surface->row_bytes = create_dumb.pitch;
174 surface->pixel_bytes = create_dumb.bpp / 8;
Tao Bao92bdb5a2018-10-21 12:12:37 -0700175 auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE,
176 MAP_SHARED, drm_fd, map_dumb.offset);
177 if (mmapped == MAP_FAILED) {
Tao Bao76be34c2017-02-07 13:30:19 -0800178 perror("mmap() failed");
Tao Bao557fa1f2017-02-07 12:51:00 -0800179 DrmDestroySurface(surface);
Tao Bao76be34c2017-02-07 13:30:19 -0800180 return nullptr;
181 }
Tao Bao92bdb5a2018-10-21 12:12:37 -0700182 surface->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
Tao Bao76be34c2017-02-07 13:30:19 -0800183 return surface;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700184}
185
Tao Bao76be34c2017-02-07 13:30:19 -0800186static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources,
187 drmModeConnector* connector) {
188 // Find the encoder. If we already have one, just use it.
189 drmModeEncoder* encoder;
190 if (connector->encoder_id) {
191 encoder = drmModeGetEncoder(fd, connector->encoder_id);
192 } else {
193 encoder = nullptr;
194 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700195
Tao Bao76be34c2017-02-07 13:30:19 -0800196 int32_t crtc;
197 if (encoder && encoder->crtc_id) {
198 crtc = encoder->crtc_id;
199 drmModeFreeEncoder(encoder);
200 return drmModeGetCrtc(fd, crtc);
201 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700202
Tao Bao76be34c2017-02-07 13:30:19 -0800203 // Didn't find anything, try to find a crtc and encoder combo.
204 crtc = -1;
205 for (int i = 0; i < connector->count_encoders; i++) {
206 encoder = drmModeGetEncoder(fd, connector->encoders[i]);
207
208 if (encoder) {
209 for (int j = 0; j < resources->count_crtcs; j++) {
210 if (!(encoder->possible_crtcs & (1 << j))) continue;
211 crtc = resources->crtcs[j];
212 break;
213 }
214 if (crtc >= 0) {
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700215 drmModeFreeEncoder(encoder);
216 return drmModeGetCrtc(fd, crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800217 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700218 }
Tao Bao76be34c2017-02-07 13:30:19 -0800219 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700220
Tao Bao76be34c2017-02-07 13:30:19 -0800221 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700222}
223
Tao Bao76be34c2017-02-07 13:30:19 -0800224static drmModeConnector* find_used_connector_by_type(int fd, drmModeRes* resources, unsigned type) {
225 for (int i = 0; i < resources->count_connectors; i++) {
226 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
227 if (connector) {
228 if ((connector->connector_type == type) && (connector->connection == DRM_MODE_CONNECTED) &&
229 (connector->count_modes > 0)) {
230 return connector;
231 }
232 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700233 }
Tao Bao76be34c2017-02-07 13:30:19 -0800234 }
235 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700236}
237
Tao Bao76be34c2017-02-07 13:30:19 -0800238static drmModeConnector* find_first_connected_connector(int fd, drmModeRes* resources) {
239 for (int i = 0; i < resources->count_connectors; i++) {
240 drmModeConnector* connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700241
Tao Bao76be34c2017-02-07 13:30:19 -0800242 connector = drmModeGetConnector(fd, resources->connectors[i]);
243 if (connector) {
244 if ((connector->count_modes > 0) && (connector->connection == DRM_MODE_CONNECTED))
245 return connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700246
Tao Bao76be34c2017-02-07 13:30:19 -0800247 drmModeFreeConnector(connector);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700248 }
Tao Bao76be34c2017-02-07 13:30:19 -0800249 }
250 return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700251}
252
Tao Bao557fa1f2017-02-07 12:51:00 -0800253drmModeConnector* MinuiBackendDrm::FindMainMonitor(int fd, drmModeRes* resources,
254 uint32_t* mode_index) {
Tao Bao76be34c2017-02-07 13:30:19 -0800255 /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */
256 static constexpr unsigned kConnectorPriority[] = {
257 DRM_MODE_CONNECTOR_LVDS,
258 DRM_MODE_CONNECTOR_eDP,
259 DRM_MODE_CONNECTOR_DSI,
260 };
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700261
Tao Bao76be34c2017-02-07 13:30:19 -0800262 drmModeConnector* main_monitor_connector = nullptr;
263 unsigned i = 0;
264 do {
265 main_monitor_connector = find_used_connector_by_type(fd, resources, kConnectorPriority[i]);
266 i++;
267 } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority));
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700268
Tao Bao76be34c2017-02-07 13:30:19 -0800269 /* If we didn't find a connector, grab the first one that is connected. */
270 if (!main_monitor_connector) {
271 main_monitor_connector = find_first_connected_connector(fd, resources);
272 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700273
Tao Bao76be34c2017-02-07 13:30:19 -0800274 /* If we still didn't find a connector, give up and return. */
275 if (!main_monitor_connector) return nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700276
Tao Bao76be34c2017-02-07 13:30:19 -0800277 *mode_index = 0;
278 for (int modes = 0; modes < main_monitor_connector->count_modes; modes++) {
279 if (main_monitor_connector->modes[modes].type & DRM_MODE_TYPE_PREFERRED) {
280 *mode_index = modes;
281 break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700282 }
Tao Bao76be34c2017-02-07 13:30:19 -0800283 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700284
Tao Bao76be34c2017-02-07 13:30:19 -0800285 return main_monitor_connector;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700286}
287
Tao Bao557fa1f2017-02-07 12:51:00 -0800288void MinuiBackendDrm::DisableNonMainCrtcs(int fd, drmModeRes* resources, drmModeCrtc* main_crtc) {
Tao Bao76be34c2017-02-07 13:30:19 -0800289 for (int i = 0; i < resources->count_connectors; i++) {
290 drmModeConnector* connector = drmModeGetConnector(fd, resources->connectors[i]);
291 drmModeCrtc* crtc = find_crtc_for_connector(fd, resources, connector);
292 if (crtc->crtc_id != main_crtc->crtc_id) {
Tao Bao557fa1f2017-02-07 12:51:00 -0800293 DrmDisableCrtc(fd, crtc);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700294 }
Tao Bao76be34c2017-02-07 13:30:19 -0800295 drmModeFreeCrtc(crtc);
296 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700297}
298
Tao Bao557fa1f2017-02-07 12:51:00 -0800299GRSurface* MinuiBackendDrm::Init() {
Tao Bao76be34c2017-02-07 13:30:19 -0800300 drmModeRes* res = nullptr;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700301
Tao Bao76be34c2017-02-07 13:30:19 -0800302 /* Consider DRM devices in order. */
303 for (int i = 0; i < DRM_MAX_MINOR; i++) {
304 char* dev_name;
305 int ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i);
306 if (ret < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700307
Tao Bao76be34c2017-02-07 13:30:19 -0800308 drm_fd = open(dev_name, O_RDWR, 0);
309 free(dev_name);
310 if (drm_fd < 0) continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700311
Tao Bao76be34c2017-02-07 13:30:19 -0800312 uint64_t cap = 0;
313 /* We need dumb buffers. */
314 ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap);
315 if (ret || cap == 0) {
316 close(drm_fd);
317 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700318 }
319
Tao Bao76be34c2017-02-07 13:30:19 -0800320 res = drmModeGetResources(drm_fd);
321 if (!res) {
322 close(drm_fd);
323 continue;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700324 }
325
Tao Bao76be34c2017-02-07 13:30:19 -0800326 /* Use this device if it has at least one connected monitor. */
327 if (res->count_crtcs > 0 && res->count_connectors > 0) {
328 if (find_first_connected_connector(drm_fd, res)) break;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700329 }
330
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700331 drmModeFreeResources(res);
Tao Bao76be34c2017-02-07 13:30:19 -0800332 close(drm_fd);
333 res = nullptr;
334 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700335
Tao Bao76be34c2017-02-07 13:30:19 -0800336 if (drm_fd < 0 || res == nullptr) {
337 perror("cannot find/open a drm device");
338 return nullptr;
339 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700340
Tao Bao76be34c2017-02-07 13:30:19 -0800341 uint32_t selected_mode;
Tao Bao557fa1f2017-02-07 12:51:00 -0800342 main_monitor_connector = FindMainMonitor(drm_fd, res, &selected_mode);
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700343
Tao Bao76be34c2017-02-07 13:30:19 -0800344 if (!main_monitor_connector) {
345 printf("main_monitor_connector not found\n");
346 drmModeFreeResources(res);
347 close(drm_fd);
348 return nullptr;
349 }
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700350
Tao Bao76be34c2017-02-07 13:30:19 -0800351 main_monitor_crtc = find_crtc_for_connector(drm_fd, res, main_monitor_connector);
352
353 if (!main_monitor_crtc) {
354 printf("main_monitor_crtc not found\n");
355 drmModeFreeResources(res);
356 close(drm_fd);
357 return nullptr;
358 }
359
Tao Bao557fa1f2017-02-07 12:51:00 -0800360 DisableNonMainCrtcs(drm_fd, res, main_monitor_crtc);
Tao Bao76be34c2017-02-07 13:30:19 -0800361
362 main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode];
363
364 int width = main_monitor_crtc->mode.hdisplay;
365 int height = main_monitor_crtc->mode.vdisplay;
366
367 drmModeFreeResources(res);
368
Tao Bao557fa1f2017-02-07 12:51:00 -0800369 GRSurfaceDrms[0] = DrmCreateSurface(width, height);
370 GRSurfaceDrms[1] = DrmCreateSurface(width, height);
371 if (!GRSurfaceDrms[0] || !GRSurfaceDrms[1]) {
372 // GRSurfaceDrms and drm_fd should be freed in d'tor.
Tao Bao76be34c2017-02-07 13:30:19 -0800373 return nullptr;
374 }
375
376 current_buffer = 0;
377
Tianjie Xuccf00a22018-06-05 17:10:23 -0700378 // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
379 if (DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1]) != 0) {
380 return nullptr;
381 }
Tao Bao76be34c2017-02-07 13:30:19 -0800382
Tao Bao557fa1f2017-02-07 12:51:00 -0800383 return GRSurfaceDrms[0];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700384}
385
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700386static void page_flip_complete(__unused int fd,
387 __unused unsigned int sequence,
388 __unused unsigned int tv_sec,
389 __unused unsigned int tv_usec,
390 void *user_data) {
391 *static_cast<bool*>(user_data) = false;
392}
393
Tao Bao557fa1f2017-02-07 12:51:00 -0800394GRSurface* MinuiBackendDrm::Flip() {
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700395 bool ongoing_flip = true;
396
Tao Bao557fa1f2017-02-07 12:51:00 -0800397 int ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id,
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700398 GRSurfaceDrms[current_buffer]->fb_id,
399 DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip);
Tao Bao76be34c2017-02-07 13:30:19 -0800400 if (ret < 0) {
401 printf("drmModePageFlip failed ret=%d\n", ret);
402 return nullptr;
403 }
Jeremy Compostella955da1e2018-06-07 10:51:33 -0700404
405 while (ongoing_flip) {
406 struct pollfd fds = {
407 .fd = drm_fd,
408 .events = POLLIN
409 };
410
411 ret = poll(&fds, 1, -1);
412 if (ret == -1 || !(fds.revents & POLLIN)) {
413 printf("poll() failed on drm fd\n");
414 break;
415 }
416
417 drmEventContext evctx = {
418 .version = DRM_EVENT_CONTEXT_VERSION,
419 .page_flip_handler = page_flip_complete
420 };
421
422 ret = drmHandleEvent(drm_fd, &evctx);
423 if (ret != 0) {
424 printf("drmHandleEvent failed ret=%d\n", ret);
425 break;
426 }
427 }
428
Tao Bao76be34c2017-02-07 13:30:19 -0800429 current_buffer = 1 - current_buffer;
Tao Bao557fa1f2017-02-07 12:51:00 -0800430 return GRSurfaceDrms[current_buffer];
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700431}
432
Tao Bao557fa1f2017-02-07 12:51:00 -0800433MinuiBackendDrm::~MinuiBackendDrm() {
434 DrmDisableCrtc(drm_fd, main_monitor_crtc);
435 DrmDestroySurface(GRSurfaceDrms[0]);
436 DrmDestroySurface(GRSurfaceDrms[1]);
Tao Bao76be34c2017-02-07 13:30:19 -0800437 drmModeFreeCrtc(main_monitor_crtc);
438 drmModeFreeConnector(main_monitor_connector);
439 close(drm_fd);
440 drm_fd = -1;
Stéphane Marchesin1a92c442015-06-29 20:05:48 -0700441}