[KMS/DRM] Go back to the LEGACY interface only because using planes breaks compatibility with HW, so no advantage on using ATOMIC.

This commit is contained in:
Manuel Alfayate Corchete 2021-01-08 18:57:12 +01:00
parent 940e1b8dd9
commit b24494734b
16 changed files with 545 additions and 1475 deletions

View File

@ -1182,8 +1182,7 @@ macro(CheckKMSDRM)
set(HAVE_SDL_VIDEO TRUE) set(HAVE_SDL_VIDEO TRUE)
file(GLOB KMSDRM_SOURCES ${SDL2_SOURCE_DIR}/src/video/kmsdrm/*.c) file(GLOB KMSDRM_SOURCES ${SDL2_SOURCE_DIR}/src/video/kmsdrm/*.c)
file(GLOB KMSDRM_LEGACY_SOURCES ${SDL2_SOURCE_DIR}/src/video/kmsdrm_legacy/*.c) set(SOURCE_FILES ${SOURCE_FILES} ${KMSDRM_SOURCES})
set(SOURCE_FILES ${SOURCE_FILES} ${KMSDRM_SOURCES} ${KMSDRM_LEGACY_SOURCES})
list(APPEND EXTRA_CFLAGS ${KMSDRM_CFLAGS}) list(APPEND EXTRA_CFLAGS ${KMSDRM_CFLAGS})

View File

@ -2252,7 +2252,6 @@ AS_HELP_STRING([--enable-kmsdrm-shared], [dynamically load kmsdrm support [[defa
AC_DEFINE(SDL_VIDEO_DRIVER_KMSDRM, 1, [ ]) AC_DEFINE(SDL_VIDEO_DRIVER_KMSDRM, 1, [ ])
SOURCES="$SOURCES $srcdir/src/video/kmsdrm/*.c" SOURCES="$SOURCES $srcdir/src/video/kmsdrm/*.c"
SOURCES="$SOURCES $srcdir/src/video/kmsdrm_legacy/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBDRM_CFLAGS $LIBGBM_CFLAGS" EXTRA_CFLAGS="$EXTRA_CFLAGS $LIBDRM_CFLAGS $LIBGBM_CFLAGS"
AC_MSG_CHECKING(for kmsdrm dynamic loading support) AC_MSG_CHECKING(for kmsdrm dynamic loading support)

View File

@ -96,7 +96,6 @@ static VideoBootStrap *bootstrap[] = {
#endif #endif
#if SDL_VIDEO_DRIVER_KMSDRM #if SDL_VIDEO_DRIVER_KMSDRM
&KMSDRM_bootstrap, &KMSDRM_bootstrap,
&KMSDRM_LEGACY_bootstrap,
#endif #endif
#if SDL_VIDEO_DRIVER_RPI #if SDL_VIDEO_DRIVER_RPI
&RPI_bootstrap, &RPI_bootstrap,

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -28,7 +27,6 @@
#include "SDL_kmsdrmdyn.h" #include "SDL_kmsdrmdyn.h"
#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC #ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC
#include "SDL_name.h" #include "SDL_name.h"

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -27,7 +26,6 @@
#include "SDL_kmsdrmvideo.h" #include "SDL_kmsdrmvideo.h"
#include "SDL_kmsdrmmouse.h" #include "SDL_kmsdrmmouse.h"
#include "SDL_kmsdrmdyn.h" #include "SDL_kmsdrmdyn.h"
#include "SDL_assert.h"
#include "../../events/SDL_mouse_c.h" #include "../../events/SDL_mouse_c.h"
#include "../../events/default_cursor.h" #include "../../events/default_cursor.h"
@ -55,40 +53,18 @@ static int KMSDRM_WarpMouseGlobal(int x, int y);
/* and mouse->cursor_shown is 1. */ /* and mouse->cursor_shown is 1. */
/**************************************************************************************/ /**************************************************************************************/
/**********************************/ static SDL_Cursor *
/* Atomic helper functions block. */ KMSDRM_CreateDefaultCursor(void)
/**********************************/
int
drm_atomic_movecursor(KMSDRM_CursorData *curdata, uint16_t x, uint16_t y)
{ {
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
if (!dispdata->cursor_plane) /* We can't move a non-existing cursor, but that's ok. */
return 0;
/* Do we have a set of changes already in the making? If not, allocate a new one. */
if (!dispdata->atomic_req)
dispdata->atomic_req = KMSDRM_drmModeAtomicAlloc();
add_plane_property(dispdata->atomic_req,
dispdata->cursor_plane, "CRTC_X", x - curdata->hot_x);
add_plane_property(dispdata->atomic_req,
dispdata->cursor_plane, "CRTC_Y", y - curdata->hot_y);
return 0;
} }
/***************************************/
/* Atomic helper functions block ends. */
/***************************************/
/* Converts a pixel from straight-alpha [AA, RR, GG, BB], which the SDL cursor surface has, /* Converts a pixel from straight-alpha [AA, RR, GG, BB], which the SDL cursor surface has,
to premultiplied-alpha [AA. AA*RR, AA*GG, AA*BB]. to premultiplied-alpha [AA. AA*RR, AA*GG, AA*BB].
These multiplications have to be done with floats instead of uint32_t's, These multiplications have to be done with floats instead of uint32_t's,
and the resulting values have to be converted to be relative to the 0-255 interval, and the resulting values have to be converted to be relative to the 0-255 interval,
where 255 is 1.00 and anything between 0 and 255 is 0.xx. */ where 255 is 1.00 and anything between 0 and 255 is 0.xx. */
void alpha_premultiply_ARGB8888 (uint32_t *pixel) { void legacy_alpha_premultiply_ARGB8888 (uint32_t *pixel) {
uint32_t A, R, G, B; uint32_t A, R, G, B;
@ -107,15 +83,9 @@ void alpha_premultiply_ARGB8888 (uint32_t *pixel) {
(*pixel) = (((uint32_t)A << 24) | ((uint32_t)R << 16) | ((uint32_t)G << 8)) | ((uint32_t)B << 0); (*pixel) = (((uint32_t)A << 24) | ((uint32_t)R << 16) | ((uint32_t)G << 8)) | ((uint32_t)B << 0);
} }
static SDL_Cursor * /* This simply gets the cursor soft-buffer ready.
KMSDRM_CreateDefaultCursor(void) We don't copy it to a GBO BO until ShowCursor() because the cusor GBM BO (living
{ in dispata) is destroyed and recreated when we recreate windows, etc. */
return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY);
}
/* This simply gets the cursor soft-buffer ready. We don't copy it to a GBO BO
until ShowCursor() because the cusor GBM BO (living in dispata) is destroyed
and recreated when we recreate windows, etc. */
static SDL_Cursor * static SDL_Cursor *
KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
{ {
@ -225,13 +195,12 @@ static int
KMSDRM_ShowCursor(SDL_Cursor * cursor) KMSDRM_ShowCursor(SDL_Cursor * cursor)
{ {
SDL_VideoDevice *video_device = SDL_GetVideoDevice(); SDL_VideoDevice *video_device = SDL_GetVideoDevice();
//SDL_VideoData *viddata = ((SDL_VideoData *)video_device->driverdata); SDL_VideoData *viddata = ((SDL_VideoData *)video_device->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
SDL_Mouse *mouse; SDL_Mouse *mouse;
KMSDRM_CursorData *curdata; KMSDRM_CursorData *curdata;
KMSDRM_FBInfo *fb; uint32_t bo_handle;
KMSDRM_PlaneInfo info = {0};
size_t bo_stride; size_t bo_stride;
size_t bufsize; size_t bufsize;
@ -239,7 +208,7 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
uint32_t pixel; uint32_t pixel;
int i,j; int i,j;
int ret = 0; int ret;
mouse = SDL_GetMouse(); mouse = SDL_GetMouse();
if (!mouse) { if (!mouse) {
@ -250,28 +219,20 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
/* Hide cursor if it's NULL or it has no focus(=winwow). */ /* Hide cursor if it's NULL or it has no focus(=winwow). */
/*********************************************************/ /*********************************************************/
if (!cursor || !mouse->focus) { if (!cursor || !mouse->focus) {
if (dispdata->cursor_plane) { /* Hide the drm cursor with no more considerations because
/* Hide the drm cursor with no more considerations because SDL_VideoQuit() takes us here after disabling the mouse
SDL_VideoQuit() takes us here after disabling the mouse so there is no mouse->cur_cursor by now. */
so there is no mouse->cur_cursor by now. */ ret = KMSDRM_drmModeSetCursor(viddata->drm_fd,
info.plane = dispdata->cursor_plane; dispdata->crtc->crtc_id, 0, 0, 0);
/* The rest of the members are zeroed, so this takes away the cursor if (ret) {
from the cursor plane. */ ret = SDL_SetError("Could not hide current cursor with drmModeSetCursor().");
drm_atomic_set_plane_props(&info); }
if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) { return ret;
ret = SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
}
}
return ret;
} }
/************************************************/ /************************************************/
/* If cursor != NULL, DO show cursor on display */ /* If cursor != NULL, DO show cursor on display */
/************************************************/ /************************************************/
if (!dispdata->cursor_plane) {
return SDL_SetError("Hardware cursor plane not initialized.");
}
curdata = (KMSDRM_CursorData *) cursor->driverdata; curdata = (KMSDRM_CursorData *) cursor->driverdata;
if (!curdata || !dispdata->cursor_bo) { if (!curdata || !dispdata->cursor_bo) {
@ -297,7 +258,7 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
for (i = 0; i < curdata->h; i++) { for (i = 0; i < curdata->h; i++) {
for (j = 0; j < curdata->w; j++) { for (j = 0; j < curdata->w; j++) {
pixel = ((uint32_t*)curdata->buffer)[i * curdata->w + j]; pixel = ((uint32_t*)curdata->buffer)[i * curdata->w + j];
alpha_premultiply_ARGB8888 (&pixel); legacy_alpha_premultiply_ARGB8888 (&pixel);
SDL_memcpy(ready_buffer + (i * dispdata->cursor_w) + j, &pixel, 4); SDL_memcpy(ready_buffer + (i * dispdata->cursor_w) + j, &pixel, 4);
} }
} }
@ -308,28 +269,20 @@ KMSDRM_ShowCursor(SDL_Cursor * cursor)
goto cleanup; goto cleanup;
} }
/* Get the fb_id for the GBM BO so we can show it on the cursor plane. */ /* Put the GBM BO buffer on screen using the DRM interface. */
fb = KMSDRM_FBFromBO(video_device, dispdata->cursor_bo); bo_handle = KMSDRM_gbm_bo_get_handle(dispdata->cursor_bo).u32;
if (curdata->hot_x == 0 && curdata->hot_y == 0) {
/* Show the GBM BO buffer on the cursor plane. */ ret = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id,
info.plane = dispdata->cursor_plane; bo_handle, dispdata->cursor_w, dispdata->cursor_h);
info.crtc_id = dispdata->crtc->crtc->crtc_id; } else {
info.fb_id = fb->fb_id; ret = KMSDRM_drmModeSetCursor2(viddata->drm_fd, dispdata->crtc->crtc_id,
info.src_w = dispdata->cursor_w; bo_handle, dispdata->cursor_w, dispdata->cursor_h, curdata->hot_x, curdata->hot_y);
info.src_h = dispdata->cursor_h;
info.crtc_x = mouse->x - curdata->hot_x;
info.crtc_y = mouse->y - curdata->hot_y;
info.crtc_w = curdata->w;
info.crtc_h = curdata->h;
drm_atomic_set_plane_props(&info);
if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
ret = SDL_SetError("Failed atomic commit in KMSDRM_ShowCursor.");
goto cleanup;
} }
ret = 0; if (ret) {
ret = SDL_SetError("Failed to set DRM cursor.");
goto cleanup;
}
cleanup: cleanup:
@ -373,7 +326,6 @@ KMSDRM_WarpMouse(SDL_Window * window, int x, int y)
static int static int
KMSDRM_WarpMouseGlobal(int x, int y) KMSDRM_WarpMouseGlobal(int x, int y)
{ {
KMSDRM_CursorData *curdata;
SDL_Mouse *mouse = SDL_GetMouse(); SDL_Mouse *mouse = SDL_GetMouse();
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
@ -382,11 +334,18 @@ KMSDRM_WarpMouseGlobal(int x, int y)
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y); SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
/* And now update the cursor graphic position on screen. */ /* And now update the cursor graphic position on screen. */
curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
if (dispdata->cursor_bo) { if (dispdata->cursor_bo) {
if (drm_atomic_movecursor(curdata, x, y)) { int ret, drm_fd;
return SDL_SetError("drm_atomic_movecursor() failed."); drm_fd = KMSDRM_gbm_device_get_fd(
} KMSDRM_gbm_bo_get_device(dispdata->cursor_bo));
ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, x, y);
if (ret) {
SDL_SetError("drmModeMoveCursor() failed.");
}
return ret;
} else { } else {
return SDL_SetError("Cursor not initialized properly."); return SDL_SetError("Cursor not initialized properly.");
} }
@ -403,30 +362,15 @@ KMSDRM_DeinitMouse(_THIS)
{ {
SDL_VideoDevice *video_device = SDL_GetVideoDevice(); SDL_VideoDevice *video_device = SDL_GetVideoDevice();
SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0); SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
KMSDRM_PlaneInfo info = {0};
/* 1- Destroy the curso GBM BO. */ /* Destroy the curso GBM BO. */
if (video_device && dispdata->cursor_bo) { if (video_device && dispdata->cursor_bo) {
/* Unsethe the cursor BO from the cursor plane.
(The other members of the plane info are zeroed). */
info.plane = dispdata->cursor_plane;
drm_atomic_set_plane_props(&info);
/* Wait until the cursor is unset from the cursor plane
before destroying it's BO. */
if (drm_atomic_commit(video_device, SDL_TRUE, SDL_FALSE)) {
SDL_SetError("Failed atomic commit in KMSDRM_DenitMouse.");
}
/* ..and finally destroy the cursor DRM BO! */
KMSDRM_gbm_bo_destroy(dispdata->cursor_bo); KMSDRM_gbm_bo_destroy(dispdata->cursor_bo);
dispdata->cursor_bo = NULL; dispdata->cursor_bo = NULL;
} }
/* 2- Free the cursor plane, on which the cursor was being shown. */
if (dispdata->cursor_plane) {
free_plane(&dispdata->cursor_plane);
}
} }
/* Create cursor BO. */
void void
KMSDRM_InitMouse(_THIS) KMSDRM_InitMouse(_THIS)
{ {
@ -442,29 +386,23 @@ KMSDRM_InitMouse(_THIS)
mouse->WarpMouse = KMSDRM_WarpMouse; mouse->WarpMouse = KMSDRM_WarpMouse;
mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal; mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal;
/***************************************************************************/ /************************************************/
/* REMEMBER TO BE SURE OF UNDOING ALL THESE STEPS PROPERLY BEFORE CALLING */ /* Create the cursor GBM BO, if we haven't yet. */
/* gbm_device_destroy, OR YOU WON'T BE ABLE TO CREATE A NEW ONE (ERROR -13 */ /************************************************/
/* on gbm_create_device). */
/***************************************************************************/
/* 1- Init cursor plane, if we haven't yet. */
if (!dispdata->cursor_plane) {
setup_plane(_this, &(dispdata->cursor_plane), DRM_PLANE_TYPE_CURSOR);
}
/* 2- Create the cursor GBM BO, if we haven't yet. */
if (!dispdata->cursor_bo) { if (!dispdata->cursor_bo) {
if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev, GBM_FORMAT_ARGB8888, if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) GBM_FORMAT_ARGB8888,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
{ {
SDL_SetError("Unsupported pixel format for cursor"); SDL_SetError("Unsupported pixel format for cursor");
return; return;
} }
if (KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_CURSOR_WIDTH, &dispdata->cursor_w) || if (KMSDRM_drmGetCap(viddata->drm_fd,
KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_CURSOR_HEIGHT, &dispdata->cursor_h)) DRM_CAP_CURSOR_WIDTH, &dispdata->cursor_w) ||
KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_CURSOR_HEIGHT,
&dispdata->cursor_h))
{ {
SDL_SetError("Could not get the recommended GBM cursor size"); SDL_SetError("Could not get the recommended GBM cursor size");
goto cleanup; goto cleanup;
@ -477,7 +415,7 @@ KMSDRM_InitMouse(_THIS)
dispdata->cursor_bo = KMSDRM_gbm_bo_create(viddata->gbm_dev, dispdata->cursor_bo = KMSDRM_gbm_bo_create(viddata->gbm_dev,
dispdata->cursor_w, dispdata->cursor_h, dispdata->cursor_w, dispdata->cursor_h,
GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR);
if (!dispdata->cursor_bo) { if (!dispdata->cursor_bo) {
SDL_SetError("Could not create GBM cursor BO"); SDL_SetError("Could not create GBM cursor BO");
@ -505,27 +443,28 @@ cleanup:
} }
} }
void
KMSDRM_QuitMouse(_THIS)
{
/* TODO: ? */
}
/* This is called when a mouse motion event occurs */ /* This is called when a mouse motion event occurs */
static void static void
KMSDRM_MoveCursor(SDL_Cursor * cursor) KMSDRM_MoveCursor(SDL_Cursor * cursor)
{ {
SDL_Mouse *mouse = SDL_GetMouse(); SDL_Mouse *mouse = SDL_GetMouse();
KMSDRM_CursorData *curdata; SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayDriverData(0);
int drm_fd, ret;
/* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity! /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
That's why we move the cursor graphic ONLY. */ That's why we move the cursor graphic ONLY. */
if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) { if (mouse && mouse->cur_cursor && mouse->cur_cursor->driverdata) {
curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata; drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(dispdata->cursor_bo));
ret = KMSDRM_drmModeMoveCursor(drm_fd, dispdata->crtc->crtc_id, mouse->x, mouse->y);
/* Some programs expect cursor movement even while they don't do SwapWindow() calls, if (ret) {
and since we ride on the atomic_commit() in SwapWindow() for cursor movement, SDL_SetError("drmModeMoveCursor() failed.");
cursor won't move in these situations. We could do an atomic_commit() here
for each cursor movement request, but it cripples the movement to 30FPS,
so a future solution is needed. SDLPoP "QUIT?" menu is an example of this
situation. */
if (drm_atomic_movecursor(curdata, mouse->x, mouse->y)) {
SDL_SetError("drm_atomic_movecursor() failed.");
} }
} }
} }

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -30,14 +29,14 @@
#define MAX_CURSOR_W 512 #define MAX_CURSOR_W 512
#define MAX_CURSOR_H 512 #define MAX_CURSOR_H 512
/* Driverdata with driver-side info about the cursor. */
typedef struct _KMSDRM_CursorData typedef struct _KMSDRM_CursorData
{ {
uint16_t hot_x, hot_y; int hot_x, hot_y;
uint16_t w, h; int w, h;
/* The buffer where we store the mouse bitmap ready to be used. /* The buffer where we store the mouse bitmap ready to be used.
We get it ready and filled in CreateCursor(), and copy it to a GBM BO in ShowCursor().*/ We get it ready and filled in CreateCursor(), and copy it
to a GBM BO in ShowCursor().*/
uint32_t *buffer; uint32_t *buffer;
size_t buffer_size; size_t buffer_size;
size_t buffer_pitch; size_t buffer_pitch;
@ -46,6 +45,7 @@ typedef struct _KMSDRM_CursorData
extern void KMSDRM_InitMouse(_THIS); extern void KMSDRM_InitMouse(_THIS);
extern void KMSDRM_DeinitMouse(_THIS); extern void KMSDRM_DeinitMouse(_THIS);
extern void KMSDRM_QuitMouse(_THIS);
extern void KMSDRM_InitCursor(); extern void KMSDRM_InitCursor();

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -24,27 +23,16 @@
#if SDL_VIDEO_DRIVER_KMSDRM #if SDL_VIDEO_DRIVER_KMSDRM
#include "SDL_log.h"
#include "SDL_kmsdrmvideo.h" #include "SDL_kmsdrmvideo.h"
#include "SDL_kmsdrmopengles.h" #include "SDL_kmsdrmopengles.h"
#include "SDL_kmsdrmdyn.h" #include "SDL_kmsdrmdyn.h"
#include "SDL_hints.h"
#ifndef EGL_PLATFORM_GBM_MESA #ifndef EGL_PLATFORM_GBM_MESA
#define EGL_PLATFORM_GBM_MESA 0x31D7 #define EGL_PLATFORM_GBM_MESA 0x31D7
#endif #endif
#ifndef EGL_SYNC_NATIVE_FENCE_ANDROID
#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144
#endif
#ifndef EGL_SYNC_NATIVE_FENCE_FD_ANDROID
#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145
#endif
#ifndef EGL_NO_NATIVE_FENCE_FD_ANDROID
#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1
#endif
/* EGL implementation of SDL OpenGL support */ /* EGL implementation of SDL OpenGL support */
void void
@ -95,291 +83,82 @@ int KMSDRM_GLES_SetSwapInterval(_THIS, int interval) {
return 0; return 0;
} }
/*********************************/
/* Atomic functions block */
/*********************************/
#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
static EGLSyncKHR create_fence(int fd, _THIS)
{
EGLint attrib_list[] = {
EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fd,
EGL_NONE,
};
EGLSyncKHR fence = _this->egl_data->eglCreateSyncKHR
(_this->egl_data->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attrib_list);
assert(fence);
return fence;
}
/***********************************************************************************/
/* Comments about buffer access protection mechanism (=fences) are the ones boxed. */
/* Also, DON'T remove the asserts: if a fence-related call fails, it's better that */
/* program exits immediately, or we could leave KMS waiting for a failed/missing */
/* fence forevever. */
/***********************************************************************************/
int int
KMSDRM_GLES_SwapWindowFenced(_THIS, SDL_Window * window) KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) {
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata); SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb; SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata);
KMSDRM_PlaneInfo info = {0}; KMSDRM_FBInfo *fb_info;
SDL_bool modesetting = SDL_FALSE; int ret, timeout;
/******************************************************************/ /* Recreate the GBM / EGL surfaces if the display mode has changed */
/* Create the GPU-side FENCE OBJECT. It will be inserted into the */ if (windata->egl_surface_dirty) {
/* GL CMDSTREAM exactly at the end of the gl commands that form a */ KMSDRM_CreateSurfaces(_this, window);
/* frame.(KMS will have to wait on it before doing a pageflip.) */
/******************************************************************/
dispdata->gpu_fence = create_fence(EGL_NO_NATIVE_FENCE_FD_ANDROID, _this);
assert(dispdata->gpu_fence);
/******************************************************************/
/* eglSwapBuffers flushes the fence down the GL CMDSTREAM, so we */
/* know for sure it's there now. */
/* Also it marks, at EGL level, the buffer that we want to become */
/* the new front buffer. (Remember that won't really happen until */
/* we request a pageflip at the KMS level and it completes. */
/******************************************************************/
if (! _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface)) {
return SDL_EGL_SetError("Failed to swap EGL buffers", "eglSwapBuffers");
} }
/******************************************************************/ /* Wait for confirmation that the next front buffer has been flipped, at which
/* EXPORT the GPU-side FENCE OBJECT to the fence INPUT FD, so we */ point the previous front buffer can be released */
/* can pass it into the kernel. Atomic ioctl will pass the */ timeout = 0;
/* in-fence fd into the kernel, thus telling KMS that it has to */ if (_this->egl_data->egl_swapinterval == 1) {
/* wait for GPU to finish rendering the frame (remember where we */ timeout = -1;
/* put the fence in the GL CMDSTREAM) before doing the changes */
/* requested in the atomic ioct (the pageflip in this case). */
/* (We export the GPU-side FENCE OJECT to the fence INPUT FD now, */
/* not sooner, because now we are sure that the GPU-side fence is */
/* in the CMDSTREAM to be lifted when the CMDSTREAM to this point */
/* is completed). */
/******************************************************************/
dispdata->kms_in_fence_fd = _this->egl_data->eglDupNativeFenceFDANDROID (_this->egl_data->egl_display,
dispdata->gpu_fence);
_this->egl_data->eglDestroySyncKHR(_this->egl_data->egl_display, dispdata->gpu_fence);
assert(dispdata->kms_in_fence_fd != -1);
/* Lock the buffer that is marked by eglSwapBuffers() to become the
next front buffer (so it can not be chosen by EGL as back buffer
to draw on), and get a handle to it to request the pageflip on it.
REMEMBER that gbm_surface_lock_front_buffer() ALWAYS has to be
called after eglSwapBuffers(). */
windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
if (!windata->next_bo) {
return SDL_SetError("Failed to lock frontbuffer");
} }
fb = KMSDRM_FBFromBO(_this, windata->next_bo); if (!KMSDRM_WaitPageFlip(_this, windata, timeout)) {
if (!fb) { return 0;
return SDL_SetError("Failed to get a new framebuffer from BO");
} }
/* Add the pageflip to the request list. */ /* Release the previous front buffer */
info.plane = dispdata->display_plane;
info.crtc_id = dispdata->crtc->crtc->crtc_id;
info.fb_id = fb->fb_id;
info.src_w = windata->src_w;
info.src_h = windata->src_h;
info.crtc_w = windata->output_w;
info.crtc_h = windata->output_h;
info.crtc_x = windata->output_x;
drm_atomic_set_plane_props(&info);
/*****************************************************************/
/* Tell the display (KMS) that it will have to wait on the fence */
/* for the GPU-side FENCE. */
/* */
/* Since KMS is a kernel thing, we have to pass an FD into */
/* the kernel, and get another FD out of the kernel. */
/* */
/* 1) To pass the GPU-side fence into the kernel, we set the */
/* INPUT FD as the IN_FENCE_FD prop of the PRIMARY PLANE. */
/* This FD tells KMS (the kernel) to wait for the GPU-side fence.*/
/* */
/* 2) To get the KMS-side fence out of the kernel, we set the */
/* OUTPUT FD as the OUT_FEWNCE_FD prop of the CRTC. */
/* This FD will be later imported as a FENCE OBJECT which will be*/
/* used to tell the GPU to wait for KMS to complete the changes */
/* requested in atomic_commit (the pageflip in this case). */
/*****************************************************************/
if (dispdata->kms_in_fence_fd != -1)
{
add_plane_property(dispdata->atomic_req, dispdata->display_plane,
"IN_FENCE_FD", dispdata->kms_in_fence_fd);
add_crtc_property(dispdata->atomic_req, dispdata->crtc,
"OUT_FENCE_PTR", VOID2U64(&dispdata->kms_out_fence_fd));
}
/* Do we have a pending modesetting? If so, set the necessary
props so it's included in the incoming atomic commit. */
if (dispdata->modeset_pending) {
uint32_t blob_id;
SDL_VideoData *viddata = (SDL_VideoData *)_this->driverdata;
add_connector_property(dispdata->atomic_req, dispdata->connector, "CRTC_ID", dispdata->crtc->crtc->crtc_id);
KMSDRM_drmModeCreatePropertyBlob(viddata->drm_fd, &dispdata->mode, sizeof(dispdata->mode), &blob_id);
add_crtc_property(dispdata->atomic_req, dispdata->crtc, "MODE_ID", blob_id);
add_crtc_property(dispdata->atomic_req, dispdata->crtc, "active", 1);
modesetting = SDL_TRUE;
dispdata->modeset_pending = SDL_FALSE;
}
/*****************************************************************/
/* Issue a non-blocking atomic commit: for triple buffering, */
/* this must not block so the game can start building another */
/* frame, even if the just-requested pageflip hasnt't completed. */
/*****************************************************************/
if (drm_atomic_commit(_this, SDL_FALSE, modesetting)) {
return SDL_SetError("Failed to issue atomic commit on pageflip");
}
/* Release the previous front buffer so EGL can chose it as back buffer
and render on it again. */
if (windata->bo) { if (windata->bo) {
KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo); KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo);
windata->bo = NULL;
} }
/* Take note of the buffer about to become front buffer, so next
time we come here we can free it like we just did with the previous
front buffer. */
windata->bo = windata->next_bo; windata->bo = windata->next_bo;
/****************************************************************/ /* Mark a buffer to becume the next front buffer.
/* Import the KMS-side FENCE OUTPUT FD from the kernel to the */ This won't happen until pagelip completes. */
/* KMS-side FENCE OBJECT so we can use use it to fence the GPU. */ if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display,
/****************************************************************/ windata->egl_surface))) {
dispdata->kms_fence = create_fence(dispdata->kms_out_fence_fd, _this); SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
assert(dispdata->kms_fence); return 0;
}
/****************************************************************/ /* Lock the next front buffer so it can't be allocated as a back buffer */
/* "Delete" the fence OUTPUT FD, because we already have the */ windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
/* KMS FENCE OBJECT, the fence itself is away from us, on the */ if (!windata->next_bo) {
/* kernel side. */ SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not lock GBM surface front buffer");
/****************************************************************/ return 0;
dispdata->kms_out_fence_fd = -1; }
/*****************************************************************/ /* Get the fb_info for the next front buffer. */
/* Tell the GPU to wait on the fence for the KMS-side FENCE, */ fb_info = KMSDRM_FBFromBO(_this, windata->next_bo);
/* which means waiting until the requested pageflip is completed.*/ if (!fb_info) {
/*****************************************************************/ return 0;
_this->egl_data->eglWaitSyncKHR(_this->egl_data->egl_display, dispdata->kms_fence, 0); }
/* Issue pageflip on the next front buffer.
The pageflip will be done during the next vblank. */
ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id,
fb_info->fb_id, DRM_MODE_PAGE_FLIP_EVENT, &windata->waiting_for_flip);
if (_this->egl_data->egl_swapinterval == 1) {
if (ret == 0) {
windata->waiting_for_flip = SDL_TRUE;
} else {
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret);
}
}
/* If we are in double-buffer mode, wait immediately for vsync
(as if we only had two buffers),
Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 <program_name>"
to enable this. */
if (_this->egl_data->egl_swapinterval == 1 && windata->double_buffer) {
KMSDRM_WaitPageFlip(_this, windata, -1);
}
return 0; return 0;
} }
int
KMSDRM_GLES_SwapWindowDoubleBuffered(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
SDL_DisplayData *dispdata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
KMSDRM_FBInfo *fb;
KMSDRM_PlaneInfo info = {0};
SDL_bool modesetting = SDL_FALSE;
/**********************************************************************************/
/* In double-buffer mode, atomic_commit will always be synchronous/blocking (ie: */
/* won't return until the requested changes are really done). */
/* Also, there's no need to fence KMS or the GPU, because we won't be entering */
/* game loop again (hence not building or executing a new cmdstring) until */
/* pageflip is done, so we don't need to protect the KMS/GPU access to the buffer.*/
/**********************************************************************************/
/* Mark, at EGL level, the buffer that we want to become the new front buffer.
It won't really happen until we request a pageflip at the KMS level and it
completes. */
if (! _this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, windata->egl_surface)) {
return SDL_EGL_SetError("Failed to swap EGL buffers", "eglSwapBuffers");
}
/* Lock the buffer that is marked by eglSwapBuffers() to become the next front buffer
(so it can not be chosen by EGL as back buffer to draw on), and get a handle to it,
to request the pageflip on it. */
windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs);
if (!windata->next_bo) {
return SDL_SetError("Failed to lock frontbuffer");
}
fb = KMSDRM_FBFromBO(_this, windata->next_bo);
if (!fb) {
return SDL_SetError("Failed to get a new framebuffer BO");
}
/* Add the pageflip to the request list. */
info.plane = dispdata->display_plane;
info.crtc_id = dispdata->crtc->crtc->crtc_id;
info.fb_id = fb->fb_id;
info.src_w = windata->src_w;
info.src_h = windata->src_h;
info.crtc_w = windata->output_w;
info.crtc_h = windata->output_h;
info.crtc_x = windata->output_x;
drm_atomic_set_plane_props(&info);
/* Do we have a pending modesetting? If so, set the necessary
props so it's included in the incoming atomic commit. */
if (dispdata->modeset_pending) {
uint32_t blob_id;
SDL_VideoData *viddata = (SDL_VideoData *)_this->driverdata;
add_connector_property(dispdata->atomic_req, dispdata->connector, "CRTC_ID", dispdata->crtc->crtc->crtc_id);
KMSDRM_drmModeCreatePropertyBlob(viddata->drm_fd, &dispdata->mode, sizeof(dispdata->mode), &blob_id);
add_crtc_property(dispdata->atomic_req, dispdata->crtc, "MODE_ID", blob_id);
add_crtc_property(dispdata->atomic_req, dispdata->crtc, "active", 1);
modesetting = SDL_TRUE;
dispdata->modeset_pending = SDL_FALSE;
}
/* Issue the one and only atomic commit where all changes will be requested!.
Blocking for double buffering: won't return until completed. */
if (drm_atomic_commit(_this, SDL_TRUE, modesetting)) {
return SDL_SetError("Failed to issue atomic commit on pageflip");
}
/* Release last front buffer so EGL can chose it as back buffer and render on it again. */
if (windata->bo) {
KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo);
}
/* Take note of current front buffer, so we can free it next time we come here. */
windata->bo = windata->next_bo;
return 0;
}
int
KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window)
{
SDL_WindowData *windata = ((SDL_WindowData *) window->driverdata);
if (windata->swap_window == NULL) {
/* We want the fenced version by default, but it needs extensions. */
if ( (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) ||
(!SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_ANDROID_native_fence_sync")) )
{
windata->swap_window = KMSDRM_GLES_SwapWindowDoubleBuffered;
} else {
windata->swap_window = KMSDRM_GLES_SwapWindowFenced;
}
}
return windata->swap_window(_this, window);
}
/***************************************/
/* End of Atomic functions block */
/***************************************/
SDL_EGL_MakeCurrent_impl(KMSDRM) SDL_EGL_MakeCurrent_impl(KMSDRM)
#endif /* SDL_VIDEO_DRIVER_KMSDRM */ #endif /* SDL_VIDEO_DRIVER_KMSDRM */

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages

View File

@ -41,32 +41,29 @@ SDL_KMSDRM_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr))
SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr ptr))
SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreeEncoder,(drmModeEncoderPtr ptr))
SDL_KMSDRM_SYM(int,drmGetCap,(int fd, uint64_t capability, uint64_t *value)) SDL_KMSDRM_SYM(int,drmGetCap,(int fd, uint64_t capability, uint64_t *value))
SDL_KMSDRM_SYM(int,drmIoctl,(int fd, unsigned long request, void *arg))
SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd)) SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd))
SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth, SDL_KMSDRM_SYM(int,drmModeAddFB,(int fd, uint32_t width, uint32_t height, uint8_t depth,
uint8_t bpp, uint32_t pitch, uint32_t bo_handle, uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
uint32_t *buf_id)) uint32_t *buf_id))
SDL_KMSDRM_SYM(int,drmModeAddFB2,(int fd, uint32_t width, uint32_t height,
uint32_t pixel_format, const uint32_t bo_handles[4],
const uint32_t pitches[4], const uint32_t offsets[4],
uint32_t *buf_id, uint32_t flags))
SDL_KMSDRM_SYM(int,drmModeAddFB2WithModifiers,(int fd, uint32_t width, uint32_t height,
uint32_t pixel_format, const uint32_t bo_handles[4],
const uint32_t pitches[4], const uint32_t offsets[4],
const uint64_t modifier[4], uint32_t *buf_id,
uint32_t flags))
SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId)) SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId))
SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf)) SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf))
SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId)) SDL_KMSDRM_SYM(drmModeCrtcPtr,drmModeGetCrtc,(int fd, uint32_t crtcId))
SDL_KMSDRM_SYM(int,drmModeSetCrtc,(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
drmModeModeInfoPtr mode))
SDL_KMSDRM_SYM(int,drmModeSetCursor,(int fd, uint32_t crtcId, uint32_t bo_handle,
uint32_t width, uint32_t height))
SDL_KMSDRM_SYM(int,drmModeSetCursor2,(int fd, uint32_t crtcId, uint32_t bo_handle,
uint32_t width, uint32_t height,
int32_t hot_x, int32_t hot_y))
SDL_KMSDRM_SYM(int,drmModeMoveCursor,(int fd, uint32_t crtcId, int x, int y))
SDL_KMSDRM_SYM(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id)) SDL_KMSDRM_SYM(drmModeEncoderPtr,drmModeGetEncoder,(int fd, uint32_t encoder_id))
SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connector_id)) SDL_KMSDRM_SYM(drmModeConnectorPtr,drmModeGetConnector,(int fd, uint32_t connector_id))
SDL_KMSDRM_SYM(int,drmHandleEvent,(int fd,drmEventContextPtr evctx))
SDL_KMSDRM_SYM(int,drmModePageFlip,(int fd, uint32_t crtc_id, uint32_t fb_id,
uint32_t flags, void *user_data))
/* Atomic functions */ /* Planes stuff. */
SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)) SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value))
SDL_KMSDRM_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd)) SDL_KMSDRM_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd))
SDL_KMSDRM_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id)) SDL_KMSDRM_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id))
@ -77,14 +74,13 @@ SDL_KMSDRM_SYM(void,drmModeFreeProperty,(drmModePropertyPtr ptr))
SDL_KMSDRM_SYM(void,drmModeFreeObjectProperties,(drmModeObjectPropertiesPtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreeObjectProperties,(drmModeObjectPropertiesPtr ptr))
SDL_KMSDRM_SYM(void,drmModeFreePlane,(drmModePlanePtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreePlane,(drmModePlanePtr ptr))
SDL_KMSDRM_SYM(void,drmModeFreePlaneResources,(drmModePlaneResPtr ptr)) SDL_KMSDRM_SYM(void,drmModeFreePlaneResources,(drmModePlaneResPtr ptr))
SDL_KMSDRM_SYM(int,drmModeSetPlane,(int fd, uint32_t plane_id, uint32_t crtc_id,
SDL_KMSDRM_SYM(drmModeAtomicReqPtr,drmModeAtomicAlloc,(void)) uint32_t fb_id, uint32_t flags,
SDL_KMSDRM_SYM(void,drmModeAtomicFree,(drmModeAtomicReqPtr req)) int32_t crtc_x, int32_t crtc_y,
SDL_KMSDRM_SYM(int,drmModeAtomicCommit,(int fd,drmModeAtomicReqPtr req,uint32_t flags,void *user_data)) uint32_t crtc_w, uint32_t crtc_h,
SDL_KMSDRM_SYM(int,drmModeAtomicAddProperty,(drmModeAtomicReqPtr req,uint32_t object_id,uint32_t property_id,uint64_t value)) uint32_t src_x, uint32_t src_y,
SDL_KMSDRM_SYM(int,drmModeCreatePropertyBlob,(int fd,const void *data,size_t size,uint32_t *id)) uint32_t src_w, uint32_t src_h))
/* Planes stuff ends. */
/* End of atomic fns */
SDL_KMSDRM_MODULE(GBM) SDL_KMSDRM_MODULE(GBM)
SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm)) SDL_KMSDRM_SYM(int,gbm_device_get_fd,(struct gbm_device *gbm))
@ -95,11 +91,6 @@ SDL_KMSDRM_SYM(struct gbm_device *,gbm_create_device,(int fd))
SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo)) SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_width,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo)) SDL_KMSDRM_SYM(unsigned int,gbm_bo_get_height,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo)) SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_stride_for_plane,(struct gbm_bo *bo,int plane))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_format,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane))
SDL_KMSDRM_SYM(int,gbm_bo_get_plane_count,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo)) SDL_KMSDRM_SYM(union gbm_bo_handle,gbm_bo_get_handle,(struct gbm_bo *bo))
SDL_KMSDRM_SYM(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count)) SDL_KMSDRM_SYM(int,gbm_bo_write,(struct gbm_bo *bo, const void *buf, size_t count))
SDL_KMSDRM_SYM(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo)) SDL_KMSDRM_SYM(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo))

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
/* /*
Simple DirectMedia Layer Simple DirectMedia Layer
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
Atomic KMSDRM backend by Manuel Alfayate Corchete <redwindwanderer@gmail.com>
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -31,17 +30,8 @@
#include <unistd.h> #include <unistd.h>
#include <xf86drm.h> #include <xf86drm.h>
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <gbm.h> #include <gbm.h>
#include <assert.h>
#include <EGL/egl.h> #include <EGL/egl.h>
#include <EGL/eglext.h>
/****************************************************************************************/
/* Driverdata pointers are void struct* used to store backend-specific variables */
/* and info that supports the SDL-side structs like SDL Display Devices, SDL_Windows... */
/* which need to be "supported" with backend-side info and mechanisms to work. */
/****************************************************************************************/
typedef struct SDL_VideoData typedef struct SDL_VideoData
{ {
@ -51,56 +41,30 @@ typedef struct SDL_VideoData
struct gbm_device *gbm_dev; struct gbm_device *gbm_dev;
SDL_Window **windows;
unsigned int max_windows;
unsigned int num_windows;
SDL_bool video_init; /* Has VideoInit succeeded? */ SDL_bool video_init; /* Has VideoInit succeeded? */
SDL_bool vulkan_mode; /* Are we in Vulkan mode? One VK window is enough to be. */ SDL_bool vulkan_mode; /* Are we in Vulkan mode? One VK window is enough to be. */
SDL_Window **windows;
int max_windows;
int num_windows;
} SDL_VideoData; } SDL_VideoData;
typedef struct plane {
drmModePlane *plane;
drmModeObjectProperties *props;
drmModePropertyRes **props_info;
} plane;
typedef struct crtc { typedef struct SDL_DisplayModeData
drmModeCrtc *crtc; {
drmModeObjectProperties *props; int mode_index;
drmModePropertyRes **props_info; } SDL_DisplayModeData;
} crtc;
typedef struct connector {
drmModeConnector *connector;
drmModeObjectProperties *props;
drmModePropertyRes **props_info;
} connector;
/* More general driverdata info that gives support and substance to the SDL_Display. */
typedef struct SDL_DisplayData typedef struct SDL_DisplayData
{ {
drmModeConnector *connector;
drmModeCrtc *crtc;
drmModeModeInfo mode; drmModeModeInfo mode;
drmModeModeInfo original_mode; drmModeModeInfo original_mode;
plane *display_plane; drmModeCrtc *saved_crtc; /* CRTC to restore on quit */
plane *cursor_plane;
crtc *crtc;
connector *connector;
/* Central atomic request list, used for the prop
changeset related to pageflip in SwapWindow. */
drmModeAtomicReq *atomic_req;
int kms_in_fence_fd;
int kms_out_fence_fd;
EGLSyncKHR kms_fence;
EGLSyncKHR gpu_fence;
SDL_bool modeset_pending;
SDL_bool gbm_init; SDL_bool gbm_init;
/* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's driverdata struct, /* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's driverdata struct,
@ -110,11 +74,12 @@ typedef struct SDL_DisplayData
struct gbm_bo *cursor_bo; struct gbm_bo *cursor_bo;
uint64_t cursor_w, cursor_h; uint64_t cursor_w, cursor_h;
SDL_bool modeset_pending;
SDL_bool set_default_cursor_pending; SDL_bool set_default_cursor_pending;
} SDL_DisplayData; } SDL_DisplayData;
/* Driverdata info that gives KMSDRM-side support and substance to the SDL_Window. */
typedef struct SDL_WindowData typedef struct SDL_WindowData
{ {
SDL_VideoData *viddata; SDL_VideoData *viddata;
@ -126,6 +91,10 @@ typedef struct SDL_WindowData
struct gbm_bo *bo; struct gbm_bo *bo;
struct gbm_bo *next_bo; struct gbm_bo *next_bo;
SDL_bool waiting_for_flip;
SDL_bool double_buffer;
int egl_surface_dirty;
EGLSurface egl_surface; EGLSurface egl_surface;
/* For scaling and AR correction. */ /* For scaling and AR correction. */
@ -135,54 +104,18 @@ typedef struct SDL_WindowData
int32_t output_h; int32_t output_h;
int32_t output_x; int32_t output_x;
/* This dictates what approach we'll use for SwapBuffers. */
int (*swap_window)(_THIS, SDL_Window * window);
} SDL_WindowData; } SDL_WindowData;
typedef struct SDL_DisplayModeData
{
int mode_index;
} SDL_DisplayModeData;
typedef struct KMSDRM_FBInfo typedef struct KMSDRM_FBInfo
{ {
int drm_fd; /* DRM file desc */ int drm_fd; /* DRM file desc */
uint32_t fb_id; /* DRM framebuffer ID */ uint32_t fb_id; /* DRM framebuffer ID */
} KMSDRM_FBInfo; } KMSDRM_FBInfo;
typedef struct KMSDRM_PlaneInfo
{
struct plane *plane;
uint32_t fb_id;
uint32_t crtc_id;
int32_t src_x;
int32_t src_y;
int32_t src_w;
int32_t src_h;
int32_t crtc_x;
int32_t crtc_y;
int32_t crtc_w;
int32_t crtc_h;
} KMSDRM_PlaneInfo;
/* Helper functions */ /* Helper functions */
int KMSDRM_CreateEGLSurface(_THIS, SDL_Window * window); int KMSDRM_CreateSurfaces(_THIS, SDL_Window * window);
KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo); KMSDRM_FBInfo *KMSDRM_FBFromBO(_THIS, struct gbm_bo *bo);
SDL_bool KMSDRM_WaitPageFlip(_THIS, SDL_WindowData *windata, int timeout);
/* Atomic functions that are used from SDL_kmsdrmopengles.c and SDL_kmsdrmmouse.c */
void drm_atomic_set_plane_props(struct KMSDRM_PlaneInfo *info);
void drm_atomic_waitpending(_THIS);
int drm_atomic_commit(_THIS, SDL_bool blocking, SDL_bool allow_modeset);
int add_plane_property(drmModeAtomicReq *req, struct plane *plane,
const char *name, uint64_t value);
int add_crtc_property(drmModeAtomicReq *req, struct crtc *crtc,
const char *name, uint64_t value);
int add_connector_property(drmModeAtomicReq *req, struct connector *connector,
const char *name, uint64_t value);
int setup_plane(_THIS, struct plane **plane, uint32_t plane_type);
void free_plane(struct plane **plane);
/****************************************************************************/ /****************************************************************************/
/* SDL_VideoDevice functions declaration */ /* SDL_VideoDevice functions declaration */

View File

@ -174,7 +174,7 @@ void KMSDRM_Vulkan_GetDrawableSize(_THIS, SDL_Window *window, int *w, int *h)
/* Instead, programs using SDL and Vulkan create their Vulkan instance */ /* Instead, programs using SDL and Vulkan create their Vulkan instance */
/* and we get it here, ready to use. */ /* and we get it here, ready to use. */
/* Extensions specific for this platform are activated in */ /* Extensions specific for this platform are activated in */
/* KMSDRM_Vulkan_GetInstanceExtensions(), like we do with */ /* KMSDRM_Vulkan_GetInstanceExtensions(), like we do with */
/* VK_KHR_DISPLAY_EXTENSION_NAME, which is what we need for x-less VK. */ /* VK_KHR_DISPLAY_EXTENSION_NAME, which is what we need for x-less VK. */
/***********************************************************************/ /***********************************************************************/
SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS,
@ -397,7 +397,7 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS,
surface); surface);
if(result != VK_SUCCESS) if(result != VK_SUCCESS)
{ {
SDL_SetError("vkCreateKMSDRMSurfaceKHR failed: %s", SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s",
SDL_Vulkan_GetResultString(result)); SDL_Vulkan_GetResultString(result));
goto clean; goto clean;
} }

View File

@ -26,8 +26,8 @@
#include "../../SDL_internal.h" #include "../../SDL_internal.h"
#ifndef SDL_kmsdrmvulkan_h_ #ifndef SDL_kmsdrm_vulkan_h_
#define SDL_kmsdrmvulkan_h_ #define SDL_kmsdrm_vulkan_h_
#include "../SDL_vulkan_internal.h" #include "../SDL_vulkan_internal.h"
#include "../SDL_sysvideo.h" #include "../SDL_sysvideo.h"
@ -48,6 +48,6 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS,
#endif #endif
#endif /* SDL_kmsdrmvulkan_h_ */ #endif /* SDL_kmsdrm_vulkan_h_ */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */