Add SDL3 backend

This commit is contained in:
Anonymous Maarten
2025-09-04 17:38:12 +02:00
parent 4495762b13
commit 6a1ec78cfb
13 changed files with 685 additions and 27 deletions

View File

@@ -153,6 +153,7 @@ if(LIBRW_PLATFORM_GL3)
if (NOT TARGET glfw)
find_package(glfw3 REQUIRED)
endif()
target_compile_definitions(librw PUBLIC LIBRW_GLFW)
target_link_libraries(librw
PUBLIC
glfw
@@ -169,6 +170,13 @@ if(LIBRW_PLATFORM_GL3)
PUBLIC
SDL2::SDL2
)
elseif (LIBRW_GL3_GFXLIB STREQUAL "SDL3")
find_package(SDL3 CONFIG REQUIRED)
target_compile_definitions(librw PUBLIC LIBRW_SDL3)
target_link_libraries(librw
PUBLIC
SDL3::SDL3
)
endif()
set(OpenGL_GL_PREFERENCE GLVND)

View File

@@ -1246,8 +1246,12 @@ getFramebufferRect(Raster *frameBuffer)
if(fb->type == Raster::CAMERA){
#ifdef LIBRW_SDL2
SDL_GetWindowSize(glGlobals.window, &r.w, &r.h);
#else
#elif defined(LIBRW_SDL3)
SDL_GetWindowSize(glGlobals.window, &r.w, &r.h);
#elif defined(LIBRW_GLFW)
glfwGetFramebufferSize(glGlobals.window, &r.w, &r.h);
#else
missing implementation
#endif
}else{
r.w = fb->width;
@@ -1412,12 +1416,20 @@ showRaster(Raster *raster, uint32 flags)
else
SDL_GL_SetSwapInterval(0);
SDL_GL_SwapWindow(glGlobals.window);
#else
#elif defined(LIBRW_SDL3)
if(flags & Raster::FLIPWAITVSYNCH)
SDL_GL_SetSwapInterval(1);
else
SDL_GL_SetSwapInterval(0);
SDL_GL_SwapWindow(glGlobals.window);
#elif defined(LIBRW_GLFW)
if(flags & Raster::FLIPWAITVSYNCH)
glfwSwapInterval(1);
else
glfwSwapInterval(0);
glfwSwapBuffers(glGlobals.window);
#else
not implemented
#endif
}
@@ -1603,7 +1615,174 @@ stopSDL2(void)
SDL_DestroyWindow(glGlobals.window);
return 1;
}
#else
#elif defined(LIBRW_SDL3)
static void
addVideoMode(const SDL_DisplayMode *mode)
{
int i;
for(i = 1; i < glGlobals.numModes; i++){
if(glGlobals.modes[i].mode.w == mode->w &&
glGlobals.modes[i].mode.h == mode->h &&
glGlobals.modes[i].mode.format == mode->format){
// had this mode already, remember highest refresh rate
if(mode->refresh_rate > glGlobals.modes[i].mode.refresh_rate)
glGlobals.modes[i].mode.refresh_rate = mode->refresh_rate;
return;
}
}
// none found, add
glGlobals.modes[glGlobals.numModes].mode = *mode;
glGlobals.modes[glGlobals.numModes].flags = VIDEOMODEEXCLUSIVE;
glGlobals.numModes++;
}
static void
makeVideoModeList(SDL_DisplayID displayIndex, SDL_DisplayID *displays)
{
int i, num, depth;
const SDL_DisplayMode *currentMode;
SDL_DisplayMode **modes;
currentMode = SDL_GetCurrentDisplayMode(displays[displayIndex]);
modes = SDL_GetFullscreenDisplayModes(displayIndex, &num);
rwFree(glGlobals.modes);
glGlobals.modes = rwNewT(DisplayMode, num+(currentMode != NULL ? 1 : 0), ID_DRIVER | MEMDUR_EVENT);
if (currentMode) {
glGlobals.modes[0].mode = *currentMode;
glGlobals.modes[0].flags = 0;
glGlobals.numModes = 1;
}
for(i = 0; i < num; i++)
addVideoMode(modes[i]);
for(i = 0; i < glGlobals.numModes; i++){
depth = SDL_BITSPERPIXEL(glGlobals.modes[i].mode.format);
// set depth to power of two
for(glGlobals.modes[i].depth = 1; glGlobals.modes[i].depth < depth; glGlobals.modes[i].depth <<= 1);
}
SDL_free(modes);
}
static int
openSDL3(EngineOpenParams *openparams)
{
glGlobals.winWidth = openparams->width;
glGlobals.winHeight = openparams->height;
glGlobals.winTitle = openparams->windowtitle;
glGlobals.pWindow = openparams->window;
memset(&gl3Caps, 0, sizeof(gl3Caps));
/* Init SDL */
if (!SDL_InitSubSystem(SDL_INIT_VIDEO)){
RWERROR((ERR_GENERAL, SDL_GetError()));
return 0;
}
glGlobals.currentDisplay = 0;
SDL_DisplayID *displays = SDL_GetDisplays(&glGlobals.numDisplays);
if (glGlobals.currentDisplay >= glGlobals.numDisplays) {
RWERROR((ERR_GENERAL, SDL_GetError()));
return 0;
}
makeVideoModeList(glGlobals.currentDisplay, displays);
SDL_free(displays);
return 1;
}
static int
closeSDL3(void)
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
return 1;
}
static struct {
int gl;
int major, minor;
} profiles[] = {
{ SDL_GL_CONTEXT_PROFILE_CORE, 3, 3 },
{ SDL_GL_CONTEXT_PROFILE_CORE, 2, 1 },
{ SDL_GL_CONTEXT_PROFILE_ES, 3, 1 },
{ SDL_GL_CONTEXT_PROFILE_ES, 2, 0 },
{ 0, 0, 0 },
};
static int
startSDL3(void)
{
SDL_Window *win;
SDL_GLContext ctx;
DisplayMode *mode;
mode = &glGlobals.modes[glGlobals.currentMode];
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, glGlobals.numSamples);
int i;
for(i = 0; profiles[i].gl; i++){
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profiles[i].gl);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, profiles[i].major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, profiles[i].minor);
if(mode->flags & VIDEOMODEEXCLUSIVE) {
win = SDL_CreateWindow(glGlobals.winTitle, mode->mode.w, mode->mode.h, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN);
if (win)
SDL_SetWindowFullscreenMode(win, &mode->mode);
} else {
win = SDL_CreateWindow(glGlobals.winTitle, glGlobals.winWidth, glGlobals.winHeight, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
if (win)
SDL_SetWindowFullscreenMode(win, NULL);
}
if(win){
gl3Caps.gles = profiles[i].gl == SDL_GL_CONTEXT_PROFILE_ES;
gl3Caps.glversion = profiles[i].major*10 + profiles[i].minor;
break;
}
}
if(win == nil){
RWERROR((ERR_GENERAL, SDL_GetError()));
return 0;
}
ctx = SDL_GL_CreateContext(win);
if (!((gl3Caps.gles ? gladLoadGLES2Loader : gladLoadGLLoader) ((GLADloadproc) SDL_GL_GetProcAddress, gl3Caps.glversion)) ) {
RWERROR((ERR_GENERAL, "gladLoadGLLoader failed"));
SDL_GL_DestroyContext(ctx);
SDL_DestroyWindow(win);
return 0;
}
printf("OpenGL version: %s\n", glGetString(GL_VERSION));
glGlobals.window = win;
glGlobals.glcontext = ctx;
*glGlobals.pWindow = win;
glGlobals.presentWidth = 0;
glGlobals.presentHeight = 0;
glGlobals.presentOffX = 0;
glGlobals.presentOffY = 0;
return 1;
}
static int
stopSDL3(void)
{
SDL_GL_DestroyContext(glGlobals.glcontext);
SDL_DestroyWindow(glGlobals.window);
return 1;
}
#elif defined(LIBRW_GLFW)
static void
addVideoMode(const GLFWvidmode *mode)
@@ -1767,6 +1946,8 @@ stopGLFW(void)
glfwDestroyWindow(glGlobals.window);
return 1;
}
#else
not implemented
#endif
static int
@@ -2007,7 +2188,94 @@ deviceSystemSDL2(DeviceReq req, void *arg, int32 n)
return 1;
}
#else
#elif defined(LIBRW_SDL3)
static int
deviceSystemSDL3(DeviceReq req, void *arg, int32 n)
{
VideoMode *rwmode;
switch(req){
case DEVICEOPEN:
return openSDL3((EngineOpenParams*)arg);
case DEVICECLOSE:
return closeSDL3();
case DEVICEINIT:
return startSDL3() && initOpenGL();
case DEVICETERM:
return termOpenGL() && stopSDL3();
case DEVICEFINALIZE:
return finalizeOpenGL();
case DEVICEGETNUMSUBSYSTEMS:
return glGlobals.numDisplays;
case DEVICEGETCURRENTSUBSYSTEM:
return glGlobals.currentDisplay;
case DEVICESETSUBSYSTEM:
if (n >= glGlobals.numDisplays)
return 0;
glGlobals.currentDisplay = n;
return 1;
case DEVICEGETSUBSSYSTEMINFO: {
const char *display_name = SDL_GetDisplayName(n);
if (display_name == nil)
return 0;
strncpy(((SubSystemInfo*)arg)->name, display_name, sizeof(SubSystemInfo::name));
return 1;
}
case DEVICEGETNUMVIDEOMODES:
return glGlobals.numModes;
case DEVICEGETCURRENTVIDEOMODE:
return glGlobals.currentMode;
case DEVICESETVIDEOMODE:
if(n >= glGlobals.numModes)
return 0;
glGlobals.currentMode = n;
return 1;
case DEVICEGETVIDEOMODEINFO:
if (n <= 0)
return 0;
rwmode = (VideoMode*)arg;
rwmode->width = glGlobals.modes[n].mode.w;
rwmode->height = glGlobals.modes[n].mode.h;
rwmode->depth = glGlobals.modes[n].depth;
rwmode->flags = glGlobals.modes[n].flags;
return 1;
case DEVICEGETMAXMULTISAMPLINGLEVELS:
{
GLint maxSamples;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
if(maxSamples == 0)
return 1;
return maxSamples;
}
case DEVICEGETMULTISAMPLINGLEVELS:
if(glGlobals.numSamples == 0)
return 1;
return glGlobals.numSamples;
case DEVICESETMULTISAMPLINGLEVELS:
glGlobals.numSamples = (uint32)n;
return 1;
default:
assert(0 && "not implemented");
return 0;
}
return 1;
}
#elif defined(LIBRW_GLFW)
static int
deviceSystemGLFW(DeviceReq req, void *arg, int32 n)
@@ -2094,6 +2362,10 @@ deviceSystemGLFW(DeviceReq req, void *arg, int32 n)
return 1;
}
#else
not implemented
#endif
Device renderdevice = {
@@ -2115,8 +2387,12 @@ Device renderdevice = {
gl3::im3DEnd,
#ifdef LIBRW_SDL2
gl3::deviceSystemSDL2
#else
#elif defined(LIBRW_SDL3)
gl3::deviceSystemSDL3
#elif defined(LIBRW_GLFW)
gl3::deviceSystemGLFW
#else
not implemented
#endif
};

View File

@@ -2,8 +2,12 @@
#include "glad/glad.h"
#ifdef LIBRW_SDL2
#include <SDL.h>
#else
#elif defined(LIBRW_SDL3)
#include <SDL3/SDL.h>
#elif defined(LIBRW_GLFW)
#include <GLFW/glfw3.h>
#else
not implemented
#endif
#endif
@@ -15,8 +19,13 @@ struct EngineOpenParams
#ifdef LIBRW_SDL2
SDL_Window **window;
bool32 fullscreen;
#else
#elif defined(LIBRW_SDL3)
SDL_Window **window;
bool32 fullscreen;
#elif defined(LIBRW_GLFW)
GLFWwindow **window;
#else
not implemented
#endif
int width, height;
const char *windowtitle;

View File

@@ -26,8 +26,12 @@ struct DisplayMode
{
#ifdef LIBRW_SDL2
SDL_DisplayMode mode;
#else
#elif defined(LIBRW_SDL3)
SDL_DisplayMode mode;
#elif defined(LIBRW_GLFW)
GLFWvidmode mode;
#else
not implemented
#endif
int32 depth;
uint32 flags;
@@ -42,13 +46,22 @@ struct GlGlobals
int numDisplays;
int currentDisplay;
#else
#elif defined(LIBRW_SDL3)
SDL_Window **pWindow;
SDL_Window *window;
SDL_GLContext glcontext;
int numDisplays;
int currentDisplay;
#elif defined(LIBRW_GLFW)
GLFWwindow **pWindow;
GLFWwindow *window;
GLFWmonitor *monitor;
int numMonitors;
int currentMonitor;
#else
not implemented
#endif
DisplayMode *modes;