summaryrefslogtreecommitdiffstats
path: root/minui/graphics_drm.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--minui/graphics_drm.cpp92
1 files changed, 69 insertions, 23 deletions
diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp
index e7d4b38ef..81b49fd95 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -17,6 +17,7 @@
#include "graphics_drm.h"
#include <fcntl.h>
+#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
@@ -45,15 +46,17 @@ void MinuiBackendDrm::DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc) {
}
}
-void MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, GRSurfaceDrm* surface) {
- int32_t ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y
- &main_monitor_connector->connector_id,
- 1, // connector_count
- &main_monitor_crtc->mode);
+int MinuiBackendDrm::DrmEnableCrtc(int drm_fd, drmModeCrtc* crtc, GRSurfaceDrm* surface) {
+ int ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, surface->fb_id, 0, 0, // x,y
+ &main_monitor_connector->connector_id,
+ 1, // connector_count
+ &main_monitor_crtc->mode);
if (ret) {
printf("drmModeSetCrtc failed ret=%d\n", ret);
}
+
+ return ret;
}
void MinuiBackendDrm::Blank(bool blank) {
@@ -67,8 +70,8 @@ void MinuiBackendDrm::Blank(bool blank) {
void MinuiBackendDrm::DrmDestroySurface(GRSurfaceDrm* surface) {
if (!surface) return;
- if (surface->data) {
- munmap(surface->data, surface->row_bytes * surface->height);
+ if (surface->mmapped_buffer_) {
+ munmap(surface->mmapped_buffer_, surface->row_bytes * surface->height);
}
if (surface->fb_id) {
@@ -113,15 +116,20 @@ GRSurfaceDrm* MinuiBackendDrm::DrmCreateSurface(int width, int height) {
*surface = {};
uint32_t format;
-#if defined(RECOVERY_ABGR)
- format = DRM_FORMAT_RGBA8888;
-#elif defined(RECOVERY_BGRA)
- format = DRM_FORMAT_ARGB8888;
-#elif defined(RECOVERY_RGBX)
- format = DRM_FORMAT_XBGR8888;
-#else
- format = DRM_FORMAT_RGB565;
-#endif
+ PixelFormat pixel_format = gr_pixel_format();
+ // PixelFormat comes in byte order, whereas DRM_FORMAT_* uses little-endian
+ // (external/libdrm/include/drm/drm_fourcc.h). Note that although drm_fourcc.h also defines a
+ // macro of DRM_FORMAT_BIG_ENDIAN, it doesn't seem to be actually supported (see the discussion
+ // in https://lists.freedesktop.org/archives/amd-gfx/2017-May/008560.html).
+ if (pixel_format == PixelFormat::ABGR) {
+ format = DRM_FORMAT_RGBA8888;
+ } else if (pixel_format == PixelFormat::BGRA) {
+ format = DRM_FORMAT_ARGB8888;
+ } else if (pixel_format == PixelFormat::RGBX) {
+ format = DRM_FORMAT_XBGR8888;
+ } else {
+ format = DRM_FORMAT_RGB565;
+ }
drm_mode_create_dumb create_dumb = {};
create_dumb.height = height;
@@ -164,15 +172,14 @@ GRSurfaceDrm* MinuiBackendDrm::DrmCreateSurface(int width, int height) {
surface->width = width;
surface->row_bytes = create_dumb.pitch;
surface->pixel_bytes = create_dumb.bpp / 8;
- surface->data = static_cast<unsigned char*>(mmap(nullptr, surface->height * surface->row_bytes,
- PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
- map_dumb.offset));
- if (surface->data == MAP_FAILED) {
+ auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE,
+ MAP_SHARED, drm_fd, map_dumb.offset);
+ if (mmapped == MAP_FAILED) {
perror("mmap() failed");
DrmDestroySurface(surface);
return nullptr;
}
-
+ surface->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
return surface;
}
@@ -368,18 +375,57 @@ GRSurface* MinuiBackendDrm::Init() {
current_buffer = 0;
- DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1]);
+ // We will likely encounter errors in the backend functions (i.e. Flip) if EnableCrtc fails.
+ if (DrmEnableCrtc(drm_fd, main_monitor_crtc, GRSurfaceDrms[1]) != 0) {
+ return nullptr;
+ }
return GRSurfaceDrms[0];
}
+static void page_flip_complete(__unused int fd,
+ __unused unsigned int sequence,
+ __unused unsigned int tv_sec,
+ __unused unsigned int tv_usec,
+ void *user_data) {
+ *static_cast<bool*>(user_data) = false;
+}
+
GRSurface* MinuiBackendDrm::Flip() {
+ bool ongoing_flip = true;
+
int ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id,
- GRSurfaceDrms[current_buffer]->fb_id, 0, nullptr);
+ GRSurfaceDrms[current_buffer]->fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, &ongoing_flip);
if (ret < 0) {
printf("drmModePageFlip failed ret=%d\n", ret);
return nullptr;
}
+
+ while (ongoing_flip) {
+ struct pollfd fds = {
+ .fd = drm_fd,
+ .events = POLLIN
+ };
+
+ ret = poll(&fds, 1, -1);
+ if (ret == -1 || !(fds.revents & POLLIN)) {
+ printf("poll() failed on drm fd\n");
+ break;
+ }
+
+ drmEventContext evctx = {
+ .version = DRM_EVENT_CONTEXT_VERSION,
+ .page_flip_handler = page_flip_complete
+ };
+
+ ret = drmHandleEvent(drm_fd, &evctx);
+ if (ret != 0) {
+ printf("drmHandleEvent failed ret=%d\n", ret);
+ break;
+ }
+ }
+
current_buffer = 1 - current_buffer;
return GRSurfaceDrms[current_buffer];
}