356 lines
15 KiB
Diff
356 lines
15 KiB
Diff
From 0e53103957dd75be9140a474be343a6b7cc3cc9e Mon Sep 17 00:00:00 2001
|
|
From: JohnnyonFlame <johnnyonflame@hotmail.com>
|
|
Date: Tue, 8 Aug 2023 03:55:43 -0300
|
|
Subject: [PATCH 5/7] KMSDRM: Rotation should respect panel orientation.
|
|
|
|
---
|
|
src/video/kmsdrm/SDL_kmsdrmdyn.h | 8 ++
|
|
src/video/kmsdrm/SDL_kmsdrmmouse.c | 60 +++++++++++++-
|
|
src/video/kmsdrm/SDL_kmsdrmvideo.c | 122 +++++++++++++++++++++++------
|
|
src/video/kmsdrm/SDL_kmsdrmvideo.h | 2 +
|
|
4 files changed, 166 insertions(+), 26 deletions(-)
|
|
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmdyn.h b/src/video/kmsdrm/SDL_kmsdrmdyn.h
|
|
index 319e3f0e3..e17e97e8e 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmdyn.h
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmdyn.h
|
|
@@ -32,6 +32,14 @@
|
|
extern "C" {
|
|
#endif
|
|
|
|
+enum drm_panel_orientation {
|
|
+ DRM_MODE_PANEL_ORIENTATION_UNKNOWN = -1,
|
|
+ DRM_MODE_PANEL_ORIENTATION_NORMAL = 0,
|
|
+ DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP,
|
|
+ DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
|
|
+ DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
|
|
+};
|
|
+
|
|
int SDL_KMSDRM_LoadSymbols(void);
|
|
void SDL_KMSDRM_UnloadSymbols(void);
|
|
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c
|
|
index 4c445ecf1..5dcaaaab6 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c
|
|
@@ -170,10 +170,30 @@ static int KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor)
|
|
}
|
|
|
|
/* Copy from the cursor buffer to a buffer that we can dump to the GBM BO. */
|
|
+ uintptr_t src_buf = (uintptr_t)curdata->buffer;
|
|
+ uintptr_t dst_buf = (uintptr_t)ready_buffer;
|
|
for (i = 0; i < curdata->h; i++) {
|
|
for (j = 0; j < curdata->w; j++) {
|
|
- src_row = ((uint32_t*)curdata->buffer)[i * curdata->w + j];
|
|
- SDL_memcpy(ready_buffer + ((curdata->w - j + 1) * bo_stride) + i, &src_row, 4);
|
|
+ uintptr_t src_pixel = src_buf + (i * curdata->w + j) * 4;
|
|
+ uintptr_t dst_pixel;
|
|
+
|
|
+ int x, y;
|
|
+ if (dispdata->orientation == 0) {
|
|
+ x = j;
|
|
+ y = i;
|
|
+ } else if (dispdata->orientation == 1) {
|
|
+ x = curdata->w - i - 1;
|
|
+ y = j;
|
|
+ } else if (dispdata->orientation == 2) {
|
|
+ x = curdata->h - j - 1;
|
|
+ y = curdata->w - i - 1;
|
|
+ } else if (dispdata->orientation == 3) {
|
|
+ x = i;
|
|
+ y = curdata->h - j - 1;
|
|
+ }
|
|
+
|
|
+ dst_pixel = dst_buf + (y * bo_stride + x * sizeof(uint32_t));
|
|
+ *(uint32_t*)dst_pixel = *(uint32_t*)src_pixel;
|
|
}
|
|
}
|
|
|
|
@@ -382,7 +402,23 @@ static int KMSDRM_WarpMouseGlobal(int x, int y)
|
|
if (dispdata->cursor_bo) {
|
|
int ret = 0;
|
|
|
|
- ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, y, dispdata->mode.vdisplay + curdata->w - x);
|
|
+ if (dispdata->orientation == 0) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ x,
|
|
+ y);
|
|
+ } else if (dispdata->orientation == 1) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ dispdata->mode.hdisplay - curdata->h - y,
|
|
+ x);
|
|
+ } else if (dispdata->orientation == 2) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ dispdata->mode.hdisplay - curdata->w - x,
|
|
+ dispdata->mode.vdisplay - curdata->h - y);
|
|
+ } else if (dispdata->orientation == 3) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ y,
|
|
+ dispdata->mode.vdisplay - curdata->w - x);
|
|
+ }
|
|
|
|
if (ret) {
|
|
SDL_SetError("drmModeMoveCursor() failed.");
|
|
@@ -443,7 +479,23 @@ static void KMSDRM_MoveCursor(SDL_Cursor *cursor)
|
|
return;
|
|
}
|
|
|
|
- ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, mouse->y, dispdata->mode.vdisplay - curdata->w - mouse->x);
|
|
+ if (dispdata->orientation == 0) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ mouse->x,
|
|
+ mouse->y);
|
|
+ } else if (dispdata->orientation == 1) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ dispdata->mode.hdisplay - curdata->h - mouse->y,
|
|
+ mouse->x);
|
|
+ } else if (dispdata->orientation == 2) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ dispdata->mode.hdisplay - curdata->w - mouse->x,
|
|
+ dispdata->mode.vdisplay - curdata->h - mouse->y);
|
|
+ } else if (dispdata->orientation == 3) {
|
|
+ ret = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id,
|
|
+ mouse->y,
|
|
+ dispdata->mode.vdisplay - curdata->w - mouse->x);
|
|
+ }
|
|
|
|
if (ret) {
|
|
SDL_SetError("drmModeMoveCursor() failed.");
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
index c5340afa8..663c4707c 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
@@ -336,24 +336,27 @@ static void KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
|
|
}
|
|
|
|
static void
|
|
-KMSDRM_InitRotateBuffer(_THIS, int frameWidth, int frameHeight)
|
|
+KMSDRM_InitRotateBuffer(_THIS, int orientation, int frameWidth, int frameHeight)
|
|
{
|
|
- int l_frameHeight;
|
|
+ int l_frameHeight, l_frameWidth;
|
|
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
|
|
|
// initialize 2D raster graphic acceleration unit (RGA)
|
|
c_RkRgaInit();
|
|
|
|
- l_frameHeight = frameHeight;
|
|
- if(l_frameHeight % 32 != 0) {
|
|
- l_frameHeight = (frameHeight + 32) & (~31);
|
|
+ if (orientation & 1) {
|
|
+ l_frameWidth = frameWidth;
|
|
+ l_frameHeight = (frameHeight + 31) & (~31);
|
|
+ } else {
|
|
+ l_frameWidth = (frameWidth + 31) & (~31);
|
|
+ l_frameHeight = frameHeight;
|
|
}
|
|
|
|
// create buffers for RGA with adjusted stride
|
|
for (int i = 0; i < RGA_BUFFERS_MAX; ++i)
|
|
{
|
|
viddata->rga_buffers[i] = KMSDRM_gbm_bo_create(viddata->gbm_dev,
|
|
- frameWidth, l_frameHeight,
|
|
+ l_frameWidth, l_frameHeight,
|
|
GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
|
assert(viddata->rga_buffers[i]);
|
|
|
|
@@ -364,10 +367,18 @@ KMSDRM_InitRotateBuffer(_THIS, int frameWidth, int frameHeight)
|
|
// setup rotation
|
|
src_info.fd = -1;
|
|
src_info.mmuFlag = 1;
|
|
- src_info.rotation = HAL_TRANSFORM_ROT_270;
|
|
+ switch (orientation) {
|
|
+ default: src_info.rotation = 0; break;
|
|
+ case 1: src_info.rotation = HAL_TRANSFORM_ROT_90; break;
|
|
+ case 2: src_info.rotation = HAL_TRANSFORM_ROT_180; break;
|
|
+ case 3: src_info.rotation = HAL_TRANSFORM_ROT_270; break;
|
|
+ }
|
|
|
|
// swap width and height and adjust stride here because our source buffer is 480x854
|
|
- rga_set_rect(&src_info.rect, 0, 0, frameHeight, frameWidth, l_frameHeight, frameWidth, RK_FORMAT_BGRA_8888);
|
|
+ if (orientation & 1)
|
|
+ rga_set_rect(&src_info.rect, 0, 0, frameHeight, frameWidth, l_frameHeight, l_frameWidth, RK_FORMAT_BGRA_8888);
|
|
+ else
|
|
+ rga_set_rect(&src_info.rect, 0, 0, frameWidth, frameHeight, l_frameWidth, l_frameHeight, RK_FORMAT_BGRA_8888);
|
|
|
|
dst_info.fd = -1;
|
|
dst_info.mmuFlag = 1;
|
|
@@ -617,6 +628,52 @@ static SDL_bool KMSDRM_VrrPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *vr
|
|
return SDL_TRUE;
|
|
}
|
|
|
|
+static int KMSDRM_ConnectorGetOrientation(uint32_t drm_fd,
|
|
+ uint32_t output_id)
|
|
+{
|
|
+ uint32_t i;
|
|
+ SDL_bool found = SDL_FALSE;
|
|
+ uint64_t orientation = DRM_MODE_PANEL_ORIENTATION_NORMAL;
|
|
+
|
|
+ drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd,
|
|
+ output_id,
|
|
+ DRM_MODE_OBJECT_CONNECTOR);
|
|
+
|
|
+ // Allow forcing specific orientations for debugging.
|
|
+ const char *override = SDL_getenv("SDL_KMSDRM_ORIENTATION");
|
|
+ if (override && override[0] != '\0') {
|
|
+ int val = SDL_atoi(override);
|
|
+ return SDL_clamp(val, 0, 3);
|
|
+ }
|
|
+
|
|
+ if (!props) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ for (i = 0; !found && i < props->count_props; ++i) {
|
|
+ drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]);
|
|
+
|
|
+ if (!drm_prop) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (SDL_strcasecmp(drm_prop->name, "panel orientation") == 0) {
|
|
+ orientation = props->prop_values[i];
|
|
+ found = SDL_TRUE;
|
|
+ }
|
|
+
|
|
+ KMSDRM_drmModeFreeProperty(drm_prop);
|
|
+ }
|
|
+
|
|
+ /* librga expresses rotations clockwise. (e.g., dts = 90? rga = 270!) */
|
|
+ switch (orientation) {
|
|
+ default: return 0;
|
|
+ case DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP: return 2;
|
|
+ case DRM_MODE_PANEL_ORIENTATION_LEFT_UP: return 1;
|
|
+ case DRM_MODE_PANEL_ORIENTATION_RIGHT_UP: return 3;
|
|
+ }
|
|
+}
|
|
+
|
|
static SDL_bool KMSDRM_ConnectorCheckVrrCapable(uint32_t drm_fd,
|
|
uint32_t output_id,
|
|
char const *name)
|
|
@@ -869,6 +926,8 @@ static void KMSDRM_AddDisplay(_THIS, drmModeConnector *connector, drmModeRes *re
|
|
dispdata->connector = connector;
|
|
dispdata->crtc = crtc;
|
|
|
|
+ /* store current connector orientation */
|
|
+ dispdata->orientation = KMSDRM_ConnectorGetOrientation(viddata->drm_fd, connector->connector_id);
|
|
/* save previous vrr state */
|
|
dispdata->saved_vrr = KMSDRM_CrtcGetVrr(viddata->drm_fd, crtc->crtc_id);
|
|
/* try to enable vrr */
|
|
@@ -893,8 +952,13 @@ static void KMSDRM_AddDisplay(_THIS, drmModeConnector *connector, drmModeRes *re
|
|
modedata->mode_index = mode_index;
|
|
|
|
display.driverdata = dispdata;
|
|
- display.desktop_mode.w = dispdata->mode.vdisplay;
|
|
- display.desktop_mode.h = dispdata->mode.hdisplay;
|
|
+ if (dispdata->orientation & 1) {
|
|
+ display.desktop_mode.w = dispdata->mode.vdisplay;
|
|
+ display.desktop_mode.h = dispdata->mode.hdisplay;
|
|
+ } else {
|
|
+ display.desktop_mode.w = dispdata->mode.hdisplay;
|
|
+ display.desktop_mode.h = dispdata->mode.vdisplay;
|
|
+ }
|
|
display.desktop_mode.refresh_rate = dispdata->mode.vrefresh;
|
|
display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888;
|
|
display.desktop_mode.driverdata = modedata;
|
|
@@ -1158,8 +1222,10 @@ static void KMSDRM_GetModeToSet(SDL_Window *window, drmModeModeInfo *out_mode)
|
|
|
|
static void KMSDRM_DirtySurfaces(SDL_Window *window)
|
|
{
|
|
- SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
|
|
drmModeModeInfo mode;
|
|
+ SDL_WindowData *windata = (SDL_WindowData *)window->driverdata;
|
|
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
|
+ SDL_DisplayData *dispdata = (SDL_DisplayData *)display->driverdata;
|
|
|
|
/* Can't recreate EGL surfaces right now, need to wait until SwapWindow
|
|
so the correct thread-local surface and context state are available */
|
|
@@ -1169,8 +1235,10 @@ static void KMSDRM_DirtySurfaces(SDL_Window *window)
|
|
or SetWindowFullscreen, send a fake event for now since the actual
|
|
recreation is deferred */
|
|
KMSDRM_GetModeToSet(window, &mode);
|
|
- SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.vdisplay, mode.hdisplay);
|
|
-
|
|
+ if (dispdata->orientation & 1)
|
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.vdisplay, mode.hdisplay);
|
|
+ else
|
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.hdisplay, mode.vdisplay);
|
|
}
|
|
|
|
/* This determines the size of the fb, which comes from the GBM surface
|
|
@@ -1204,14 +1272,18 @@ int KMSDRM_CreateSurfaces(_THIS, SDL_Window *window)
|
|
SDL_video.c expects. Hulk-smash the display's current_mode to keep the
|
|
mode that's set in sync with what SDL_video.c thinks is set */
|
|
KMSDRM_GetModeToSet(window, &dispdata->mode);
|
|
-
|
|
- display->current_mode.w = dispdata->mode.vdisplay;
|
|
- display->current_mode.h = dispdata->mode.hdisplay;
|
|
+ if (dispdata->orientation & 1) {
|
|
+ display->current_mode.w = dispdata->mode.vdisplay;
|
|
+ display->current_mode.h = dispdata->mode.hdisplay;
|
|
+ } else {
|
|
+ display->current_mode.w = dispdata->mode.hdisplay;
|
|
+ display->current_mode.h = dispdata->mode.vdisplay;
|
|
+ }
|
|
display->current_mode.refresh_rate = dispdata->mode.vrefresh;
|
|
display->current_mode.format = SDL_PIXELFORMAT_ARGB8888;
|
|
|
|
windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev,
|
|
- dispdata->mode.vdisplay, dispdata->mode.hdisplay,
|
|
+ display->current_mode.w, display->current_mode.h,
|
|
surface_fmt, surface_flags);
|
|
|
|
if (!windata->gs) {
|
|
@@ -1235,7 +1307,7 @@ int KMSDRM_CreateSurfaces(_THIS, SDL_Window *window)
|
|
ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context);
|
|
|
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
|
|
- dispdata->mode.vdisplay, dispdata->mode.hdisplay);
|
|
+ display->current_mode.w, display->current_mode.h);
|
|
|
|
windata->egl_surface_dirty = SDL_FALSE;
|
|
|
|
@@ -1318,8 +1390,14 @@ void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
|
|
modedata->mode_index = i;
|
|
}
|
|
|
|
- mode.w = conn->modes[i].vdisplay;
|
|
- mode.h = conn->modes[i].hdisplay;
|
|
+ if (dispdata->orientation & 1) {
|
|
+ mode.w = conn->modes[i].vdisplay;
|
|
+ mode.h = conn->modes[i].hdisplay;
|
|
+ } else {
|
|
+ mode.w = conn->modes[i].hdisplay;
|
|
+ mode.h = conn->modes[i].vdisplay;
|
|
+ }
|
|
+
|
|
mode.refresh_rate = conn->modes[i].vrefresh;
|
|
mode.format = SDL_PIXELFORMAT_ARGB8888;
|
|
mode.driverdata = modedata;
|
|
@@ -1573,8 +1651,8 @@ int KMSDRM_CreateWindow(_THIS, SDL_Window *window)
|
|
SDL_SetMouseFocus(window);
|
|
SDL_SetKeyboardFocus(window);
|
|
|
|
- data = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
|
- KMSDRM_InitRotateBuffer(_this, data->mode.hdisplay, data->mode.vdisplay);
|
|
+ data = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
|
|
+ KMSDRM_InitRotateBuffer(_this, dispdata->orientation, data->mode.hdisplay, data->mode.vdisplay);
|
|
|
|
/* Tell the app that the window has moved to top-left. */
|
|
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, 0, 0);
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
|
|
index 890575fb8..8d2dc646f 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
|
|
@@ -78,6 +78,8 @@ typedef struct SDL_DisplayData
|
|
|
|
drmModeCrtc *saved_crtc; /* CRTC to restore on quit */
|
|
SDL_bool saved_vrr;
|
|
+
|
|
+ uint64_t orientation;
|
|
|
|
/* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's driverdata struct,
|
|
because setting/unsetting up these is done on window creation/destruction,
|
|
--
|
|
2.20.1
|
|
|