From f50e61403f24ddf8458595ef3679e891a61b2630 Mon Sep 17 00:00:00 2001 From: Terence Noone Date: Wed, 22 Jul 2026 05:11:53 -0400 Subject: [PATCH] engine: Fix SDL3 support Gets SDL3 building again on macOS. The game is able to boot to the main menu and play with hlsdk-portable and HL assets. Some bugs when changing video modes. --- engine/platform/sdl3/platform_sdl3.h | 8 +++ engine/platform/sdl3/sensor_sdl3.c | 99 ++++++++++++++++++++++++++++ engine/platform/sdl3/sys_sdl3.c | 4 +- engine/platform/sdl3/vid_sdl3.c | 61 +++++++++++++++++ 4 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 engine/platform/sdl3/sensor_sdl3.c diff --git a/engine/platform/sdl3/platform_sdl3.h b/engine/platform/sdl3/platform_sdl3.h index b9b91f92..51cbcefb 100644 --- a/engine/platform/sdl3/platform_sdl3.h +++ b/engine/platform/sdl3/platform_sdl3.h @@ -28,4 +28,12 @@ GNU General Public License for more details. void SDLash_InitCursors( void ); void SDLash_FreeCursors( void ); +// +// sensor_sdl3.c +// +void SDLash_InitSensors( void ); +void SDLash_ShutdownSensors( void ); +qboolean SDLash_GyroIsAvailable( void ); +void SDLash_SensorUpdate( SDL_SensorEvent sensor ); + #endif // PLATFORM_SDL3_H diff --git a/engine/platform/sdl3/sensor_sdl3.c b/engine/platform/sdl3/sensor_sdl3.c new file mode 100644 index 00000000..4d9872c7 --- /dev/null +++ b/engine/platform/sdl3/sensor_sdl3.c @@ -0,0 +1,99 @@ +/* +sensor_sdl3.c - SDL3 sensor handling +Copyright (C) 2026 Xash3D FWGS contributors + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#include "common.h" +#include "input.h" +#include "platform_sdl3.h" + +static SDL_SensorID g_system_gyro_id = -1; +static SDL_Sensor *g_system_gyro; + +/* +============== +SDLash_InitSensors + +============== +*/ +void SDLash_InitSensors( void ) +{ + if( SDL_InitSubSystem( SDL_INIT_SENSOR ) == 0 ) + { + int num_sensors; + SDL_SensorID *sensors = SDL_GetSensors(&num_sensors); + + for( int i = 0; i < num_sensors; i++ ) + { + if( SDL_GetSensorTypeForID( i ) == SDL_SENSOR_GYRO ) + { + g_system_gyro = SDL_OpenSensor( i ); + if( g_system_gyro ) + { + g_system_gyro_id = sensors[i]; + Con_Printf( "SDL: Opened built-in gyroscope: %s\n", SDL_GetSensorName( g_system_gyro ) ); + break; + } + } + } + SDL_free(sensors); + } + else + { + Con_Reportf( S_ERROR "Failed to init SDL Sensor subsystem: %s\n", SDL_GetError() ); + } +} + +/* +============== +SDLash_ShutdownSensors + +============== +*/ +void SDLash_ShutdownSensors( void ) +{ + if( g_system_gyro ) + { + SDL_CloseSensor( g_system_gyro ); + g_system_gyro = NULL; + g_system_gyro_id = -1; + } + + SDL_QuitSubSystem( SDL_INIT_SENSOR ); +} + +/* +============== +SDLash_GyroIsAvailable + +============== +*/ +qboolean SDLash_GyroIsAvailable( void ) +{ + return ( g_system_gyro != NULL ); +} + +/* +============== +SDLash_SensorUpdate + +============== +*/ +void SDLash_SensorUpdate( SDL_SensorEvent sensor ) +{ + if( sensor.which == g_system_gyro_id ) + { + IN_GyroEvent( sensor.data ); + } +} + diff --git a/engine/platform/sdl3/sys_sdl3.c b/engine/platform/sdl3/sys_sdl3.c index bc17ef39..21256eef 100644 --- a/engine/platform/sdl3/sys_sdl3.c +++ b/engine/platform/sdl3/sys_sdl3.c @@ -90,10 +90,8 @@ static void SDLCALL SDLash_LogOutputFunction( void *userdata, int category, SDL_ } } -void SDLash_Init( const char *basedir ) +void SDLash_Init( void ) { - (void)basedir; - // TODO: initial state, to be filled from gameinfo! SDL_SetAppMetadata( XASH_ENGINE_NAME, XASH_VERSION, "su.xash.engine" ); SDL_SetAppMetadataProperty( SDL_PROP_APP_METADATA_TYPE_STRING, "game" ); diff --git a/engine/platform/sdl3/vid_sdl3.c b/engine/platform/sdl3/vid_sdl3.c index 6f5fc704..d91eea94 100644 --- a/engine/platform/sdl3/vid_sdl3.c +++ b/engine/platform/sdl3/vid_sdl3.c @@ -203,6 +203,41 @@ static qboolean VID_CreateWindow( const int input_width, const int input_height, return true; } +void VID_Info_f ( void ) +{ + Uint32 flags = SDL_GetWindowFlags( host.hWnd ); + int width, height; + int render_width, render_height; + int x, y; + + SDL_GetWindowSize( host.hWnd, &width, &height ); + SDL_GetWindowSizeInPixels( host.hWnd, &render_width, &render_height); + SDL_GetWindowPosition( host.hWnd, &x, &y ); + + Con_Printf( "Video: " S_GREEN "SDL3" S_DEFAULT "\n" ); + Con_Printf( "Video driver: " S_GREEN "%s" S_DEFAULT "\n", SDL_GetCurrentVideoDriver( )); + Con_Printf( "Window size: " S_GREEN "%dx%d" S_DEFAULT " (" S_YELLOW"real %dx%d" S_DEFAULT")\n", width, height, render_width, render_height ); + Con_Printf( "Window position: " S_GREEN "%dx%d" S_DEFAULT "\n", x, y ); + Con_Printf( "Window mode: %s" S_DEFAULT "\n", + FBitSet( flags, SDL_WINDOW_FULLSCREEN ) ? S_YELLOW "fullscreen" : + S_CYAN "windowed" ); + Con_Printf( "Window bordered: %s" S_DEFAULT "\n", FBitSet( flags, SDL_WINDOW_BORDERLESS ) ? S_RED "false" : S_GREEN "true" ); + Con_Printf( "Window resizable: %s" S_DEFAULT "\n", FBitSet( flags, SDL_WINDOW_RESIZABLE ) ? S_GREEN "true" : S_RED "false" ); + Con_Printf( "Window maximized: %s" S_DEFAULT "\n", FBitSet( flags, SDL_WINDOW_MAXIMIZED ) ? S_GREEN "true" : S_RED "false" ); + + int display_index = SDL_GetDisplayForWindow( host.hWnd ); + if( display_index >= 0 ) + Con_Printf( "Window display index: " S_GREEN "%d" S_DEFAULT "\n", display_index ); + else + Con_Printf( "Window display index: " S_RED "fail: " S_DEFAULT "%s\n", SDL_GetError( )); + + const SDL_DisplayMode *dm = SDL_GetWindowFullscreenMode( host.hWnd ); + if ( dm ) + Con_Printf( "Window display mode: " S_GREEN "%dx%d@%f" S_DEFAULT "\n", dm->w, dm->h, dm->refresh_rate ); + else + Con_Printf( "Window display mode: " S_RED "fail: " S_DEFAULT "%s\n", SDL_GetError( )); +} + static void R_InitVideoModes( void ) { SDL_DisplayID display = SDL_GetDisplayForWindow( host.hWnd ); @@ -257,6 +292,32 @@ void Platform_Minimize_f( void ) SDL_MinimizeWindow( host.hWnd ); } +platform_orientation_t Platform_GetDisplayOrientation( void ) +{ + if (host.hWnd) + { + int display_index = SDL_GetDisplayForWindow( host.hWnd ); + if( display_index >= 0 ) + { + switch( SDL_GetCurrentDisplayOrientation( display_index ) ) + { + case SDL_ORIENTATION_LANDSCAPE: + return ORIENTATION_LANDSCAPE; + case SDL_ORIENTATION_LANDSCAPE_FLIPPED: + return ORIENTATION_LANDSCAPE_FLIPPED; + case SDL_ORIENTATION_PORTRAIT: + return ORIENTATION_PORTRAIT; + case SDL_ORIENTATION_PORTRAIT_FLIPPED: + return ORIENTATION_PORTRAIT_FLIPPED; + default: + return ORIENTATION_UNKNOWN; + } + } + } + + return ORIENTATION_UNKNOWN; +} + void GL_UpdateSwapInterval( void ) { if( FBitSet( gl_vsync.flags, FCVAR_CHANGED ))