From 30f41c02aec763d32e62351452da9ef582bc3472 Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Fri, 6 Mar 2026 13:30:59 -0800 Subject: Move contrib libraries to contrib repo --- contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.c | 161 -- contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.h | 54 - .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.c | 44 - .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.h | 29 - .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.c | 410 ----- .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.h | 53 - .../src/video/kmsdrm/SDL_kmsdrmopengles.c | 203 --- .../src/video/kmsdrm/SDL_kmsdrmopengles.h | 42 - contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmsym.h | 145 -- .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.c | 1820 -------------------- .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.h | 176 -- .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.c | 520 ------ .../SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.h | 51 - 13 files changed, 3708 deletions(-) delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmsym.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.h delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.c delete mode 100644 contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.h (limited to 'contrib/SDL-3.2.8/src/video/kmsdrm') diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.c deleted file mode 100644 index a532cea..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM - -#define DEBUG_DYNAMIC_KMSDRM 0 - -#include "SDL_kmsdrmdyn.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC - -typedef struct -{ - void *lib; - const char *libname; -} kmsdrmdynlib; - -#ifndef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM -#define SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM NULL -#endif - -static kmsdrmdynlib kmsdrmlibs[] = { - { NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC_GBM }, - { NULL, SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC } -}; - -static void *KMSDRM_GetSym(const char *fnname, int *pHasModule, bool required) -{ - int i; - void *fn = NULL; - for (i = 0; i < SDL_arraysize(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].lib) { - fn = SDL_LoadFunction(kmsdrmlibs[i].lib, fnname); - if (fn) { - break; - } - } - } - -#if DEBUG_DYNAMIC_KMSDRM - if (fn) - SDL_Log("KMSDRM: Found '%s' in %s (%p)", fnname, kmsdrmlibs[i].libname, fn); - else - SDL_Log("KMSDRM: Symbol '%s' NOT FOUND!", fnname); -#endif - - if (!fn && required) { - *pHasModule = 0; // kill this module. - } - - return fn; -} - -#endif // SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC - -// Define all the function pointers and wrappers... -#define SDL_KMSDRM_MODULE(modname) int SDL_KMSDRM_HAVE_##modname = 0; -#define SDL_KMSDRM_SYM(rc, fn, params) SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL; -#define SDL_KMSDRM_SYM_CONST(type, name) SDL_DYNKMSDRMCONST_##name KMSDRM_##name = NULL; -#define SDL_KMSDRM_SYM_OPT(rc, fn, params) SDL_DYNKMSDRMFN_##fn KMSDRM_##fn = NULL; -#include "SDL_kmsdrmsym.h" - -static int kmsdrm_load_refcount = 0; - -void SDL_KMSDRM_UnloadSymbols(void) -{ - // Don't actually unload if more than one module is using the libs... - if (kmsdrm_load_refcount > 0) { - if (--kmsdrm_load_refcount == 0) { -#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC - int i; -#endif - - // set all the function pointers to NULL. -#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 0; -#define SDL_KMSDRM_SYM(rc, fn, params) KMSDRM_##fn = NULL; -#define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = NULL; -#define SDL_KMSDRM_SYM_OPT(rc, fn, params) KMSDRM_##fn = NULL; -#include "SDL_kmsdrmsym.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC - for (i = 0; i < SDL_arraysize(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].lib) { - SDL_UnloadObject(kmsdrmlibs[i].lib); - kmsdrmlibs[i].lib = NULL; - } - } -#endif - } - } -} - -// returns non-zero if all needed symbols were loaded. -bool SDL_KMSDRM_LoadSymbols(void) -{ - bool result = true; // always succeed if not using Dynamic KMSDRM stuff. - - // deal with multiple modules needing these symbols... - if (kmsdrm_load_refcount++ == 0) { -#ifdef SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC - int i; - int *thismod = NULL; - for (i = 0; i < SDL_arraysize(kmsdrmlibs); i++) { - if (kmsdrmlibs[i].libname) { - kmsdrmlibs[i].lib = SDL_LoadObject(kmsdrmlibs[i].libname); - } - } - -#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; // default yes -#include "SDL_kmsdrmsym.h" - -#define SDL_KMSDRM_MODULE(modname) thismod = &SDL_KMSDRM_HAVE_##modname; -#define SDL_KMSDRM_SYM(rc, fn, params) KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn)KMSDRM_GetSym(#fn, thismod, true); -#define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = *(SDL_DYNKMSDRMCONST_##name *)KMSDRM_GetSym(#name, thismod, true); -#define SDL_KMSDRM_SYM_OPT(rc, fn, params) KMSDRM_##fn = (SDL_DYNKMSDRMFN_##fn)KMSDRM_GetSym(#fn, thismod, false); -#include "SDL_kmsdrmsym.h" - - if ((SDL_KMSDRM_HAVE_LIBDRM) && (SDL_KMSDRM_HAVE_GBM)) { - // all required symbols loaded. - SDL_ClearError(); - } else { - // in case something got loaded... - SDL_KMSDRM_UnloadSymbols(); - result = false; - } - -#else // no dynamic KMSDRM - -#define SDL_KMSDRM_MODULE(modname) SDL_KMSDRM_HAVE_##modname = 1; // default yes -#define SDL_KMSDRM_SYM(rc, fn, params) KMSDRM_##fn = fn; -#define SDL_KMSDRM_SYM_CONST(type, name) KMSDRM_##name = name; -#define SDL_KMSDRM_SYM_OPT(rc, fn, params) KMSDRM_##fn = fn; -#include "SDL_kmsdrmsym.h" - -#endif - } - - return result; -} - -#endif // SDL_VIDEO_DRIVER_KMSDRM diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.h deleted file mode 100644 index 55c5199..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmdyn.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#ifndef SDL_kmsdrmdyn_h_ -#define SDL_kmsdrmdyn_h_ - -#include "SDL_internal.h" - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -extern bool SDL_KMSDRM_LoadSymbols(void); -extern void SDL_KMSDRM_UnloadSymbols(void); - -// Declare all the function pointers and wrappers... -#define SDL_KMSDRM_SYM(rc, fn, params) \ - typedef rc(*SDL_DYNKMSDRMFN_##fn) params; \ - extern SDL_DYNKMSDRMFN_##fn KMSDRM_##fn; -#define SDL_KMSDRM_SYM_CONST(type, name) \ - typedef type SDL_DYNKMSDRMCONST_##name; \ - extern SDL_DYNKMSDRMCONST_##name KMSDRM_##name; -#define SDL_KMSDRM_SYM_OPT(rc, fn, params) \ - typedef rc(*SDL_DYNKMSDRMFN_##fn) params; \ - extern SDL_DYNKMSDRMFN_##fn KMSDRM_##fn; -#include "SDL_kmsdrmsym.h" - -#ifdef __cplusplus -} -#endif - -#endif // SDL_kmsdrmdyn_h_ diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.c deleted file mode 100644 index 78fb9f4..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM - -#include "SDL_kmsdrmvideo.h" -#include "SDL_kmsdrmevents.h" - -#ifdef SDL_INPUT_LINUXEV -#include "../../core/linux/SDL_evdev.h" -#elif defined SDL_INPUT_WSCONS -#include "../../core/openbsd/SDL_wscons.h" -#endif - -void KMSDRM_PumpEvents(SDL_VideoDevice *_this) -{ -#ifdef SDL_INPUT_LINUXEV - SDL_EVDEV_Poll(); -#elif defined SDL_INPUT_WSCONS - SDL_WSCONS_PumpEvents(); -#endif -} - -#endif // SDL_VIDEO_DRIVER_KMSDRM diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.h deleted file mode 100644 index 35473f8..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmevents.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifndef SDL_kmsdrmevents_h_ -#define SDL_kmsdrmevents_h_ - -extern void KMSDRM_PumpEvents(SDL_VideoDevice *_this); - -#endif // SDL_kmsdrmevents_h_ diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.c deleted file mode 100644 index bb50ae3..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM - -#include "SDL_kmsdrmvideo.h" -#include "SDL_kmsdrmmouse.h" -#include "SDL_kmsdrmdyn.h" - -#include "../../events/SDL_mouse_c.h" -#include "../../events/default_cursor.h" - -#include "../SDL_pixels_c.h" - -static SDL_Cursor *KMSDRM_CreateDefaultCursor(void); -static SDL_Cursor *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y); -static bool KMSDRM_ShowCursor(SDL_Cursor *cursor); -static bool KMSDRM_MoveCursor(SDL_Cursor *cursor); -static void KMSDRM_FreeCursor(SDL_Cursor *cursor); - -/**************************************************************************************/ -// BEFORE CODING ANYTHING MOUSE/CURSOR RELATED, REMEMBER THIS. -// How does SDL manage cursors internally? First, mouse =! cursor. The mouse can have -// many cursors in mouse->cursors. -// -SDL tells us to create a cursor with KMSDRM_CreateCursor(). It can create many -// cursosr with this, not only one. -// -SDL stores those cursors in a cursors array, in mouse->cursors. -// -Whenever it wants (or the programmer wants) takes a cursor from that array -// and shows it on screen with KMSDRM_ShowCursor(). -// KMSDRM_ShowCursor() simply shows or hides the cursor it receives: it does NOT -// mind if it's mouse->cur_cursor, etc. -// -If KMSDRM_ShowCursor() returns successfully, that cursor becomes -// mouse->cur_cursor and mouse->cursor_shown is 1. -/**************************************************************************************/ - -static SDL_Cursor *KMSDRM_CreateDefaultCursor(void) -{ - return SDL_CreateCursor(default_cdata, default_cmask, DEFAULT_CWIDTH, DEFAULT_CHEIGHT, DEFAULT_CHOTX, DEFAULT_CHOTY); -} - -/* Given a display's internal, destroy the cursor BO for it. - To be called from KMSDRM_DestroyWindow(), as that's where we - destroy the internal for the window's display. */ -void KMSDRM_DestroyCursorBO(SDL_VideoDevice *_this, SDL_VideoDisplay *display) -{ - SDL_DisplayData *dispdata = display->internal; - - // Destroy the curso GBM BO. - if (dispdata->cursor_bo) { - KMSDRM_gbm_bo_destroy(dispdata->cursor_bo); - dispdata->cursor_bo = NULL; - dispdata->cursor_bo_drm_fd = -1; - } -} - -/* Given a display's internal, create the cursor BO for it. - To be called from KMSDRM_CreateWindow(), as that's where we - build a window and assign a display to it. */ -bool KMSDRM_CreateCursorBO(SDL_VideoDisplay *display) -{ - - SDL_VideoDevice *dev = SDL_GetVideoDevice(); - SDL_VideoData *viddata = dev->internal; - SDL_DisplayData *dispdata = display->internal; - - if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev, - GBM_FORMAT_ARGB8888, - GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE)) { - return SDL_SetError("Unsupported pixel format for cursor"); - } - - if (KMSDRM_drmGetCap(viddata->drm_fd, - DRM_CAP_CURSOR_WIDTH, &dispdata->cursor_w) || - KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_CURSOR_HEIGHT, - &dispdata->cursor_h)) { - return SDL_SetError("Could not get the recommended GBM cursor size"); - } - - if (dispdata->cursor_w == 0 || dispdata->cursor_h == 0) { - return SDL_SetError("Could not get an usable GBM cursor size"); - } - - dispdata->cursor_bo = KMSDRM_gbm_bo_create(viddata->gbm_dev, - dispdata->cursor_w, dispdata->cursor_h, - GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE | GBM_BO_USE_LINEAR); - - if (!dispdata->cursor_bo) { - return SDL_SetError("Could not create GBM cursor BO"); - } - - dispdata->cursor_bo_drm_fd = viddata->drm_fd; - return true; -} - -// Remove a cursor buffer from a display's DRM cursor BO. -static bool KMSDRM_RemoveCursorFromBO(SDL_VideoDisplay *display) -{ - bool result = true; - - SDL_DisplayData *dispdata = display->internal; - SDL_VideoDevice *video_device = SDL_GetVideoDevice(); - SDL_VideoData *viddata = video_device->internal; - - const int rc = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id, 0, 0, 0); - if (rc < 0) { - result = SDL_SetError("drmModeSetCursor() failed: %s", strerror(-rc)); - } - return result; -} - -// Dump a cursor buffer to a display's DRM cursor BO. -static bool KMSDRM_DumpCursorToBO(SDL_VideoDisplay *display, SDL_Cursor *cursor) -{ - SDL_DisplayData *dispdata = display->internal; - SDL_CursorData *curdata = cursor->internal; - SDL_VideoDevice *video_device = SDL_GetVideoDevice(); - SDL_VideoData *viddata = video_device->internal; - - uint32_t bo_handle; - size_t bo_stride; - size_t bufsize; - uint8_t *ready_buffer = NULL; - uint8_t *src_row; - - int i, rc; - bool result = true; - - if (!curdata || !dispdata->cursor_bo) { - return SDL_SetError("Cursor or display not initialized properly."); - } - - /* Prepare a buffer we can dump to our GBM BO (different - size, alpha premultiplication...) */ - bo_stride = KMSDRM_gbm_bo_get_stride(dispdata->cursor_bo); - bufsize = bo_stride * dispdata->cursor_h; - - ready_buffer = (uint8_t *)SDL_calloc(1, bufsize); - - if (!ready_buffer) { - result = false; - goto cleanup; - } - - // Copy from the cursor buffer to a buffer that we can dump to the GBM BO. - for (i = 0; i < curdata->h; i++) { - src_row = &((uint8_t *)curdata->buffer)[i * curdata->w * 4]; - SDL_memcpy(ready_buffer + (i * bo_stride), src_row, (size_t)4 * curdata->w); - } - - // Dump the cursor buffer to our GBM BO. - if (KMSDRM_gbm_bo_write(dispdata->cursor_bo, ready_buffer, bufsize)) { - result = SDL_SetError("Could not write to GBM cursor BO"); - goto cleanup; - } - - // Put the GBM BO buffer on screen using the DRM interface. - bo_handle = KMSDRM_gbm_bo_get_handle(dispdata->cursor_bo).u32; - if (curdata->hot_x == 0 && curdata->hot_y == 0) { - rc = KMSDRM_drmModeSetCursor(viddata->drm_fd, dispdata->crtc->crtc_id, - bo_handle, dispdata->cursor_w, dispdata->cursor_h); - } else { - rc = KMSDRM_drmModeSetCursor2(viddata->drm_fd, dispdata->crtc->crtc_id, - bo_handle, dispdata->cursor_w, dispdata->cursor_h, curdata->hot_x, curdata->hot_y); - } - if (rc < 0) { - result = SDL_SetError("Failed to set DRM cursor: %s", strerror(-rc)); - goto cleanup; - } - -cleanup: - - if (ready_buffer) { - SDL_free(ready_buffer); - } - return result; -} - -// This is only for freeing the SDL_cursor. -static void KMSDRM_FreeCursor(SDL_Cursor *cursor) -{ - SDL_CursorData *curdata; - - // Even if the cursor is not ours, free it. - if (cursor) { - curdata = cursor->internal; - // Free cursor buffer - if (curdata->buffer) { - SDL_free(curdata->buffer); - curdata->buffer = NULL; - } - // Free cursor itself - if (cursor->internal) { - SDL_free(cursor->internal); - } - SDL_free(cursor); - } -} - -/* 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 *KMSDRM_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y) -{ - SDL_CursorData *curdata; - SDL_Cursor *cursor, *result; - - curdata = NULL; - result = NULL; - - cursor = (SDL_Cursor *)SDL_calloc(1, sizeof(*cursor)); - if (!cursor) { - goto cleanup; - } - curdata = (SDL_CursorData *)SDL_calloc(1, sizeof(*curdata)); - if (!curdata) { - goto cleanup; - } - - // hox_x and hot_y are the coordinates of the "tip of the cursor" from it's base. - curdata->hot_x = hot_x; - curdata->hot_y = hot_y; - curdata->w = surface->w; - curdata->h = surface->h; - curdata->buffer = NULL; - - /* Configure the cursor buffer info. - This buffer has the original size of the cursor surface we are given. */ - curdata->buffer_pitch = surface->w; - curdata->buffer_size = (size_t)surface->w * surface->h * 4; - curdata->buffer = (uint32_t *)SDL_malloc(curdata->buffer_size); - - if (!curdata->buffer) { - goto cleanup; - } - - /* All code below assumes ARGB8888 format for the cursor surface, - like other backends do. Also, the GBM BO pixels have to be - alpha-premultiplied, but the SDL surface we receive has - straight-alpha pixels, so we always have to convert. */ - SDL_PremultiplyAlpha(surface->w, surface->h, - surface->format, surface->pixels, surface->pitch, - SDL_PIXELFORMAT_ARGB8888, curdata->buffer, surface->w * 4, true); - - cursor->internal = curdata; - - result = cursor; - -cleanup: - if (!result) { - if (curdata) { - if (curdata->buffer) { - SDL_free(curdata->buffer); - } - SDL_free(curdata); - } - if (cursor) { - SDL_free(cursor); - } - } - - return result; -} - -// Show the specified cursor, or hide if cursor is NULL or has no focus. -static bool KMSDRM_ShowCursor(SDL_Cursor *cursor) -{ - SDL_VideoDisplay *display; - SDL_Window *window; - SDL_Mouse *mouse = SDL_GetMouse(); - - int i; - bool result = true; - - // Get the mouse focused window, if any. - window = mouse->focus; - - if (!window || !cursor) { - /* If no window is focused by mouse or cursor is NULL, - since we have no window (no mouse->focus) and hence - we have no display, we simply hide mouse on all displays. - This happens on video quit, where we get here after - the mouse focus has been unset, yet SDL wants to - restore the system default cursor (makes no sense here). */ - SDL_DisplayID *displays = SDL_GetDisplays(NULL); - if (displays) { - // Iterate on the displays, hiding the cursor. - for (i = 0; i < displays[i]; i++) { - display = SDL_GetVideoDisplay(displays[i]); - result = KMSDRM_RemoveCursorFromBO(display); - } - SDL_free(displays); - } - } else { - display = SDL_GetVideoDisplayForWindow(window); - if (display) { - if (cursor) { - /* Dump the cursor to the display DRM cursor BO so it becomes visible - on that display. */ - result = KMSDRM_DumpCursorToBO(display, cursor); - } else { - // Hide the cursor on that display. - result = KMSDRM_RemoveCursorFromBO(display); - } - } - } - - return result; -} - -static bool KMSDRM_WarpMouseGlobal(float x, float y) -{ - SDL_Mouse *mouse = SDL_GetMouse(); - - if (mouse && mouse->cur_cursor && mouse->focus) { - SDL_Window *window = mouse->focus; - SDL_DisplayData *dispdata = SDL_GetDisplayDriverDataForWindow(window); - - // Update internal mouse position. - SDL_SendMouseMotion(0, mouse->focus, SDL_GLOBAL_MOUSE_ID, false, x, y); - - // And now update the cursor graphic position on screen. - if (dispdata->cursor_bo) { - const int rc = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, (int)x, (int)y); - if (rc < 0) { - return SDL_SetError("drmModeMoveCursor() failed: %s", strerror(-rc)); - } - return true; - } else { - return SDL_SetError("Cursor not initialized properly."); - } - } else { - return SDL_SetError("No mouse or current cursor."); - } -} - -static bool KMSDRM_WarpMouse(SDL_Window *window, float x, float y) -{ - // Only one global/fullscreen window is supported - return KMSDRM_WarpMouseGlobal(x, y); -} - -void KMSDRM_InitMouse(SDL_VideoDevice *_this, SDL_VideoDisplay *display) -{ - SDL_Mouse *mouse = SDL_GetMouse(); - SDL_DisplayData *dispdata = display->internal; - - mouse->CreateCursor = KMSDRM_CreateCursor; - mouse->ShowCursor = KMSDRM_ShowCursor; - mouse->MoveCursor = KMSDRM_MoveCursor; - mouse->FreeCursor = KMSDRM_FreeCursor; - mouse->WarpMouse = KMSDRM_WarpMouse; - mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal; - - /* Only create the default cursor for this display if we haven't done so before, - we don't want several cursors to be created for the same display. */ - if (!dispdata->default_cursor_init) { - SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor()); - dispdata->default_cursor_init = true; - } -} - -void KMSDRM_QuitMouse(SDL_VideoDevice *_this) -{ - // TODO: ? -} - -// This is called when a mouse motion event occurs -static bool KMSDRM_MoveCursor(SDL_Cursor *cursor) -{ - SDL_Mouse *mouse = SDL_GetMouse(); - - /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity! - That's why we move the cursor graphic ONLY. */ - if (mouse && mouse->cur_cursor && mouse->focus) { - SDL_Window *window = mouse->focus; - SDL_DisplayData *dispdata = SDL_GetDisplayDriverDataForWindow(window); - - if (!dispdata->cursor_bo) { - return SDL_SetError("Cursor not initialized properly."); - } - - const int rc = KMSDRM_drmModeMoveCursor(dispdata->cursor_bo_drm_fd, dispdata->crtc->crtc_id, (int)mouse->x, (int)mouse->y); - if (rc < 0) { - return SDL_SetError("drmModeMoveCursor() failed: %s", strerror(-rc)); - } - } - return true; -} - -#endif // SDL_VIDEO_DRIVER_KMSDRM diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.h deleted file mode 100644 index 53e33f4..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmmouse.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifndef SDL_KMSDRM_mouse_h_ -#define SDL_KMSDRM_mouse_h_ - -#include - -#define MAX_CURSOR_W 512 -#define MAX_CURSOR_H 512 - -struct SDL_CursorData -{ - int hot_x, hot_y; - int w, h; - - /* 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().*/ - uint32_t *buffer; - size_t buffer_size; - size_t buffer_pitch; - -}; - -extern void KMSDRM_InitMouse(SDL_VideoDevice *_this, SDL_VideoDisplay *display); -extern void KMSDRM_QuitMouse(SDL_VideoDevice *_this); - -extern bool KMSDRM_CreateCursorBO(SDL_VideoDisplay *display); -extern void KMSDRM_DestroyCursorBO(SDL_VideoDevice *_this, SDL_VideoDisplay *display); -extern void KMSDRM_InitCursor(void); - -#endif // SDL_KMSDRM_mouse_h_ diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.c deleted file mode 100644 index cc93cde..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM - -#include "SDL_kmsdrmvideo.h" -#include "SDL_kmsdrmopengles.h" -#include "SDL_kmsdrmdyn.h" -#include - -#ifndef EGL_PLATFORM_GBM_MESA -#define EGL_PLATFORM_GBM_MESA 0x31D7 -#endif - -// EGL implementation of SDL OpenGL support - -void KMSDRM_GLES_DefaultProfileConfig(SDL_VideoDevice *_this, int *mask, int *major, int *minor) -{ - /* if SDL was _also_ built with the Raspberry Pi driver (so we're - definitely a Pi device) or with the ROCKCHIP video driver - (it's a ROCKCHIP device), default to GLES2. */ -#if defined(SDL_VIDEO_DRIVER_RPI) || defined(SDL_VIDEO_DRIVER_ROCKCHIP) - *mask = SDL_GL_CONTEXT_PROFILE_ES; - *major = 2; - *minor = 0; -#endif -} - -bool KMSDRM_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path) -{ - /* Just pretend you do this here, but don't do it until KMSDRM_CreateWindow(), - where we do the same library load we would normally do here. - because this gets called by SDL_CreateWindow() before KMSDR_CreateWindow(), - so gbm dev isn't yet created when this is called, AND we can't alter the - call order in SDL_CreateWindow(). */ -#if 0 - NativeDisplayType display = (NativeDisplayType)_this->internal->gbm_dev; - return SDL_EGL_LoadLibrary(_this, path, display, EGL_PLATFORM_GBM_MESA); -#endif - return true; -} - -void KMSDRM_GLES_UnloadLibrary(SDL_VideoDevice *_this) -{ - /* As with KMSDRM_GLES_LoadLibrary(), we define our own "dummy" unloading function - so we manually unload the library whenever we want. */ -} - -SDL_EGL_CreateContext_impl(KMSDRM) - -bool KMSDRM_GLES_SetSwapInterval(SDL_VideoDevice *_this, int interval) -{ - if (!_this->egl_data) { - return SDL_SetError("EGL not initialized"); - } - - if (interval == 0 || interval == 1) { - _this->egl_data->egl_swapinterval = interval; - } else { - return SDL_SetError("Only swap intervals of 0 or 1 are supported"); - } - - return true; -} - -bool KMSDRM_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *windata = window->internal; - SDL_DisplayData *dispdata = SDL_GetDisplayDriverDataForWindow(window); - SDL_VideoData *viddata = _this->internal; - KMSDRM_FBInfo *fb_info; - int ret = 0; - - /* Always wait for the previous issued flip before issuing a new one, - even if you do async flips. */ - uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT; - - // Skip the swap if we've switched away to another VT - if (windata->egl_surface == EGL_NO_SURFACE) { - // Wait a bit, throttling to ~100 FPS - SDL_Delay(10); - return true; - } - - // Recreate the GBM / EGL surfaces if the display mode has changed - if (windata->egl_surface_dirty) { - KMSDRM_CreateSurfaces(_this, window); - } - - /* Wait for confirmation that the next front buffer has been flipped, at which - point the previous front buffer can be released */ - if (!KMSDRM_WaitPageflip(_this, windata)) { - return SDL_SetError("Wait for previous pageflip failed"); - } - - // Release the previous front buffer - if (windata->bo) { - KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo); - windata->bo = NULL; - } - - windata->bo = windata->next_bo; - - /* Mark a buffer to become the next front buffer. - This won't happen until pagelip completes. */ - if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, - windata->egl_surface))) { - return SDL_SetError("eglSwapBuffers failed"); - } - - /* From the GBM surface, get the next BO to become the next front buffer, - and lock it so it can't be allocated as a back buffer (to prevent EGL - from drawing into it!) */ - windata->next_bo = KMSDRM_gbm_surface_lock_front_buffer(windata->gs); - if (!windata->next_bo) { - return SDL_SetError("Could not lock front buffer on GBM surface"); - } - - // Get an actual usable fb for the next front buffer. - fb_info = KMSDRM_FBFromBO(_this, windata->next_bo); - if (!fb_info) { - return SDL_SetError("Could not get a framebuffer"); - } - - if (!windata->bo) { - /* On the first swap, immediately present the new front buffer. Before - drmModePageFlip can be used the CRTC has to be configured to use - the current connector and mode with drmModeSetCrtc */ - ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, - dispdata->crtc->crtc_id, fb_info->fb_id, 0, 0, - &dispdata->connector->connector_id, 1, &dispdata->mode); - - if (ret) { - return SDL_SetError("Could not set videomode on CRTC."); - } - } else { - /* On subsequent swaps, queue the new front buffer to be flipped during - the next vertical blank - - Remember: drmModePageFlip() never blocks, it just issues the flip, - which will be done during the next vblank, or immediately if - we pass the DRM_MODE_PAGE_FLIP_ASYNC flag. - Since calling drmModePageFlip() will return EBUSY if we call it - without having completed the last issued flip, we must pass the - DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0). - That makes it flip immediately, without waiting for the next vblank - to do so, so even if we don't block on EGL, the flip will have completed - when we get here again. */ - if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) { - flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC; - } - - ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id, - fb_info->fb_id, flip_flags, &windata->waiting_for_flip); - - if (ret == 0) { - windata->waiting_for_flip = true; - } else { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret); - } - - /* Wait immediately for vsync (as if we only had two buffers). - Even if we are already doing a WaitPageflip at the beginning of this - function, this is NOT redundant because here we wait immediately - after submitting the image to the screen, reducing lag, and if - we have waited here, there won't be a pending pageflip so the - WaitPageflip at the beginning of this function will be a no-op. - Just leave it here and don't worry. - Run your SDL program with "SDL_VIDEO_DOUBLE_BUFFER=1 " - to enable this. */ - if (windata->double_buffer) { - if (!KMSDRM_WaitPageflip(_this, windata)) { - return SDL_SetError("Immediate wait for previous pageflip failed"); - } - } - } - - return true; -} - -SDL_EGL_MakeCurrent_impl(KMSDRM) - -#endif // SDL_VIDEO_DRIVER_KMSDRM diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.h deleted file mode 100644 index 6a4fa56..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmopengles.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ -#include "SDL_internal.h" - -#ifndef SDL_kmsdrmopengles_h_ -#define SDL_kmsdrmopengles_h_ - -#include "../SDL_egl_c.h" - -// OpenGLES functions -#define KMSDRM_GLES_GetAttribute SDL_EGL_GetAttribute -#define KMSDRM_GLES_GetProcAddress SDL_EGL_GetProcAddressInternal -#define KMSDRM_GLES_DestroyContext SDL_EGL_DestroyContext -#define KMSDRM_GLES_GetSwapInterval SDL_EGL_GetSwapInterval - -extern void KMSDRM_GLES_DefaultProfileConfig(SDL_VideoDevice *_this, int *mask, int *major, int *minor); -extern bool KMSDRM_GLES_SetSwapInterval(SDL_VideoDevice *_this, int interval); -extern bool KMSDRM_GLES_LoadLibrary(SDL_VideoDevice *_this, const char *path); -extern void KMSDRM_GLES_UnloadLibrary(SDL_VideoDevice *_this); -extern SDL_GLContext KMSDRM_GLES_CreateContext(SDL_VideoDevice *_this, SDL_Window *window); -extern bool KMSDRM_GLES_SwapWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern bool KMSDRM_GLES_MakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context); - -#endif // SDL_kmsdrmopengles_h_ diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmsym.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmsym.h deleted file mode 100644 index 801942d..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmsym.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* *INDENT-OFF* */ // clang-format off - -#ifndef SDL_KMSDRM_MODULE -#define SDL_KMSDRM_MODULE(modname) -#endif - -#ifndef SDL_KMSDRM_SYM -#define SDL_KMSDRM_SYM(rc,fn,params) -#endif - -#ifndef SDL_KMSDRM_SYM_CONST -#define SDL_KMSDRM_SYM_CONST(type, name) -#endif - -#ifndef SDL_KMSDRM_SYM_OPT -#define SDL_KMSDRM_SYM_OPT(rc,fn,params) -#endif - - -SDL_KMSDRM_MODULE(LIBDRM) -SDL_KMSDRM_SYM(void,drmModeFreeResources,(drmModeResPtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreeFB,(drmModeFBPtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreeCrtc,(drmModeCrtcPtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreeConnector,(drmModeConnectorPtr 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,drmSetMaster,(int fd)) -SDL_KMSDRM_SYM(int,drmDropMaster,(int fd)) -SDL_KMSDRM_SYM(int,drmAuthMagic,(int fd, drm_magic_t magic)) -SDL_KMSDRM_SYM(drmModeResPtr,drmModeGetResources,(int fd)) -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, - uint32_t *buf_id)) - -SDL_KMSDRM_SYM_OPT(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_OPT(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_OPT(const char *,drmModeGetConnectorTypeName,(uint32_t connector_type)) - -SDL_KMSDRM_SYM(int,drmModeRmFB,(int fd, uint32_t bufferId)) -SDL_KMSDRM_SYM(drmModeFBPtr,drmModeGetFB,(int fd, uint32_t buf)) -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(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)) - -// Planes stuff. -SDL_KMSDRM_SYM(int,drmSetClientCap,(int fd, uint64_t capability, uint64_t value)) -SDL_KMSDRM_SYM(drmModePlaneResPtr,drmModeGetPlaneResources,(int fd)) -SDL_KMSDRM_SYM(drmModePlanePtr,drmModeGetPlane,(int fd, uint32_t plane_id)) -SDL_KMSDRM_SYM(drmModeObjectPropertiesPtr,drmModeObjectGetProperties,(int fd,uint32_t object_id,uint32_t object_type)) -SDL_KMSDRM_SYM(int,drmModeObjectSetProperty,(int fd, uint32_t object_id, - uint32_t object_type, uint32_t property_id, - uint64_t value)) -SDL_KMSDRM_SYM(drmModePropertyPtr,drmModeGetProperty,(int fd, uint32_t propertyId)) - -SDL_KMSDRM_SYM(void,drmModeFreeProperty,(drmModePropertyPtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreeObjectProperties,(drmModeObjectPropertiesPtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreePlane,(drmModePlanePtr ptr)) -SDL_KMSDRM_SYM(void,drmModeFreePlaneResources,(drmModePlaneResPtr ptr)) -SDL_KMSDRM_SYM(int,drmModeSetPlane,(int fd, uint32_t plane_id, uint32_t crtc_id, - uint32_t fb_id, uint32_t flags, - int32_t crtc_x, int32_t crtc_y, - uint32_t crtc_w, uint32_t crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h)) -// Planes stuff ends. - -SDL_KMSDRM_MODULE(GBM) -SDL_KMSDRM_SYM(int,gbm_device_is_format_supported,(struct gbm_device *gbm, - uint32_t format, uint32_t usage)) -SDL_KMSDRM_SYM(void,gbm_device_destroy,(struct gbm_device *gbm)) -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_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_format,(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(struct gbm_device *,gbm_bo_get_device,(struct gbm_bo *bo)) -SDL_KMSDRM_SYM(void,gbm_bo_set_user_data,(struct gbm_bo *bo, void *data, - void (*destroy_user_data)(struct gbm_bo *, void *))) -SDL_KMSDRM_SYM(void *,gbm_bo_get_user_data,(struct gbm_bo *bo)) -SDL_KMSDRM_SYM(void,gbm_bo_destroy,(struct gbm_bo *bo)) -SDL_KMSDRM_SYM(struct gbm_bo *,gbm_bo_create,(struct gbm_device *gbm, - uint32_t width, uint32_t height, - uint32_t format, uint32_t usage)) -SDL_KMSDRM_SYM(struct gbm_surface *,gbm_surface_create,(struct gbm_device *gbm, - uint32_t width, uint32_t height, - uint32_t format, uint32_t flags)) -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_OPT(uint64_t,gbm_bo_get_modifier,(struct gbm_bo *bo)) -SDL_KMSDRM_SYM_OPT(int,gbm_bo_get_plane_count,(struct gbm_bo *bo)) -SDL_KMSDRM_SYM_OPT(uint32_t,gbm_bo_get_offset,(struct gbm_bo *bo, int plane)) -SDL_KMSDRM_SYM_OPT(uint32_t,gbm_bo_get_stride_for_plane,(struct gbm_bo *bo, int plane)) -SDL_KMSDRM_SYM_OPT(union gbm_bo_handle,gbm_bo_get_handle_for_plane,(struct gbm_bo *bo, int plane)) - -#undef SDL_KMSDRM_MODULE -#undef SDL_KMSDRM_SYM -#undef SDL_KMSDRM_SYM_CONST -#undef SDL_KMSDRM_SYM_OPT - -/* *INDENT-ON* */ // clang-format on diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.c deleted file mode 100644 index be1db82..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ /dev/null @@ -1,1820 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifdef SDL_VIDEO_DRIVER_KMSDRM - -/* Include this first, as some system headers may pull in EGL headers that - * define EGL types as native types for other enabled platforms, which can - * result in type-mismatch warnings when building with LTO. - */ -#include "../SDL_egl_c.h" - -// SDL internals -#include "../../events/SDL_events_c.h" -#include "../../events/SDL_keyboard_c.h" -#include "../../events/SDL_mouse_c.h" - -#ifdef SDL_INPUT_LINUXEV -#include "../../core/linux/SDL_evdev.h" -#elif defined SDL_INPUT_WSCONS -#include "../../core/openbsd/SDL_wscons.h" -#endif - -// KMS/DRM declarations -#include "SDL_kmsdrmdyn.h" -#include "SDL_kmsdrmevents.h" -#include "SDL_kmsdrmmouse.h" -#include "SDL_kmsdrmvideo.h" -#include "SDL_kmsdrmopengles.h" -#include "SDL_kmsdrmvulkan.h" -#include -#include -#include -#include -#include -#include - -#ifdef SDL_PLATFORM_OPENBSD -static bool moderndri = false; -#else -static bool moderndri = true; -#endif - -static char kmsdrm_dri_path[16]; -static int kmsdrm_dri_pathsize = 0; -static char kmsdrm_dri_devname[8]; -static int kmsdrm_dri_devnamesize = 0; -static char kmsdrm_dri_cardpath[32]; - -#ifndef EGL_PLATFORM_GBM_MESA -#define EGL_PLATFORM_GBM_MESA 0x31D7 -#endif - -static int get_driindex(void) -{ - int available = -ENOENT; - char device[sizeof(kmsdrm_dri_cardpath)]; - int drm_fd; - int i; - int devindex = -1; - DIR *folder; - const char *hint; - struct dirent *res; - - hint = SDL_GetHint(SDL_HINT_KMSDRM_DEVICE_INDEX); - if (hint && *hint) { - char *endptr = NULL; - const int idx = (int)SDL_strtol(hint, &endptr, 10); - if ((*endptr == '\0') && (idx >= 0)) { /* *endptr==0 means "whole string was a valid number" */ - return idx; // we'll take the user's request here. - } - } - - SDL_strlcpy(device, kmsdrm_dri_path, sizeof(device)); - folder = opendir(device); - if (!folder) { - SDL_SetError("Failed to open directory '%s'", device); - return -ENOENT; - } - - SDL_strlcpy(device + kmsdrm_dri_pathsize, kmsdrm_dri_devname, - sizeof(device) - kmsdrm_dri_pathsize); - while((res = readdir(folder)) != NULL && available < 0) { - if (SDL_memcmp(res->d_name, kmsdrm_dri_devname, - kmsdrm_dri_devnamesize) == 0) { - SDL_strlcpy(device + kmsdrm_dri_pathsize + kmsdrm_dri_devnamesize, - res->d_name + kmsdrm_dri_devnamesize, - sizeof(device) - kmsdrm_dri_pathsize - - kmsdrm_dri_devnamesize); - - drm_fd = open(device, O_RDWR | O_CLOEXEC); - if (drm_fd >= 0) { - devindex = SDL_atoi(device + kmsdrm_dri_pathsize + - kmsdrm_dri_devnamesize); - if (SDL_KMSDRM_LoadSymbols()) { - drmModeRes *resources = KMSDRM_drmModeGetResources(drm_fd); - if (resources) { - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, - "%s%d connector, encoder and CRTC counts are: %d %d %d", - kmsdrm_dri_cardpath, devindex, - resources->count_connectors, - resources->count_encoders, - resources->count_crtcs); - - if (resources->count_connectors > 0 && - resources->count_encoders > 0 && - resources->count_crtcs > 0) { - available = -ENOENT; - for (i = 0; i < resources->count_connectors && available < 0; i++) { - drmModeConnector *conn = - KMSDRM_drmModeGetConnector( - drm_fd, resources->connectors[i]); - - if (!conn) { - continue; - } - - if (conn->connection == DRM_MODE_CONNECTED && - conn->count_modes) { - bool access_denied = false; - if (SDL_GetHintBoolean( - SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER, - true)) { - /* Skip this device if we can't obtain - * DRM master */ - KMSDRM_drmSetMaster(drm_fd); - if (KMSDRM_drmAuthMagic(drm_fd, 0) == -EACCES) { - access_denied = true; - } - } - - if (!access_denied) { - available = devindex; - } - } - - KMSDRM_drmModeFreeConnector(conn); - } - } - KMSDRM_drmModeFreeResources(resources); - } - SDL_KMSDRM_UnloadSymbols(); - } - close(drm_fd); - } else { - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, - "Failed to open KMSDRM device %s, errno: %d", device, errno); - } - } - } - - closedir(folder); - - return available; -} - -static void CalculateRefreshRate(drmModeModeInfo *mode, int *numerator, int *denominator) -{ - *numerator = mode->clock * 1000; - *denominator = mode->htotal * mode->vtotal; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - *numerator *= 2; - } - - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { - *denominator *= 2; - } - - if (mode->vscan > 1) { - *denominator *= mode->vscan; - } -} - -static bool KMSDRM_Available(void) -{ -#ifdef SDL_PLATFORM_OPENBSD - struct utsname nameofsystem; - double releaseversion; -#endif - int ret = -ENOENT; - -#ifdef SDL_PLATFORM_OPENBSD - if (!(uname(&nameofsystem) < 0)) { - releaseversion = SDL_atof(nameofsystem.release); - if (releaseversion >= 6.9) { - moderndri = true; - } - } -#endif - - if (moderndri) { - SDL_strlcpy(kmsdrm_dri_path, "/dev/dri/", sizeof(kmsdrm_dri_path)); - SDL_strlcpy(kmsdrm_dri_devname, "card", sizeof(kmsdrm_dri_devname)); - } else { - SDL_strlcpy(kmsdrm_dri_path, "/dev/", sizeof(kmsdrm_dri_path)); - SDL_strlcpy(kmsdrm_dri_devname, "drm", sizeof(kmsdrm_dri_devname)); - } - - kmsdrm_dri_pathsize = SDL_strlen(kmsdrm_dri_path); - kmsdrm_dri_devnamesize = SDL_strlen(kmsdrm_dri_devname); - (void)SDL_snprintf(kmsdrm_dri_cardpath, sizeof(kmsdrm_dri_cardpath), "%s%s", - kmsdrm_dri_path, kmsdrm_dri_devname); - - ret = get_driindex(); - if (ret >= 0) { - return true; - } - - return false; -} - -static void KMSDRM_DeleteDevice(SDL_VideoDevice *device) -{ - if (device->internal) { - SDL_free(device->internal); - device->internal = NULL; - } - - SDL_free(device); - - SDL_KMSDRM_UnloadSymbols(); -} - -static SDL_VideoDevice *KMSDRM_CreateDevice(void) -{ - SDL_VideoDevice *device; - SDL_VideoData *viddata; - int devindex; - - if (!KMSDRM_Available()) { - return NULL; - } - - devindex = get_driindex(); - if (devindex < 0) { - SDL_SetError("devindex (%d) must not be negative.", devindex); - return NULL; - } - - if (!SDL_KMSDRM_LoadSymbols()) { - return NULL; - } - - device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice)); - if (!device) { - return NULL; - } - - viddata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData)); - if (!viddata) { - goto cleanup; - } - viddata->devindex = devindex; - viddata->drm_fd = -1; - - device->internal = viddata; - - // Setup all functions which we can handle - device->VideoInit = KMSDRM_VideoInit; - device->VideoQuit = KMSDRM_VideoQuit; - device->GetDisplayModes = KMSDRM_GetDisplayModes; - device->SetDisplayMode = KMSDRM_SetDisplayMode; - device->CreateSDLWindow = KMSDRM_CreateWindow; - device->SetWindowTitle = KMSDRM_SetWindowTitle; - device->SetWindowPosition = KMSDRM_SetWindowPosition; - device->SetWindowSize = KMSDRM_SetWindowSize; - device->SetWindowFullscreen = KMSDRM_SetWindowFullscreen; - device->ShowWindow = KMSDRM_ShowWindow; - device->HideWindow = KMSDRM_HideWindow; - device->RaiseWindow = KMSDRM_RaiseWindow; - device->MaximizeWindow = KMSDRM_MaximizeWindow; - device->MinimizeWindow = KMSDRM_MinimizeWindow; - device->RestoreWindow = KMSDRM_RestoreWindow; - device->DestroyWindow = KMSDRM_DestroyWindow; - - device->GL_LoadLibrary = KMSDRM_GLES_LoadLibrary; - device->GL_GetProcAddress = KMSDRM_GLES_GetProcAddress; - device->GL_UnloadLibrary = KMSDRM_GLES_UnloadLibrary; - device->GL_CreateContext = KMSDRM_GLES_CreateContext; - device->GL_MakeCurrent = KMSDRM_GLES_MakeCurrent; - device->GL_SetSwapInterval = KMSDRM_GLES_SetSwapInterval; - device->GL_GetSwapInterval = KMSDRM_GLES_GetSwapInterval; - device->GL_SwapWindow = KMSDRM_GLES_SwapWindow; - device->GL_DestroyContext = KMSDRM_GLES_DestroyContext; - device->GL_DefaultProfileConfig = KMSDRM_GLES_DefaultProfileConfig; - -#ifdef SDL_VIDEO_VULKAN - device->Vulkan_LoadLibrary = KMSDRM_Vulkan_LoadLibrary; - device->Vulkan_UnloadLibrary = KMSDRM_Vulkan_UnloadLibrary; - device->Vulkan_GetInstanceExtensions = KMSDRM_Vulkan_GetInstanceExtensions; - device->Vulkan_CreateSurface = KMSDRM_Vulkan_CreateSurface; - device->Vulkan_DestroySurface = KMSDRM_Vulkan_DestroySurface; -#endif - - device->PumpEvents = KMSDRM_PumpEvents; - device->free = KMSDRM_DeleteDevice; - - return device; - -cleanup: - if (device) { - SDL_free(device); - } - - if (viddata) { - SDL_free(viddata); - } - return NULL; -} - -VideoBootStrap KMSDRM_bootstrap = { - "kmsdrm", - "KMS/DRM Video Driver", - KMSDRM_CreateDevice, - NULL, // no ShowMessageBox implementation - false -}; - -static void KMSDRM_FBDestroyCallback(struct gbm_bo *bo, void *data) -{ - KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)data; - - if (fb_info && fb_info->drm_fd >= 0 && fb_info->fb_id != 0) { - KMSDRM_drmModeRmFB(fb_info->drm_fd, fb_info->fb_id); - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Delete DRM FB %u", fb_info->fb_id); - } - - SDL_free(fb_info); -} - -KMSDRM_FBInfo *KMSDRM_FBFromBO(SDL_VideoDevice *_this, struct gbm_bo *bo) -{ - SDL_VideoData *viddata = _this->internal; - unsigned w, h; - int rc = -1; - int num_planes = 0; - uint32_t format, strides[4] = { 0 }, handles[4] = { 0 }, offsets[4] = { 0 }, flags = 0; - uint64_t modifiers[4] = { 0 }; - - // Check for an existing framebuffer - KMSDRM_FBInfo *fb_info = (KMSDRM_FBInfo *)KMSDRM_gbm_bo_get_user_data(bo); - - if (fb_info) { - return fb_info; - } - - /* Create a structure that contains enough info to remove the framebuffer - when the backing buffer is destroyed */ - fb_info = (KMSDRM_FBInfo *)SDL_calloc(1, sizeof(KMSDRM_FBInfo)); - - if (!fb_info) { - return NULL; - } - - fb_info->drm_fd = viddata->drm_fd; - - /* Create framebuffer object for the buffer using the modifiers requested by GBM. - Use of the modifiers is necessary on some platforms. */ - w = KMSDRM_gbm_bo_get_width(bo); - h = KMSDRM_gbm_bo_get_height(bo); - format = KMSDRM_gbm_bo_get_format(bo); - - if (KMSDRM_drmModeAddFB2WithModifiers && - KMSDRM_gbm_bo_get_modifier && - KMSDRM_gbm_bo_get_plane_count && - KMSDRM_gbm_bo_get_offset && - KMSDRM_gbm_bo_get_stride_for_plane && - KMSDRM_gbm_bo_get_handle_for_plane) { - - modifiers[0] = KMSDRM_gbm_bo_get_modifier(bo); - num_planes = KMSDRM_gbm_bo_get_plane_count(bo); - for (int i = 0; i < num_planes; i++) { - strides[i] = KMSDRM_gbm_bo_get_stride_for_plane(bo, i); - handles[i] = KMSDRM_gbm_bo_get_handle_for_plane(bo, i).u32; - offsets[i] = KMSDRM_gbm_bo_get_offset(bo, i); - modifiers[i] = modifiers[0]; - } - - if (modifiers[0] && modifiers[0] != DRM_FORMAT_MOD_INVALID) { - flags = DRM_MODE_FB_MODIFIERS; - } - - rc = KMSDRM_drmModeAddFB2WithModifiers(viddata->drm_fd, w, h, format, handles, strides, offsets, modifiers, &fb_info->fb_id, flags); - } - - if (rc < 0) { - strides[0] = KMSDRM_gbm_bo_get_stride(bo); - handles[0] = KMSDRM_gbm_bo_get_handle(bo).u32; - rc = KMSDRM_drmModeAddFB(viddata->drm_fd, w, h, 24, 32, strides[0], handles[0], &fb_info->fb_id); - } - - if (rc < 0) { - SDL_free(fb_info); - return NULL; - } - - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "New DRM FB (%u): %ux%u, from BO %p", - fb_info->fb_id, w, h, (void *)bo); - - // Associate our DRM framebuffer with this buffer object - KMSDRM_gbm_bo_set_user_data(bo, fb_info, KMSDRM_FBDestroyCallback); - - return fb_info; -} - -static void KMSDRM_FlipHandler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *data) -{ - *((bool *)data) = false; -} - -bool KMSDRM_WaitPageflip(SDL_VideoDevice *_this, SDL_WindowData *windata) -{ - - SDL_VideoData *viddata = _this->internal; - drmEventContext ev = { 0 }; - struct pollfd pfd = { 0 }; - int ret; - - ev.version = DRM_EVENT_CONTEXT_VERSION; - ev.page_flip_handler = KMSDRM_FlipHandler; - - pfd.fd = viddata->drm_fd; - pfd.events = POLLIN; - - /* Stay on the while loop until we get the desired event. - We need the while the loop because we could be in a situation where: - -We get and event on the FD in time, thus not on exiting on return number 1. - -The event is not an error, thus not exiting on return number 2. - -The event is of POLLIN type, but even then, if the event is not a pageflip, - drmHandleEvent() won't unset wait_for_pageflip, so we have to iterate - and go polling again. - - If it wasn't for the while loop, we could erroneously exit the function - without the pageflip event to arrive! - - For example, vblank events hit the FD and they are POLLIN events too (POLLIN - means "there's data to read on the FD"), but they are not the pageflip event - we are waiting for, so the drmEventHandle() doesn't run the flip handler, and - since waiting_for_flip is set on the pageflip handle, it's not set and we stay - on the loop, until we get the event for the pageflip, which is fine. - */ - while (windata->waiting_for_flip) { - - pfd.revents = 0; - - /* poll() waits for events arriving on the FD, and returns < 0 if timeout passes - with no events or a signal occurred before any requested event (-EINTR). - We wait forever (timeout = -1), but even if we DO get an event, we have yet - to see if it's of the required type, then if it's a pageflip, etc */ - ret = poll(&pfd, 1, -1); - - if (ret < 0) { - if (errno == EINTR) { - /* poll() returning < 0 and setting errno = EINTR means there was a signal before - any requested event, so we immediately poll again. */ - continue; - } else { - // There was another error. Don't pull again or we could get into a busy loop. - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll error"); - return false; - } - } - - if (pfd.revents & (POLLHUP | POLLERR)) { - // An event arrived on the FD in time, but it's an error. - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "DRM poll hup or error"); - return false; - } - - if (pfd.revents & POLLIN) { - /* There is data to read on the FD! - Is the event a pageflip? We know it is a pageflip if it matches the - event we are passing in &ev. If it does, drmHandleEvent() will unset - windata->waiting_for_flip and we will get out of the "while" loop. - If it's not, we keep iterating on the loop. */ - KMSDRM_drmHandleEvent(viddata->drm_fd, &ev); - } - - /* If we got to this point in the loop, we may iterate or exit the loop: - -A legit (non-error) event arrived, and it was a POLLING event, and it was consumed - by drmHandleEvent(). - -If it was a PAGEFLIP event, waiting_for_flip will be unset by drmHandleEvent() - and we will exit the loop. - -If it wasn't a PAGEFLIP, drmHandleEvent() won't unset waiting_for_flip, so we - iterare back to polling. - -A legit (non-error) event arrived, but it's not a POLLIN event, so it hasn't to be - consumed by drmHandleEvent(), so waiting_for_flip isn't set and we iterate back - to polling. */ - } - - return true; -} - -/* Given w, h and refresh rate, returns the closest DRM video mode - available on the DRM connector of the display. - We use the SDL mode list (which we filled in KMSDRM_GetDisplayModes) - because it's ordered, while the list on the connector is mostly random.*/ -static drmModeModeInfo *KMSDRM_GetClosestDisplayMode(SDL_VideoDisplay *display, int width, int height) -{ - - SDL_DisplayData *dispdata = display->internal; - drmModeConnector *connector = dispdata->connector; - - SDL_DisplayMode closest; - drmModeModeInfo *drm_mode; - - if (SDL_GetClosestFullscreenDisplayMode(display->id, width, height, 0.0f, false, &closest)) { - const SDL_DisplayModeData *modedata = closest.internal; - drm_mode = &connector->modes[modedata->mode_index]; - return drm_mode; - } else { - return NULL; - } -} - -/*****************************************************************************/ -// SDL Video and Display initialization/handling functions -/* _this is a SDL_VideoDevice * */ -/*****************************************************************************/ - -static bool KMSDRM_DropMaster(SDL_VideoDevice *_this) -{ - SDL_VideoData *viddata = _this->internal; - - /* Check if we have DRM master to begin with */ - if (KMSDRM_drmAuthMagic(viddata->drm_fd, 0) == -EACCES) { - /* Nope, nothing to do then */ - return true; - } - - return KMSDRM_drmDropMaster(viddata->drm_fd) == 0; -} - -// Deinitializes the internal of the SDL Displays in the SDL display list. -static void KMSDRM_DeinitDisplays(SDL_VideoDevice *_this) -{ - SDL_VideoData *viddata = _this->internal; - SDL_DisplayID *displays; - SDL_DisplayData *dispdata; - int i; - - displays = SDL_GetDisplays(NULL); - if (displays) { - // Iterate on the SDL Display list. - for (i = 0; displays[i]; ++i) { - - // Get the internal for this display - dispdata = SDL_GetDisplayDriverData(displays[i]); - - // Free connector - if (dispdata && dispdata->connector) { - KMSDRM_drmModeFreeConnector(dispdata->connector); - dispdata->connector = NULL; - } - - // Free CRTC - if (dispdata && dispdata->crtc) { - KMSDRM_drmModeFreeCrtc(dispdata->crtc); - dispdata->crtc = NULL; - } - } - SDL_free(displays); - } - - if (viddata->drm_fd >= 0) { - close(viddata->drm_fd); - viddata->drm_fd = -1; - } -} - -static uint32_t KMSDRM_CrtcGetPropId(uint32_t drm_fd, - drmModeObjectPropertiesPtr props, - char const *name) -{ - uint32_t i, prop_id = 0; - - for (i = 0; !prop_id && i < props->count_props; ++i) { - drmModePropertyPtr drm_prop = - KMSDRM_drmModeGetProperty(drm_fd, props->props[i]); - - if (!drm_prop) { - continue; - } - - if (SDL_strcmp(drm_prop->name, name) == 0) { - prop_id = drm_prop->prop_id; - } - - KMSDRM_drmModeFreeProperty(drm_prop); - } - - return prop_id; -} - -static bool KMSDRM_VrrPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *vrr_prop_id) -{ - drmModeObjectPropertiesPtr drm_props; - - drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd, - crtc_id, - DRM_MODE_OBJECT_CRTC); - - if (!drm_props) { - return false; - } - - *vrr_prop_id = KMSDRM_CrtcGetPropId(drm_fd, - drm_props, - "VRR_ENABLED"); - - KMSDRM_drmModeFreeObjectProperties(drm_props); - - return true; -} - -static bool KMSDRM_ConnectorCheckVrrCapable(uint32_t drm_fd, - uint32_t output_id, - char const *name) -{ - uint32_t i; - bool found = false; - uint64_t prop_value = 0; - - drmModeObjectPropertiesPtr props = KMSDRM_drmModeObjectGetProperties(drm_fd, - output_id, - DRM_MODE_OBJECT_CONNECTOR); - - if (!props) { - return false; - } - - 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, name) == 0) { - prop_value = props->prop_values[i]; - found = true; - } - - KMSDRM_drmModeFreeProperty(drm_prop); - } - if (found) { - return prop_value ? true : false; - } - - return false; -} - -static void KMSDRM_CrtcSetVrr(uint32_t drm_fd, uint32_t crtc_id, bool enabled) -{ - uint32_t vrr_prop_id; - if (!KMSDRM_VrrPropId(drm_fd, crtc_id, &vrr_prop_id)) { - return; - } - - KMSDRM_drmModeObjectSetProperty(drm_fd, - crtc_id, - DRM_MODE_OBJECT_CRTC, - vrr_prop_id, - enabled); -} - -static bool KMSDRM_CrtcGetVrr(uint32_t drm_fd, uint32_t crtc_id) -{ - uint32_t object_prop_id, vrr_prop_id; - drmModeObjectPropertiesPtr props; - bool object_prop_value; - int i; - - if (!KMSDRM_VrrPropId(drm_fd, crtc_id, &vrr_prop_id)) { - return false; - } - - props = KMSDRM_drmModeObjectGetProperties(drm_fd, - crtc_id, - DRM_MODE_OBJECT_CRTC); - - if (!props) { - return false; - } - - for (i = 0; i < props->count_props; ++i) { - drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]); - - if (!drm_prop) { - continue; - } - - object_prop_id = drm_prop->prop_id; - object_prop_value = props->prop_values[i] ? true : false; - - KMSDRM_drmModeFreeProperty(drm_prop); - - if (object_prop_id == vrr_prop_id) { - return object_prop_value; - } - } - return false; -} - -static bool KMSDRM_OrientationPropId(uint32_t drm_fd, uint32_t crtc_id, uint32_t *orientation_prop_id) -{ - drmModeObjectPropertiesPtr drm_props; - - drm_props = KMSDRM_drmModeObjectGetProperties(drm_fd, - crtc_id, - DRM_MODE_OBJECT_CONNECTOR); - - if (!drm_props) { - return false; - } - - *orientation_prop_id = KMSDRM_CrtcGetPropId(drm_fd, - drm_props, - "panel orientation"); - - KMSDRM_drmModeFreeObjectProperties(drm_props); - - return true; -} - -static int KMSDRM_CrtcGetOrientation(uint32_t drm_fd, uint32_t crtc_id) -{ - uint32_t orientation_prop_id; - drmModeObjectPropertiesPtr props; - int i; - bool done = false; - int orientation = 0; - - if (!KMSDRM_OrientationPropId(drm_fd, crtc_id, &orientation_prop_id)) { - return orientation; - } - - props = KMSDRM_drmModeObjectGetProperties(drm_fd, - crtc_id, - DRM_MODE_OBJECT_CONNECTOR); - - if (!props) { - return orientation; - } - - for (i = 0; i < props->count_props && !done; ++i) { - drmModePropertyPtr drm_prop = KMSDRM_drmModeGetProperty(drm_fd, props->props[i]); - - if (!drm_prop) { - continue; - } - - if (drm_prop->prop_id == orientation_prop_id && (drm_prop->flags & DRM_MODE_PROP_ENUM)) { - if (drm_prop->count_enums) { - // "Normal" is the default of no rotation (0 degrees) - if (SDL_strcmp(drm_prop->enums[0].name, "Left Side Up") == 0) { - orientation = 90; - } else if (SDL_strcmp(drm_prop->enums[0].name, "Upside Down") == 0) { - orientation = 180; - } else if (SDL_strcmp(drm_prop->enums[0].name, "Right Side Up") == 0) { - orientation = 270; - } - } - - done = true; - } - - KMSDRM_drmModeFreeProperty(drm_prop); - } - - KMSDRM_drmModeFreeObjectProperties(props); - - return orientation; -} - -/* Gets a DRM connector, builds an SDL_Display with it, and adds it to the - list of SDL Displays in _this->displays[] */ -static void KMSDRM_AddDisplay(SDL_VideoDevice *_this, drmModeConnector *connector, drmModeRes *resources) -{ - SDL_VideoData *viddata = _this->internal; - SDL_DisplayData *dispdata = NULL; - SDL_VideoDisplay display = { 0 }; - SDL_DisplayModeData *modedata = NULL; - drmModeEncoder *encoder = NULL; - drmModeCrtc *crtc = NULL; - const char *connector_type = NULL; - SDL_DisplayID display_id; - SDL_PropertiesID display_properties; - char name_fmt[64]; - int orientation; - int mode_index; - int i, j; - int ret = 0; - - // Reserve memory for the new display's internal. - dispdata = (SDL_DisplayData *)SDL_calloc(1, sizeof(SDL_DisplayData)); - if (!dispdata) { - ret = -1; - goto cleanup; - } - - /* Initialize some of the members of the new display's internal - to sane values. */ - dispdata->cursor_bo = NULL; - dispdata->cursor_bo_drm_fd = -1; - - /* Since we create and show the default cursor on KMSDRM_InitMouse(), - and we call KMSDRM_InitMouse() when we create a window, we have to know - if the display used by the window already has a default cursor or not. - If we don't, new default cursors would stack up on mouse->cursors and SDL - would have to hide and delete them at quit, not to mention the memory leak... */ - dispdata->default_cursor_init = false; - - // Try to find the connector's current encoder - for (i = 0; i < resources->count_encoders; i++) { - encoder = KMSDRM_drmModeGetEncoder(viddata->drm_fd, resources->encoders[i]); - - if (!encoder) { - continue; - } - - if (encoder->encoder_id == connector->encoder_id) { - break; - } - - KMSDRM_drmModeFreeEncoder(encoder); - encoder = NULL; - } - - if (!encoder) { - // No encoder was connected, find the first supported one - for (i = 0; i < resources->count_encoders; i++) { - encoder = KMSDRM_drmModeGetEncoder(viddata->drm_fd, - resources->encoders[i]); - - if (!encoder) { - continue; - } - - for (j = 0; j < connector->count_encoders; j++) { - if (connector->encoders[j] == encoder->encoder_id) { - break; - } - } - - if (j != connector->count_encoders) { - break; - } - - KMSDRM_drmModeFreeEncoder(encoder); - encoder = NULL; - } - } - - if (!encoder) { - ret = SDL_SetError("No connected encoder found for connector."); - goto cleanup; - } - - // Try to find a CRTC connected to this encoder - crtc = KMSDRM_drmModeGetCrtc(viddata->drm_fd, encoder->crtc_id); - - /* If no CRTC was connected to the encoder, find the first CRTC - that is supported by the encoder, and use that. */ - if (!crtc) { - for (i = 0; i < resources->count_crtcs; i++) { - if (encoder->possible_crtcs & (1 << i)) { - encoder->crtc_id = resources->crtcs[i]; - crtc = KMSDRM_drmModeGetCrtc(viddata->drm_fd, encoder->crtc_id); - break; - } - } - } - - if (!crtc) { - ret = SDL_SetError("No CRTC found for connector."); - goto cleanup; - } - - // Find the index of the mode attached to this CRTC - mode_index = -1; - - for (i = 0; i < connector->count_modes; i++) { - drmModeModeInfo *mode = &connector->modes[i]; - - if (!SDL_memcmp(mode, &crtc->mode, sizeof(crtc->mode))) { - mode_index = i; - break; - } - } - - if (mode_index == -1) { - int current_area, largest_area = 0; - - // Find the preferred mode or the highest resolution mode - for (i = 0; i < connector->count_modes; i++) { - drmModeModeInfo *mode = &connector->modes[i]; - - if (mode->type & DRM_MODE_TYPE_PREFERRED) { - mode_index = i; - break; - } - - current_area = mode->hdisplay * mode->vdisplay; - if (current_area > largest_area) { - mode_index = i; - largest_area = current_area; - } - } - if (mode_index != -1) { - crtc->mode = connector->modes[mode_index]; - } - } - - if (mode_index == -1) { - ret = SDL_SetError("Failed to find index of mode attached to the CRTC."); - goto cleanup; - } - - /*********************************************/ - // Create an SDL Display for this connector. - /*********************************************/ - - /*********************************************/ - // Part 1: setup the SDL_Display internal. - /*********************************************/ - - /* Get the mode currently setup for this display, - which is the mode currently setup on the CRTC - we found for the active connector. */ - dispdata->mode = crtc->mode; - dispdata->original_mode = crtc->mode; - dispdata->fullscreen_mode = crtc->mode; - - if (dispdata->mode.hdisplay == 0 || dispdata->mode.vdisplay == 0) { - ret = SDL_SetError("Couldn't get a valid connector videomode."); - goto cleanup; - } - - // Store the connector and crtc for this display. - dispdata->connector = connector; - dispdata->crtc = crtc; - - // save previous vrr state - dispdata->saved_vrr = KMSDRM_CrtcGetVrr(viddata->drm_fd, crtc->crtc_id); - // try to enable vrr - if (KMSDRM_ConnectorCheckVrrCapable(viddata->drm_fd, connector->connector_id, "VRR_CAPABLE")) { - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Enabling VRR"); - KMSDRM_CrtcSetVrr(viddata->drm_fd, crtc->crtc_id, true); - } - - // Set the name by the connector type, if possible - if (KMSDRM_drmModeGetConnectorTypeName) { - connector_type = KMSDRM_drmModeGetConnectorTypeName(connector->connector_type); - if (connector_type == NULL) { - connector_type = "Unknown"; - } - SDL_snprintf(name_fmt, sizeof(name_fmt), "%s-%u", connector_type, connector->connector_type_id); - } - - /*****************************************/ - // Part 2: setup the SDL_Display itself. - /*****************************************/ - - /* Setup the display. - There's no problem with it being still incomplete. */ - modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); - - if (!modedata) { - ret = -1; - goto cleanup; - } - - modedata->mode_index = mode_index; - - display.internal = dispdata; - display.desktop_mode.w = dispdata->mode.hdisplay; - display.desktop_mode.h = dispdata->mode.vdisplay; - CalculateRefreshRate(&dispdata->mode, &display.desktop_mode.refresh_rate_numerator, &display.desktop_mode.refresh_rate_denominator); - display.desktop_mode.format = SDL_PIXELFORMAT_ARGB8888; - display.desktop_mode.internal = modedata; - if (connector_type) { - display.name = name_fmt; - } - - // Add the display to the list of SDL displays. - display_id = SDL_AddVideoDisplay(&display, false); - if (!display_id) { - ret = -1; - goto cleanup; - } - - orientation = KMSDRM_CrtcGetOrientation(viddata->drm_fd, crtc->crtc_id); - display_properties = SDL_GetDisplayProperties(display_id); - SDL_SetNumberProperty(display_properties, SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER, orientation); - -cleanup: - if (encoder) { - KMSDRM_drmModeFreeEncoder(encoder); - } - if (ret) { - // Error (complete) cleanup - if (dispdata) { - if (dispdata->connector) { - KMSDRM_drmModeFreeConnector(dispdata->connector); - dispdata->connector = NULL; - } - if (dispdata->crtc) { - KMSDRM_drmModeFreeCrtc(dispdata->crtc); - dispdata->crtc = NULL; - } - SDL_free(dispdata); - } - } -} // NOLINT(clang-analyzer-unix.Malloc): If no error `dispdata` is saved in the display - -static void KMSDRM_SortDisplays(SDL_VideoDevice *_this) -{ - const char *name_hint = SDL_GetHint(SDL_HINT_VIDEO_DISPLAY_PRIORITY); - - if (name_hint) { - char *saveptr; - char *str = SDL_strdup(name_hint); - SDL_VideoDisplay **sorted_list = SDL_malloc(sizeof(SDL_VideoDisplay *) * _this->num_displays); - - if (str && sorted_list) { - int sorted_index = 0; - - // Sort the requested displays to the front of the list. - const char *token = SDL_strtok_r(str, ",", &saveptr); - while (token) { - for (int i = 0; i < _this->num_displays; ++i) { - SDL_VideoDisplay *d = _this->displays[i]; - if (d && SDL_strcmp(token, d->name) == 0) { - sorted_list[sorted_index++] = d; - _this->displays[i] = NULL; - break; - } - } - - token = SDL_strtok_r(NULL, ",", &saveptr); - } - - // Append the remaining displays to the end of the list. - for (int i = 0; i < _this->num_displays; ++i) { - if (_this->displays[i]) { - sorted_list[sorted_index++] = _this->displays[i]; - } - } - - // Copy the sorted list back to the display list. - SDL_memcpy(_this->displays, sorted_list, sizeof(SDL_VideoDisplay *) * _this->num_displays); - } - - SDL_free(str); - SDL_free(sorted_list); - } -} - -/* Initializes the list of SDL displays: we build a new display for each - connecter connector we find. - This is to be called early, in VideoInit(), because it gets us - the videomode information, which SDL needs immediately after VideoInit(). */ -static bool KMSDRM_InitDisplays(SDL_VideoDevice *_this) -{ - - SDL_VideoData *viddata = _this->internal; - drmModeRes *resources = NULL; - uint64_t async_pageflip = 0; - int i; - bool result = true; - - // Open /dev/dri/cardNN (/dev/drmN if on OpenBSD version less than 6.9) - (void)SDL_snprintf(viddata->devpath, sizeof(viddata->devpath), "%s%d", - kmsdrm_dri_cardpath, viddata->devindex); - - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opening device %s", viddata->devpath); - viddata->drm_fd = open(viddata->devpath, O_RDWR | O_CLOEXEC); - - if (viddata->drm_fd < 0) { - result = SDL_SetError("Could not open %s", viddata->devpath); - goto cleanup; - } - - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Opened DRM FD (%d)", viddata->drm_fd); - - // Get all of the available connectors / devices / crtcs - resources = KMSDRM_drmModeGetResources(viddata->drm_fd); - if (!resources) { - result = SDL_SetError("drmModeGetResources(%d) failed", viddata->drm_fd); - goto cleanup; - } - - /* Iterate on the available connectors. For every connected connector, - we create an SDL_Display and add it to the list of SDL Displays. */ - for (i = 0; i < resources->count_connectors; i++) { - drmModeConnector *connector = KMSDRM_drmModeGetConnector(viddata->drm_fd, - resources->connectors[i]); - - if (!connector) { - continue; - } - - if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes) { - /* If it's a connected connector with available videomodes, try to add - an SDL Display representing it. KMSDRM_AddDisplay() is purposely void, - so if it fails (no encoder for connector, no valid video mode for - connector etc...) we can keep looking for connected connectors. */ - KMSDRM_AddDisplay(_this, connector, resources); - } else { - // If it's not, free it now. - KMSDRM_drmModeFreeConnector(connector); - } - } - - // Have we added any SDL displays? - if (SDL_GetPrimaryDisplay() == 0) { - result = SDL_SetError("No connected displays found."); - goto cleanup; - } - - // Sort the displays, if necessary - KMSDRM_SortDisplays(_this); - - // Determine if video hardware supports async pageflips. - if (KMSDRM_drmGetCap(viddata->drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &async_pageflip) != 0) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not determine async page flip capability."); - } - viddata->async_pageflip_support = async_pageflip ? true : false; - - /***********************************/ - // Block for Vulkan compatibility. - /***********************************/ - - /* Vulkan requires DRM master on its own FD to work, so try to drop master - on our FD. This will only work without root on kernels v5.8 and later. - If it doesn't work, just close the FD and we'll reopen it later. */ - if (!KMSDRM_DropMaster(_this)) { - close(viddata->drm_fd); - viddata->drm_fd = -1; - } - -cleanup: - if (resources) { - KMSDRM_drmModeFreeResources(resources); - } - if (!result) { - if (viddata->drm_fd >= 0) { - close(viddata->drm_fd); - viddata->drm_fd = -1; - } - } - return result; -} - -/* Init the Vulkan-INCOMPATIBLE stuff: - Reopen FD, create gbm dev, create dumb buffer and setup display plane. - This is to be called late, in WindowCreate(), and ONLY if this is not - a Vulkan window. - We are doing this so late to allow Vulkan to work if we build a VK window. - These things are incompatible with Vulkan, which accesses the same resources - internally so they must be free when trying to build a Vulkan surface. -*/ -static bool KMSDRM_GBMInit(SDL_VideoDevice *_this, SDL_DisplayData *dispdata) -{ - SDL_VideoData *viddata = _this->internal; - bool result = true; - - // Reopen the FD if we weren't able to drop master on the original one - if (viddata->drm_fd < 0) { - viddata->drm_fd = open(viddata->devpath, O_RDWR | O_CLOEXEC); - if (viddata->drm_fd < 0) { - return SDL_SetError("Could not reopen %s", viddata->devpath); - } - } - - // Set the FD as current DRM master. - KMSDRM_drmSetMaster(viddata->drm_fd); - - // Create the GBM device. - viddata->gbm_dev = KMSDRM_gbm_create_device(viddata->drm_fd); - if (!viddata->gbm_dev) { - result = SDL_SetError("Couldn't create gbm device."); - } - - viddata->gbm_init = true; - - return result; -} - -// Deinit the Vulkan-incompatible KMSDRM stuff. -static void KMSDRM_GBMDeinit(SDL_VideoDevice *_this, SDL_DisplayData *dispdata) -{ - SDL_VideoData *viddata = _this->internal; - - /* Destroy GBM device. GBM surface is destroyed by DestroySurfaces(), - already called when we get here. */ - if (viddata->gbm_dev) { - KMSDRM_gbm_device_destroy(viddata->gbm_dev); - viddata->gbm_dev = NULL; - } - - /* Finally drop DRM master if possible, otherwise close DRM FD. - May be reopened on next non-vulkan window creation. */ - if (viddata->drm_fd >= 0 && !KMSDRM_DropMaster(_this)) { - close(viddata->drm_fd); - viddata->drm_fd = -1; - } - - viddata->gbm_init = false; -} - -static void KMSDRM_DestroySurfaces(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *viddata = _this->internal; - SDL_WindowData *windata = window->internal; - SDL_DisplayData *dispdata = SDL_GetDisplayDriverDataForWindow(window); - int ret; - - /**********************************************/ - // Wait for last issued pageflip to complete. - /**********************************************/ - // KMSDRM_WaitPageflip(_this, windata); - - /************************************************************************/ - // Restore the original CRTC configuration: configure the crtc with the - // original video mode and make it point to the original TTY buffer. - /************************************************************************/ - - ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc->crtc_id, - dispdata->crtc->buffer_id, 0, 0, &dispdata->connector->connector_id, 1, - &dispdata->original_mode); - - // If we failed to set the original mode, try to set the connector preferred mode. - if (ret && (dispdata->crtc->mode_valid == 0)) { - ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc->crtc_id, - dispdata->crtc->buffer_id, 0, 0, &dispdata->connector->connector_id, 1, - &dispdata->original_mode); - } - - if (ret) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not restore CRTC"); - } - - /***************************/ - // Destroy the EGL surface - /***************************/ - - SDL_EGL_MakeCurrent(_this, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - if (windata->egl_surface != EGL_NO_SURFACE) { - SDL_EGL_DestroySurface(_this, windata->egl_surface); - windata->egl_surface = EGL_NO_SURFACE; - } - - /***************************/ - // Destroy the GBM buffers - /***************************/ - - if (windata->bo) { - KMSDRM_gbm_surface_release_buffer(windata->gs, windata->bo); - windata->bo = NULL; - } - - if (windata->next_bo) { - KMSDRM_gbm_surface_release_buffer(windata->gs, windata->next_bo); - windata->next_bo = NULL; - } - - /***************************/ - // Destroy the GBM surface - /***************************/ - - if (windata->gs) { - KMSDRM_gbm_surface_destroy(windata->gs); - windata->gs = NULL; - } -} - -static void KMSDRM_GetModeToSet(SDL_Window *window, drmModeModeInfo *out_mode) -{ - SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window); - SDL_DisplayData *dispdata = display->internal; - - if (window->fullscreen_exclusive) { - *out_mode = dispdata->fullscreen_mode; - } else { - drmModeModeInfo *mode = KMSDRM_GetClosestDisplayMode(display, window->windowed.w, window->windowed.h); - if (mode) { - *out_mode = *mode; - } else { - *out_mode = dispdata->original_mode; - } - } -} - -static void KMSDRM_DirtySurfaces(SDL_Window *window) -{ - SDL_WindowData *windata = window->internal; - drmModeModeInfo mode; - - /* Can't recreate EGL surfaces right now, need to wait until SwapWindow - so the correct thread-local surface and context state are available */ - windata->egl_surface_dirty = true; - - /* The app may be waiting for the resize event after calling SetWindowSize - or SetWindowFullscreen, send a fake event for now since the actual - recreation is deferred */ - KMSDRM_GetModeToSet(window, &mode); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, mode.hdisplay, mode.vdisplay); -} - -/* This determines the size of the fb, which comes from the GBM surface - that we create here. */ -bool KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *viddata = _this->internal; - SDL_WindowData *windata = window->internal; - SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window); - SDL_DisplayData *dispdata = display->internal; - - uint32_t surface_fmt = GBM_FORMAT_ARGB8888; - uint32_t surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; - - EGLContext egl_context; - - bool result = true; - - // If the current window already has surfaces, destroy them before creating other. - if (windata->gs) { - KMSDRM_DestroySurfaces(_this, window); - } - - if (!KMSDRM_gbm_device_is_format_supported(viddata->gbm_dev, - surface_fmt, surface_flags)) { - SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, - "GBM surface format not supported. Trying anyway."); - } - - /* The KMSDRM backend doesn't always set the mode the higher-level code in - 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 - - FIXME: How do we do that now? Can we get a better idea at the higher level? - */ - KMSDRM_GetModeToSet(window, &dispdata->mode); - - windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, - dispdata->mode.hdisplay, dispdata->mode.vdisplay, - surface_fmt, surface_flags); - - if (!windata->gs) { - return SDL_SetError("Could not create GBM surface"); - } - - /* We can't get the EGL context yet because SDL_CreateRenderer has not been called, - but we need an EGL surface NOW, or GL won't be able to render into any surface - and we won't see the first frame. */ - SDL_EGL_SetRequiredVisualId(_this, surface_fmt); - windata->egl_surface = SDL_EGL_CreateSurface(_this, window, (NativeWindowType)windata->gs); - - if (windata->egl_surface == EGL_NO_SURFACE) { - result = SDL_SetError("Could not create EGL window surface"); - goto cleanup; - } - - /* Current context passing to EGL is now done here. If something fails, - go back to delayed SDL_EGL_MakeCurrent() call in SwapWindow. */ - egl_context = (EGLContext)SDL_GL_GetCurrentContext(); - result = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context); - - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, - dispdata->mode.hdisplay, dispdata->mode.vdisplay); - - windata->egl_surface_dirty = false; - -cleanup: - - if (!result) { - // Error (complete) cleanup. - if (windata->gs) { - KMSDRM_gbm_surface_destroy(windata->gs); - windata->gs = NULL; - } - } - - return result; -} - -#ifdef SDL_INPUT_LINUXEV -static void KMSDRM_ReleaseVT(void *userdata) -{ - SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; - SDL_VideoData *viddata = _this->internal; - int i; - - for (i = 0; i < viddata->num_windows; i++) { - SDL_Window *window = viddata->windows[i]; - if (!(window->flags & SDL_WINDOW_VULKAN)) { - KMSDRM_DestroySurfaces(_this, window); - } - } - KMSDRM_drmDropMaster(viddata->drm_fd); -} - -static void KMSDRM_AcquireVT(void *userdata) -{ - SDL_VideoDevice *_this = (SDL_VideoDevice *)userdata; - SDL_VideoData *viddata = _this->internal; - int i; - - KMSDRM_drmSetMaster(viddata->drm_fd); - for (i = 0; i < viddata->num_windows; i++) { - SDL_Window *window = viddata->windows[i]; - if (!(window->flags & SDL_WINDOW_VULKAN)) { - KMSDRM_CreateSurfaces(_this, window); - } - } -} -#endif // defined SDL_INPUT_LINUXEV - -bool KMSDRM_VideoInit(SDL_VideoDevice *_this) -{ - bool result = true; - - SDL_VideoData *viddata = _this->internal; - SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "KMSDRM_VideoInit()"); - - viddata->video_init = false; - viddata->gbm_init = false; - - /* Get KMSDRM resources info and store what we need. Getting and storing - this info isn't a problem for VK compatibility. - For VK-incompatible initializations we have KMSDRM_GBMInit(), which is - called on window creation, and only when we know it's not a VK window. */ - if (!KMSDRM_InitDisplays(_this)) { - result = SDL_SetError("error getting KMSDRM displays information"); - } - -#ifdef SDL_INPUT_LINUXEV - SDL_EVDEV_Init(); - SDL_EVDEV_SetVTSwitchCallbacks(KMSDRM_ReleaseVT, _this, KMSDRM_AcquireVT, _this); -#elif defined(SDL_INPUT_WSCONS) - SDL_WSCONS_Init(); -#endif - - viddata->video_init = true; - - return result; -} - -/* The internal pointers, like dispdata, viddata, windata, etc... - are freed by SDL internals, so not our job. */ -void KMSDRM_VideoQuit(SDL_VideoDevice *_this) -{ - SDL_VideoData *viddata = _this->internal; - - KMSDRM_DeinitDisplays(_this); - -#ifdef SDL_INPUT_LINUXEV - SDL_EVDEV_SetVTSwitchCallbacks(NULL, NULL, NULL, NULL); - SDL_EVDEV_Quit(); -#elif defined(SDL_INPUT_WSCONS) - SDL_WSCONS_Quit(); -#endif - - // Clear out the window list - SDL_free(viddata->windows); - viddata->windows = NULL; - viddata->max_windows = 0; - viddata->num_windows = 0; - viddata->video_init = false; -} - -// Read modes from the connector modes, and store them in display->display_modes. -bool KMSDRM_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display) -{ - SDL_DisplayData *dispdata = display->internal; - drmModeConnector *conn = dispdata->connector; - SDL_DisplayMode mode; - int i; - - for (i = 0; i < conn->count_modes; i++) { - SDL_DisplayModeData *modedata = SDL_calloc(1, sizeof(SDL_DisplayModeData)); - - if (modedata) { - modedata->mode_index = i; - } - - SDL_zero(mode); - mode.w = conn->modes[i].hdisplay; - mode.h = conn->modes[i].vdisplay; - CalculateRefreshRate(&conn->modes[i], &mode.refresh_rate_numerator, &mode.refresh_rate_denominator); - mode.format = SDL_PIXELFORMAT_ARGB8888; - mode.internal = modedata; - - if (!SDL_AddFullscreenDisplayMode(display, &mode)) { - SDL_free(modedata); - } - } - return true; -} - -bool KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode) -{ - /* Set the dispdata->mode to the new mode and leave actual modesetting - pending to be done on SwapWindow() via drmModeSetCrtc() */ - - SDL_VideoData *viddata = _this->internal; - SDL_DisplayData *dispdata = display->internal; - SDL_DisplayModeData *modedata = mode->internal; - drmModeConnector *conn = dispdata->connector; - int i; - - // Don't do anything if we are in Vulkan mode. - if (viddata->vulkan_mode) { - return true; - } - - if (!modedata) { - return SDL_SetError("Mode doesn't have an associated index"); - } - - /* Take note of the new mode to be set, and leave the CRTC modeset pending - so it's done in SwapWindow. */ - dispdata->fullscreen_mode = conn->modes[modedata->mode_index]; - - for (i = 0; i < viddata->num_windows; i++) { - KMSDRM_DirtySurfaces(viddata->windows[i]); - } - - return true; -} - -void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_WindowData *windata = window->internal; - SDL_DisplayData *dispdata = SDL_GetDisplayDriverDataForWindow(window); - SDL_VideoData *viddata; - bool is_vulkan = window->flags & SDL_WINDOW_VULKAN; // Is this a VK window? - unsigned int i, j; - - if (!windata) { - return; - } - - // restore vrr state - KMSDRM_CrtcSetVrr(windata->viddata->drm_fd, dispdata->crtc->crtc_id, dispdata->saved_vrr); - - viddata = windata->viddata; - - if (!is_vulkan && viddata->gbm_init) { - - // Destroy cursor GBM BO of the display of this window. - KMSDRM_DestroyCursorBO(_this, SDL_GetVideoDisplayForWindow(window)); - - // Destroy GBM surface and buffers. - KMSDRM_DestroySurfaces(_this, window); - - /* Unload library and deinit GBM, but only if this is the last window. - Note that this is the right comparison because num_windows could be 1 - if there is a complete window, or 0 if we got here from SDL_CreateWindow() - because KMSDRM_CreateWindow() returned an error so the window wasn't - added to the windows list. */ - if (viddata->num_windows <= 1) { - - // Unload EGL/GL library and free egl_data. - if (_this->egl_data) { - SDL_EGL_UnloadLibrary(_this); - _this->gl_config.driver_loaded = 0; - } - - // Free display plane, and destroy GBM device. - KMSDRM_GBMDeinit(_this, dispdata); - } - - } else { - - // If we were in Vulkan mode, get out of it. - if (viddata->vulkan_mode) { - viddata->vulkan_mode = false; - } - } - - /********************************************/ - // Remove from the internal SDL window list - /********************************************/ - - for (i = 0; i < viddata->num_windows; i++) { - if (viddata->windows[i] == window) { - viddata->num_windows--; - - for (j = i; j < viddata->num_windows; j++) { - viddata->windows[j] = viddata->windows[j + 1]; - } - - break; - } - } - - /*********************************************************************/ - // Free the window internal. Bye bye, surface and buffer pointers! - /*********************************************************************/ - SDL_free(window->internal); - window->internal = NULL; -} - -/**********************************************************************/ -// We simply IGNORE if it's a fullscreen window, window->flags don't -// reflect it: if it's fullscreen, KMSDRM_SetWindwoFullscreen() will -// be called by SDL later, and we can manage it there. -/**********************************************************************/ -bool KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props) -{ - SDL_WindowData *windata = NULL; - SDL_VideoData *viddata = _this->internal; - SDL_VideoDisplay *display = SDL_GetVideoDisplayForWindow(window); - SDL_DisplayData *dispdata = display->internal; - bool is_vulkan = window->flags & SDL_WINDOW_VULKAN; // Is this a VK window? - bool vulkan_mode = viddata->vulkan_mode; // Do we have any Vulkan windows? - NativeDisplayType egl_display; - drmModeModeInfo *mode; - bool result = true; - - // Allocate window internal data - windata = (SDL_WindowData *)SDL_calloc(1, sizeof(SDL_WindowData)); - if (!windata) { - return false; - } - - // Setup driver data for this window - windata->viddata = viddata; - window->internal = windata; - - // Do we want a double buffering scheme to get low video lag? - windata->double_buffer = false; - if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, false)) { - windata->double_buffer = true; - } - - if (!is_vulkan && !vulkan_mode) { // NON-Vulkan block. - - /* Maybe you didn't ask for an OPENGL window, but that's what you will get. - See following comments on why. */ - window->flags |= SDL_WINDOW_OPENGL; - - if (!(viddata->gbm_init)) { - - /* After SDL_CreateWindow, most SDL programs will do SDL_CreateRenderer(), - which will in turn call GL_CreateRenderer() or GLES2_CreateRenderer(). - In order for the GL_CreateRenderer() or GLES2_CreateRenderer() call to - succeed without an unnecessary window re-creation, we must: - -Mark the window as being OPENGL - -Load the GL library (which can't be done until the GBM device has been - created, so we have to do it here instead of doing it on VideoInit()) - and mark it as loaded by setting gl_config.driver_loaded to 1. - So if you ever see KMSDRM_CreateWindow() to be called two times in tests, - don't be shy to debug GL_CreateRenderer() or GLES2_CreateRenderer() - to find out why! - */ - - /* Reopen FD, create gbm dev, setup display plane, etc,. - but only when we come here for the first time, - and only if it's not a VK window. */ - if (!KMSDRM_GBMInit(_this, dispdata)) { - return SDL_SetError("Can't init GBM on window creation."); - } - } - - /* Manually load the GL library. KMSDRM_EGL_LoadLibrary() has already - been called by SDL_CreateWindow() but we don't do anything there, - our KMSDRM_EGL_LoadLibrary() is a dummy precisely to be able to load it here. - If we let SDL_CreateWindow() load the lib, it would be loaded - before we call KMSDRM_GBMInit(), causing all GLES programs to fail. */ - if (!_this->egl_data) { - egl_display = (NativeDisplayType)_this->internal->gbm_dev; - if (!SDL_EGL_LoadLibrary(_this, NULL, egl_display, EGL_PLATFORM_GBM_MESA)) { - // Try again with OpenGL ES 2.0 - _this->gl_config.profile_mask = SDL_GL_CONTEXT_PROFILE_ES; - _this->gl_config.major_version = 2; - _this->gl_config.minor_version = 0; - if (!SDL_EGL_LoadLibrary(_this, NULL, egl_display, EGL_PLATFORM_GBM_MESA)) { - return SDL_SetError("Can't load EGL/GL library on window creation."); - } - } - - _this->gl_config.driver_loaded = 1; - } - - /* Create the cursor BO for the display of this window, - now that we know this is not a VK window. */ - KMSDRM_CreateCursorBO(display); - - /* Create and set the default cursor for the display - of this window, now that we know this is not a VK window. */ - KMSDRM_InitMouse(_this, display); - - /* The FULLSCREEN flags are cut out from window->flags at this point, - so we can't know if a window is fullscreen or not, hence all windows - are considered "windowed" at this point of their life. - If a window is fullscreen, SDL internals will call - KMSDRM_SetWindowFullscreen() to reconfigure it if necessary. */ - mode = KMSDRM_GetClosestDisplayMode(display, window->windowed.w, window->windowed.h); - - if (mode) { - dispdata->fullscreen_mode = *mode; - } else { - dispdata->fullscreen_mode = dispdata->original_mode; - } - - /* Create the window surfaces with the size we have just chosen. - Needs the window diverdata in place. */ - if (!KMSDRM_CreateSurfaces(_this, window)) { - return SDL_SetError("Can't window GBM/EGL surfaces on window creation."); - } - } // NON-Vulkan block ends. - - /* Add window to the internal list of tracked windows. Note, while it may - seem odd to support multiple fullscreen windows, some apps create an - extra window as a dummy surface when working with multiple contexts */ - if (viddata->num_windows >= viddata->max_windows) { - unsigned int new_max_windows = viddata->max_windows + 1; - SDL_Window **new_windows = (SDL_Window **)SDL_realloc(viddata->windows, - new_max_windows * sizeof(SDL_Window *)); - if (!new_windows) { - return false; - } - viddata->windows = new_windows; - viddata->max_windows = new_max_windows; - - } - - viddata->windows[viddata->num_windows++] = window; - - // If we have just created a Vulkan window, establish that we are in Vulkan mode now. - viddata->vulkan_mode = is_vulkan; - - SDL_PropertiesID props = SDL_GetWindowProperties(window); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER, viddata->devindex); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER, viddata->drm_fd); - SDL_SetPointerProperty(props, SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER, viddata->gbm_dev); - - /* Focus on the newly created window. - SDL_SetMouseFocus() also takes care of calling KMSDRM_ShowCursor() if necessary. */ - SDL_SetMouseFocus(window); - SDL_SetKeyboardFocus(window); - - // Tell the app that the window has moved to top-left. - SDL_Rect display_bounds; - SDL_GetDisplayBounds(SDL_GetDisplayForWindow(window), &display_bounds); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, display_bounds.x, display_bounds.y); - - /* Allocated windata will be freed in KMSDRM_DestroyWindow, - and KMSDRM_DestroyWindow() will be called by SDL_CreateWindow() - if we return error on any of the previous returns of the function. */ - return result; -} - -void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -bool KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window) -{ - return SDL_Unsupported(); -} -void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window) -{ - SDL_VideoData *viddata = _this->internal; - if (!viddata->vulkan_mode) { - KMSDRM_DirtySurfaces(window); - } -} -SDL_FullscreenResult KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *display, SDL_FullscreenOp fullscreen) -{ - SDL_VideoData *viddata = _this->internal; - if (!viddata->vulkan_mode) { - KMSDRM_DirtySurfaces(window); - } - return SDL_FULLSCREEN_SUCCEEDED; -} -void KMSDRM_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -void KMSDRM_HideWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -void KMSDRM_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -void KMSDRM_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -void KMSDRM_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} -void KMSDRM_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window) -{ -} - -#endif // SDL_VIDEO_DRIVER_KMSDRM diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.h deleted file mode 100644 index 5bd2e9c..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -#include "SDL_internal.h" - -#ifndef SDL_kmsdrmvideo_h -#define SDL_kmsdrmvideo_h - -#include "../SDL_sysvideo.h" - -#include -#include -#include -#include -#include -#include - -#ifndef DRM_FORMAT_MOD_INVALID -#define DRM_FORMAT_MOD_INVALID 0x00ffffffffffffffULL -#endif - -#ifndef DRM_MODE_FB_MODIFIERS -#define DRM_MODE_FB_MODIFIERS 2 -#endif - -#ifndef DRM_MODE_PAGE_FLIP_ASYNC -#define DRM_MODE_PAGE_FLIP_ASYNC 2 -#endif - -#ifndef DRM_MODE_OBJECT_CONNECTOR -#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0 -#endif - -#ifndef DRM_MODE_OBJECT_CRTC -#define DRM_MODE_OBJECT_CRTC 0xcccccccc -#endif - -#ifndef DRM_CAP_ASYNC_PAGE_FLIP -#define DRM_CAP_ASYNC_PAGE_FLIP 7 -#endif - -#ifndef DRM_CAP_CURSOR_WIDTH -#define DRM_CAP_CURSOR_WIDTH 8 -#endif - -#ifndef DRM_CAP_CURSOR_HEIGHT -#define DRM_CAP_CURSOR_HEIGHT 9 -#endif - -#ifndef GBM_FORMAT_ARGB8888 -#define GBM_FORMAT_ARGB8888 ((uint32_t)('A') | ((uint32_t)('R') << 8) | ((uint32_t)('2') << 16) | ((uint32_t)('4') << 24)) -#define GBM_BO_USE_CURSOR (1 << 1) -#define GBM_BO_USE_WRITE (1 << 3) -#define GBM_BO_USE_LINEAR (1 << 4) -#endif - -struct SDL_VideoData -{ - int devindex; // device index that was passed on creation - int drm_fd; // DRM file desc - char devpath[32]; // DRM dev path. - - struct gbm_device *gbm_dev; - - bool video_init; // Has VideoInit succeeded? - bool vulkan_mode; // Are we in Vulkan mode? One VK window is enough to be. - bool async_pageflip_support; // Does the hardware support async. pageflips? - - SDL_Window **windows; - int max_windows; - int num_windows; - - /* Even if we have several displays, we only have to - open 1 FD and create 1 gbm device. */ - bool gbm_init; - -}; - -struct SDL_DisplayModeData -{ - int mode_index; -}; - -struct SDL_DisplayData -{ - drmModeConnector *connector; - drmModeCrtc *crtc; - drmModeModeInfo mode; - drmModeModeInfo original_mode; - drmModeModeInfo fullscreen_mode; - - drmModeCrtc *saved_crtc; // CRTC to restore on quit - bool saved_vrr; - - /* DRM & GBM cursor stuff lives here, not in an SDL_Cursor's internal struct, - because setting/unsetting up these is done on window creation/destruction, - where we may not have an SDL_Cursor at all (so no SDL_Cursor internal). - There's only one cursor GBM BO because we only support one cursor. */ - struct gbm_bo *cursor_bo; - int cursor_bo_drm_fd; - uint64_t cursor_w, cursor_h; - - bool default_cursor_init; -}; - -struct SDL_WindowData -{ - SDL_VideoData *viddata; - /* SDL internals expect EGL surface to be here, and in KMSDRM the GBM surface is - what supports the EGL surface on the driver side, so all these surfaces and buffers - are expected to be here, in the struct pointed by SDL_Window internal pointer: - this one. So don't try to move these to dispdata! */ - struct gbm_surface *gs; - struct gbm_bo *bo; - struct gbm_bo *next_bo; - - bool waiting_for_flip; - bool double_buffer; - - EGLSurface egl_surface; - bool egl_surface_dirty; -}; - -typedef struct KMSDRM_FBInfo -{ - int drm_fd; // DRM file desc - uint32_t fb_id; // DRM framebuffer ID -} KMSDRM_FBInfo; - -// Helper functions -extern bool KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window); -extern KMSDRM_FBInfo *KMSDRM_FBFromBO(SDL_VideoDevice *_this, struct gbm_bo *bo); -extern KMSDRM_FBInfo *KMSDRM_FBFromBO2(SDL_VideoDevice *_this, struct gbm_bo *bo, int w, int h); -extern bool KMSDRM_WaitPageflip(SDL_VideoDevice *_this, SDL_WindowData *windata); - -/****************************************************************************/ -// SDL_VideoDevice functions declaration -/****************************************************************************/ - -// Display and window functions -extern bool KMSDRM_VideoInit(SDL_VideoDevice *_this); -extern void KMSDRM_VideoQuit(SDL_VideoDevice *_this); -extern bool KMSDRM_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); -extern bool KMSDRM_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); -extern bool KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); -extern void KMSDRM_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); -extern bool KMSDRM_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window); -extern SDL_FullscreenResult KMSDRM_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window *window, SDL_VideoDisplay *_display, SDL_FullscreenOp fullscreen); -extern void KMSDRM_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_HideWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_MaximizeWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_MinimizeWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window); -extern void KMSDRM_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window); - -#endif // SDL_kmsdrmvideo_h diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.c deleted file mode 100644 index d58277b..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* - * @author Manuel Alfayate Corchere . - * Based on Jacob Lifshay's SDL_x11vulkan.c. - */ - -#include "SDL_internal.h" - -#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_KMSDRM) - -#include "../SDL_vulkan_internal.h" - -#include "SDL_kmsdrmvideo.h" -#include "SDL_kmsdrmdyn.h" -#include "SDL_kmsdrmvulkan.h" - -#include - -#ifdef SDL_PLATFORM_OPENBSD -#define DEFAULT_VULKAN "libvulkan.so" -#else -#define DEFAULT_VULKAN "libvulkan.so.1" -#endif - -bool KMSDRM_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path) -{ - VkExtensionProperties *extensions = NULL; - Uint32 i, extensionCount = 0; - bool hasSurfaceExtension = false; - bool hasDisplayExtension = false; - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; - - if (_this->vulkan_config.loader_handle) { - return SDL_SetError("Vulkan already loaded"); - } - - // Load the Vulkan library - if (!path) { - path = SDL_GetHint(SDL_HINT_VULKAN_LIBRARY); - } - if (!path) { - path = DEFAULT_VULKAN; - } - - _this->vulkan_config.loader_handle = SDL_LoadObject(path); - - if (!_this->vulkan_config.loader_handle) { - return false; - } - - SDL_strlcpy(_this->vulkan_config.loader_path, path, - SDL_arraysize(_this->vulkan_config.loader_path)); - - vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction( - _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr"); - - if (!vkGetInstanceProcAddr) { - goto fail; - } - - _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr; - _this->vulkan_config.vkEnumerateInstanceExtensionProperties = - (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)( - VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"); - - if (!_this->vulkan_config.vkEnumerateInstanceExtensionProperties) { - goto fail; - } - - extensions = SDL_Vulkan_CreateInstanceExtensionsList( - (PFN_vkEnumerateInstanceExtensionProperties) - _this->vulkan_config.vkEnumerateInstanceExtensionProperties, - &extensionCount); - - if (!extensions) { - goto fail; - } - - for (i = 0; i < extensionCount; i++) { - if (SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0) { - hasSurfaceExtension = true; - } else if (SDL_strcmp(VK_KHR_DISPLAY_EXTENSION_NAME, extensions[i].extensionName) == 0) { - hasDisplayExtension = true; - } - } - - SDL_free(extensions); - - if (!hasSurfaceExtension) { - SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_SURFACE_EXTENSION_NAME " extension"); - goto fail; - } else if (!hasDisplayExtension) { - SDL_SetError("Installed Vulkan doesn't implement the " VK_KHR_DISPLAY_EXTENSION_NAME "extension"); - goto fail; - } - - return true; - -fail: - SDL_UnloadObject(_this->vulkan_config.loader_handle); - _this->vulkan_config.loader_handle = NULL; - return false; -} - -void KMSDRM_Vulkan_UnloadLibrary(SDL_VideoDevice *_this) -{ - if (_this->vulkan_config.loader_handle) { - SDL_UnloadObject(_this->vulkan_config.loader_handle); - _this->vulkan_config.loader_handle = NULL; - } -} - -/*********************************************************************/ -// Here we can put whatever Vulkan extensions we want to be enabled -// at instance creation, which is done in the programs, not in SDL. -// So: programs call SDL_Vulkan_GetInstanceExtensions() and here -// we put the extensions specific to this backend so the programs -// get a list with the extension we want, so they can include that -// list in the ppEnabledExtensionNames and EnabledExtensionCount -// members of the VkInstanceCreateInfo struct passed to -// vkCreateInstance(). -/*********************************************************************/ -char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, - Uint32 *count) -{ - static const char *const extensionsForKMSDRM[] = { - VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME - }; - if (count) { - *count = SDL_arraysize(extensionsForKMSDRM); - } - return extensionsForKMSDRM; -} - -/***********************************************************************/ -// First thing to know is that we don't call vkCreateInstance() here. -// Instead, programs using SDL and Vulkan create their Vulkan instance -// and we get it here, ready to use. -// Extensions specific for this platform are activated in -// KMSDRM_Vulkan_GetInstanceExtensions(), like we do with -// VK_KHR_DISPLAY_EXTENSION_NAME, which is what we need for x-less VK. -/***********************************************************************/ -bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, - SDL_Window *window, - VkInstance instance, - const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR *surface) -{ - VkPhysicalDevice gpu = NULL; - uint32_t gpu_count; - uint32_t display_count; - uint32_t mode_count; - uint32_t plane_count; - uint32_t plane = UINT32_MAX; - - VkPhysicalDevice *physical_devices = NULL; - VkPhysicalDeviceProperties *device_props = NULL; - VkDisplayPropertiesKHR *display_props = NULL; - VkDisplayModePropertiesKHR *mode_props = NULL; - VkDisplayPlanePropertiesKHR *plane_props = NULL; - VkDisplayPlaneCapabilitiesKHR plane_caps; - - VkDisplayModeCreateInfoKHR display_mode_create_info; - VkDisplaySurfaceCreateInfoKHR display_plane_surface_create_info; - - VkExtent2D image_size; - VkDisplayKHR display; - VkDisplayModeKHR display_mode = (VkDisplayModeKHR)0; - VkDisplayModePropertiesKHR display_mode_props = { 0 }; - VkDisplayModeParametersKHR new_mode_parameters = { { 0, 0 }, 0 }; - // Prefer a plane that supports per-pixel alpha. - VkDisplayPlaneAlphaFlagBitsKHR alpha_mode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; - - VkResult result; - bool ret = false; - bool valid_gpu = false; - bool mode_found = false; - bool plane_supports_display = false; - - // Get the display index from the display being used by the window. - int display_index = SDL_GetDisplayIndex(SDL_GetDisplayForWindow(window)); - int i, j; - - // Get the function pointers for the functions we will use. - PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = - (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; - - PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR = - (PFN_vkCreateDisplayPlaneSurfaceKHR)vkGetInstanceProcAddr( - instance, "vkCreateDisplayPlaneSurfaceKHR"); - - PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices = - (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr( - instance, "vkEnumeratePhysicalDevices"); - - PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = - (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr( - instance, "vkGetPhysicalDeviceProperties"); - - PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR = - (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)vkGetInstanceProcAddr( - instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"); - - PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR = - (PFN_vkGetDisplayModePropertiesKHR)vkGetInstanceProcAddr( - instance, "vkGetDisplayModePropertiesKHR"); - - PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR = - (PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)vkGetInstanceProcAddr( - instance, "vkGetPhysicalDeviceDisplayPlanePropertiesKHR"); - - PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR = - (PFN_vkGetDisplayPlaneSupportedDisplaysKHR)vkGetInstanceProcAddr( - instance, "vkGetDisplayPlaneSupportedDisplaysKHR"); - - PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR = - (PFN_vkGetDisplayPlaneCapabilitiesKHR)vkGetInstanceProcAddr( - instance, "vkGetDisplayPlaneCapabilitiesKHR"); - - PFN_vkCreateDisplayModeKHR vkCreateDisplayModeKHR = - (PFN_vkCreateDisplayModeKHR)vkGetInstanceProcAddr( - instance, "vkCreateDisplayModeKHR"); - - if (!_this->vulkan_config.loader_handle) { - SDL_SetError("Vulkan is not loaded"); - goto clean; - } - - /*************************************/ - // Block for vulkan surface creation - /*************************************/ - - /****************************************************************/ - // If we got vkCreateDisplayPlaneSurfaceKHR() pointer, it means - // that the VK_KHR_Display extension is active on the instance. - // That's the central extension we need for x-less VK! - /****************************************************************/ - if (!vkCreateDisplayPlaneSurfaceKHR) { - SDL_SetError(VK_KHR_DISPLAY_EXTENSION_NAME - " extension is not enabled in the Vulkan instance."); - goto clean; - } - - /* A GPU (or physical_device, in vkcube terms) is a physical GPU. - A machine with more than one video output doesn't need to have more than one GPU, - like the Pi4 which has 1 GPU and 2 video outputs. - Just in case, we test that the GPU we choose is Vulkan-capable. - If there are new reports about VK init failures, hardcode - gpu = physical_devices[0], instead of probing, and go with that. - */ - - // Get the physical device count. - vkEnumeratePhysicalDevices(instance, &gpu_count, NULL); - - if (gpu_count == 0) { - SDL_SetError("Vulkan can't find physical devices (gpus)."); - goto clean; - } - - // Get the physical devices. - physical_devices = SDL_malloc(sizeof(VkPhysicalDevice) * gpu_count); - device_props = SDL_malloc(sizeof(VkPhysicalDeviceProperties)); - vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices); - - // Iterate on the physical devices. - for (i = 0; i < gpu_count; i++) { - - // Get the physical device properties. - vkGetPhysicalDeviceProperties( - physical_devices[i], - device_props); - - // Is this device a real GPU that supports API version 1 at least? - if (device_props->apiVersion >= 1 && - (device_props->deviceType == 1 || device_props->deviceType == 2)) { - gpu = physical_devices[i]; - valid_gpu = true; - break; - } - } - - if (!valid_gpu) { - SDL_SetError("Vulkan can't find a valid physical device (gpu)."); - goto clean; - } - - /* A display is a video output. 1 GPU can have N displays. - Vulkan only counts the connected displays. - Get the display count of the GPU. */ - vkGetPhysicalDeviceDisplayPropertiesKHR(gpu, &display_count, NULL); - if (display_count == 0) { - SDL_SetError("Vulkan can't find any displays."); - goto clean; - } - - // Get the props of the displays of the physical device. - display_props = (VkDisplayPropertiesKHR *)SDL_malloc(display_count * sizeof(*display_props)); - vkGetPhysicalDeviceDisplayPropertiesKHR(gpu, - &display_count, - display_props); - - // Get the chosen display based on the display index. - display = display_props[display_index].display; - - // Get the list of the display videomodes. - vkGetDisplayModePropertiesKHR(gpu, - display, - &mode_count, NULL); - - if (mode_count == 0) { - SDL_SetError("Vulkan can't find any video modes for display %i (%s)", 0, - display_props[display_index].displayName); - goto clean; - } - - mode_props = (VkDisplayModePropertiesKHR *)SDL_malloc(mode_count * sizeof(*mode_props)); - vkGetDisplayModePropertiesKHR(gpu, - display, - &mode_count, mode_props); - - /* Get a video mode equal to the window size among the predefined ones, - if possible. - REMEMBER: We have to get a small enough videomode for the window size, - because videomode determines how big the scanout region is and we can't - scanout a region bigger than the window (we would be reading past the - buffer, and Vulkan would give us a confusing VK_ERROR_SURFACE_LOST_KHR). */ - for (i = 0; i < mode_count; i++) { - if (mode_props[i].parameters.visibleRegion.width == window->w && - mode_props[i].parameters.visibleRegion.height == window->h) { - display_mode_props = mode_props[i]; - mode_found = true; - break; - } - } - - if (mode_found && - display_mode_props.parameters.visibleRegion.width > 0 && - display_mode_props.parameters.visibleRegion.height > 0) { - // Found a suitable mode among the predefined ones. Use that. - display_mode = display_mode_props.displayMode; - } else { - - /* Couldn't find a suitable mode among the predefined ones, so try to create our own. - This won't work for some video chips atm (like Pi's VideoCore) so these are limited - to supported resolutions. Don't try to use "closest" resolutions either, because - those are often bigger than the window size, thus causing out-of-bunds scanout. */ - new_mode_parameters.visibleRegion.width = window->w; - new_mode_parameters.visibleRegion.height = window->h; - /* SDL (and DRM, if we look at drmModeModeInfo vrefresh) uses plain integer Hz for - display mode refresh rate, but Vulkan expects higher precision. */ - new_mode_parameters.refreshRate = (uint32_t)(window->current_fullscreen_mode.refresh_rate * 1000); - - SDL_zero(display_mode_create_info); - display_mode_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR; - display_mode_create_info.parameters = new_mode_parameters; - result = vkCreateDisplayModeKHR(gpu, - display, - &display_mode_create_info, - NULL, &display_mode); - if (result != VK_SUCCESS) { - SDL_SetError("Vulkan couldn't find a predefined mode for that window size and couldn't create a suitable mode."); - goto clean; - } - } - - // Just in case we get here without a display_mode. - if (!display_mode) { - SDL_SetError("Vulkan couldn't get a display mode."); - goto clean; - } - - // Get the list of the physical device planes. - vkGetPhysicalDeviceDisplayPlanePropertiesKHR(gpu, &plane_count, NULL); - if (plane_count == 0) { - SDL_SetError("Vulkan can't find any planes."); - goto clean; - } - plane_props = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * plane_count); - vkGetPhysicalDeviceDisplayPlanePropertiesKHR(gpu, &plane_count, plane_props); - - /* Iterate on the list of planes of the physical device - to find a plane that matches these criteria: - -It must be compatible with the chosen display + mode. - -It isn't currently bound to another display. - -It supports per-pixel alpha, if possible. */ - for (i = 0; i < plane_count; i++) { - - uint32_t supported_displays_count = 0; - VkDisplayKHR *supported_displays; - - // See if the plane is compatible with the current display. - vkGetDisplayPlaneSupportedDisplaysKHR(gpu, i, &supported_displays_count, NULL); - if (supported_displays_count == 0) { - // This plane doesn't support any displays. Continue to the next plane. - continue; - } - - // Get the list of displays supported by this plane. - supported_displays = (VkDisplayKHR *)SDL_malloc(sizeof(VkDisplayKHR) * supported_displays_count); - vkGetDisplayPlaneSupportedDisplaysKHR(gpu, i, - &supported_displays_count, supported_displays); - - /* The plane must be bound to the chosen display, or not in use. - If none of these is true, iterate to another plane. */ - if (!((plane_props[i].currentDisplay == display) || (plane_props[i].currentDisplay == VK_NULL_HANDLE))) { - continue; - } - - /* Iterate the list of displays supported by this plane - in order to find out if the chosen display is among them. */ - plane_supports_display = false; - for (j = 0; j < supported_displays_count; j++) { - if (supported_displays[j] == display) { - plane_supports_display = true; - break; - } - } - - // Free the list of displays supported by this plane. - if (supported_displays) { - SDL_free(supported_displays); - } - - // If the display is not supported by this plane, iterate to the next plane. - if (!plane_supports_display) { - continue; - } - - // Want a plane that supports the alpha mode we have chosen. - vkGetDisplayPlaneCapabilitiesKHR(gpu, display_mode, i, &plane_caps); - if (plane_caps.supportedAlpha == alpha_mode) { - // Yep, this plane is alright. - plane = i; - break; - } - } - - // If we couldn't find an appropriate plane, error out. - if (plane == UINT32_MAX) { - SDL_SetError("Vulkan couldn't find an appropriate plane."); - goto clean; - } - - /********************************************/ - // Let's finally create the Vulkan surface! - /********************************************/ - - image_size.width = window->w; - image_size.height = window->h; - - SDL_zero(display_plane_surface_create_info); - display_plane_surface_create_info.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR; - display_plane_surface_create_info.displayMode = display_mode; - display_plane_surface_create_info.planeIndex = plane; - display_plane_surface_create_info.imageExtent = image_size; - display_plane_surface_create_info.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - display_plane_surface_create_info.alphaMode = alpha_mode; - result = vkCreateDisplayPlaneSurfaceKHR(instance, - &display_plane_surface_create_info, - allocator, - surface); - if (result != VK_SUCCESS) { - SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s", - SDL_Vulkan_GetResultString(result)); - goto clean; - } - - ret = true; // success! - -clean: - if (physical_devices) { - SDL_free(physical_devices); - } - if (display_props) { - SDL_free(display_props); - } - if (device_props) { - SDL_free(device_props); - } - if (plane_props) { - SDL_free(plane_props); - } - if (mode_props) { - SDL_free(mode_props); - } - - return ret; -} - -void KMSDRM_Vulkan_DestroySurface(SDL_VideoDevice *_this, - VkInstance instance, - VkSurfaceKHR surface, - const struct VkAllocationCallbacks *allocator) -{ - if (_this->vulkan_config.loader_handle) { - SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator); - } -} - -#endif diff --git a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.h b/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.h deleted file mode 100644 index aabfd92..0000000 --- a/contrib/SDL-3.2.8/src/video/kmsdrm/SDL_kmsdrmvulkan.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2025 Sam Lantinga - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -/* - * @author Manuel Alfayate Corchere . - * Based on Jacob Lifshay's SDL_x11vulkan.c. - */ - -#include "SDL_internal.h" - -#ifndef SDL_kmsdrm_vulkan_h_ -#define SDL_kmsdrm_vulkan_h_ - -#include - -#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_KMSDRM) - -extern bool KMSDRM_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path); -extern void KMSDRM_Vulkan_UnloadLibrary(SDL_VideoDevice *_this); -extern char const* const* KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uint32 *count); -extern bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this, - SDL_Window *window, - VkInstance instance, - const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR *surface); -extern void KMSDRM_Vulkan_DestroySurface(SDL_VideoDevice *_this, - VkInstance instance, - VkSurfaceKHR surface, - const struct VkAllocationCallbacks *allocator); - -#endif - -#endif // SDL_kmsdrm_vulkan_h_ -- cgit v1.2.3