From eceb35c96c8992568407215d6857ff098a8a6e06 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Tue, 3 Feb 2026 17:38:02 +0000 Subject: [PATCH] Add VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER and move detection to video drivers (#14817) --- src/video/SDL_sysvideo.h | 4 +-- src/video/SDL_video.c | 38 ++++++++---------------- src/video/dummy/SDL_nullvideo.c | 1 - src/video/haiku/SDL_bvideo.cc | 3 ++ src/video/offscreen/SDL_offscreenvideo.c | 3 ++ src/video/vita/SDL_vitavideo.c | 1 + src/video/x11/SDL_x11video.c | 17 ++++++++++- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e642714350..84233a62b6 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -191,7 +191,8 @@ typedef enum VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS = 0x04, VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY = 0x08, VIDEO_DEVICE_CAPS_SENDS_DISPLAY_CHANGES = 0x10, - VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES = 0x20 + VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES = 0x20, + VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER = 0x40 } DeviceCaps; // Fullscreen operations @@ -404,7 +405,6 @@ struct SDL_VideoDevice // Data common to all drivers SDL_ThreadID thread; bool checked_texture_framebuffer; - bool is_dummy; bool suspend_screensaver; void *wakeup_window; int num_displays; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 2c63af15be..a7133b11d6 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -69,12 +69,6 @@ #include <3ds.h> #endif -#ifdef SDL_PLATFORM_LINUX -#include -#include -#include -#endif - #ifndef GL_RGBA_FLOAT_MODE_ARB #define GL_RGBA_FLOAT_MODE_ARB 0x8820 #endif /* GL_RGBA_FLOAT_MODE_ARB */ @@ -222,6 +216,11 @@ static bool SDL_DriverSendsHDRChanges(SDL_VideoDevice *_this) return !!(_this->device_caps & VIDEO_DEVICE_CAPS_SENDS_HDR_CHANGES); } +static bool SDL_DriverHasSlowFramebuffer(SDL_VideoDevice *_this) +{ + return !!(_this->device_caps & VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER); +} + // Hint to treat all window ops as synchronous static bool syncHint; @@ -3579,11 +3578,11 @@ bool SDL_SyncWindow(SDL_Window *window) static bool ShouldAttemptTextureFramebuffer(void) { const char *hint; - bool attempt_texture_framebuffer = true; + bool attempt_texture_framebuffer; - // The dummy driver never has GPU support, of course. - if (_this->is_dummy) { - return false; + // If the driver doesn't support window framebuffers, always use the render API. + if (!_this->CreateWindowFramebuffer) { + return true; } // See if there's a hint override @@ -3595,24 +3594,11 @@ static bool ShouldAttemptTextureFramebuffer(void) attempt_texture_framebuffer = true; } } else { - // Check for platform specific defaults -#ifdef SDL_PLATFORM_LINUX - // On WSL, direct X11 is faster than using OpenGL for window framebuffers, so try to detect WSL and avoid texture framebuffer. - if ((_this->CreateWindowFramebuffer) && (SDL_strcmp(_this->name, "x11") == 0)) { - struct stat sb; - if ((stat("/proc/sys/fs/binfmt_misc/WSLInterop", &sb) == 0) || (stat("/run/WSL", &sb) == 0)) { // if either of these exist, we're on WSL. - attempt_texture_framebuffer = false; - } - } -#endif -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) // GDI BitBlt() is way faster than Direct3D dynamic textures right now. (!!! FIXME: is this still true?) - if (_this->CreateWindowFramebuffer && (SDL_strcmp(_this->name, "windows") == 0)) { + if (SDL_DriverHasSlowFramebuffer(_this)) { + attempt_texture_framebuffer = true; + } else { attempt_texture_framebuffer = false; } -#endif -#ifdef SDL_PLATFORM_EMSCRIPTEN - attempt_texture_framebuffer = false; -#endif } return attempt_texture_framebuffer; } diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c index 58063e2b46..9410d4d2b9 100644 --- a/src/video/dummy/SDL_nullvideo.c +++ b/src/video/dummy/SDL_nullvideo.c @@ -100,7 +100,6 @@ static SDL_VideoDevice *DUMMY_InternalCreateDevice(const char *enable_hint) if (!device) { return NULL; } - device->is_dummy = true; // Set the function pointers device->VideoInit = DUMMY_VideoInit; diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 8fa4ac0fef..93fc67d18f 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -107,6 +107,9 @@ static SDL_VideoDevice * HAIKU_CreateDevice(void) device->free = HAIKU_DeleteDevice; + // TODO: Is this needed? + device->device_caps = VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER; + return device; } diff --git a/src/video/offscreen/SDL_offscreenvideo.c b/src/video/offscreen/SDL_offscreenvideo.c index 0ff648f49c..716bf60dd1 100644 --- a/src/video/offscreen/SDL_offscreenvideo.c +++ b/src/video/offscreen/SDL_offscreenvideo.c @@ -110,6 +110,9 @@ static SDL_VideoDevice *OFFSCREEN_CreateDevice(void) device->DestroyWindow = OFFSCREEN_DestroyWindow; device->SetWindowSize = OFFSCREEN_SetWindowSize; + // TODO: Is this needed? + device->device_caps = VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER; + return device; } diff --git a/src/video/vita/SDL_vitavideo.c b/src/video/vita/SDL_vitavideo.c index 4efaaed6c1..379fe788a0 100644 --- a/src/video/vita/SDL_vitavideo.c +++ b/src/video/vita/SDL_vitavideo.c @@ -112,6 +112,7 @@ static SDL_VideoDevice *VITA_Create(void) /* // Disabled, causes issues on high-framerate updates. SDL still emulates this. + // TODO: Is VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER needed? device->CreateWindowFramebuffer = VITA_CreateWindowFramebuffer; device->UpdateWindowFramebuffer = VITA_UpdateWindowFramebuffer; device->DestroyWindowFramebuffer = VITA_DestroyWindowFramebuffer; diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 90cb140e53..7c0122d755 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -77,6 +77,16 @@ static bool X11_IsXWayland(Display *d) return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True; } +static bool X11_IsWSL(void) +{ +#ifdef SDL_PLATFORM_LINUX + if (SDL_GetPathInfo("/proc/sys/fs/binfmt_misc/WSLInterop", NULL) || SDL_GetPathInfo("/run/WSL", NULL)) { // if either of these exist, we're on WSL. + return true; + } +#endif + return false; +} + static SDL_VideoDevice *X11_CreateDevice(void) { SDL_VideoDevice *device; @@ -255,7 +265,8 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->system_theme = SDL_SystemTheme_Get(); #endif - device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT; + device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | + VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER; data->is_xwayland = X11_IsXWayland(x11_display); if (data->is_xwayland) { @@ -264,6 +275,10 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->device_caps |= VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED | VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; } + if (X11_IsWSL()) { + // On WSL, direct X11 is faster than using OpenGL for window framebuffers, so try to detect WSL and avoid texture framebuffer. + device->device_caps &= ~VIDEO_DEVICE_CAPS_SLOW_FRAMEBUFFER; + } return device; }