305 lines
11 KiB
Diff
305 lines
11 KiB
Diff
From d60c64d4142a0a706632c50b79474ee51464f973 Mon Sep 17 00:00:00 2001
|
|
From: Johnny on Flame <johnnyonflame@hotmail.com>
|
|
Date: Sun, 6 Aug 2023 20:57:02 +0000
|
|
Subject: [PATCH 3/7] Implement librga framebuffer rotation.
|
|
|
|
---
|
|
CMakeLists.txt | 2 +-
|
|
Makefile.in | 2 +-
|
|
src/video/kmsdrm/SDL_kmsdrmopengles.c | 26 +++++++++-
|
|
src/video/kmsdrm/SDL_kmsdrmsym.h | 2 +-
|
|
src/video/kmsdrm/SDL_kmsdrmvideo.c | 75 +++++++++++++++++++++++----
|
|
src/video/kmsdrm/SDL_kmsdrmvideo.h | 8 +++
|
|
6 files changed, 102 insertions(+), 13 deletions(-)
|
|
|
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
index d6c82c819..374f24e85 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -663,7 +663,7 @@ if(USE_GCC OR USE_CLANG OR USE_INTELCC)
|
|
check_c_compiler_flag("" HAVE_NO_UNDEFINED)
|
|
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
|
|
if(HAVE_NO_UNDEFINED AND NOT (USE_CLANG AND WINDOWS))
|
|
- list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,--no-undefined")
|
|
+ list(APPEND EXTRA_LDFLAGS_BUILD "-Wl,--no-undefined -lrga")
|
|
endif()
|
|
endif()
|
|
|
|
diff --git a/Makefile.in b/Makefile.in
|
|
index eb4c4bc1a..5cd04eeec 100644
|
|
--- a/Makefile.in
|
|
+++ b/Makefile.in
|
|
@@ -23,7 +23,7 @@ CXX = @CXX@
|
|
INCLUDE = @INCLUDE@
|
|
CFLAGS = @BUILD_CFLAGS@
|
|
EXTRA_CFLAGS = @EXTRA_CFLAGS@
|
|
-LDFLAGS = @BUILD_LDFLAGS@
|
|
+LDFLAGS = @BUILD_LDFLAGS@ -lrga
|
|
EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
|
|
LIBTOOL = @LIBTOOL@
|
|
INSTALL = @INSTALL@
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmopengles.c b/src/video/kmsdrm/SDL_kmsdrmopengles.c
|
|
index 487168203..47db85ef1 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmopengles.c
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmopengles.c
|
|
@@ -29,11 +29,15 @@
|
|
#include "SDL_kmsdrmopengles.h"
|
|
#include "SDL_kmsdrmdyn.h"
|
|
#include <errno.h>
|
|
+#include<stdbool.h>
|
|
|
|
#ifndef EGL_PLATFORM_GBM_MESA
|
|
#define EGL_PLATFORM_GBM_MESA 0x31D7
|
|
#endif
|
|
|
|
+extern rga_info_t src_info;
|
|
+extern rga_info_t dst_info;
|
|
+
|
|
/* EGL implementation of SDL OpenGL support */
|
|
|
|
void KMSDRM_GLES_DefaultProfileConfig(_THIS, int *mask, int *major, int *minor)
|
|
@@ -93,6 +97,7 @@ int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
|
|
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
|
KMSDRM_FBInfo *fb_info;
|
|
int ret = 0;
|
|
+ struct gbm_bo* rga_buffer = NULL;
|
|
|
|
/* Always wait for the previous issued flip before issuing a new one,
|
|
even if you do async flips. */
|
|
@@ -136,7 +141,26 @@ int KMSDRM_GLES_SwapWindow(_THIS, SDL_Window *window)
|
|
}
|
|
|
|
/* Get an actual usable fb for the next front buffer. */
|
|
- fb_info = KMSDRM_FBFromBO(_this, windata->next_bo);
|
|
+ if (src_info.fd) {
|
|
+ close(src_info.fd);
|
|
+ }
|
|
+ src_info.fd = KMSDRM_gbm_bo_get_fd(windata->next_bo);
|
|
+ dst_info.fd = viddata->rga_buffer_prime_fds[viddata->rga_buffer_index];
|
|
+ if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) {
|
|
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO,
|
|
+ "Failed to rga blit\n");
|
|
+ }
|
|
+
|
|
+ rga_buffer = viddata->rga_buffers[viddata->rga_buffer_index];
|
|
+ fb_info = KMSDRM_FBFromBO(_this, rga_buffer);
|
|
+
|
|
+ if (!fb_info) {
|
|
+ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get a framebuffer");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ viddata->rga_buffer_index = (viddata->rga_buffer_index + 1) % RGA_BUFFERS_MAX;
|
|
+
|
|
if (fb_info == NULL) {
|
|
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not get a framebuffer");
|
|
return 0;
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmsym.h b/src/video/kmsdrm/SDL_kmsdrmsym.h
|
|
index 8b9e7b257..b33373805 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmsym.h
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmsym.h
|
|
@@ -122,7 +122,7 @@ SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm,
|
|
SDL_KMSDRM_SYM(void,gbm_surface_destroy,(struct gbm_surface *surf))
|
|
SDL_KMSDRM_SYM(struct gbm_bo *,gbm_surface_lock_front_buffer,(struct gbm_surface *surf))
|
|
SDL_KMSDRM_SYM(void,gbm_surface_release_buffer,(struct gbm_surface *surf, struct gbm_bo *bo))
|
|
-
|
|
+SDL_KMSDRM_SYM(int,gbm_bo_get_fd,(struct gbm_bo *bo))
|
|
|
|
#undef SDL_KMSDRM_MODULE
|
|
#undef SDL_KMSDRM_SYM
|
|
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
index ebe15fe9c..c5340afa8 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
|
|
@@ -44,6 +44,7 @@
|
|
#include "SDL_kmsdrmopengles.h"
|
|
#include "SDL_kmsdrmmouse.h"
|
|
#include "SDL_kmsdrmdyn.h"
|
|
+#include <sys/ioctl.h>
|
|
#include "SDL_kmsdrmvulkan.h"
|
|
#include <sys/stat.h>
|
|
#include <sys/param.h>
|
|
@@ -51,6 +52,7 @@
|
|
#include <dirent.h>
|
|
#include <poll.h>
|
|
#include <errno.h>
|
|
+#include<stdbool.h>
|
|
|
|
#ifdef __OpenBSD__
|
|
static SDL_bool moderndri = SDL_FALSE;
|
|
@@ -68,6 +70,9 @@ static char kmsdrm_dri_cardpath[32];
|
|
#define EGL_PLATFORM_GBM_MESA 0x31D7
|
|
#endif
|
|
|
|
+rga_info_t src_info = {0};
|
|
+rga_info_t dst_info = {0};
|
|
+
|
|
static int get_driindex(void)
|
|
{
|
|
int available = -ENOENT;
|
|
@@ -330,6 +335,46 @@ static void KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data)
|
|
SDL_free(fb_info);
|
|
}
|
|
|
|
+static void
|
|
+KMSDRM_InitRotateBuffer(_THIS, int frameWidth, int frameHeight)
|
|
+{
|
|
+ int l_frameHeight;
|
|
+ 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);
|
|
+ }
|
|
+
|
|
+ // 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,
|
|
+ GBM_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
|
+ assert(viddata->rga_buffers[i]);
|
|
+
|
|
+ viddata->rga_buffer_prime_fds[i] = KMSDRM_gbm_bo_get_fd(viddata->rga_buffers[i]);
|
|
+ }
|
|
+ viddata->rga_buffer_index = 0;
|
|
+
|
|
+ // setup rotation
|
|
+ src_info.fd = -1;
|
|
+ src_info.mmuFlag = 1;
|
|
+ src_info.rotation = HAL_TRANSFORM_ROT_270;
|
|
+
|
|
+ // 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);
|
|
+
|
|
+ dst_info.fd = -1;
|
|
+ dst_info.mmuFlag = 1;
|
|
+
|
|
+ rga_set_rect(&dst_info.rect, 0, 0, frameWidth, frameHeight, frameWidth, frameHeight, RK_FORMAT_BGRA_8888);
|
|
+}
|
|
+
|
|
KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo)
|
|
{
|
|
SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
|
|
@@ -848,8 +893,8 @@ static void KMSDRM_AddDisplay(_THIS, drmModeConnector *connector, drmModeRes *re
|
|
modedata->mode_index = mode_index;
|
|
|
|
display.driverdata = dispdata;
|
|
- display.desktop_mode.w = dispdata->mode.hdisplay;
|
|
- display.desktop_mode.h = dispdata->mode.vdisplay;
|
|
+ display.desktop_mode.w = dispdata->mode.vdisplay;
|
|
+ display.desktop_mode.h = dispdata->mode.hdisplay;
|
|
display.desktop_mode.refresh_rate = dispdata->mode.vrefresh;
|
|
display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888;
|
|
display.desktop_mode.driverdata = modedata;
|
|
@@ -1124,7 +1169,8 @@ 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.hdisplay, mode.vdisplay);
|
|
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode.vdisplay, mode.hdisplay);
|
|
+
|
|
}
|
|
|
|
/* This determines the size of the fb, which comes from the GBM surface
|
|
@@ -1159,13 +1205,13 @@ int KMSDRM_CreateSurfaces(_THIS, SDL_Window *window)
|
|
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.hdisplay;
|
|
- display->current_mode.h = dispdata->mode.vdisplay;
|
|
+ display->current_mode.w = dispdata->mode.vdisplay;
|
|
+ display->current_mode.h = dispdata->mode.hdisplay;
|
|
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.hdisplay, dispdata->mode.vdisplay,
|
|
+ dispdata->mode.vdisplay, dispdata->mode.hdisplay,
|
|
surface_fmt, surface_flags);
|
|
|
|
if (!windata->gs) {
|
|
@@ -1189,7 +1235,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.hdisplay, dispdata->mode.vdisplay);
|
|
+ dispdata->mode.vdisplay, dispdata->mode.hdisplay);
|
|
|
|
windata->egl_surface_dirty = SDL_FALSE;
|
|
|
|
@@ -1272,8 +1318,8 @@ void KMSDRM_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
|
|
modedata->mode_index = i;
|
|
}
|
|
|
|
- mode.w = conn->modes[i].hdisplay;
|
|
- mode.h = conn->modes[i].vdisplay;
|
|
+ mode.w = conn->modes[i].vdisplay;
|
|
+ mode.h = conn->modes[i].hdisplay;
|
|
mode.refresh_rate = conn->modes[i].vrefresh;
|
|
mode.format = SDL_PIXELFORMAT_ARGB8888;
|
|
mode.driverdata = modedata;
|
|
@@ -1386,6 +1432,13 @@ void KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
|
|
/*********************************************************************/
|
|
SDL_free(window->driverdata);
|
|
window->driverdata = NULL;
|
|
+ for (int i = 0; i < RGA_BUFFERS_MAX; ++i) {
|
|
+ close(viddata->rga_buffer_prime_fds[i]);
|
|
+ }
|
|
+ if (src_info.fd) {
|
|
+ close(src_info.fd);
|
|
+ }
|
|
+ c_RkRgaDeInit();
|
|
}
|
|
|
|
/**********************************************************************/
|
|
@@ -1404,6 +1457,7 @@ int KMSDRM_CreateWindow(_THIS, SDL_Window *window)
|
|
NativeDisplayType egl_display;
|
|
drmModeModeInfo *mode;
|
|
int ret = 0;
|
|
+ SDL_DisplayData *data;
|
|
|
|
/* Allocate window internal data */
|
|
windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData));
|
|
@@ -1519,6 +1573,9 @@ 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);
|
|
+
|
|
/* 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 b48f6ef70..890575fb8 100644
|
|
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
|
|
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
|
|
@@ -32,6 +32,10 @@
|
|
#include <xf86drmMode.h>
|
|
#include <gbm.h>
|
|
#include <EGL/egl.h>
|
|
+#include <rga/RgaApi.h>
|
|
+#include <assert.h>
|
|
+
|
|
+#define RGA_BUFFERS_MAX (3)
|
|
|
|
typedef struct SDL_VideoData
|
|
{
|
|
@@ -53,6 +57,10 @@ typedef struct SDL_VideoData
|
|
open 1 FD and create 1 gbm device. */
|
|
SDL_bool gbm_init;
|
|
|
|
+ struct gbm_bo* rga_buffers[RGA_BUFFERS_MAX];
|
|
+ int rga_buffer_prime_fds[RGA_BUFFERS_MAX];
|
|
+ int rga_buffer_index;
|
|
+
|
|
} SDL_VideoData;
|
|
|
|
typedef struct SDL_DisplayModeData
|
|
--
|
|
2.20.1
|
|
|