It builds with SDL3 and SDL2 and SDL1.2 (on Linux)

TextInput doesn't work with SDL3 yet, and non-Linux(-y) platforms
like macOS or Windows don't support SDL3 yet
This commit is contained in:
Daniel Gibson 2024-10-07 17:22:03 +02:00
parent 5d3f143220
commit 1a1962088d
13 changed files with 662 additions and 97 deletions

View file

@ -1224,6 +1224,9 @@ include_directories(${CMAKE_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR})
add_library(idlib STATIC ${src_idlib})
if(SDL3)
target_link_libraries(idlib SDL3::Headers) # so it can use SDL_Endian.h
endif()
if (AROS)
add_library(dll STATIC ${src_arosdll})
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "i386")

View file

@ -26,7 +26,13 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <SDL.h>
#ifdef D3_SDL3
#include <SDL3/SDL.h>
// DG: compat with SDL2
#define SDL_setenv SDL_setenv_unsafe
#else // SDL1.2 or SDL2
#include <SDL.h>
#endif
#include "sys/platform.h"
#include "idlib/containers/HashTable.h"
@ -2799,7 +2805,12 @@ void idCommonLocal::SetMachineSpec( void ) {
}
}
static unsigned int AsyncTimer(unsigned int interval, void *) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
static Uint32 AsyncTimer(void * /*userdata*/, SDL_TimerID /* timerID */, Uint32 interval)
#else // SDL2 or SDL1.2
static unsigned int AsyncTimer(unsigned int interval, void *)
#endif
{
common->Async();
Sys_TriggerEvent(TRIGGER_EVENT_ONE);
@ -2947,13 +2958,19 @@ void idCommonLocal::Init( int argc, char **argv ) {
#endif
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(3, 0, 0)
if ( ! SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD) )
{
if ( SDL_Init(SDL_INIT_VIDEO) ) { // retry without joystick/gamepad if it failed
Sys_Printf( "WARNING: Couldn't get SDL gamepad support! Gamepads won't work!\n" );
} else
#elif SDL_VERSION_ATLEAST(2, 0, 0)
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) != 0)
{
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) == 0) { // retry without joystick/gamecontroller if it failed
Sys_Printf( "WARNING: Couldn't get SDL gamecontroller support! Gamepads won't work!\n" );
} else
#else
#else // SDL1.2
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) // no gamecontroller support in SDL1
{
#endif
@ -3005,14 +3022,22 @@ void idCommonLocal::Init( int argc, char **argv ) {
idCVar::RegisterStaticVars();
// print engine version
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(3, 0, 0)
int sdlv = SDL_GetVersion();
int sdlvmaj = SDL_VERSIONNUM_MAJOR(sdlv);
int sdlvmin = SDL_VERSIONNUM_MINOR(sdlv);
int sdlvmicro = SDL_VERSIONNUM_MICRO(sdlv);
Printf( "%s using SDL v%d.%d.%d\n", version.string, sdlvmaj, sdlvmin, sdlvmicro );
#else
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_version sdlv;
SDL_GetVersion(&sdlv);
#else
#else
SDL_version sdlv = *SDL_Linked_Version();
#endif
#endif
Printf( "%s using SDL v%u.%u.%u\n",
version.string, sdlv.major, sdlv.minor, sdlv.patch );
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
Printf( "SDL video driver: %s\n", SDL_GetCurrentVideoDriver() );

View file

@ -2,7 +2,11 @@
#include <algorithm> // std::sort - TODO: replace with something custom..
#include <SDL.h> // to show display size
#ifdef D3_SDL3
#include <SDL3/SDL.h>
#else // SDL1.2 or SDL2
#include <SDL.h>
#endif
#define IMGUI_DEFINE_MATH_OPERATORS
@ -1903,9 +1907,15 @@ static void DrawVideoOptionsMenu()
}
// resolution info text
int sdlDisplayIdx = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
#if SDL_VERSION_ATLEAST(3, 0, 0)
// in SDL3 it's a Display ID, in SDL2 a Display Index, in both cases the value
// can be fed into SDL_GetDisplayBounds()
SDL_DisplayID sdlDisplayId_x = SDL_GetDisplayForWindow( SDL_GL_GetCurrentWindow() );
#else // SDL2
int sdlDisplayId_x = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
#endif
SDL_Rect displayRect = {};
SDL_GetDisplayBounds( sdlDisplayIdx, &displayRect );
SDL_GetDisplayBounds( sdlDisplayId_x, &displayRect );
if ( (int)glConfig.winWidth != glConfig.vidWidth ) {
ImGui::TextDisabled( "Current Resolution: %g x %g (Physical: %d x %d)",
glConfig.winWidth, glConfig.winHeight, glConfig.vidWidth, glConfig.vidHeight );

View file

@ -42,7 +42,11 @@ If you have questions concerning this license or the applicable additional terms
#endif
#endif
#include <SDL_opengl.h>
#ifdef D3_SDL3
#include <SDL3/SDL_opengl.h>
#else // SDL1.2 or SDL2
#include <SDL_opengl.h>
#endif
#if defined( ID_DEDICATED ) && defined( _WIN32 )
// restore WINGDIAPI

View file

@ -28,7 +28,14 @@ If you have questions concerning this license or the applicable additional terms
#include <float.h>
#include <SDL_cpuinfo.h>
#ifdef D3_SDL3
#include <SDL3/SDL_cpuinfo.h>
// in SDL3, SDL_Has3DNow() has been removed, and nowadays it's not really relevant anyway,
// so just replace it with 0/false
#define SDL_Has3DNow() 0
#else // SDL1.2 or SDL2
#include <SDL_cpuinfo.h>
#endif
// MSVC header intrin.h uses strcmp and errors out when not set
#define IDSTR_NO_REDIRECT

View file

@ -26,7 +26,13 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <SDL.h>
#ifdef D3_SDL3
// HACK: I don't want SDL.h to drag in SDL_oldnames.h to avoid all the warnings about redefined definitions
#define SDL_oldnames_h_
#include <SDL3/SDL.h>
#else // SDL1.2 or SDL2
#include <SDL.h>
#endif
#include "sys/platform.h"
#include "idlib/containers/List.h"
@ -61,6 +67,109 @@ If you have questions concerning this license or the applicable additional terms
#define SDLK_PRINTSCREEN SDLK_PRINT
#endif
// unholy hacks to make it work with SDL3 (and also SDL2 and partly SDL1.2)
#if SDL_VERSION_ATLEAST(3, 0, 0)
// in SDL3 SDL_GetKeyFromScancode() got additional arguments that I don't care about
#define SDL_GetKeyFromScancode(SC) SDL_GetKeyFromScancode(SC, 0, true)
#define SDLK_z SDLK_Z
#define SDL_TEXTINPUT SDL_EVENT_TEXT_INPUT
#define SDL_KEYDOWN SDL_EVENT_KEY_DOWN
#define SDL_KEYUP SDL_EVENT_KEY_UP
#define SDL_USEREVENT SDL_EVENT_USER
#define SDL_QUIT SDL_EVENT_QUIT
#define SDL_MOUSEBUTTONDOWN SDL_EVENT_MOUSE_BUTTON_DOWN
#define SDL_MOUSEBUTTONUP SDL_EVENT_MOUSE_BUTTON_UP
#define SDL_MOUSEMOTION SDL_EVENT_MOUSE_MOTION
#define SDL_MOUSEWHEEL SDL_EVENT_MOUSE_WHEEL
#define SDL_JoystickGUID SDL_GUID
#define SDL_JoystickGetGUID SDL_GetJoystickGUID
#define SDL_JoystickName SDL_GetJoystickName
#define SDL_JoystickGetGUIDString SDL_GUIDToString
#define SDL_JOYDEVICEADDED SDL_EVENT_JOYSTICK_ADDED
#define SDL_JOYDEVICEREMOVED SDL_EVENT_JOYSTICK_REMOVED
// game controllers have been renamed to gamepads and the
// corresponding SDL_Event members are now prefixed with g instead of c
#define cbutton gbutton
#define caxis gaxis
#define SDL_GameController SDL_Gamepad
#define SDL_GameControllerAxis SDL_GamepadAxis
#define SDL_GameControllerButton SDL_GamepadButton
#define SDL_GameControllerGetType SDL_GetGamepadType
#define SDL_GameControllerName SDL_GetGamepadName
#define SDL_GameControllerGetJoystick SDL_GetGamepadJoystick
#define SDL_GameControllerGetVendor SDL_GetGamepadVendor
#define SDL_GameControllerGetProduct SDL_GetGamepadProduct
#define SDL_GameControllerOpen SDL_OpenGamepad
#define SDL_CONTROLLERAXISMOTION SDL_EVENT_GAMEPAD_AXIS_MOTION
#define SDL_CONTROLLERBUTTONDOWN SDL_EVENT_GAMEPAD_BUTTON_DOWN
#define SDL_CONTROLLERBUTTONUP SDL_EVENT_GAMEPAD_BUTTON_UP
#define SDL_CONTROLLER_AXIS_LEFTX SDL_GAMEPAD_AXIS_LEFTX
#define SDL_CONTROLLER_AXIS_LEFTY SDL_GAMEPAD_AXIS_LEFTY
#define SDL_CONTROLLER_AXIS_MAX SDL_GAMEPAD_AXIS_MAX
#define SDL_CONTROLLER_AXIS_RIGHTX SDL_GAMEPAD_AXIS_RIGHTX
#define SDL_CONTROLLER_AXIS_RIGHTY SDL_GAMEPAD_AXIS_RIGHTY
#define SDL_CONTROLLER_AXIS_TRIGGERLEFT SDL_GAMEPAD_AXIS_LEFT_TRIGGER
#define SDL_CONTROLLER_AXIS_TRIGGERRIGHT SDL_GAMEPAD_AXIS_RIGHT_TRIGGER
//#define SDL_CONTROLLER_BINDTYPE_AXIS SDL_GAMEPAD_BINDTYPE_AXIS
//#define SDL_CONTROLLER_BINDTYPE_BUTTON SDL_GAMEPAD_BINDTYPE_BUTTON
//#define SDL_CONTROLLER_BINDTYPE_HAT SDL_GAMEPAD_BINDTYPE_HAT
//#define SDL_CONTROLLER_BINDTYPE_NONE SDL_GAMEPAD_BINDTYPE_NONE
#define SDL_CONTROLLER_BUTTON_A SDL_GAMEPAD_BUTTON_SOUTH
#define SDL_CONTROLLER_BUTTON_B SDL_GAMEPAD_BUTTON_EAST
#define SDL_CONTROLLER_BUTTON_X SDL_GAMEPAD_BUTTON_WEST
#define SDL_CONTROLLER_BUTTON_Y SDL_GAMEPAD_BUTTON_NORTH
#define SDL_CONTROLLER_BUTTON_BACK SDL_GAMEPAD_BUTTON_BACK
#define SDL_CONTROLLER_BUTTON_DPAD_DOWN SDL_GAMEPAD_BUTTON_DPAD_DOWN
#define SDL_CONTROLLER_BUTTON_DPAD_LEFT SDL_GAMEPAD_BUTTON_DPAD_LEFT
#define SDL_CONTROLLER_BUTTON_DPAD_RIGHT SDL_GAMEPAD_BUTTON_DPAD_RIGHT
#define SDL_CONTROLLER_BUTTON_DPAD_UP SDL_GAMEPAD_BUTTON_DPAD_UP
#define SDL_CONTROLLER_BUTTON_GUIDE SDL_GAMEPAD_BUTTON_GUIDE
#define SDL_CONTROLLER_BUTTON_INVALID SDL_GAMEPAD_BUTTON_INVALID
#define SDL_CONTROLLER_BUTTON_LEFTSHOULDER SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
#define SDL_CONTROLLER_BUTTON_LEFTSTICK SDL_GAMEPAD_BUTTON_LEFT_STICK
#define SDL_CONTROLLER_BUTTON_MISC1 SDL_GAMEPAD_BUTTON_MISC1
#define SDL_CONTROLLER_BUTTON_PADDLE1 SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1
#define SDL_CONTROLLER_BUTTON_PADDLE2 SDL_GAMEPAD_BUTTON_LEFT_PADDLE1
#define SDL_CONTROLLER_BUTTON_PADDLE3 SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2
#define SDL_CONTROLLER_BUTTON_PADDLE4 SDL_GAMEPAD_BUTTON_LEFT_PADDLE2
#define SDL_CONTROLLER_BUTTON_RIGHTSHOULDER SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
#define SDL_CONTROLLER_BUTTON_RIGHTSTICK SDL_GAMEPAD_BUTTON_RIGHT_STICK
#define SDL_CONTROLLER_BUTTON_START SDL_GAMEPAD_BUTTON_START
#define SDL_CONTROLLER_BUTTON_TOUCHPAD SDL_GAMEPAD_BUTTON_TOUCHPAD
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_LEFT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT
#define SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
#define SDL_CONTROLLER_TYPE_PS3 SDL_GAMEPAD_TYPE_PS3
#define SDL_CONTROLLER_TYPE_PS4 SDL_GAMEPAD_TYPE_PS4
#define SDL_CONTROLLER_TYPE_PS5 SDL_GAMEPAD_TYPE_PS5
#define SDL_CONTROLLER_TYPE_UNKNOWN SDL_GAMEPAD_TYPE_STANDARD
#define SDL_CONTROLLER_TYPE_VIRTUAL SDL_GAMEPAD_TYPE_VIRTUAL
#define SDL_CONTROLLER_TYPE_XBOX360 SDL_GAMEPAD_TYPE_XBOX360
#define SDL_CONTROLLER_TYPE_XBOXONE SDL_GAMEPAD_TYPE_XBOXONE
#define IS_SDL_BTN_DOWN(EV) EV.down
// FIXME: at some point I need to enable (and possibly later disable) SDL_TextInput!
#else // SDL2 and SDL1.2
#define IS_SDL_BTN_DOWN(EV) (EV.state == SDL_PRESSED)
#endif // SDL_VERSION_ATLEAST(3, 0, 0) - unholy hacks
extern idCVar in_useGamepad; // from UsercmdGen.cpp
extern idCVar joy_deadZone; // ditto
@ -78,7 +187,7 @@ static idCVar in_ignoreConsoleKey("in_ignoreConsoleKey", "0", CVAR_SYSTEM | CVAR
"Console only opens with Shift+Esc, not ` or ^ etc");
static idCVar in_nograb("in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents input grabbing");
static idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
idCVar in_grabKeyboard("in_grabKeyboard", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL,
"if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work)");
idCVar joy_gamepadLayout("joy_gamepadLayout", "-1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_INTEGER,
@ -100,7 +209,7 @@ struct kbd_poll_t {
int key;
bool state;
kbd_poll_t() {
kbd_poll_t() : key(0), state(false) {
}
kbd_poll_t(int k, bool s) {
@ -113,7 +222,7 @@ struct mouse_poll_t {
int action;
int value;
mouse_poll_t() {
mouse_poll_t() : action(0), value(0) {
}
mouse_poll_t(int a, int v) {
@ -269,10 +378,11 @@ const char* Sys_GetLocalizedJoyKeyName( int key ) {
if (key >= K_FIRST_JOY && key <= K_LAST_JOY) {
if (key <= K_JOY_BTN_BACK) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
#if 0 //SDL_VERSION_ATLEAST(3, 0, 0)
// TODO: or use the SDL2 code and just set joy_gamepadLayout automatically based on SDL_GetGamepadType() ?
SDL_GamepadButton gpbtn = SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH);
SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabelForType(TODO, gpbtn);
SDL_GamepadButton gpbtn = (SDL_GamepadButton)(SDL_GAMEPAD_BUTTON_SOUTH + (key - K_JOY_BTN_SOUTH));
SDL_GamepadType sdlGamepadType = TODO;
SDL_GamepadButtonLabel label = SDL_GetGamepadButtonLabelForType(sdlGamepadType, gpbtn);
switch(label) {
case SDL_GAMEPAD_BUTTON_LABEL_A:
return "Pad A";
@ -844,7 +954,8 @@ void Sys_InitInput() {
in_kbd.SetModified();
Sys_GetConsoleKey(false); // initialize consoleKeymappingIdx from in_kbd
#if SDL_VERSION_ATLEAST(2, 0, 0)
const char* grabKeyboardEnv = SDL_getenv(SDL_HINT_GRAB_KEYBOARD);
// NOTE: SDL3 doesn't support that hint/env var, but whatever, support the env var anyway
const char* grabKeyboardEnv = SDL_getenv("SDL_GRAB_KEYBOARD");
if ( grabKeyboardEnv ) {
common->Printf( "The SDL_GRAB_KEYBOARD environment variable is set, setting the in_grabKeyboard CVar to the same value (%s)\n", grabKeyboardEnv );
in_grabKeyboard.SetString( grabKeyboardEnv );
@ -861,7 +972,19 @@ void Sys_InitInput() {
memset( buttonStates, 0, sizeof( buttonStates ) );
memset( joyAxis, 0, sizeof( joyAxis ) );
#if SDL_VERSION_ATLEAST(2, 0, 0) // gamecontroller/gamepad not supported in SDL1
#if SDL_VERSION_ATLEAST(3, 0, 0)
int numJoysticks = 0;
SDL_JoystickID* joysticks = SDL_GetJoysticks(&numJoysticks);
for( int i = 0; i < numJoysticks; ++i )
{
SDL_GameController* gc = SDL_GameControllerOpen( joysticks[i] );
if ( gc != NULL ) {
setGamepadType( gc );
}
}
SDL_free(joysticks);
#elif SDL_VERSION_ATLEAST(2, 0, 0)
// use button positions instead of button labels,
// Sys_GetLocalizedJoyKeyName() will do the translation
// (I think this also was the default before 2.0.12?)
@ -875,7 +998,7 @@ void Sys_InitInput() {
setGamepadType( gc );
}
}
#endif
#endif // gamecontroller/gamepad not supported in SDL1
}
/*
@ -1082,6 +1205,7 @@ sysEvent_t Sys_GetEvent() {
SDL_Event ev;
sysEvent_t res = { };
int key;
bool isDown = false;
static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };
@ -1094,7 +1218,9 @@ sysEvent_t Sys_GetEvent() {
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
static char s[SDL_TEXTINPUTEVENT_TEXT_SIZE] = {0};
// s used to have SDL_TEXTINPUTEVENT_TEXT_SIZE (32) bytes, but in SDL3 the string can have
// arbitrary size, however I assume that 128 should still be more than enough
static char s[128] = {0};
static size_t s_pos = 0;
if (s[0] != '\0') {
@ -1103,7 +1229,7 @@ sysEvent_t Sys_GetEvent() {
++s_pos;
if (!s[s_pos] || s_pos == SDL_TEXTINPUTEVENT_TEXT_SIZE) {
if (!s[s_pos] || s_pos == sizeof(s)) {
memset(s, 0, sizeof(s));
s_pos = 0;
}
@ -1131,7 +1257,36 @@ sysEvent_t Sys_GetEvent() {
}
switch (ev.type) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(3, 0, 0)
case SDL_EVENT_WINDOW_FOCUS_GAINED: {
// unset modifier, in case alt-tab was used to leave window and ALT is still set
// as that can cause fullscreen-toggling when pressing enter...
SDL_Keymod currentmod = SDL_GetModState();
int newmod = SDL_KMOD_NONE;
if (currentmod & SDL_KMOD_CAPS) // preserve capslock
newmod |= SDL_KMOD_CAPS;
SDL_SetModState((SDL_Keymod)newmod);
} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST
in_hasFocus = true;
// start playing the game sound world again (when coming from editor)
session->SetPlayingSoundWorld();
continue; // handle next event
case SDL_EVENT_WINDOW_FOCUS_LOST:
in_hasFocus = false;
continue; // handle next event
case SDL_EVENT_WINDOW_RESIZED:
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
GLimp_UpdateWindowSize();
continue; // handle next event
#elif SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_WINDOWEVENT:
switch (ev.window.event) {
case SDL_WINDOWEVENT_FOCUS_GAINED: {
@ -1188,7 +1343,11 @@ sysEvent_t Sys_GetEvent() {
#endif
case SDL_KEYDOWN:
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (ev.key.key == SDLK_RETURN && (ev.key.mod & SDL_KMOD_ALT) > 0) {
#else
if (ev.key.keysym.sym == SDLK_RETURN && (ev.key.keysym.mod & KMOD_ALT) > 0) {
#endif
cvarSystem->SetCVarBool("r_fullscreen", !renderSystem->IsFullScreen());
PushConsoleEvent("vid_restart partial");
return res_none;
@ -1213,12 +1372,18 @@ sysEvent_t Sys_GetEvent() {
continue; // handle next event
}
}
#else
#else // SDL2+
{
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_Scancode sc = ev.key.scancode;
SDL_Keycode keycode = ev.key.key;
#else // SDL2
SDL_Scancode sc = ev.key.keysym.scancode;
SDL_Keycode keycode = ev.key.keysym.sym;
#endif
// workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
// always map those physical keys (scancodes) to those keycodes anyway
// see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
SDL_Scancode sc = ev.key.keysym.scancode;
if(sc == SDL_SCANCODE_0)
{
key = '0';
@ -1232,10 +1397,10 @@ sysEvent_t Sys_GetEvent() {
}
else
{
key = mapkey(ev.key.keysym.sym);
key = mapkey(keycode);
}
if ( !in_ignoreConsoleKey.GetBool() && ev.key.keysym.scancode == SDL_SCANCODE_GRAVE ) {
if ( !in_ignoreConsoleKey.GetBool() && sc == SDL_SCANCODE_GRAVE ) {
// that key between Esc, Tab and 1 is the console key
key = K_CONSOLE;
}
@ -1245,22 +1410,23 @@ sysEvent_t Sys_GetEvent() {
key = getKeynumForSDLscancode(sc);
if(!key) {
if (ev.type == SDL_KEYDOWN) {
common->Warning("unmapped SDL key %d (scancode %d)", ev.key.keysym.sym, (int)sc);
common->Warning("unmapped SDL key %d (scancode %d)", keycode, (int)sc);
}
continue; // handle next event
}
}
}
#endif
isDown = IS_SDL_BTN_DOWN( ev.key );
res.evType = SE_KEY;
res.evValue = key;
res.evValue2 = ev.key.state == SDL_PRESSED ? 1 : 0;
res.evValue2 = isDown;
kbd_polls.Append(kbd_poll_t(key, ev.key.state == SDL_PRESSED));
kbd_polls.Append( kbd_poll_t( key, isDown ) );
#if SDL_VERSION_ATLEAST(2, 0, 0)
if (key == K_BACKSPACE && ev.key.state == SDL_PRESSED)
if (key == K_BACKSPACE && isDown)
c = key;
#else
if (ev.key.state == SDL_PRESSED && (ev.key.keysym.unicode & 0xff00) == 0)
@ -1277,7 +1443,14 @@ sysEvent_t Sys_GetEvent() {
if ( isAscii(ev.text.text) ) {
res.evValue = ev.text.text[0];
if ( ev.text.text[1] != '\0' ) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
// yes, it's ok if this is not 0-terminated, the code generating
// events from s handles that
strncpy(s, ev.text.text, sizeof(s));
#else // SDL2
memcpy( s, ev.text.text, SDL_TEXTINPUTEVENT_TEXT_SIZE );
s[SDL_TEXTINPUTEVENT_TEXT_SIZE] = '\0';
#endif
s_pos = 1; // pos 0 is returned
}
return res;
@ -1294,10 +1467,6 @@ sysEvent_t Sys_GetEvent() {
}
continue; // handle next event
case SDL_TEXTEDITING:
// on windows we get this event whenever the window gains focus.. just ignore it.
continue;
#endif
case SDL_MOUSEMOTION:
@ -1335,20 +1504,21 @@ sysEvent_t Sys_GetEvent() {
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
isDown = IS_SDL_BTN_DOWN(ev.button);
res.evType = SE_KEY;
switch (ev.button.button) {
case SDL_BUTTON_LEFT:
res.evValue = K_MOUSE1;
mouse_polls.Append(mouse_poll_t(M_ACTION1, ev.button.state == SDL_PRESSED ? 1 : 0));
mouse_polls.Append(mouse_poll_t(M_ACTION1, isDown));
break;
case SDL_BUTTON_MIDDLE:
res.evValue = K_MOUSE3;
mouse_polls.Append(mouse_poll_t(M_ACTION3, ev.button.state == SDL_PRESSED ? 1 : 0));
mouse_polls.Append(mouse_poll_t(M_ACTION3, isDown));
break;
case SDL_BUTTON_RIGHT:
res.evValue = K_MOUSE2;
mouse_polls.Append(mouse_poll_t(M_ACTION2, ev.button.state == SDL_PRESSED ? 1 : 0));
mouse_polls.Append(mouse_poll_t(M_ACTION2, isDown));
break;
#if !SDL_VERSION_ATLEAST(2, 0, 0)
@ -1370,14 +1540,14 @@ sysEvent_t Sys_GetEvent() {
{
int buttonIndex = ev.button.button - SDL_BUTTON_LEFT;
res.evValue = K_MOUSE1 + buttonIndex;
mouse_polls.Append( mouse_poll_t( M_ACTION1 + buttonIndex, ev.button.state == SDL_PRESSED ? 1 : 0 ) );
mouse_polls.Append( mouse_poll_t( M_ACTION1 + buttonIndex, isDown ) );
}
else
#endif
continue; // handle next event
}
res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;
res.evValue2 = isDown;
return res;
@ -1390,8 +1560,10 @@ sysEvent_t Sys_GetEvent() {
continue;
}
isDown = IS_SDL_BTN_DOWN(ev.cbutton);
res.evType = SE_KEY;
res.evValue2 = ev.cbutton.state == SDL_PRESSED ? 1 : 0;
res.evValue2 = isDown;
// special case: always treat the start button as escape so it opens/closes the menu
// (also makes that button non-bindable)
@ -1410,7 +1582,7 @@ sysEvent_t Sys_GetEvent() {
}
sys_jEvents jEvent = mapjoybutton( (SDL_GameControllerButton)ev.cbutton.button );
joystick_polls.Append( joystick_poll_t(jEvent, ev.cbutton.state == SDL_PRESSED ? 1 : 0) );
joystick_polls.Append( joystick_poll_t(jEvent, isDown) );
if ( ( jEvent >= J_ACTION_FIRST ) && ( jEvent <= J_ACTION_MAX ) ) {
res.evValue = K_FIRST_JOY + ( jEvent - J_ACTION_FIRST );
@ -1630,7 +1802,8 @@ void Sys_GenerateEvents() {
if (s)
PushConsoleEvent(s);
#ifndef ID_DEDICATED // doesn't make sense on dedicated server
// doesn't make sense on dedicated server and SDL3 handles this in GLimp_GrabInput()
#if !defined(ID_DEDICATED) && ! SDL_VERSION_ATLEAST(3, 0, 0)
if ( in_grabKeyboard.IsModified() ) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetHint( SDL_HINT_GRAB_KEYBOARD, in_grabKeyboard.GetString() );

View file

@ -26,7 +26,17 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <SDL.h>
#ifdef D3_SDL3
#include <SDL3/SDL.h>
// backwards-compat with SDL2
#define SDL_WINDOW_ALLOW_HIGHDPI SDL_WINDOW_HIGH_PIXEL_DENSITY
#define SDL_GL_DeleteContext SDL_GL_DestroyContext
typedef SDL_WindowFlags My_SDL_WindowFlags;
#else // SDL1.2 or SDL2
#include <SDL.h>
// for compat with SDL3 - unfortunately SDL2 also has a SDL_WindowFlags type, but it's an enum
typedef Uint32 My_SDL_WindowFlags;
#endif
#include "sys/platform.h"
#include "framework/Licensee.h"
@ -99,7 +109,6 @@ If you have questions concerning this license or the applicable additional terms
#endif // _WIN32 and ID_ALLOW_TOOLS
#if SDL_VERSION_ATLEAST(2, 0, 0)
static SDL_Window *window = NULL;
static SDL_GLContext context = NULL;
@ -109,6 +118,24 @@ static SDL_Surface *window = NULL;
#define SDL_WINDOW_FULLSCREEN SDL_FULLSCREEN
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
extern idCVar in_grabKeyboard;
static void SetSDLIcon()
{
#include "doom_icon.h" // contains the struct d3_icon
SDL_Surface* icon = SDL_CreateSurfaceFrom(d3_icon.width, d3_icon.height,
SDL_PIXELFORMAT_RGBA32, (void*)d3_icon.pixel_data,
d3_icon.bytes_per_pixel*d3_icon.width);
SDL_SetWindowIcon(window, icon);
SDL_DestroySurface(icon);
}
#else // SDL2 and SDL1.2
static void SetSDLIcon()
{
Uint32 rmask, gmask, bmask, amask;
@ -141,6 +168,7 @@ static void SetSDLIcon()
SDL_FreeSurface(icon);
}
#endif // SDL2 and SDL1.2
/*
===================
@ -152,16 +180,23 @@ bool GLimp_Init(glimpParms_t parms) {
assert(SDL_WasInit(SDL_INIT_VIDEO));
Uint32 flags = SDL_WINDOW_OPENGL;
My_SDL_WindowFlags flags = SDL_WINDOW_OPENGL;
if (parms.fullScreen == 1)
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
if(parms.fullScreenDesktop)
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
else
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
// in SDL3 windows with SDL_WINDOW_FULLSCREEN set are fullscreen-desktop by default
// and for exclusive fullscreen SDL_SetWindowFullscreenMode() must be called
// after creating the window, so only set the flag if we want fullscreen-desktop mode
if(parms.fullScreen && parms.fullScreenDesktop) {
flags |= SDL_WINDOW_FULLSCREEN;
}
#elif SDL_VERSION_ATLEAST(2, 0, 0)
flags |= parms.fullScreenDesktop ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN;
#else // SDL1.2
flags |= SDL_WINDOW_FULLSCREEN;
#endif
}
r_windowResizable.ClearModified();
@ -190,9 +225,10 @@ bool GLimp_Init(glimpParms_t parms) {
* (unless the user disables that with r_fillWindowAlphaChan 0) */
#ifdef SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY
SDL_SetHint(SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY, "1");
#else // little hack so this works if the SDL2 version used for building is older than runtime version
#elif SDL_MAJOR_VERSION == 2 // little hack so this works if the SDL2 version used for building is older than runtime version
SDL_SetHint("SDL_VIDEO_EGL_ALLOW_TRANSPARENCY", "1");
#endif
// Note: for SDL3 we use SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN below
#endif
int colorbits = 24;
@ -277,7 +313,7 @@ try_again:
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, (multisamples > 1) ? 1 : 0);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisamples);
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(2, 0, 0) // SDL2 and SDL3 window creation
if ( r_glDebugContext.GetBool() ) {
common->Printf( "Requesting an OpenGL Debug Context (r_glDebugContext is enabled)\n" );
@ -292,37 +328,137 @@ try_again:
windowMode, parms.width, parms.height, r_mode.GetInteger());
}
int displayIndex = 0;
#if SDL_VERSION_ATLEAST(2, 0, 4)
Uint32 selectedDisplay = 0;
#if SDL_VERSION_ATLEAST(2, 0, 4)
// try to put the window on the display the mousecursor currently is on
{
#if SDL_VERSION_ATLEAST(3, 0, 0)
float x, y;
int numDisplays = 0;
SDL_DisplayID* displayIDs = SDL_GetDisplays(&numDisplays);
#else // SDL2
int numDisplays = SDL_GetNumVideoDisplays();
int x, y;
#endif
SDL_GetGlobalMouseState(&x, &y);
int numDisplays = SDL_GetNumVideoDisplays();
common->Printf("SDL detected %d displays: \n", numDisplays);
bool found = false;
for ( int j=0; j<numDisplays; ++j ) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_DisplayID displayId_x = displayIDs[j];
#else // SDL2
int displayId_x = j;
#endif
SDL_Rect rect;
if (SDL_GetDisplayBounds(j, &rect) == 0) {
if (SDL_GetDisplayBounds(displayId_x, &rect) == 0) {
common->Printf(" %d: %dx%d at (%d, %d) to (%d, %d)\n", j, rect.w, rect.h,
rect.x, rect.y, rect.x+rect.w, rect.y+rect.h);
if ( !found && x >= rect.x && x < rect.x + rect.w
&& y >= rect.y && y < rect.y + rect.h )
{
displayIndex = j;
selectedDisplay = j;
found = true;
}
}
}
common->Printf("Will use display %d because mouse cursor is at (%d, %d).\n",
displayIndex, x, y);
#if SDL_VERSION_ATLEAST(3, 0, 0)
if(displayIDs != NULL) {
SDL_DisplayID displayID = displayIDs[selectedDisplay];
common->Printf("Will use display %u (%u) because mouse cursor is at (%g, %g).\n",
selectedDisplay, displayID, x, y);
selectedDisplay = displayID;
SDL_free(displayIDs);
}
#else // SDL2
common->Printf("Will use display %u because mouse cursor is at (%d, %d).\n",
selectedDisplay, x, y);
#endif
}
#endif
#endif // SDL_VERSION_ATLEAST(2, 0, 4)
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_PropertiesID props = SDL_CreateProperties();
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, ENGINE_VERSION);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay));
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay));
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, parms.width);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, parms.height);
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER, flags);
// TODO: the following is probably redundant with the flag already set
//if ( parms.fullScreen && parms.fullScreenDesktop ) {
// SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, true);
//} // for exclusive fullscreen, create in windowed mode first, need to call
// TODO: SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN, true);
// as replacement for SDL_VIDEO_EGL_ALLOW_TRANSPARENCY - but when?
// I don't want this on all platforms.. but can I already detect wayland at this point?
// Also: recent mesa versions should have this fixed, so maybe ignore the issue for SDL3? what about nvidia?
window = SDL_CreateWindowWithProperties(props);
SDL_DestroyProperties(props);
if (window == NULL) {
common->Warning("Couldn't set GL mode %d/%d/%d with %dx MSAA: %s",
channelcolorbits, tdepthbits, tstencilbits, parms.multiSamples, SDL_GetError());
// before trying to reduce color channel size or whatever, first try reducing MSAA, if possible
if (multisamples > 1) {
multisamples = (multisamples <= 2) ? 0 : (multisamples/2);
// using goto because enhancing that logic which reduces attributes
// based on i (so it'd first try reducing MSAA) would be too painful
goto try_again;
}
continue;
} else {
// creating the window succeeded, so adjust r_multiSamples to the value that was actually used
parms.multiSamples = multisamples;
r_multiSamples.SetInteger(multisamples);
}
// handle exclusive fullscreen mode
// TODO: just call GLimp_SetScreenParms() ?
if (parms.fullScreen && !parms.fullScreenDesktop) {
SDL_DisplayID displayID = SDL_GetDisplayForWindow( window );
SDL_DisplayMode mode = {};
if ( SDL_GetClosestFullscreenDisplayMode(displayID, parms.width, parms.height,
parms.displayHz, true, &mode) )
{
if ( ! SDL_SetWindowFullscreenMode(window, &mode) ) {
common->Warning("Can't set window fullscreen mode: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
window = NULL;
return false; // trying other color depth etc is unlikely to help with this issue
}
if ( ! SDL_SetWindowFullscreen(window, true) ) {
common->Warning("Can't switch window to fullscreen mode: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
window = NULL;
return false; // trying other color depth etc is unlikely to help with this issue
}
if ( ! SDL_SyncWindow(window) ) {
common->Warning("SDL_SyncWindow() failed: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
window = NULL;
return false; // trying other color depth etc is unlikely to help with this issue
}
} else {
common->Warning("Can't get display mode: %s\n", SDL_GetError());
SDL_DestroyWindow(window);
window = NULL;
return false; // trying other color depth etc is unlikely to help with this issue
}
}
#else // SDL2
window = SDL_CreateWindow(ENGINE_VERSION,
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(displayIndex),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay),
SDL_WINDOWPOS_UNDEFINED_DISPLAY(selectedDisplay),
parms.width, parms.height, flags);
if (!window) {
@ -364,8 +500,8 @@ try_again:
common->Warning("Current display mode isn't requested display mode\n");
common->Warning("Likely SDL bug #4700, trying to work around it..\n");
int dIdx = SDL_GetWindowDisplayIndex(window);
if(dIdx != displayIndex) {
common->Warning("Window's display index is %d, but we wanted %d!\n", dIdx, displayIndex);
if(dIdx != selectedDisplay) {
common->Warning("Window's display index is %d, but we wanted %d!\n", dIdx, selectedDisplay);
}
/* Mkay, try to hack around that. */
@ -413,6 +549,7 @@ try_again:
common->Warning("Now we have the requested resolution (%d x %d)\n", parms.width, parms.height);
}
}
#endif // SDL2
context = SDL_GL_CreateContext(window);
@ -424,7 +561,8 @@ try_again:
SetSDLIcon(); // for SDL2 this must be done after creating the window
glConfig.isFullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN;
// TODO: also check for fullscreen-desktop?
glConfig.isFullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) != 0;
const char* fsStr = glConfig.isFullscreen ? "fullscreen " : "";
if ( (int)glConfig.winWidth != glConfig.vidWidth ) {
common->Printf( "Got a HighDPI %swindow with physical resolution %d x %d and virtual resolution %g x %g\n",
@ -432,7 +570,7 @@ try_again:
} else {
common->Printf( "Got a %swindow with resolution %g x %g\n", fsStr, glConfig.winWidth, glConfig.winHeight );
}
#else
#else // SDL1.2 window creation
SDL_WM_SetCaption(ENGINE_VERSION, ENGINE_VERSION);
SetSDLIcon(); // for SDL1.2 this must be done before creating the window
@ -654,6 +792,9 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
}
SDL_RestoreWindow( window ); // make sure we're not maximized, then setting the size wouldn't work
SDL_SetWindowSize( window, parms.width, parms.height );
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_SyncWindow( window );
#endif
} else { // we want some kind of fullscreen mode
// it's probably safest to first switch to windowed mode
@ -661,6 +802,60 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
SDL_SetWindowFullscreen( window, 0 );
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
if ( wantFullscreenDesktop ) {
SDL_SetWindowFullscreenMode( window, NULL ); // setting it to NULL enables fullscreen desktop mode
SDL_SetWindowFullscreen( window, true );
// TODO: check return values
if ( ! SDL_SyncWindow( window ) ) {
common->Warning( "SDL_SyncWindow() failed: %s\n", SDL_GetError() );
//TODO: probably not SDL_DestroyWindow( window );
//window = NULL;
return false;
}
} else { // want real fullscreen
SDL_DisplayID displayID = SDL_GetDisplayForWindow( window );
SDL_DisplayMode mode = {};
if ( SDL_GetClosestFullscreenDisplayMode( displayID, parms.width, parms.height,
parms.displayHz, true, &mode ) )
{
if ( ! SDL_SetWindowFullscreenMode( window, &mode ) ) {
common->Warning( "Can't set window fullscreen mode: %s\n", SDL_GetError() );
//TODO: probably not SDL_DestroyWindow( window );
//window = NULL;
return false;
}
if ( ! SDL_SetWindowFullscreen( window, true ) ) {
common->Warning( "Can't switch window to fullscreen mode: %s\n", SDL_GetError() );
//TODO: probably not SDL_DestroyWindow( window );
//window = NULL;
return false;
}
if ( ! SDL_SyncWindow( window ) ) {
common->Warning( "SDL_SyncWindow() failed: %s\n", SDL_GetError() );
//TODO: probably not SDL_DestroyWindow( window );
//window = NULL;
return false;
}
} else {
if ( parms.displayHz != 0 ) {
common->Warning( "Can't get display mode for %d x %d @ %dHz: %s\n", parms.width,
parms.height, parms.displayHz, SDL_GetError() );
} else {
common->Warning( "Can't get display mode for %d x %d: %s\n", parms.width,
parms.height, SDL_GetError() );
}
//TODO: probably not SDL_DestroyWindow( window );
//window = NULL;
return false;
}
}
#else // SDL2
if ( wantFullscreenDesktop ) {
if ( SDL_SetWindowFullscreen( window, SDL_WINDOW_FULLSCREEN_DESKTOP ) != 0 ) {
common->Warning( "GLimp_SetScreenParms(): Couldn't switch to fullscreen desktop mode, SDL error: %s\n", SDL_GetError() );
@ -703,6 +898,7 @@ bool GLimp_SetScreenParms(glimpParms_t parms) {
return false;
}
}
#endif // SDL2
}
glConfig.isFullscreen = (SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN) != 0;
@ -732,10 +928,23 @@ glimpParms_t GLimp_GetCurState()
}
ret.multiSamples = curMultiSamples;
Uint32 winFlags = SDL_GetWindowFlags( window );
My_SDL_WindowFlags winFlags = SDL_GetWindowFlags( window );
ret.fullScreen = (winFlags & SDL_WINDOW_FULLSCREEN) != 0;
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (ret.fullScreen) {
const SDL_DisplayMode* fullscreenMode = SDL_GetWindowFullscreenMode( window );
if (fullscreenMode != NULL) {
ret.width = fullscreenMode->w;
ret.height = fullscreenMode->h;
ret.displayHz = fullscreenMode->refresh_rate;
} else {
// SDL_WINDOW_FULLSCREEN is set, but SDL_GetWindowFullscreenMode() returns NULL
// => fullscreen desktop mode
ret.fullScreenDesktop = true;
}
}
#else // SDL2
ret.fullScreenDesktop = (winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
if ( ret.fullScreen && !ret.fullScreenDesktop ) { // I think SDL_GetWindowDisplayMode() is only for "real" fullscreen?
SDL_DisplayMode real_mode = {};
if ( SDL_GetWindowDisplayMode( window, &real_mode ) == 0 ) {
@ -746,7 +955,9 @@ glimpParms_t GLimp_GetCurState()
common->Warning( "GLimp_GetCurState(): Can't get display mode: %s\n", SDL_GetError() );
}
}
if ( ret.width == 0 && ret.height == 0 ) { // windowed mode or SDL_GetWindowDisplayMode() failed
#endif
if ( ret.width == 0 && ret.height == 0 ) { // windowed mode, fullscreen-desktop mode or SDL_GetWindowDisplayMode() failed
SDL_GetWindowSize( window, &ret.width, &ret.height );
}
@ -797,11 +1008,14 @@ void GLimp_SwapBuffers() {
#endif
}
// SDL3 doesn't support hardware gamma
#if ! SDL_VERSION_ATLEAST(3, 0, 0)
static bool gammaOrigError = false;
static bool gammaOrigSet = false;
static unsigned short gammaOrigRed[256];
static unsigned short gammaOrigGreen[256];
static unsigned short gammaOrigBlue[256];
#endif
/*
=================
@ -809,6 +1023,12 @@ GLimp_SetGamma
=================
*/
void GLimp_SetGamma(unsigned short red[256], unsigned short green[256], unsigned short blue[256]) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
if ( ! r_gammaInShader.GetBool() ) {
common->Warning( "This build of dhewm3 uses SDL3, which does not support hardware gamma." );
common->Warning( "If you want to adjust gamma or brightness, enable r_gammaInShader" );
}
#else // SDL2 and SDL1.2
if (!window) {
common->Warning("GLimp_SetGamma called without window");
return;
@ -833,6 +1053,7 @@ void GLimp_SetGamma(unsigned short red[256], unsigned short green[256], unsigned
if (SDL_SetGammaRamp(red, green, blue))
#endif
common->Warning("Couldn't set gamma ramp: %s", SDL_GetError());
#endif // SDL2 and SDL1.2
}
/*
@ -843,6 +1064,7 @@ Restore original system gamma setting
=================
*/
void GLimp_ResetGamma() {
#if ! SDL_VERSION_ATLEAST(3, 0, 0) // only for SDL2 and SDL1.2
if( gammaOrigError ) {
common->Warning( "Can't reset hardware gamma because getting the Gamma Ramp at startup failed!\n" );
common->Warning( "You might have to restart the game for gamma/brightness in shaders to work properly.\n" );
@ -850,12 +1072,13 @@ void GLimp_ResetGamma() {
}
if( gammaOrigSet ) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetWindowGammaRamp( window, gammaOrigRed, gammaOrigGreen, gammaOrigBlue );
#else
#else
SDL_SetGammaRamp( gammaOrigRed, gammaOrigGreen, gammaOrigBlue );
#endif
#endif
}
#endif // ! SDL_VERSION_ATLEAST(3, 0, 0)
}
@ -893,8 +1116,21 @@ void GLimp_GrabInput(int flags) {
common->Warning("GLimp_GrabInput called without window");
return;
}
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(3, 0, 0)
if (flags & GRAB_HIDECURSOR) {
SDL_HideCursor();
} else {
SDL_ShowCursor();
}
SDL_SetWindowRelativeMouseMode( window, (flags & GRAB_RELATIVEMOUSE) != 0 );
if (flags & GRAB_GRABMOUSE) {
SDL_SetWindowMouseGrab( window, true );
SDL_SetWindowKeyboardGrab( window, in_grabKeyboard.GetBool() );
} else {
SDL_SetWindowMouseGrab( window, false );
SDL_SetWindowKeyboardGrab( window, false );
}
#elif SDL_VERSION_ATLEAST(2, 0, 0)
SDL_ShowCursor( (flags & GRAB_HIDECURSOR) ? SDL_DISABLE : SDL_ENABLE );
SDL_SetRelativeMouseMode( (flags & GRAB_RELATIVEMOUSE) ? SDL_TRUE : SDL_FALSE );
SDL_SetWindowGrab( window, (flags & GRAB_GRABMOUSE) ? SDL_TRUE : SDL_FALSE );
@ -909,7 +1145,11 @@ void GLimp_GrabInput(int flags) {
bool GLimp_SetSwapInterval( int swapInterval )
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
#if SDL_VERSION_ATLEAST(3, 0, 0)
if ( ! SDL_GL_SetSwapInterval( swapInterval ) ) {
#elif SDL_VERSION_ATLEAST(2, 0, 0)
if ( SDL_GL_SetSwapInterval( swapInterval ) < 0 ) {
#endif
common->Warning( "SDL_GL_SetSwapInterval( %d ) not supported", swapInterval );
return false;
}
@ -922,7 +1162,10 @@ bool GLimp_SetSwapInterval( int swapInterval )
bool GLimp_SetWindowResizable( bool enableResizable )
{
#if SDL_VERSION_ATLEAST(2, 0, 5)
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_SetWindowResizable( window, enableResizable );
return true;
#elif SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetWindowResizable( window, (SDL_bool)enableResizable );
return true;
#else
@ -934,7 +1177,18 @@ bool GLimp_SetWindowResizable( bool enableResizable )
void GLimp_UpdateWindowSize()
{
#if SDL_VERSION_ATLEAST(2, 0, 0)
Uint32 winFlags = SDL_GetWindowFlags( window );
My_SDL_WindowFlags winFlags = SDL_GetWindowFlags( window );
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_GetWindowSizeInPixels( window, &glConfig.vidWidth, &glConfig.vidHeight );
const SDL_DisplayMode* fullscreenMode = SDL_GetWindowFullscreenMode( window );
if ( (winFlags & SDL_WINDOW_FULLSCREEN) != 0 && fullscreenMode != NULL) {
glConfig.winWidth = fullscreenMode->w;
glConfig.winHeight = fullscreenMode->h;
}
#else // SDL2
SDL_GL_GetDrawableSize( window, &glConfig.vidWidth, &glConfig.vidHeight );
if ( (winFlags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN ) {
// real fullscreen mode => must use SDL_GetWindowDisplayMode()
// TODO: well, theoretically SDL_GetWindowSize() should work for fullscreen mode as well,
@ -951,13 +1205,13 @@ void GLimp_UpdateWindowSize()
} else {
common->Warning( "GLimp_UpdateWindowSize(): SDL_GetWindowDisplayMode() failed: %s\n", SDL_GetError() );
}
} else {
}
#endif // SDL2
else {
int ww=0, wh=0;
SDL_GetWindowSize( window, &ww, &wh );
glConfig.winWidth = ww;
glConfig.winHeight = wh;
}
SDL_GL_GetDrawableSize( window, &glConfig.vidWidth, &glConfig.vidHeight );
#endif
}

View file

@ -32,7 +32,7 @@ If you have questions concerning this license or the applicable additional terms
#include <sys/types.h>
#include <fcntl.h>
#include <SDL_main.h>
//#include <SDL_main.h> - not needed, dhewm3 doesn't currently use SDL's SDL_main
#include "sys/platform.h"
#include "framework/Licensee.h"

View file

@ -49,7 +49,13 @@ If you have questions concerning this license or the applicable additional terms
#include "sys/posix/posix_public.h"
#include <SDL.h> // clipboard
// SDL.h for clipboard:
#ifdef D3_SDL3
#include <SDL3/SDL.h>
#else // SDL1.2 or SDL2
#include <SDL.h>
#endif
#define COMMAND_HISTORY 64

View file

@ -1,7 +1,20 @@
#define IMGUI_DEFINE_MATH_OPERATORS
#include <SDL.h>
#ifdef D3_SDL3
#include <SDL3/SDL.h>
// compat with SDL2
#define SDL_TEXTINPUT SDL_EVENT_TEXT_INPUT
#define SDL_CONTROLLERAXISMOTION SDL_EVENT_GAMEPAD_AXIS_MOTION
#define SDL_CONTROLLERBUTTONDOWN SDL_EVENT_GAMEPAD_BUTTON_DOWN
#define SDL_MOUSEBUTTONDOWN SDL_EVENT_MOUSE_BUTTON_DOWN
#define SDL_MOUSEMOTION SDL_EVENT_MOUSE_MOTION
#define SDL_MOUSEWHEEL SDL_EVENT_MOUSE_WHEEL
#define SDL_KEYDOWN SDL_EVENT_KEY_DOWN
#else // SDL2
#include <SDL.h>
#endif
#include "sys_imgui.h"
@ -13,7 +26,20 @@ typedef char* (*MY_XGETDEFAULTFUN)(Display*, const char*, const char*);
#endif
#include "../libs/imgui/backends/imgui_impl_opengl2.h"
#include "../libs/imgui/backends/imgui_impl_sdl2.h"
#if SDL_VERSION_ATLEAST(3, 0, 0)
#include "../libs/imgui/backends/imgui_impl_sdl3.h"
#define ImGui_ImplSDLx_InitForOpenGL ImGui_ImplSDL3_InitForOpenGL
#define ImGui_ImplSDLx_Shutdown ImGui_ImplSDL3_Shutdown
#define ImGui_ImplSDLx_NewFrame ImGui_ImplSDL3_NewFrame
#define ImGui_ImplSDLx_ProcessEvent ImGui_ImplSDL3_ProcessEvent
#else
#include "../libs/imgui/backends/imgui_impl_sdl2.h"
#define ImGui_ImplSDLx_InitForOpenGL ImGui_ImplSDL2_InitForOpenGL
#define ImGui_ImplSDLx_Shutdown ImGui_ImplSDL2_Shutdown
#define ImGui_ImplSDLx_NewFrame ImGui_ImplSDL2_NewFrame
#define ImGui_ImplSDLx_ProcessEvent ImGui_ImplSDL2_ProcessEvent
#endif
#include "framework/Common.h"
#include "framework/KeyInput.h"
@ -145,7 +171,7 @@ void ShowWarningOverlay( const char* text )
warningOverlayStartPos = ImGui::GetMousePos();
}
#if SDL_MAJOR_VERSION == 2 // not used with SDL3
static float GetDefaultDPI()
{
SDL_Window* win = sdlWindow;
@ -185,6 +211,7 @@ static float GetDefaultDPI()
}
return dpi;
}
#endif // SDL2-only
static float GetDefaultScale()
{
@ -192,8 +219,13 @@ static float GetDefaultScale()
// in HighDPI mode, the font sizes are already scaled (to window coordinates), apparently
return 1.0f;
}
#if SDL_VERSION_ATLEAST(3, 0, 0)
float ret = SDL_GetWindowDisplayScale( sdlWindow );
#else
// TODO: different reference DPI on mac? also, doesn't work that well on my laptop..
float ret = GetDefaultDPI() / 96.0f;
#endif
ret = round(ret*2.0)*0.5; // round to .0 or .5
return ret;
}
@ -250,7 +282,7 @@ bool Init(void* _sdlWindow, void* sdlGlContext)
imgui_scale.SetModified(); // so NewFrame() will load the scaled font
// Setup Platform/Renderer backends
if ( ! ImGui_ImplSDL2_InitForOpenGL( sdlWindow, sdlGlContext ) ) {
if ( ! ImGui_ImplSDLx_InitForOpenGL( sdlWindow, sdlGlContext ) ) {
ImGui::DestroyContext( imguiCtx );
imguiCtx = NULL;
common->Warning( "Failed to initialize ImGui SDL platform backend!\n" );
@ -258,7 +290,7 @@ bool Init(void* _sdlWindow, void* sdlGlContext)
}
if ( ! ImGui_ImplOpenGL2_Init() ) {
ImGui_ImplSDL2_Shutdown();
ImGui_ImplSDLx_Shutdown();
ImGui::DestroyContext( imguiCtx );
imguiCtx = NULL;
common->Warning( "Failed to initialize ImGui OpenGL renderer backend!\n" );
@ -302,7 +334,7 @@ void Shutdown()
// TODO: only if init was successful!
ImGui_ImplOpenGL2_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui_ImplSDLx_Shutdown();
ImGui::DestroyContext( imguiCtx );
imgui_initialized = false;
}
@ -345,7 +377,7 @@ void NewFrame()
else
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
ImGui_ImplSDL2_NewFrame();
ImGui_ImplSDLx_NewFrame();
ImGui::NewFrame();
haveNewFrame = true;
@ -379,7 +411,7 @@ bool ProcessEvent(const void* sdlEvent)
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
bool imguiUsedEvent = ImGui_ImplSDL2_ProcessEvent( ev );
bool imguiUsedEvent = ImGui_ImplSDLx_ProcessEvent( ev );
if ( keybindModeEnabled ) {
// in keybind mode, all input events are passed to Doom3 so it can translate them
// to internal events and we can access and use them to create a new binding
@ -424,7 +456,11 @@ bool ProcessEvent(const void* sdlEvent)
return true;
case SDL_KEYDOWN:
//case SDL_KEYUP: NOTE: see above why key up events are passed to the engine
#if SDL_VERSION_ATLEAST(3, 0, 0)
if ( ev->key.key < SDLK_F1 || ev->key.key > SDLK_F12) {
#else
if ( ev->key.keysym.sym < SDLK_F1 || ev->key.keysym.sym > SDLK_F12) {
#endif
// F1 - F12 are passed to the engine so its shortcuts
// (like quickload or screenshot) still work
// Doom3's menu does the same

View file

@ -26,10 +26,15 @@ If you have questions concerning this license or the applicable additional terms
===========================================================================
*/
#include <SDL_version.h>
#include <SDL_mutex.h>
#include <SDL_thread.h>
#include <SDL_timer.h>
#ifdef D3_SDL3
#define SDL_oldnames_h_ // HACK: I don't want SDL.h to drag in SDL_oldnames.h to avoid all the warnings about redefined definitions
#include <SDL3/SDL.h>
#else // SDL1.2 or SDL2
#include <SDL_version.h>
#include <SDL_mutex.h>
#include <SDL_thread.h>
#include <SDL_timer.h>
#endif
#include "sys/platform.h"
#include "framework/Common.h"
@ -40,6 +45,15 @@ If you have questions concerning this license or the applicable additional terms
// SDL1.2 doesn't have SDL_threadID but uses Uint32.
// this typedef helps using the same code for SDL1.2 and SDL2
typedef Uint32 SDL_threadID;
#elif SDL_MAJOR_VERSION >= 3
// backwards-compat with SDL2
#define SDL_mutex SDL_Mutex
#define SDL_cond SDL_Condition
#define SDL_threadID SDL_ThreadID
#define SDL_CreateCond SDL_CreateCondition
#define SDL_DestroyCond SDL_DestroyCondition
#define SDL_CondWait SDL_WaitCondition
#define SDL_CondSignal SDL_SignalCondition
#endif
#if __cplusplus >= 201103
@ -159,8 +173,12 @@ Sys_EnterCriticalSection
void Sys_EnterCriticalSection(int index) {
assert(index >= 0 && index < MAX_CRITICAL_SECTIONS);
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_LockMutex(mutex[index]); // in SDL3, this returns void and can't fail
#else // SDL2 and SDL1.2
if (SDL_LockMutex(mutex[index]) != 0)
common->Error("ERROR: SDL_LockMutex failed\n");
#endif
}
/*
@ -171,8 +189,12 @@ Sys_LeaveCriticalSection
void Sys_LeaveCriticalSection(int index) {
assert(index >= 0 && index < MAX_CRITICAL_SECTIONS);
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_UnlockMutex(mutex[index]); // in SDL3, this returns void and can't fail
#else // SDL2 and SDL1.2
if (SDL_UnlockMutex(mutex[index]) != 0)
common->Error("ERROR: SDL_UnlockMutex failed\n");
#endif
}
/*
@ -204,8 +226,12 @@ void Sys_WaitForEvent(int index) {
signaled[index] = false;
} else {
waiting[index] = true;
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_CondWait(cond[index], mutex[CRITICAL_SECTION_SYS]); // in SDL3, this returns void and can't fail
#else // SDL2 and SDL1.2
if (SDL_CondWait(cond[index], mutex[CRITICAL_SECTION_SYS]) != 0)
common->Error("ERROR: SDL_CondWait failed\n");
#endif
waiting[index] = false;
}
@ -223,8 +249,12 @@ void Sys_TriggerEvent(int index) {
Sys_EnterCriticalSection(CRITICAL_SECTION_SYS);
if (waiting[index]) {
#if SDL_VERSION_ATLEAST(3, 0, 0)
SDL_CondSignal(cond[index]); // in SDL3, this returns void and can't fail
#else // SDL2 and SDL1.2
if (SDL_CondSignal(cond[index]) != 0)
common->Error("ERROR: SDL_CondSignal failed\n");
#endif
} else {
// emulate windows behaviour: if no thread is waiting, leave the signal on so next wait keeps going
signaled[index] = true;

View file

@ -41,6 +41,14 @@ If you have questions concerning this license or the applicable additional terms
const int MAX_MSGLEN = 8600;
#endif
#if SDL_VERSION_ATLEAST(3, 0, 0)
// compat with SDL2
#define SDL_CreateCond SDL_CreateCondition
#define SDL_DestroyCond SDL_DestroyCondition
#define SDL_CondWait SDL_WaitCondition
#define SDL_CondSignal SDL_SignalCondition
#endif
/*
================
rvDebuggerServer::rvDebuggerServer

View file

@ -28,7 +28,16 @@ If you have questions concerning this license or the applicable additional terms
#ifndef DEBUGGERSERVER_H_
#define DEBUGGERSERVER_H_
#include <SDL.h>
#ifdef D3_SDL3
#define SDL_oldnames_h_ // HACK: I don't want SDL.h to drag in SDL_oldnames.h to avoid all the warnings about redefined definitions
#include <SDL3/SDL.h>
// backwards-compat with SDL <= 2
#define SDL_mutex SDL_Mutex
#define SDL_cond SDL_Condition
#else // SDL1.2 or SDL2
#include <SDL.h>
#endif
#include "sys/platform.h"
#include "idlib/Str.h"
#include "DebuggerMessages.h"