diff --git a/libs/SDL3/.editorconfig b/libs/SDL3/.editorconfig index de2d6de96..1618303cf 100644 --- a/libs/SDL3/.editorconfig +++ b/libs/SDL3/.editorconfig @@ -65,5 +65,5 @@ tab_width = 4 [{*.bat,*.rc}] end_of_line = crlf -[*.cocci]' +[*.cocci] insert_final_newline = true diff --git a/libs/SDL3/.git-hash b/libs/SDL3/.git-hash deleted file mode 100644 index 3520a2b9c..000000000 --- a/libs/SDL3/.git-hash +++ /dev/null @@ -1 +0,0 @@ -17d4f8d6990d2bd92d6a8be4b23c4dc1626fb923 diff --git a/libs/SDL3/.gitignore b/libs/SDL3/.gitignore new file mode 100644 index 000000000..3c45e91b7 --- /dev/null +++ b/libs/SDL3/.gitignore @@ -0,0 +1,166 @@ +build/ +build-*/ +!build-scripts/ +buildbot/ +/VERSION.txt +__pycache__ + +*.so +*.so.* +*.dll +*.exe +*.o +*.obj +*.res +*.lib +*.a +*.la +*.dSYM +*,e1f +*,ff8 +*.lnk +*.err +*.exp +*.map +*.orig +*~ +*.swp +*.tmp +*.rej + +# for CMake +CMakeFiles/ +CMakeCache.txt +cmake_install.cmake +cmake_uninstall.cmake +SDL3ConfigVersion.cmake +.ninja_* +*.ninja +compile_commands.json +.cache/ + +# for CLion +.idea +cmake-build-* + +# for Xcode +*.mode1* +*.perspective* +*.pbxuser +(^|/)build($|/) +.DS_Store +xcuserdata +*.xcworkspace + +# for Visual Studio Code +.vscode/ + +# for Visual C++ +.vs +Debug +Release +*.user +*.ncb +*.suo +*.sdf +VisualC/tests/gamepadmap/axis.bmp +VisualC/tests/gamepadmap/button.bmp +VisualC/tests/gamepadmap/gamepadmap.bmp +VisualC/tests/gamepadmap/gamepadmap_back.bmp +VisualC/tests/loopwave/sample.wav +VisualC/tests/testautomation/*.bmp +VisualC/tests/testgamepad/axis.bmp +VisualC/tests/testgamepad/button.bmp +VisualC/tests/testgamepad/gamepadmap.bmp +VisualC/tests/testgamepad/gamepadmap_back.bmp +VisualC/tests/testoverlay/moose.dat +VisualC/tests/testrendertarget/icon.bmp +VisualC/tests/testrendertarget/sample.bmp +VisualC/tests/testscale/icon.bmp +VisualC/tests/testscale/sample.bmp +VisualC/tests/testsprite/icon.bmp +VisualC/tests/testyuv/testyuv.bmp +VisualC-GDK/**/Layout +src/render/direct3d12/D3D12_*_One.h +src/render/direct3d12/D3D12_*_Series.h +src/gpu/d3d12/D3D12_*_One.h +src/gpu/d3d12/D3D12_*_Series.h +Directory.Build.props + +# for Android +android-project/local.properties +android-project/.gradle/ + +test/checkkeys +test/checkkeysthreads +test/gamepadmap +test/loopwave +test/loopwavequeue +test/testatomic +test/testaudiorecording +test/testaudiohotplug +test/testaudioinfo +test/testautomation +test/testbounds +test/testcustomcursor +test/testdisplayinfo +test/testdraw +test/testdrawchessboard +test/testdropfile +test/testerror +test/testevdev +test/testfile +test/testfilesystem +test/testgamepad +test/testgeometry +test/testgesture +test/testgl +test/testgles +test/testgles2 +test/testhaptic +test/testhittesting +test/testhotplug +test/testiconv +test/testime +test/testintersections +test/testjoystick +test/testkeys +test/testloadso +test/testlocale +test/testlock +test/testmessage +test/testmouse +test/testmultiaudio +test/testnative +test/testoverlay +test/testplatform +test/testpower +test/testqsort +test/testrelative +test/testrendercopyex +test/testrendertarget +test/testresample +test/testrumble +test/testscale +test/testsem +test/testsensor +test/testshader +test/testshape +test/testsprite +test/testspriteminimal +test/teststreaming +test/testsurround +test/testthread +test/testtimer +test/testurl +test/testver +test/testviewport +test/testvulkan +test/testwm +test/testyuv +test/torturethread + +# for Doxygen +docs/output +SDL.tag +doxygen_warn.txt diff --git a/libs/SDL3/.wikiheaders-options b/libs/SDL3/.wikiheaders-options index d8df030fe..720a9de24 100644 --- a/libs/SDL3/.wikiheaders-options +++ b/libs/SDL3/.wikiheaders-options @@ -1,19 +1,23 @@ -projectfullname = SDL +projectfullname = Simple Directmedia Layer projectshortname = SDL incsubdir = include/SDL3 wikisubdir = readmesubdir = docs -apiprefixregex = (SDL_|SDLK_|KMOD_|AUDIO_) +apiprefixregex = (SDL_|SDLK_) mainincludefname = SDL3/SDL.h versionfname = include/SDL3/SDL_version.h versionmajorregex = \A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z versionminorregex = \A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z -versionpatchregex = \A\#define\s+SDL_PATCHLEVEL\s+(\d+)\Z +versionmicroregex = \A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z selectheaderregex = \ASDL.*?\.h\Z projecturl = https://libsdl.org/ wikiurl = https://wiki.libsdl.org bugreporturl = https://github.com/libsdl-org/sdlwiki/issues/new warn_about_missing = 0 -wikipreamble = (This is the documentation for SDL3, which is under heavy development and the API is changing! [SDL2](https://wiki.libsdl.org/SDL2/) is the current stable version!) -wikiheaderfiletext = Defined in [%fname%](https://github.com/libsdl-org/SDL/blob/main/include/SDL3/%fname%), but apps should _only_ `#include `! -manpageheaderfiletext = Defined in %fname%, but apps should only #include ! +wikipreamble = (This is the documentation for SDL3, which is the current stable version. [SDL2](https://wiki.libsdl.org/SDL2/) was the previous version!) +wikiheaderfiletext = Defined in [](https://github.com/libsdl-org/SDL/blob/main/include/SDL3/%fname%) +manpageheaderfiletext = Defined in SDL3/%fname% + +# All SDL_test_* headers become undefined categories, everything else just converts like SDL_audio.h -> Audio +# A handful of others we fix up in the header itself with /* WIKI CATEGORY: x */ comments. +headercategoryeval = s/\ASDL_test_?.*?\.h\Z//; s/\ASDL_?(.*?)\.h\Z/$1/; ucfirst(); diff --git a/libs/SDL3/Android.mk b/libs/SDL3/Android.mk index a60a0d363..b352cb318 100644 --- a/libs/SDL3/Android.mk +++ b/libs/SDL3/Android.mk @@ -10,9 +10,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := SDL3 -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/include/build_config $(LOCAL_PATH)/src -LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_SRC_FILES := \ $(subst $(LOCAL_PATH)/,, \ @@ -30,16 +30,23 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/core/*.c) \ $(wildcard $(LOCAL_PATH)/src/core/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \ + $(LOCAL_PATH)/src/dialog/SDL_dialog_utils.c \ + $(LOCAL_PATH)/src/dialog/android/SDL_androiddialog.c \ $(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \ $(wildcard $(LOCAL_PATH)/src/events/*.c) \ $(wildcard $(LOCAL_PATH)/src/file/*.c) \ + $(wildcard $(LOCAL_PATH)/src/gpu/*.c) \ + $(wildcard $(LOCAL_PATH)/src/gpu/vulkan/*.c) \ $(wildcard $(LOCAL_PATH)/src/haptic/*.c) \ $(wildcard $(LOCAL_PATH)/src/haptic/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/hidapi/*.c) \ $(wildcard $(LOCAL_PATH)/src/hidapi/android/*.cpp) \ $(wildcard $(LOCAL_PATH)/src/joystick/*.c) \ $(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/joystick/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/joystick/hidapi/*.c) \ + $(wildcard $(LOCAL_PATH)/src/joystick/steam/*.c) \ $(wildcard $(LOCAL_PATH)/src/joystick/virtual/*.c) \ $(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \ $(wildcard $(LOCAL_PATH)/src/locale/*.c) \ @@ -50,14 +57,19 @@ LOCAL_SRC_FILES := \ $(wildcard $(LOCAL_PATH)/src/misc/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/power/*.c) \ $(wildcard $(LOCAL_PATH)/src/power/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/process/*.c) \ + $(wildcard $(LOCAL_PATH)/src/process/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/filesystem/*.c) \ $(wildcard $(LOCAL_PATH)/src/filesystem/android/*.c) \ $(wildcard $(LOCAL_PATH)/src/filesystem/posix/*.c) \ $(wildcard $(LOCAL_PATH)/src/sensor/*.c) \ $(wildcard $(LOCAL_PATH)/src/sensor/android/*.c) \ + $(wildcard $(LOCAL_PATH)/src/sensor/dummy/*.c) \ $(wildcard $(LOCAL_PATH)/src/render/*.c) \ $(wildcard $(LOCAL_PATH)/src/render/*/*.c) \ $(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \ + $(wildcard $(LOCAL_PATH)/src/storage/*.c) \ + $(wildcard $(LOCAL_PATH)/src/storage/generic/*.c) \ $(wildcard $(LOCAL_PATH)/src/thread/*.c) \ $(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \ $(wildcard $(LOCAL_PATH)/src/time/*.c) \ @@ -89,7 +101,7 @@ LOCAL_CXXFLAGS += -std=gnu++11 LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid -LOCAL_LDFLAGS := -Wl,--no-undefined -Wl,--version-script=$(LOCAL_PATH)/src/dynapi/SDL_dynapi.sym +LOCAL_LDFLAGS := -Wl,--no-undefined -Wl,--no-undefined-version -Wl,--version-script=$(LOCAL_PATH)/src/dynapi/SDL_dynapi.sym ifeq ($(NDK_DEBUG),1) cmd-strip := diff --git a/libs/SDL3/BUGS.txt b/libs/SDL3/BUGS.txt index eb973d5e6..b1463e777 100644 --- a/libs/SDL3/BUGS.txt +++ b/libs/SDL3/BUGS.txt @@ -1,16 +1,16 @@ - -Bugs are now managed in the SDL issue tracker, here: - - https://github.com/libsdl-org/SDL/issues - -You may report bugs there, and search to see if a given issue has already - been reported, discussed, and maybe even fixed. - - -You may also find help at the SDL forums/mailing list: - - https://discourse.libsdl.org/ - -Bug reports are welcome here, but we really appreciate if you use the issue - tracker, as bugs discussed on the mailing list may be forgotten or missed. - + +Bugs are now managed in the SDL issue tracker, here: + + https://github.com/libsdl-org/SDL/issues + +You may report bugs there, and search to see if a given issue has already + been reported, discussed, and maybe even fixed. + + +You may also find help at the SDL forums/mailing list: + + https://discourse.libsdl.org/ + +Bug reports are welcome here, but we really appreciate if you use the issue + tracker, as bugs discussed on the mailing list may be forgotten or missed. + diff --git a/libs/SDL3/CMakeLists.txt b/libs/SDL3/CMakeLists.txt index c0f065c3f..24c03d0a7 100644 --- a/libs/SDL3/CMakeLists.txt +++ b/libs/SDL3/CMakeLists.txt @@ -4,11 +4,8 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) message(FATAL_ERROR "Prevented in-tree build. Please create a build directory outside of the SDL source code and run \"cmake -S ${CMAKE_SOURCE_DIR} -B .\" from there") endif() -# MSVC runtime library flags are selected by an abstraction. -set(CMAKE_POLICY_DEFAULT_CMP0091 NEW) - # See docs/release_checklist.md -project(SDL3 LANGUAGES C VERSION "3.1.1") +project(SDL3 LANGUAGES C VERSION "3.1.3") if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(SDL3_SUBPROJECT OFF) @@ -48,15 +45,17 @@ list(APPEND CMAKE_MODULE_PATH "${SDL3_SOURCE_DIR}/cmake") include("${SDL3_SOURCE_DIR}/cmake/macros.cmake") include("${SDL3_SOURCE_DIR}/cmake/sdlchecks.cmake") include("${SDL3_SOURCE_DIR}/cmake/sdlcompilers.cmake") +include("${SDL3_SOURCE_DIR}/cmake/sdlcpu.cmake") include("${SDL3_SOURCE_DIR}/cmake/sdlmanpages.cmake") include("${SDL3_SOURCE_DIR}/cmake/sdlplatform.cmake") include("${SDL3_SOURCE_DIR}/cmake/sdltargets.cmake") -include("${SDL3_SOURCE_DIR}/cmake/CheckCPUArchitecture.cmake") include("${SDL3_SOURCE_DIR}/cmake/GetGitRevisionDescription.cmake") include("${SDL3_SOURCE_DIR}/cmake/3rdparty.cmake") +include("${SDL3_SOURCE_DIR}/cmake/PreseedMSVCCache.cmake") +include("${SDL3_SOURCE_DIR}/cmake/PreseedEmscriptenCache.cmake") SDL_DetectCompiler() -SDL_DetectCPUArchitecture() +SDL_DetectTargetCPUArchitectures(SDL_CPUS) # Increment this if there is an incompatible change - but if that happens, # we should rename the library from SDL3 to SDL4, at which point this would @@ -133,7 +132,7 @@ endif() # The hidraw support doesn't catch Xbox, PS4 and Nintendo controllers, # so we'll just use libusb when it's available. libusb does not support iOS, # so we default to yes on iOS. -if(IOS OR TVOS OR VISIONOS OR ANDROID) +if(IOS OR TVOS OR VISIONOS OR WATCHOS OR ANDROID) set(SDL_HIDAPI_LIBUSB_AVAILABLE FALSE) else() set(SDL_HIDAPI_LIBUSB_AVAILABLE TRUE) @@ -152,25 +151,11 @@ endif() # Default option knobs set(SDL_LIBC_DEFAULT ON) set(SDL_SYSTEM_ICONV_DEFAULT ON) -if(WINDOWS OR IOS OR TVOS OR VISIONOS) +if(WINDOWS OR MACOS OR IOS OR TVOS OR VISIONOS OR WATCHOS) set(SDL_SYSTEM_ICONV_DEFAULT OFF) endif() if(MSVC) - dep_option(SDL_STATIC_VCRT "Use /MT for static VC runtimes" ON "NOT WINDOWS_STORE" OFF) - if(SDL_STATIC_VCRT) - if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY) - set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - endif() - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) - if(${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif() - endforeach() - endif() - if(NOT SDL_LIBC) # Make sure /RTC1 is disabled, otherwise it will use functions from the CRT foreach(flag_var @@ -248,6 +233,7 @@ endmacro() define_sdl_subsystem(Audio) define_sdl_subsystem(Video) +define_sdl_subsystem(GPU DEPS SDL_VIDEO) define_sdl_subsystem(Render DEPS SDL_VIDEO) define_sdl_subsystem(Camera DEPS SDL_VIDEO) define_sdl_subsystem(Joystick) @@ -268,11 +254,17 @@ else() set(SDL_RPATH_DEFAULT OFF) endif() +set(SDL_PRESEED_AVAILABLE OFF) +if(COMMAND SDL_Preseed_CMakeCache) + set(SDL_PRESEED_AVAILABLE ON) +endif() + # Allow some projects to be built conditionally. set_option(SDL_DISABLE_INSTALL "Disable installation of SDL3" ${SDL3_SUBPROJECT}) cmake_dependent_option(SDL_DISABLE_INSTALL_CPACK "Create binary SDL3 archive using CPack" ${SDL3_SUBPROJECT} "NOT SDL_DISABLE_INSTALL" ON) -cmake_dependent_option(SDL_DISABLE_INSTALL_DOCS "Install docs for SDL3" ${SDL3_SUBPROJECT} "NOT SDL_DISABLE_INSTALL;NOT SDL_FRAMEWORK" ON) +cmake_dependent_option(SDL_DISABLE_INSTALL_DOCS "Install docs for SDL3" ON "NOT SDL_DISABLE_INSTALL;NOT SDL_FRAMEWORK" ON) set_option(SDL_DISABLE_UNINSTALL "Disable uninstallation of SDL3" OFF) +cmake_dependent_option(SDL_PRESEED "Preseed CMake cache to speed up configuration" ON "${SDL_PRESEED_AVAILABLE}" OFF) cmake_dependent_option(SDL_DISABLE_ANDROID_JAR "Disable creation of SDL3.jar" ${SDL3_SUBPROJECT} "ANDROID" ON) @@ -290,7 +282,6 @@ dep_option(SDL_MMX "Use MMX assembly routines" ON "SDL_ASSEMBLY; dep_option(SDL_ALTIVEC "Use Altivec assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_POWERPC32 OR SDL_CPU_POWERPC64" OFF) dep_option(SDL_ARMSIMD "Use SIMD assembly blitters on ARM" OFF "SDL_ASSEMBLY;SDL_CPU_ARM32" OFF) dep_option(SDL_ARMNEON "Use NEON assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF) -dep_option(SDL_ARMNEON_BLITTERS "Use NEON assembly blitters on ARM32" OFF "SDL_VIDEO;SDL_ASSEMBLY;SDL_ARMNEON;SDL_CPU_ARM32" OFF) dep_option(SDL_LSX "Use LSX assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_LOONGARCH64" OFF) dep_option(SDL_LASX "Use LASX assembly routines" ON "SDL_ASSEMBLY;SDL_CPU_LOONGARCH64" OFF) @@ -303,8 +294,8 @@ dep_option(SDL_DISKAUDIO "Support the disk writer audio driver" ON "SD dep_option(SDL_DUMMYAUDIO "Support the dummy audio driver" ON "SDL_AUDIO" OFF) dep_option(SDL_DUMMYVIDEO "Use dummy video driver" ON "SDL_VIDEO" OFF) dep_option(SDL_IBUS "Enable IBus support" ON "${UNIX_SYS}" OFF) -dep_option(SDL_OPENGL "Include OpenGL support" ON "SDL_VIDEO;NOT VISIONOS" OFF) -dep_option(SDL_OPENGLES "Include OpenGL ES support" ON "SDL_VIDEO;NOT VISIONOS" OFF) +dep_option(SDL_OPENGL "Include OpenGL support" ON "SDL_VIDEO;NOT IOS;NOT VISIONOS;NOT TVOS;NOT WATCHOS" OFF) +dep_option(SDL_OPENGLES "Include OpenGL ES support" ON "SDL_VIDEO;NOT VISIONOS;NOT TVOS;NOT WATCHOS" OFF) set_option(SDL_PTHREADS "Use POSIX threads for multi-threading" ${SDL_PTHREADS_DEFAULT}) dep_option(SDL_PTHREADS_SEM "Use pthread semaphores" ON "SDL_PTHREADS" OFF) dep_option(SDL_OSS "Support the OSS audio API" ${SDL_OSS_DEFAULT} "UNIX_SYS OR RISCOS;SDL_AUDIO" OFF) @@ -337,11 +328,14 @@ dep_option(SDL_COCOA "Use Cocoa video driver" ON "APPLE" OFF) dep_option(SDL_DIRECTX "Use DirectX for Windows audio/video" ON "SDL_AUDIO OR SDL_VIDEO;WINDOWS" OFF) dep_option(SDL_XINPUT "Use Xinput for Windows" ON "WINDOWS" OFF) dep_option(SDL_WASAPI "Use the Windows WASAPI audio driver" ON "WINDOWS;SDL_AUDIO" OFF) -dep_option(SDL_RENDER_D3D "Enable the Direct3D render driver" ON "SDL_RENDER" OFF) +dep_option(SDL_RENDER_D3D "Enable the Direct3D 9 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF) +dep_option(SDL_RENDER_D3D11 "Enable the Direct3D 11 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF) +dep_option(SDL_RENDER_D3D12 "Enable the Direct3D 12 render driver" ON "SDL_RENDER;SDL_DIRECTX" OFF) dep_option(SDL_RENDER_METAL "Enable the Metal render driver" ON "SDL_RENDER;${APPLE}" OFF) +dep_option(SDL_RENDER_GPU "Enable the SDL_GPU render driver" ON "SDL_RENDER;SDL_GPU" OFF) dep_option(SDL_VIVANTE "Use Vivante EGL video driver" ON "${UNIX_SYS};SDL_CPU_ARM32" OFF) -dep_option(SDL_VULKAN "Enable Vulkan support" ON "SDL_VIDEO;ANDROID OR APPLE OR LINUX OR WINDOWS" OFF) -dep_option(SDL_RENDER_VULKAN "Enable the Vulkan render driver" ON "SDL_RENDER;SDL_VULKAN;ANDROID OR APPLE OR LINUX OR WINDOWS" OFF) +dep_option(SDL_VULKAN "Enable Vulkan support" ON "SDL_VIDEO;ANDROID OR APPLE OR LINUX OR FREEBSD OR WINDOWS" OFF) +dep_option(SDL_RENDER_VULKAN "Enable the Vulkan render driver" ON "SDL_RENDER;SDL_VULKAN" OFF) dep_option(SDL_METAL "Enable Metal support" ON "APPLE" OFF) dep_option(SDL_KMSDRM "Use KMS DRM video driver" ${UNIX_SYS} "SDL_VIDEO" OFF) dep_option(SDL_KMSDRM_SHARED "Dynamically load KMS DRM support" ON "SDL_KMSDRM" OFF) @@ -358,6 +352,7 @@ set_option(SDL_LIBUDEV "Enable libudev support" ON) set_option(SDL_ASAN "Use AddressSanitizer to detect memory errors" OFF) set_option(SDL_CCACHE "Use Ccache to speed up build" OFF) set_option(SDL_CLANG_TIDY "Run clang-tidy static analysis" OFF) +set_option(SDL_GPU_DXVK "Build SDL_GPU with DXVK support" OFF) set(SDL_VENDOR_INFO "" CACHE STRING "Vendor name and/or version to add to SDL_REVISION") @@ -365,23 +360,27 @@ cmake_dependent_option(SDL_SHARED "Build a shared version of the library" ${SDL_ cmake_dependent_option(SDL_STATIC "Build a static version of the library" ${SDL_STATIC_DEFAULT} ${SDL_STATIC_AVAILABLE} OFF) option(SDL_TEST_LIBRARY "Build the SDL3_test library" ON) -dep_option(SDL_STATIC_PIC "Static version of the library should be built with Position Independent Code" "${CMAKE_POSITION_INDEPENDENT_CODE}" "SDL_STATIC" OFF) dep_option(SDL_TESTS "Build the test directory" OFF SDL_TEST_LIBRARY OFF) -dep_option(SDL_INSTALL_TESTS "Install test-cases" OFF "NOT SDL_DISABLE_INSTALL;NOT SDL_FRAMEWORK;NOT WINDOWS_STORE" OFF) +dep_option(SDL_INSTALL_TESTS "Install test-cases" OFF "NOT SDL_DISABLE_INSTALL;NOT SDL_FRAMEWORK" OFF) dep_option(SDL_TESTS_LINK_SHARED "link tests to shared SDL library" "${SDL_SHARED}" "SDL_SHARED;SDL_STATIC" "${SDL_SHARED}") set(SDL_TESTS_TIMEOUT_MULTIPLIER "1" CACHE STRING "Timeout multiplier to account for really slow machines") +set_option(SDL_EXAMPLES "Build the examples directory") +dep_option(SDL_EXAMPLES_LINK_SHARED "link examples to shared SDL library" "${SDL_SHARED}" "SDL_SHARED;SDL_STATIC" "${SDL_SHARED}") + if(VITA) set_option(VIDEO_VITA_PIB "Build with PSVita piglet gles2 support" OFF) set_option(VIDEO_VITA_PVR "Build with PSVita PVR gles/gles2 support" OFF) endif() -set(HAVE_STATIC_PIC "${SDL_STATIC_PIC}") - if(NOT (SDL_SHARED OR SDL_STATIC)) message(FATAL_ERROR "SDL_SHARED and SDL_STATIC cannot both be disabled") endif() +if(SDL_PRESEED) + SDL_Preseed_CMakeCache() +endif() + if(SDL_SHARED) add_library(SDL3-shared SHARED) add_library(SDL3::SDL3-shared ALIAS SDL3-shared) @@ -429,11 +428,6 @@ if (LIBC_IS_GLIBC AND CMAKE_SIZEOF_VOID_P EQUAL 4) sdl_compile_definitions(PRIVATE "_TIME_BITS=64") endif() -if(WINDOWS_STORE) - sdl_compile_definitions(PRIVATE "SDL_BUILDING_WINRT=1") - sdl_compile_options(PRIVATE "-ZW") -endif() - check_linker_supports_version_file(HAVE_WL_VERSION_SCRIPT) if(HAVE_WL_VERSION_SCRIPT) sdl_shared_link_options("-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/dynapi/SDL_dynapi.sym") @@ -460,48 +454,17 @@ endif() sdl_compile_definitions(PRIVATE "USING_GENERATED_CONFIG_H") sdl_include_directories( PRIVATE - "${SDL3_BINARY_DIR}/include-config-$>" + "${SDL3_BINARY_DIR}/include-config-$>/build_config" "${SDL3_BINARY_DIR}/include" "${SDL3_SOURCE_DIR}/include" ) # Note: The clang toolset for Visual Studio does not support the '-idirafter' option. if(USE_GCC OR USE_INTELCC OR (USE_CLANG AND NOT MSVC_CLANG)) - sdl_compile_options(NO_EXPORT PUBLIC "$") + sdl_compile_options(NO_EXPORT PRIVATE "$") else() - sdl_include_directories(NO_EXPORT SYSTEM PUBLIC "$") + sdl_include_directories(NO_EXPORT SYSTEM PRIVATE "$") endif() -# General source files -sdl_glob_sources( - "${SDL3_SOURCE_DIR}/src/*.c" - "${SDL3_SOURCE_DIR}/src/atomic/*.c" - "${SDL3_SOURCE_DIR}/src/audio/*.c" - "${SDL3_SOURCE_DIR}/src/camera/*.c" - "${SDL3_SOURCE_DIR}/src/core/*.c" - "${SDL3_SOURCE_DIR}/src/cpuinfo/*.c" - "${SDL3_SOURCE_DIR}/src/dynapi/*.c" - "${SDL3_SOURCE_DIR}/src/events/*.c" - "${SDL3_SOURCE_DIR}/src/file/*.c" - "${SDL3_SOURCE_DIR}/src/filesystem/*.c" - "${SDL3_SOURCE_DIR}/src/joystick/*.c" - "${SDL3_SOURCE_DIR}/src/haptic/*.c" - "${SDL3_SOURCE_DIR}/src/hidapi/*.c" - "${SDL3_SOURCE_DIR}/src/libm/*.c" - "${SDL3_SOURCE_DIR}/src/locale/*.c" - "${SDL3_SOURCE_DIR}/src/main/*.c" - "${SDL3_SOURCE_DIR}/src/misc/*.c" - "${SDL3_SOURCE_DIR}/src/power/*.c" - "${SDL3_SOURCE_DIR}/src/render/*.c" - "${SDL3_SOURCE_DIR}/src/render/*/*.c" - "${SDL3_SOURCE_DIR}/src/sensor/*.c" - "${SDL3_SOURCE_DIR}/src/stdlib/*.c" - "${SDL3_SOURCE_DIR}/src/storage/*.c" - "${SDL3_SOURCE_DIR}/src/thread/*.c" - "${SDL3_SOURCE_DIR}/src/time/*.c" - "${SDL3_SOURCE_DIR}/src/timer/*.c" - "${SDL3_SOURCE_DIR}/src/video/*.c" - "${SDL3_SOURCE_DIR}/src/video/yuv2rgb/*.c" -) if(MSVC AND TARGET SDL3-shared) if(SDL_CPU_X64) enable_language(ASM_MASM) @@ -829,6 +792,24 @@ if(SDL_ASSEMBLY) endif() endif() + if(SDL_ARMNEON) + check_c_source_compiles(" + #include + void floats_add(float *dest, float *a, float *b, unsigned size) { + for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) { + vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b))); + } + } + int main(int argc, char *argv[]) { + floats_add((float*)0, (float*)0, (float*)0, 0); + return 0; + }" COMPILER_SUPPORTS_ARMNEON) + + if(COMPILER_SUPPORTS_ARMNEON) + set(HAVE_ARMNEON TRUE) + endif() + endif() + if(USE_GCC OR USE_CLANG) # TODO: Those all seem to be quite GCC specific - needs to be # reworked for better compiler support @@ -883,85 +864,6 @@ if(SDL_ASSEMBLY) set(HAVE_LASX TRUE) endif() endif() - - if(SDL_ARMSIMD) - cmake_push_check_state() - string(APPEND CMAKE_REQUIRED_FLAGS " -x assembler-with-cpp") - list(APPEND CMAKE_REQUIRED_LINK_OPTIONS -x none) - check_c_source_compiles(" - .text - .arch armv6 - .object_arch armv4 - .arm - .altmacro - #ifndef __ARM_EABI__ - #error EABI is required (to be sure that calling conventions are compatible) - #endif - main: - .global main - pld [r0] - uqadd8 r0, r0, r0 - " ARMSIMD_FOUND) - cmake_pop_check_state() - - if(ARMSIMD_FOUND) - set(HAVE_ARMSIMD TRUE) - set(SDL_ARM_SIMD_BLITTERS 1) - enable_language(ASM) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/arm/pixman-arm-simd*.S") - set_property(SOURCE ${ARMSIMD_SOURCES} APPEND PROPERTY COMPILE_OPTIONS -x assembler-with-cpp) - set(WARN_ABOUT_ARM_SIMD_ASM_MIT TRUE) - endif() - endif() - - if(SDL_ARMNEON_BLITTERS) - cmake_push_check_state() - string(APPEND CMAKE_REQUIRED_FLAGS " -x assembler-with-cpp") - list(APPEND CMAKE_REQUIRED_LINK_OPTIONS -x none) - check_c_source_compiles(" - .text - .fpu neon - .arch armv7a - .object_arch armv4 - .eabi_attribute 10, 0 - .arm - .altmacro - #ifndef __ARM_EABI__ - #error EABI is required (to be sure that calling conventions are compatible) - #endif - main: - .global main - pld [r0] - vmovn.u16 d0, q0 - " COMPILER_SUPPORTS_ARMNEON_ASSEMBLY) - cmake_pop_check_state() - if(COMPILER_SUPPORTS_ARMNEON_ASSEMBLY) - set(HAVE_ARMNEON_BLITTERS TRUE) - set(SDL_ARM_NEON_BLITTERS 1) - enable_language(ASM) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/arm/pixman-arm-neon*.S") - set_property(SOURCE ${ARMNEON_SOURCES} APPEND PROPERTY COMPILE_OPTIONS -x assembler-with-cpp) - set(WARN_ABOUT_ARM_NEON_ASM_MIT TRUE) - endif() - endif() - - if(SDL_ARMNEON) - check_c_source_compiles(" - #include - void floats_add(float *dest, float *a, float *b, unsigned size) { - for (; size >= 4; size -= 4, dest += 4, a += 4, b += 4) { - vst1q_f32(dest, vaddq_f32(vld1q_f32(a), vld1q_f32(b))); - } - } - int main(int argc, char *argv[]) { - floats_add((float*)0, (float*)0, (float*)0, 0); - return 0; - }" COMPILER_SUPPORTS_ARMNEON) - - if(COMPILER_SUPPORTS_ARMNEON) - set(HAVE_ARMNEON TRUE) - endif() - endif() endif() endif() @@ -1037,6 +939,7 @@ if(SDL_LIBC) memory.h signal.h stdarg.h + stdbool.h stddef.h stdint.h stdio.h @@ -1071,7 +974,7 @@ if(SDL_LIBC) pow powf putenv realloc rindex round roundf scalbn scalbnf setenv sin sinf sqr sqrt sqrtf sscanf strchr - strcmp strlcat strlcpy strlen strncmp strnlen + strcmp strlcat strlcpy strlen strncmp strnlen strpbrk strrchr strstr strnstr strtod strtok_r strtol strtoll strtoul strtoull tan tanf trunc truncf unsetenv @@ -1101,6 +1004,43 @@ if(SDL_LIBC) endforeach() cmake_pop_check_state() + cmake_push_check_state() + if(MSVC) + string(APPEND CMAKE_REQUIRED_FLAGS " -we4244 -WX") # 'conversion' conversion from 'type1' to 'type2', possible loss of data + else() + string(APPEND CMAKE_REQUIRED_FLAGS " -Wfloat-conversion -Werror") + endif() + foreach(math_fn isinf isnan) + string(TOUPPER "${math_fn}" MATH_FN) + check_c_source_compiles(" + #include + int main() { + double d = 3.14159; + return ${math_fn}(d); + } + " LIBC_HAS_${MATH_FN}) + set(HAVE_${MATH_FN} ${LIBC_HAS_${MATH_FN}}) + + check_c_source_compiles(" + #include + int main() { + float f = 3.14159f; + return ${math_fn}(f); + } + " LIBC_${MATH_FN}_HANDLES_FLOAT) + set(HAVE_${MATH_FN}_FLOAT_MACRO ${LIBC_${MATH_FN}_HANDLES_FLOAT}) + + check_c_source_compiles(" + #include + int main() { + float f = 3.14159f; + return ${math_fn}f(f); + } + " LIBC_HAS_${MATH_FN}F) + set(HAVE_${MATH_FN}F "${LIBC_HAS_${MATH_FN}F}") + endforeach() + cmake_pop_check_state() + if(NOT WINDOWS) check_symbol_exists(getpagesize "unistd.h" HAVE_GETPAGESIZE) check_symbol_exists(sigaction "signal.h" HAVE_SIGACTION) @@ -1169,6 +1109,53 @@ else() endif() endif() +# General source files +sdl_glob_sources( + "${SDL3_SOURCE_DIR}/src/*.c" + "${SDL3_SOURCE_DIR}/src/atomic/*.c" + "${SDL3_SOURCE_DIR}/src/audio/*.c" + "${SDL3_SOURCE_DIR}/src/camera/*.c" + "${SDL3_SOURCE_DIR}/src/core/*.c" + "${SDL3_SOURCE_DIR}/src/cpuinfo/*.c" + "${SDL3_SOURCE_DIR}/src/dynapi/*.c" + "${SDL3_SOURCE_DIR}/src/events/*.c" + "${SDL3_SOURCE_DIR}/src/file/*.c" + "${SDL3_SOURCE_DIR}/src/filesystem/*.c" + "${SDL3_SOURCE_DIR}/src/gpu/*.c" + "${SDL3_SOURCE_DIR}/src/joystick/*.c" + "${SDL3_SOURCE_DIR}/src/haptic/*.c" + "${SDL3_SOURCE_DIR}/src/hidapi/*.c" + "${SDL3_SOURCE_DIR}/src/locale/*.c" + "${SDL3_SOURCE_DIR}/src/main/*.c" + "${SDL3_SOURCE_DIR}/src/misc/*.c" + "${SDL3_SOURCE_DIR}/src/power/*.c" + "${SDL3_SOURCE_DIR}/src/render/*.c" + "${SDL3_SOURCE_DIR}/src/render/*/*.c" + "${SDL3_SOURCE_DIR}/src/sensor/*.c" + "${SDL3_SOURCE_DIR}/src/stdlib/*.c" + "${SDL3_SOURCE_DIR}/src/storage/*.c" + "${SDL3_SOURCE_DIR}/src/thread/*.c" + "${SDL3_SOURCE_DIR}/src/time/*.c" + "${SDL3_SOURCE_DIR}/src/timer/*.c" + "${SDL3_SOURCE_DIR}/src/video/*.c" + "${SDL3_SOURCE_DIR}/src/video/yuv2rgb/*.c" +) + +# Build uclibc as a static library such that non-used symbols don't end up in the SDL3 shared library. +file(GLOB SDL_UCLIBC_SOURCES "${SDL3_SOURCE_DIR}/src/libm/*.c") +add_library(SDL_uclibc STATIC "${SDL_UCLIBC_SOURCES}") +target_compile_definitions(SDL_uclibc PRIVATE USING_GENERATED_CONFIG_H) +target_include_directories(SDL_uclibc PRIVATE "${SDL3_BINARY_DIR}/include-config-$>/build_config") +target_include_directories(SDL_uclibc PRIVATE "${SDL3_SOURCE_DIR}/src") +target_include_directories(SDL_uclibc PRIVATE "${SDL3_SOURCE_DIR}/include") +SDL_AddCommonCompilerFlags(SDL_uclibc) +sdl_sources(STATIC "$") +if(TARGET SDL3-shared) + target_link_libraries(SDL3-shared PRIVATE SDL_uclibc) +endif() +if(HAVE_GCC_FVISIBILITY) + set_property(TARGET SDL_uclibc PROPERTY C_VISIBILITY_PRESET "hidden") +endif() # Enable/disable various subsystems of the SDL library foreach(_SUB ${SDL_SUBSYSTEMS}) @@ -1276,9 +1263,6 @@ if(ANDROID) endif() if(SDL_AUDIO) - set(SDL_AUDIO_DRIVER_ANDROID 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/android/*.c") - set(SDL_AUDIO_DRIVER_OPENSLES 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/openslES/*.c") @@ -1382,6 +1366,10 @@ if(ANDROID) if(VULKAN_PASSED_ANDROID_CHECKS) set(SDL_VIDEO_VULKAN 1) set(HAVE_VULKAN TRUE) + if(SDL_RENDER_VULKAN) + set(SDL_VIDEO_RENDER_VULKAN 1) + set(HAVE_RENDER_VULKAN TRUE) + endif() endif() endif() endif() @@ -1395,7 +1383,7 @@ if(ANDROID) find_package(Java) find_package(SdlAndroidPlatform MODULE) - if(Java_FOUND AND SdlAndroidPlatform_FOUND) + if(Java_FOUND AND SdlAndroidPlatform_FOUND AND NOT CMAKE_VERSION VERSION_LESS "3.19") include(UseJava) set(path_android_jar "${SDL_ANDROID_PLATFORM_ROOT}/android.jar") set(android_java_sources_root "${SDL3_SOURCE_DIR}/android-project/app/src/main/java") @@ -1715,6 +1703,16 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) ) endif() + if(SDL_GPU AND SDL_GPU_DXVK) + if(PKG_CONFIG_FOUND) + pkg_search_module(DXVK_NATIVE dxvk-dxgi) + if(DXVK_NATIVE_FOUND) + set(HAVE_D3D11_H TRUE) + sdl_include_directories(PRIVATE SYSTEM ${DXVK_NATIVE_INCLUDE_DIRS}) + endif() + endif() + endif() + # Always compiled for Linux, unconditionally: sdl_sources( "${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c" @@ -1733,7 +1731,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) if(FREEBSD OR NETBSD OR OPENBSD OR BSDI) CheckUSBHID() endif() - if(LINUX AND HAVE_LINUX_INPUT_H AND NOT ANDROID) + if((LINUX OR FREEBSD) AND HAVE_LINUX_INPUT_H AND NOT ANDROID) set(SDL_JOYSTICK_LINUX 1) sdl_glob_sources( "${SDL3_SOURCE_DIR}/src/joystick/linux/*.c" @@ -1828,14 +1826,7 @@ elseif(WINDOWS) int main(int argc, char **argv) { return 0; }" HAVE_WIN32_CC) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.c") - - if(WINDOWS_STORE) - enable_language(CXX) - sdl_glob_sources( - "${SDL3_SOURCE_DIR}/src/core/winrt/*.c" - "${SDL3_SOURCE_DIR}/src/core/winrt/*.cpp" - ) - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/windows/*.c") if(TARGET SDL3-shared AND MSVC AND NOT SDL_LIBC) # Prevent codegen that would use the VC runtime libraries. @@ -1845,11 +1836,8 @@ elseif(WINDOWS) endif() endif() - if(WINDOWS_STORE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/winrt/*.cpp") - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/windows/*.c") - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/windows/*.c") + set(HAVE_SDL_MISC TRUE) # Check for DirectX @@ -1865,25 +1853,17 @@ elseif(WINDOWS) string(APPEND CMAKE_REQUIRED_FLAGS " /I\"$ENV{DXSDK_DIR}\\Include\"") endif() - check_include_file(d3d9.h HAVE_D3D_H) + check_include_file(d3d9.h HAVE_D3D9_H) check_include_file(d3d11_1.h HAVE_D3D11_H) - check_c_source_compiles(" - #include - #include - #include - ID3D12Device1 *device; - #if WDK_NTDDI_VERSION > 0x0A000008 - int main(int argc, char **argv) { return 0; } - #endif" HAVE_D3D12_H) check_include_file(ddraw.h HAVE_DDRAW_H) check_include_file(dsound.h HAVE_DSOUND_H) check_include_file(dinput.h HAVE_DINPUT_H) - if(WINDOWS_STORE OR SDL_CPU_ARM32) + if(SDL_CPU_ARM32) # !!! FIXME: this should probably check if we're !(x86 or x86-64) instead of arm. set(HAVE_DINPUT_H 0) endif() check_include_file(dxgi.h HAVE_DXGI_H) cmake_pop_check_state() - if(HAVE_D3D_H OR HAVE_D3D11_H OR HAVE_D3D12_H OR HAVE_DDRAW_H OR HAVE_DSOUND_H OR HAVE_DINPUT_H) + if(HAVE_D3D9_H OR HAVE_D3D11_H OR HAVE_DDRAW_H OR HAVE_DSOUND_H OR HAVE_DINPUT_H) set(HAVE_DIRECTX TRUE) if(NOT MINGW AND NOT USE_WINSDK_DIRECTX) if(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -1903,23 +1883,39 @@ elseif(WINDOWS) #include #include int main(int argc, char **argv) { return 0; }" HAVE_XINPUT_H) - check_c_source_compiles(" - #define COBJMACROS - #include - __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *s2; - int main(int argc, char **argv) { return 0; }" HAVE_WINDOWS_GAMING_INPUT_H) endif() # headers needed elsewhere + check_c_source_compiles(" + #define COBJMACROS + #include + static __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *s2; + int main(int argc, char **argv) { return 0; }" HAVE_WINDOWS_GAMING_INPUT_H + ) + check_c_source_compiles(" + #include + #define COBJMACROS + #include + int main(int argc, char **argv) { return 0; }" HAVE_GAMEINPUT_H + ) + check_include_file(dxgi1_6.h HAVE_DXGI1_6_H) check_include_file(tpcshrd.h HAVE_TPCSHRD_H) check_include_file(roapi.h HAVE_ROAPI_H) check_include_file(mmdeviceapi.h HAVE_MMDEVICEAPI_H) check_include_file(audioclient.h HAVE_AUDIOCLIENT_H) check_include_file(sensorsapi.h HAVE_SENSORSAPI_H) check_include_file(shellscalingapi.h HAVE_SHELLSCALINGAPI_H) + check_c_source_compiles(" + #include + #include + #include + #include + int main(int argc, char **argv) { return 0; } + " HAVE_MFAPI_H + ) if(SDL_AUDIO) - if(HAVE_DSOUND_H AND NOT WINDOWS_STORE) + if(HAVE_DSOUND_H) set(SDL_AUDIO_DRIVER_DSOUND 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/directsound/*.c") set(HAVE_SDL_AUDIO TRUE) @@ -1929,37 +1925,25 @@ elseif(WINDOWS) set(SDL_AUDIO_DRIVER_WASAPI 1) set(HAVE_WASAPI TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/wasapi/*.c") - if(WINDOWS_STORE) - sdl_sources("${SDL3_SOURCE_DIR}/src/audio/wasapi/SDL_wasapi_winrt.cpp") - endif() set(HAVE_SDL_AUDIO TRUE) endif() endif() if(SDL_VIDEO) - if(WINDOWS_STORE) - set(SDL_VIDEO_DRIVER_WINRT 1) - sdl_glob_sources( - "${SDL3_SOURCE_DIR}/src/video/winrt/*.c" - "${SDL3_SOURCE_DIR}/src/video/winrt/*.cpp" - "${SDL3_SOURCE_DIR}/src/render/direct3d11/*.cpp" - ) - else() - set(SDL_VIDEO_DRIVER_WINDOWS 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/windows/*.c") - endif() + set(SDL_VIDEO_DRIVER_WINDOWS 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/windows/*.c") - if(SDL_RENDER_D3D AND HAVE_D3D_H AND NOT WINDOWS_STORE) + if(SDL_RENDER_D3D AND HAVE_D3D9_H) set(SDL_VIDEO_RENDER_D3D 1) set(HAVE_RENDER_D3D TRUE) endif() - if(SDL_RENDER_D3D AND HAVE_D3D11_H) + if(SDL_RENDER_D3D11 AND HAVE_D3D11_H) set(SDL_VIDEO_RENDER_D3D11 1) - set(HAVE_RENDER_D3D TRUE) + set(HAVE_RENDER_D3D11 TRUE) endif() - if(SDL_RENDER_D3D AND HAVE_D3D12_H AND NOT WINDOWS_STORE) + if(SDL_RENDER_D3D12) set(SDL_VIDEO_RENDER_D3D12 1) - set(HAVE_RENDER_D3D TRUE) + set(HAVE_RENDER_D3D12 TRUE) endif() set(HAVE_SDL_VIDEO TRUE) endif() @@ -1977,39 +1961,26 @@ elseif(WINDOWS) "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_systhread.c" "${SDL3_SOURCE_DIR}/src/thread/windows/SDL_systls.c" ) + set(HAVE_SDL_THREADS TRUE) - if(SDL_SENSOR AND HAVE_SENSORSAPI_H AND NOT WINDOWS_STORE) + if(SDL_SENSOR AND HAVE_SENSORSAPI_H) set(SDL_SENSOR_WINDOWS 1) set(HAVE_SDL_SENSORS TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/sensor/windows/*.c") endif() if(SDL_POWER) - if(WINDOWS_STORE) - set(SDL_POWER_WINRT 1) - sdl_sources("${SDL3_SOURCE_DIR}/src/power/winrt/SDL_syspower.cpp") - else() - set(SDL_POWER_WINDOWS 1) - sdl_sources("${SDL3_SOURCE_DIR}/src/power/windows/SDL_syspower.c") - set(HAVE_SDL_POWER TRUE) - endif() + set(SDL_POWER_WINDOWS 1) + sdl_sources("${SDL3_SOURCE_DIR}/src/power/windows/SDL_syspower.c") + set(HAVE_SDL_POWER TRUE) endif() - if(WINDOWS_STORE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/winrt/*.c") - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/windows/*.c") - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/locale/windows/*.c") set(HAVE_SDL_LOCALE TRUE) set(SDL_FILESYSTEM_WINDOWS 1) - if(WINDOWS_STORE) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/winrt/*.cpp") - sdl_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/SDL_sysfsops.c") - else() - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c") - endif() + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/filesystem/windows/*.c") set(HAVE_SDL_FILESYSTEM TRUE) set(SDL_FSOPS_WINDOWS 1) @@ -2017,27 +1988,12 @@ elseif(WINDOWS) set(SDL_STORAGE_GENERIC 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c") - if(NOT WINDOWS_STORE) - set(SDL_STORAGE_STEAM 1) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c") - endif() + set(SDL_STORAGE_STEAM 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c") set(HAVE_SDL_STORAGE 1) # Libraries for Win32 native and MinGW - if(NOT WINDOWS_STORE) - sdl_link_dependency(base LIBS kernel32 user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32) - endif() - - if(WINDOWS_STORE) - sdl_link_dependency(windows - LIBS - vccorlib$<$:d>.lib - msvcrt$<$:d>.lib - LINK_OPTIONS - /nodefaultlib:vccorlib$<$:d> - /nodefaultlib:msvcrt$<$:d> - ) - endif() + sdl_link_dependency(base LIBS kernel32 user32 gdi32 winmm imm32 ole32 oleaut32 version uuid advapi32 setupapi shell32) set(SDL_TIME_WINDOWS 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/time/windows/*.c") @@ -2054,7 +2010,7 @@ elseif(WINDOWS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/windows/*.c") if(SDL_VIDEO) - if(SDL_OPENGL AND NOT WINDOWS_STORE) + if(SDL_OPENGL) set(SDL_VIDEO_OPENGL 1) set(SDL_VIDEO_OPENGL_WGL 1) set(SDL_VIDEO_RENDER_OGL 1) @@ -2085,26 +2041,26 @@ elseif(WINDOWS) if(SDL_JOYSTICK) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/windows/*.c") - if(NOT WINDOWS_STORE) - set(SDL_JOYSTICK_RAWINPUT 1) - endif() + set(SDL_JOYSTICK_RAWINPUT 1) if(HAVE_DINPUT_H) set(SDL_JOYSTICK_DINPUT 1) sdl_link_dependency(joystick LIBS dinput8) endif() if(HAVE_XINPUT_H) - if(NOT WINDOWS_STORE) - set(SDL_JOYSTICK_XINPUT 1) - set(HAVE_XINPUT TRUE) - endif() - if(HAVE_WINDOWS_GAMING_INPUT_H) - set(SDL_JOYSTICK_WGI 1) - endif() + set(SDL_JOYSTICK_XINPUT 1) + set(HAVE_XINPUT TRUE) + endif() + if(HAVE_WINDOWS_GAMING_INPUT_H) + set(SDL_JOYSTICK_WGI 1) + endif() + if(HAVE_GAMEINPUT_H) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/gdk/*.c") + set(SDL_JOYSTICK_GAMEINPUT 1) endif() set(HAVE_SDL_JOYSTICK TRUE) if(SDL_HAPTIC) - if(HAVE_DINPUT_H AND NOT WINDOWS_STORE) + if(HAVE_DINPUT_H) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/windows/*.c") set(SDL_HAPTIC_DINPUT 1) set(HAVE_SDL_HAPTIC TRUE) @@ -2113,13 +2069,14 @@ elseif(WINDOWS) endif() if(SDL_CAMERA) - if(NOT WINDOWS_STORE) + if(HAVE_MFAPI_H) set(HAVE_CAMERA TRUE) set(SDL_CAMERA_DRIVER_MEDIAFOUNDATION 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/mediafoundation/*.c") endif() endif() + enable_language(RC) sdl_glob_sources(SHARED "${SDL3_SOURCE_DIR}/src/core/windows/*.rc") if(MINGW OR CYGWIN) sdl_pc_link_options("-mwindows") @@ -2134,7 +2091,7 @@ elseif(APPLE) # !!! FIXME: we need Carbon for some very old API calls in # !!! FIXME: src/video/cocoa/SDL_cocoakeyboard.c, but we should figure out # !!! FIXME: how to dump those. - if(DARWIN OR MACOSX) + if(MACOS) set(SDL_FRAMEWORK_COCOA 1) set(SDL_FRAMEWORK_CARBON 1) set(SDL_FRAMEWORK_UTTYPES 1) @@ -2143,7 +2100,7 @@ elseif(APPLE) set(SDL_FRAMEWORK_COREVIDEO 1) # iOS can use a CADisplayLink for main callbacks. macOS just uses the generic one atm. - if(IOS OR TVOS OR VISIONOS) + if(IOS OR TVOS OR VISIONOS OR WATCHOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ios/*.m") set(HAVE_SDL_MAIN_CALLBACKS TRUE) endif() @@ -2151,14 +2108,14 @@ elseif(APPLE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/file/cocoa/*.m") if(SDL_CAMERA) - if(IOS OR TVOS OR MACOSX OR DARWIN) + if(MACOS OR IOS) set(SDL_CAMERA_DRIVER_COREMEDIA 1) set(HAVE_CAMERA TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/coremedia/*.m") endif() endif() - if(IOS OR TVOS OR VISIONOS) + if(IOS OR TVOS OR VISIONOS OR WATCHOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/ios/*.m") else() sdl_glob_sources("${SDL3_SOURCE_DIR}/src/misc/macos/*.m") @@ -2180,10 +2137,10 @@ elseif(APPLE) if(SDL_JOYSTICK) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/apple/*.m") - if(IOS OR TVOS OR VISIONOS) + if(IOS OR TVOS OR VISIONOS OR WATCHOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/joystick/steam/*.c") set(SDL_JOYSTICK_MFI 1) - if(IOS OR VISIONOS) + if(IOS OR VISIONOS OR WATCHOS) set(SDL_FRAMEWORK_COREMOTION 1) endif() set(SDL_FRAMEWORK_GAMECONTROLLER 1) @@ -2225,7 +2182,7 @@ elseif(APPLE) endif() if(SDL_HAPTIC) - if (IOS OR TVOS OR VISIONOS) + if (IOS OR TVOS OR VISIONOS OR WATCHOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/haptic/dummy/*.c") set(SDL_HAPTIC_DUMMY 1) else() @@ -2238,7 +2195,7 @@ elseif(APPLE) endif() if(SDL_POWER) - if (IOS OR TVOS OR VISIONOS) + if (IOS OR TVOS OR VISIONOS OR WATCHOS) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/power/uikit/*.m") set(SDL_POWER_UIKIT 1) else() @@ -2267,7 +2224,7 @@ elseif(APPLE) # TODO: SDL_STORAGE_ICLOUD set(SDL_STORAGE_GENERIC 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/generic/*.c") - if(DARWIN OR MACOSX) + if(MACOS) set(SDL_STORAGE_STEAM 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/storage/steam/*.c") endif() @@ -2278,7 +2235,7 @@ elseif(APPLE) set(HAVE_SDL_FSOPS TRUE) if(SDL_SENSOR) - if(IOS OR VISIONOS) + if(IOS OR VISIONOS OR WATCHOS) set(SDL_SENSOR_COREMOTION 1) set(HAVE_SDL_SENSORS TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/sensor/coremotion/*.m") @@ -2287,7 +2244,7 @@ elseif(APPLE) # iOS hack needed - http://code.google.com/p/ios-cmake/ ? if(SDL_VIDEO) - if (IOS OR TVOS OR VISIONOS) + if(IOS OR TVOS OR VISIONOS OR WATCHOS) set(SDL_VIDEO_DRIVER_UIKIT 1) set(SDL_FRAMEWORK_COREGRAPHICS 1) set(SDL_FRAMEWORK_QUARTZCORE 1) @@ -2307,7 +2264,7 @@ elseif(APPLE) endif() if(SDL_OPENGLES) - if(IOS OR TVOS OR VISIONOS) + if(IOS OR TVOS OR VISIONOS OR WATCHOS) set(SDL_FRAMEWORK_OPENGLES 1) set(SDL_VIDEO_OPENGL_ES 1) else() @@ -2348,81 +2305,88 @@ elseif(APPLE) set(SDL_VIDEO_RENDER_METAL 1) set(HAVE_RENDER_METAL TRUE) endif() + if (SDL_GPU) + set(SDL_GPU_METAL 1) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/metal/*.m") + endif() endif() endif() endif() + # Minimum version for $ + cmake_minimum_required(VERSION 3.24) + # Actually load the frameworks at the end so we don't duplicate include. if(SDL_FRAMEWORK_COREVIDEO) find_library(COREMEDIA CoreMedia) if(COREMEDIA) - sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreMedia") + sdl_link_dependency(corevideo LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreMedia") endif() - sdl_link_dependency(corevideo LINK_OPTIONS "-Wl,-framework,CoreVideo") + sdl_link_dependency(corevideo LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreVideo") endif() if(SDL_FRAMEWORK_COCOA) - sdl_link_dependency(cocoa LINK_OPTIONS "-Wl,-framework,Cocoa") + sdl_link_dependency(cocoa LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,Cocoa") endif() if(SDL_FRAMEWORK_IOKIT) - sdl_link_dependency(iokit LINK_OPTIONS "-Wl,-framework,IOKit") + sdl_link_dependency(iokit LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,IOKit") endif() if(SDL_FRAMEWORK_FF) - sdl_link_dependency(ff LINK_OPTIONS "-Wl,-framework,ForceFeedback") + sdl_link_dependency(ff LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,ForceFeedback") endif() if(SDL_FRAMEWORK_CARBON) - sdl_link_dependency(carbon LINK_OPTIONS "-Wl,-framework,Carbon") + sdl_link_dependency(carbon LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,Carbon") endif() if(SDL_FRAMEWORK_COREAUDIO) - sdl_link_dependency(core_audio LINK_OPTIONS "-Wl,-framework,CoreAudio") + sdl_link_dependency(core_audio LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreAudio") endif() if(SDL_FRAMEWORK_AUDIOTOOLBOX) - sdl_link_dependency(audio_toolbox LINK_OPTIONS "-Wl,-framework,AudioToolbox") + sdl_link_dependency(audio_toolbox LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,AudioToolbox") endif() if(SDL_FRAMEWORK_AVFOUNDATION) - sdl_link_dependency(av_foundation LINK_OPTIONS "-Wl,-framework,AVFoundation") + sdl_link_dependency(av_foundation LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,AVFoundation") endif() if(SDL_FRAMEWORK_COREBLUETOOTH) - sdl_link_dependency(core_bluetooth LINK_OPTIONS "-Wl,-framework,CoreBluetooth") + sdl_link_dependency(core_bluetooth LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreBluetooth") endif() if(SDL_FRAMEWORK_COREGRAPHICS) - sdl_link_dependency(core_graphics LINK_OPTIONS "-Wl,-framework,CoreGraphics") + sdl_link_dependency(core_graphics LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreGraphics") endif() if(SDL_FRAMEWORK_COREMOTION) - sdl_link_dependency(core_motion LINK_OPTIONS "-Wl,-framework,CoreMotion") + sdl_link_dependency(core_motion LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreMotion") endif() if(SDL_FRAMEWORK_FOUNDATION) - sdl_link_dependency(foundation LINK_OPTIONS "-Wl,-framework,Foundation") + sdl_link_dependency(foundation LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,Foundation") endif() if(SDL_FRAMEWORK_GAMECONTROLLER) find_library(GAMECONTROLLER GameController) if(GAMECONTROLLER) - sdl_link_dependency(game_controller LINK_OPTIONS "-Wl,-weak_framework,GameController") + sdl_link_dependency(game_controller LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-weak_framework,GameController") endif() endif() if(SDL_FRAMEWORK_METAL) - if(IOS OR TVOS OR VISIONOS) - sdl_link_dependency(metal LINK_OPTIONS "-Wl,-framework,Metal") + if(IOS OR TVOS OR VISIONOS OR WATCHOS) + sdl_link_dependency(metal LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,Metal") else() - sdl_link_dependency(metal LINK_OPTIONS "-Wl,-weak_framework,Metal") + sdl_link_dependency(metal LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-weak_framework,Metal") endif() endif() if(SDL_FRAMEWORK_OPENGLES) - sdl_link_dependency(opengles LINK_OPTIONS "-Wl,-framework,OpenGLES") + sdl_link_dependency(opengles LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,OpenGLES") endif() if(SDL_FRAMEWORK_QUARTZCORE) - if(IOS OR TVOS OR VISIONOS) - sdl_link_dependency(quartz_core LINK_OPTIONS "-Wl,-framework,QuartzCore") + if(IOS OR TVOS OR VISIONOS OR WATCHOS) + sdl_link_dependency(quartz_core LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,QuartzCore") else() - sdl_link_dependency(metal LINK_OPTIONS "-Wl,-weak_framework,QuartzCore") + sdl_link_dependency(metal LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-weak_framework,QuartzCore") endif() endif() if(SDL_FRAMEWORK_UIKIT) - sdl_link_dependency(ui_kit LINK_OPTIONS "-Wl,-framework,UIKit") + sdl_link_dependency(ui_kit LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,UIKit") endif() if(SDL_FRAMEWORK_COREHAPTICS) find_library(COREHAPTICS CoreHaptics) if(COREHAPTICS) - sdl_link_dependency(core_haptics LINK_OPTIONS "-Wl,-framework,CoreHaptics") + sdl_link_dependency(core_haptics LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-framework,CoreHaptics") endif() endif() @@ -2682,7 +2646,7 @@ elseif(VITA) sdl_compile_definitions(PRIVATE "__VITA__") elseif(PSP) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/psp/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/psp/*.c") if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_PSP 1) @@ -2750,8 +2714,9 @@ elseif(PSP) elseif(PS2) sdl_compile_definitions(PRIVATE "PS2" "__PS2__") sdl_include_directories(PRIVATE SYSTEM "$ENV{PS2SDK}/ports/include" "$ENV{PS2DEV}/gsKit/include") + target_include_directories(SDL_uclibc PRIVATE "$ENV{PS2SDK}/ports/include" "$ENV{PS2DEV}/gsKit/include") - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/ps2/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/ps2/*.c") if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_PS2 1) @@ -2808,7 +2773,7 @@ elseif(PS2) ps2_drivers ) elseif(N3DS) - sdl_glob_sources("${SDL3_SOURCE_DIR}/src/core/n3ds/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/main/n3ds/*.c") if(SDL_AUDIO) set(SDL_AUDIO_DRIVER_N3DS 1) @@ -2873,7 +2838,11 @@ elseif(N3DS) endif() if (SDL_DIALOG) - if(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/SDL_dialog_utils.c) + if(ANDROID) + sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/android/SDL_androiddialog.c) + set(HAVE_SDL_DIALOG TRUE) + elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_unixdialog.c) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_portaldialog.c) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/unix/SDL_zenitydialog.c) @@ -2881,20 +2850,69 @@ if (SDL_DIALOG) elseif(HAIKU) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/haiku/SDL_haikudialog.cc) set(HAVE_SDL_DIALOG TRUE) - elseif(WINDOWS AND NOT WINDOWS_STORE) + elseif(WINDOWS) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/windows/SDL_windowsdialog.c) set(HAVE_SDL_DIALOG TRUE) - elseif(APPLE) + elseif(MACOS) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/cocoa/SDL_cocoadialog.m) - sdl_link_dependency(uniformtypeidentifiers LINK_OPTIONS "-Wl,-weak_framework,UniformTypeIdentifiers") + sdl_link_dependency(uniformtypeidentifiers LIBS "$" PKG_CONFIG_LINK_OPTIONS "-Wl,-weak_framework,UniformTypeIdentifiers") set(HAVE_SDL_DIALOG TRUE) endif() endif() +sdl_sources("${SDL3_SOURCE_DIR}/src/process/SDL_process.c") +if(WINDOWS) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/process/windows/*.c") + set(SDL_PROCESS_WINDOWS 1) + set(HAVE_SDL_PROCESS TRUE) +else() + check_c_source_compiles(" +#include +#include + +int main(void) +{ + int pipes[2]; + int pid; + + const char * args[] = { + \"/bin/false\", + NULL + }; + + const char * env[] = { NULL }; + + pipe(pipes); + + posix_spawnattr_t attr; + posix_spawn_file_actions_t fa; + + posix_spawnattr_init(&attr); + posix_spawn_file_actions_init(&fa); + + posix_spawn_file_actions_addclose(&fa, pipes[0]); + posix_spawn_file_actions_adddup2(&fa, pipes[1], STDOUT_FILENO); + + posix_spawn(&pid, args[0], &fa, &attr, (char * const *) args, (char * const *) env); + posix_spawnp(&pid, args[0], &fa, &attr, (char * const *) args, (char * const *) env); + + posix_spawn_file_actions_destroy(&fa); + posix_spawnattr_destroy(&attr); + + return 0; +} +" HAVE_POSIX_SPAWN) + if(HAVE_POSIX_SPAWN) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/process/posix/*.c") + set(SDL_PROCESS_POSIX 1) + set(HAVE_SDL_PROCESS TRUE) + endif() +endif() + # Platform-independent options if(SDL_VIDEO) - if(SDL_OFFSCREEN AND SDL_VIDEO_OPENGL_EGL) + if(SDL_OFFSCREEN) set(SDL_VIDEO_DRIVER_OFFSCREEN 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/video/offscreen/*.c") set(HAVE_OFFSCREEN TRUE) @@ -2902,6 +2920,28 @@ if(SDL_VIDEO) endif() endif() +if(SDL_GPU) + if(HAVE_D3D11_H) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d11/*.c") + set(SDL_GPU_D3D11 1) + set(HAVE_SDL_GPU TRUE) + endif() + if(SDL_RENDER_D3D12) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/d3d12/*.c") + set(SDL_GPU_D3D12 1) + set(HAVE_SDL_GPU TRUE) + endif() + if(SDL_VIDEO_VULKAN) + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/gpu/vulkan/*.c") + set(SDL_GPU_VULKAN 1) + set(HAVE_SDL_GPU TRUE) + endif() + if(SDL_RENDER_GPU) + set(SDL_VIDEO_RENDER_GPU 1) + set(HAVE_RENDER_GPU TRUE) + endif() +endif() + # Dummies # configure.ac does it differently: # if not have X @@ -2958,6 +2998,10 @@ if(NOT HAVE_SDL_DIALOG) set(SDL_DIALOG_DUMMY 1) sdl_sources(${SDL3_SOURCE_DIR}/src/dialog/dummy/SDL_dummydialog.c) endif() +if(NOT HAVE_SDL_PROCESS) + set(SDL_PROCESS_DUMMY 1) + sdl_glob_sources(${SDL3_SOURCE_DIR}/src/process/dummy/*.c) +endif() if(NOT HAVE_CAMERA) set(SDL_CAMERA_DRIVER_DUMMY 1) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/dummy/*.c") @@ -3041,9 +3085,11 @@ macro(check_add_debug_flag FLAG SUFFIX) string(APPEND CMAKE_C_FLAGS_DEBUG " ${FLAG}") endif() - check_cxx_compiler_flag(${FLAG} HAS_CXX_${SUFFIX}) - if(HAS_CXX_${SUFFIX}) - string(APPEND CMAKE_CXX_FLAGS_DEBUG " ${FLAG}") + if(CMAKE_CXX_COMPILER) + check_cxx_compiler_flag(${FLAG} HAS_CXX_${SUFFIX}) + if(HAS_CXX_${SUFFIX}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " ${FLAG}") + endif() endif() endmacro() @@ -3062,18 +3108,20 @@ macro(asan_check_add_debug_flag2 ASAN_FLAG) cmake_push_check_state() list(APPEND CMAKE_REQUIRED_LIBRARIES ${FLAG} asan) - check_c_compiler_flag (${FLAG} HAS_C_FLAG_${ASAN_FLAG}) - check_cxx_compiler_flag (${FLAG} HAS_CXX_FLAG_${ASAN_FLAG}) - cmake_pop_check_state() + check_c_compiler_flag (${FLAG} HAS_C_FLAG_${ASAN_FLAG}) if (HAS_C_FLAG_${ASAN_FLAG}) string(APPEND CMAKE_C_FLAGS_DEBUG " ${FLAG}") endif() - if (HAS_CXX_${ASAN_FLAG}) - string(APPEND CMAKE_CXX_FLAGS_DEBUG " ${FLAG}") + if(CMAKE_CXX_COMPILER) + check_cxx_compiler_flag (${FLAG} HAS_CXX_FLAG_${ASAN_FLAG}) + if (HAS_CXX_${ASAN_FLAG}) + string(APPEND CMAKE_CXX_FLAGS_DEBUG " ${FLAG}") + endif() endif() + cmake_pop_check_state() if(HAS_C_${ASAN_FLAG} OR HAS_CXX_${ASAN_FLAG}) set(HAVE_ASAN ON) endif() @@ -3214,7 +3262,6 @@ target_include_directories(SDL3_Headers INTERFACE "$" "$" - "$" ) if(SDL_FRAMEWORK) target_include_directories(SDL3_Headers @@ -3230,7 +3277,6 @@ else() target_include_directories(SDL3_Headers INTERFACE "$" - "$" ) endif() @@ -3251,7 +3297,7 @@ if(SDL_SHARED) ) endif() if(NOT SDL_LIBC) - if(MSVC AND (NOT MSVC_CLANG AND NOT WINDOWS_STORE)) + if(MSVC AND NOT MSVC_CLANG) # Don't try to link with the default set of libraries. # Note: The clang toolset for Visual Studio does not support /NODEFAULTLIB. target_link_options(SDL3-shared PRIVATE "/NODEFAULTLIB") @@ -3266,9 +3312,13 @@ if(SDL_SHARED) endif() endif() if(APPLE) + cmake_minimum_required(VERSION 3.17) set_target_properties(SDL3-shared PROPERTIES MACOSX_RPATH TRUE FRAMEWORK "${SDL_FRAMEWORK}" + SOVERSION "${SDL_SO_VERSION_MAJOR}" + MACHO_COMPATIBILITY_VERSION "${SDL_DYLIB_COMPAT_VERSION}" + MACHO_CURRENT_VERSION "${SDL_DYLIB_CURRENT_VERSION}" ) if(SDL_FRAMEWORK) set_target_properties(SDL3-shared PROPERTIES @@ -3278,10 +3328,6 @@ if(SDL_SHARED) RESOURCE "${SDL_FRAMEWORK_RESOURCES}" ) endif() - set_target_properties(SDL3-shared PROPERTIES - SOVERSION "${SDL_DYLIB_COMPAT_VERSION}" # SOVERSION corresponds to compatibility version - VERSION "${SDL_DYLIB_CURRENT_VERSION}" # VERSION corresponds to the current version - ) elseif(UNIX AND NOT ANDROID) set_target_properties(SDL3-shared PROPERTIES VERSION "${SDL_SO_VERSION}" @@ -3297,7 +3343,7 @@ if(SDL_SHARED) target_link_libraries(SDL3-shared PRIVATE ${SDL_CMAKE_DEPENDS}) target_include_directories(SDL3-shared PRIVATE - "$>>" + "$>>/build_config" "$" ) target_link_libraries(SDL3-shared PUBLIC $) @@ -3319,13 +3365,12 @@ endif() if(SDL_STATIC) set_target_properties(SDL3-static PROPERTIES OUTPUT_NAME "${sdl_static_libname}" - POSITION_INDEPENDENT_CODE "${SDL_STATIC_PIC}" ) target_compile_definitions(SDL3-static PRIVATE SDL_STATIC_LIB) target_link_libraries(SDL3-static PRIVATE ${SDL_CMAKE_DEPENDS}) target_include_directories(SDL3-static PRIVATE - "$>>" + "$>>/build_config" "$" ) target_link_libraries(SDL3-static PUBLIC $) @@ -3583,7 +3628,11 @@ if(NOT SDL_DISABLE_INSTALL) if(ANDROID) if(TARGET SDL3-jar) set(SDL_INSTALL_JAVADIR "${CMAKE_INSTALL_DATAROOTDIR}/java" CACHE PATH "Path where to install java clases + java sources") - install(FILES $ + set(PROGUARD_RULES_PATH "${CMAKE_CURRENT_SOURCE_DIR}/android-project/app/proguard-rules.pro") + # install_jar or $ does not work on Windows: a SDL3.jar symlink is not generated + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SDL3-${SDL3_VERSION}.jar" + DESTINATION "${SDL_INSTALL_JAVADIR}/SDL3") + install(FILES "${PROGUARD_RULES_PATH}" RENAME "proguard.txt" DESTINATION "${SDL_INSTALL_JAVADIR}/SDL3") configure_package_config_file(cmake/SDL3jarTargets.cmake.in SDL3jarTargets.cmake INSTALL_DESTINATION "${SDL_SDL_INSTALL_CMAKEDIR}" @@ -3635,6 +3684,13 @@ if(SDL_TESTS) add_subdirectory(test) endif() +##### Examples subproject (must appear after the install/uninstall targets) ##### + +if(SDL_EXAMPLES) + set(HAVE_EXAMPLES ON) + add_subdirectory(examples) +endif() + ##### Fix Objective C builds ##### string(APPEND CMAKE_OBJC_FLAGS " ${CMAKE_C_FLAGS}") diff --git a/libs/SDL3/INSTALL.md b/libs/SDL3/INSTALL.md index f071eab0f..647341d3b 100644 --- a/libs/SDL3/INSTALL.md +++ b/libs/SDL3/INSTALL.md @@ -20,6 +20,10 @@ Read docs/README-macos.md Run: `cmake -S . -B build && cmake --build build && cmake --install build` +### macOS for universal architecture: + +Run: `cmake -S . -B build -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" && cmake --build build && cmake --install build` + ## Linux and other UNIX systems: Run: `cmake -S . -B build && cmake --build build && cmake --install build` diff --git a/libs/SDL3/README-SDL.txt b/libs/SDL3/README-SDL.txt index 2984b145e..8d92955a9 100644 --- a/libs/SDL3/README-SDL.txt +++ b/libs/SDL3/README-SDL.txt @@ -1,13 +1,13 @@ - -Please distribute this file with the SDL runtime environment: - -The Simple DirectMedia Layer (SDL for short) is a cross-platform library -designed to make it easy to write multi-media software, such as games -and emulators. - -The Simple DirectMedia Layer library source code is available from: -https://www.libsdl.org/ - -This library is distributed under the terms of the zlib license: -http://www.zlib.net/zlib_license.html - + +Please distribute this file with the SDL runtime environment: + +The Simple DirectMedia Layer (SDL for short) is a cross-platform library +designed to make it easy to write multi-media software, such as games +and emulators. + +The Simple DirectMedia Layer library source code is available from: +https://www.libsdl.org/ + +This library is distributed under the terms of the zlib license: +http://www.zlib.net/zlib_license.html + diff --git a/libs/SDL3/VERSION.txt b/libs/SDL3/VERSION.txt deleted file mode 100644 index 94ff29cc4..000000000 --- a/libs/SDL3/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -3.1.1 diff --git a/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj b/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj index d68a2f60a..c779b40cc 100644 --- a/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj +++ b/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj @@ -63,27 +63,21 @@ - - - - - - @@ -122,7 +116,7 @@ Disabled - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -152,7 +146,7 @@ Disabled - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -172,6 +166,7 @@ $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) + $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) Building shader blobs (Xbox Series) @@ -186,7 +181,7 @@ Disabled - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -206,6 +201,7 @@ $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one + $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one Building shader blobs (Xbox One) @@ -219,7 +215,7 @@ .\Release/SDL.tlb - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -250,7 +246,7 @@ .\Release/SDL.tlb - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -272,6 +268,7 @@ $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) + $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) Building shader blobs (Xbox Series) @@ -285,7 +282,7 @@ .\Release/SDL.tlb - $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) + $(ProjectDir)\..\..\include;$(ProjectDir)\..\..\include\build_config;$(ProjectDir)\..\..\src;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -307,11 +304,17 @@ $(SolutionDir)..\src\render\direct3d12\compile_shaders_xbox.bat $(SolutionDir) one + $(SolutionDir)..\src\gpu\d3d12\compile_shaders_xbox.bat $(SolutionDir) one Building shader blobs (Xbox One) + + + $(TreatWarningsAsError) + + @@ -331,6 +334,7 @@ + @@ -360,7 +364,8 @@ - + + @@ -382,7 +387,6 @@ - @@ -416,15 +420,18 @@ + + + @@ -507,10 +514,13 @@ + + + @@ -562,6 +572,7 @@ + @@ -570,6 +581,7 @@ + @@ -606,7 +618,6 @@ - @@ -635,11 +646,13 @@ NotUsing NotUsing + + @@ -678,6 +691,7 @@ + @@ -728,6 +742,10 @@ + + + + @@ -739,6 +757,9 @@ + + + CompileAsCpp @@ -750,6 +771,9 @@ + + + @@ -766,6 +790,8 @@ + + @@ -790,7 +816,9 @@ NotUsing + + @@ -841,6 +869,7 @@ + @@ -854,6 +883,15 @@ + + + + CompileAsCpp + CompileAsCpp + CompileAsCpp + CompileAsCpp + + diff --git a/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj.filters b/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj.filters index 722b2ed3c..46d3b4775 100644 --- a/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj.filters +++ b/libs/SDL3/VisualC-GDK/SDL/SDL.vcxproj.filters @@ -4,6 +4,9 @@ + + dialog + filesystem @@ -15,6 +18,8 @@ + + @@ -32,18 +37,19 @@ - + + @@ -51,6 +57,10 @@ + + + + @@ -70,6 +80,7 @@ + @@ -102,6 +113,10 @@ + + + + @@ -112,6 +127,9 @@ + + + @@ -156,7 +174,9 @@ + + @@ -206,6 +226,7 @@ + @@ -218,7 +239,6 @@ - @@ -238,6 +258,7 @@ + @@ -267,7 +288,8 @@ - + + @@ -288,7 +310,6 @@ - @@ -319,17 +340,20 @@ + + filesystem + @@ -428,6 +452,7 @@ + @@ -436,6 +461,7 @@ + diff --git a/libs/SDL3/VisualC-GDK/SDL_test/SDL_test.vcxproj b/libs/SDL3/VisualC-GDK/SDL_test/SDL_test.vcxproj index 136a46131..7505baf86 100644 --- a/libs/SDL3/VisualC-GDK/SDL_test/SDL_test.vcxproj +++ b/libs/SDL3/VisualC-GDK/SDL_test/SDL_test.vcxproj @@ -62,27 +62,21 @@ - - - - - - @@ -190,6 +184,11 @@ true + + + $(TreatWarningsAsError) + + @@ -201,7 +200,6 @@ - diff --git a/libs/SDL3/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj b/libs/SDL3/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj index 5680fe311..d7ad95cf2 100644 --- a/libs/SDL3/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj +++ b/libs/SDL3/VisualC-GDK/tests/testcontroller/testcontroller.vcxproj @@ -63,27 +63,21 @@ - - - - - - @@ -266,6 +260,11 @@ xgameruntime.lib;%(AdditionalDependencies) + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC-GDK/tests/testgdk/src/testgdk.cpp b/libs/SDL3/VisualC-GDK/tests/testgdk/src/testgdk.cpp index bddecf3c5..b3aa9ec8b 100644 --- a/libs/SDL3/VisualC-GDK/tests/testgdk/src/testgdk.cpp +++ b/libs/SDL3/VisualC-GDK/tests/testgdk/src/testgdk.cpp @@ -35,8 +35,8 @@ extern "C" { static SDLTest_CommonState *state; static int num_sprites; static SDL_Texture **sprites; -static SDL_bool cycle_color; -static SDL_bool cycle_alpha; +static bool cycle_color; +static bool cycle_alpha; static int cycle_direction = 1; static int current_alpha = 0; static int current_color = 0; @@ -193,11 +193,11 @@ LoadSprite(const char *file) for (i = 0; i < state->num_windows; ++i) { /* This does the SDL_LoadBMP step repeatedly, but that's OK for test code. */ - sprites[i] = LoadTexture(state->renderers[i], file, SDL_TRUE, &sprite_w, &sprite_h); + sprites[i] = LoadTexture(state->renderers[i], file, true, &sprite_w, &sprite_h); if (!sprites[i]) { return -1; } - if (SDL_SetTextureBlendMode(sprites[i], blendMode) < 0) { + if (!SDL_SetTextureBlendMode(sprites[i], blendMode)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set blend mode: %s\n", SDL_GetError()); SDL_DestroyTexture(sprites[i]); return -1; @@ -309,7 +309,7 @@ loop() /* Check for events */ while (SDL_PollEvent(&event)) { if (event.type == SDL_EVENT_KEY_DOWN && !event.key.repeat) { - SDL_Log("Initial SDL_EVENT_KEY_DOWN: %s", SDL_GetScancodeName(event.key.keysym.scancode)); + SDL_Log("Initial SDL_EVENT_KEY_DOWN: %s", SDL_GetScancodeName(event.key.scancode)); } #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) /* On Xbox, ignore the keydown event because the features aren't supported */ @@ -371,10 +371,10 @@ main(int argc, char *argv[]) } } } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) { - cycle_color = SDL_TRUE; + cycle_color = true; consumed = 1; } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) { - cycle_alpha = SDL_TRUE; + cycle_alpha = true; consumed = 1; } else if (SDL_isdigit(*argv[i])) { num_sprites = SDL_atoi(argv[i]); @@ -425,7 +425,7 @@ main(int argc, char *argv[]) } /* Load the wave file into memory */ - if (SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen) == -1) { + if (!SDL_LoadWAV(soundname, &wave.spec, &wave.sound, &wave.soundlen)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n", soundname, SDL_GetError()); quit(1); } @@ -438,7 +438,7 @@ main(int argc, char *argv[]) SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver()); - stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, &wave.spec, NULL, NULL); + stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &wave.spec, NULL, NULL); if (!stream) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create audio stream: %s\n", SDL_GetError()); return -1; diff --git a/libs/SDL3/VisualC-GDK/tests/testgdk/testgdk.vcxproj b/libs/SDL3/VisualC-GDK/tests/testgdk/testgdk.vcxproj index c43e5f4d9..41293cada 100644 --- a/libs/SDL3/VisualC-GDK/tests/testgdk/testgdk.vcxproj +++ b/libs/SDL3/VisualC-GDK/tests/testgdk/testgdk.vcxproj @@ -63,27 +63,21 @@ - - - - - - @@ -290,6 +284,11 @@ + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC-GDK/tests/testsprite/testsprite.vcxproj b/libs/SDL3/VisualC-GDK/tests/testsprite/testsprite.vcxproj index 9534f5b0b..3885aec28 100644 --- a/libs/SDL3/VisualC-GDK/tests/testsprite/testsprite.vcxproj +++ b/libs/SDL3/VisualC-GDK/tests/testsprite/testsprite.vcxproj @@ -63,27 +63,21 @@ - - - - - - @@ -290,6 +284,11 @@ + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} @@ -386,4 +385,4 @@ copy "%(FullPath)" "$(OutDir)\" - \ No newline at end of file + diff --git a/libs/SDL3/VisualC-WinRT/SDL-UWP.sln b/libs/SDL3/VisualC-WinRT/SDL-UWP.sln deleted file mode 100644 index 86bd92dea..000000000 --- a/libs/SDL3/VisualC-WinRT/SDL-UWP.sln +++ /dev/null @@ -1,69 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.33027.164 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL3-UWP", "SDL-UWP.vcxproj", "{89E9B32E-A86A-47C3-A948-D2B1622925CE}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdraw", "testdraw\testdraw.vcxproj", "{95943BBE-F378-4068-A3FD-DAE1B8309B6E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Debug|ARM64 = Debug|ARM64 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|ARM = Release|ARM - Release|ARM64 = Release|ARM64 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|ARM.ActiveCfg = Debug|ARM - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|ARM.Build.0 = Debug|ARM - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|ARM64.Build.0 = Debug|ARM64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|x64.ActiveCfg = Debug|x64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|x64.Build.0 = Debug|x64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|x86.ActiveCfg = Debug|Win32 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Debug|x86.Build.0 = Debug|Win32 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|ARM.ActiveCfg = Release|ARM - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|ARM.Build.0 = Release|ARM - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|ARM64.ActiveCfg = Release|ARM64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|ARM64.Build.0 = Release|ARM64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|x64.ActiveCfg = Release|x64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|x64.Build.0 = Release|x64 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|x86.ActiveCfg = Release|Win32 - {89E9B32E-A86A-47C3-A948-D2B1622925CE}.Release|x86.Build.0 = Release|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM.ActiveCfg = Debug|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM.Build.0 = Debug|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM.Deploy.0 = Debug|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM64.Build.0 = Debug|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|ARM64.Deploy.0 = Debug|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x64.ActiveCfg = Debug|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x64.Build.0 = Debug|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x64.Deploy.0 = Debug|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x86.ActiveCfg = Debug|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x86.Build.0 = Debug|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Debug|x86.Deploy.0 = Debug|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM.ActiveCfg = Release|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM.Build.0 = Release|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM.Deploy.0 = Release|ARM - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM64.ActiveCfg = Release|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM64.Build.0 = Release|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|ARM64.Deploy.0 = Release|ARM64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x64.ActiveCfg = Release|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x64.Build.0 = Release|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x64.Deploy.0 = Release|x64 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x86.ActiveCfg = Release|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x86.Build.0 = Release|Win32 - {95943BBE-F378-4068-A3FD-DAE1B8309B6E}.Release|x86.Deploy.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {30680F51-7BB9-41D0-A0D6-BC44A1557D87} - EndGlobalSection -EndGlobal diff --git a/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj b/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj deleted file mode 100644 index ba706bb95..000000000 --- a/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj +++ /dev/null @@ -1,906 +0,0 @@ - - - - - Debug - ARM64 - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - Create - Create - Create - Create - Create - Create - Create - Create - - - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - Create - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - - - - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NotUsing - - - - - - - - - - - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - true - true - true - true - true - true - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - true - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - $(IntDir)$(TargetName)_cpp.pch - - - - - - - {89e9b32e-a86a-47c3-a948-d2b1622925ce} - DynamicLibrary - SDL3-UWP - SDL3 - en-US - 14.0 - true - Windows Store - 8.2 - 10.0.16299.0 - 10.0.16299.0 - 10.0 - - - - DynamicLibrary - true - v142 - - - DynamicLibrary - true - v142 - - - DynamicLibrary - true - v142 - - - DynamicLibrary - true - v142 - - - DynamicLibrary - false - true - v142 - - - DynamicLibrary - false - true - v142 - - - DynamicLibrary - false - true - v142 - - - DynamicLibrary - false - true - v142 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - false - false - SDL3 - $(SolutionDir)/../src;$(IncludePath) - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - - - Use - false - ..\include;%(AdditionalIncludeDirectories) - DLL_EXPORT;_CRT_SECURE_NO_WARNINGS;SDL_BUILDING_WINRT=1;%(PreprocessorDefinitions) - SDL_internal.h - - - Console - false - false - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - - - - - diff --git a/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj.filters b/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj.filters deleted file mode 100644 index a8da66c1a..000000000 --- a/libs/SDL3/VisualC-WinRT/SDL-UWP.vcxproj.filters +++ /dev/null @@ -1,960 +0,0 @@ - - - - - {fa0ff2df-c3d6-498a-96f1-1f88e7ce0da3} - - - {68e1b30b-19ed-4612-93e4-6260c5a979e5} - - - {00004a2523fc69c7128c60648c860000} - - - {0000318d975e0a2867ab1d5727bf0000} - - - {00009e5236c2ac679fe0bc30beb90000} - - - {000031d805439b865ff4550d2f620000} - - - {00004389761f0ae646deb5a3d65f0000} - - - {0000bc587ef6c558d75ce2e620cb0000} - - - {0000948771d0040a6a55997a7f1e0000} - - - {0000012051ca8361c8e1013aee1d0000} - - - - - Header Files - - - API Headers - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - camera - - - camera - - - filesystem - - - Header Files - - - Header Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - main - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - video - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Header Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Header Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - camera\dummy - - - camera - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - filesystem - - - filesystem\windows - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - main\generic - - - main - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - time - - - time\windows - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - stdlib - - - Source Files - - - Source Files - - - diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/LockScreenLogo.scale-200.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/LockScreenLogo.scale-200.png deleted file mode 100644 index 735f57adb..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/LockScreenLogo.scale-200.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/SplashScreen.scale-200.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/SplashScreen.scale-200.png deleted file mode 100644 index 023e7f1fe..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/SplashScreen.scale-200.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square150x150Logo.scale-200.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square150x150Logo.scale-200.png deleted file mode 100644 index af49fec1a..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square150x150Logo.scale-200.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.scale-200.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.scale-200.png deleted file mode 100644 index ce342a2ec..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.scale-200.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.targetsize-24_altform-unplated.png deleted file mode 100644 index f6c02ce97..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Square44x44Logo.targetsize-24_altform-unplated.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/StoreLogo.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/StoreLogo.png deleted file mode 100644 index 7385b56c0..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/StoreLogo.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Wide310x150Logo.scale-200.png b/libs/SDL3/VisualC-WinRT/testdraw/Assets/Wide310x150Logo.scale-200.png deleted file mode 100644 index 288995b39..000000000 Binary files a/libs/SDL3/VisualC-WinRT/testdraw/Assets/Wide310x150Logo.scale-200.png and /dev/null differ diff --git a/libs/SDL3/VisualC-WinRT/testdraw/Package.appxmanifest b/libs/SDL3/VisualC-WinRT/testdraw/Package.appxmanifest deleted file mode 100644 index 05a4c5750..000000000 --- a/libs/SDL3/VisualC-WinRT/testdraw/Package.appxmanifest +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - testdraw - Daniel - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj b/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj deleted file mode 100644 index f612acf98..000000000 --- a/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj +++ /dev/null @@ -1,331 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - Debug - ARM - - - Release - ARM - - - Debug - ARM64 - - - Release - ARM64 - - - - {95943bbe-f378-4068-a3fd-dae1b8309b6e} - DirectXApp - testdraw - en-US - 14.0 - true - Windows Store - 10.0.19041.0 - 10.0.17763.0 - 10.0 - false - - - - Application - true - v142 - - - Application - true - v142 - - - Application - true - v142 - true - - - Application - true - v142 - - - Application - false - true - v142 - true - - - Application - false - true - v142 - true - - - Application - false - true - v142 - true - - - Application - false - true - v142 - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - _DEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm; $(VCInstallDir)\lib\arm - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - NDEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm64; $(VCInstallDir)\lib\arm64 - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - _DEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\arm64; $(VCInstallDir)\lib\arm64 - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - NDEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - _DEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store; $(VCInstallDir)\lib - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - NDEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 - /nodefaultlib:vccorlibd /nodefaultlib:msvcrtd vccorlibd.lib msvcrtd.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - _DEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - d2d1.lib; d3d11.lib; dxgi.lib; windowscodecs.lib; dwrite.lib; %(AdditionalDependencies) - %(AdditionalLibraryDirectories); $(VCInstallDir)\lib\store\amd64; $(VCInstallDir)\lib\amd64 - /nodefaultlib:vccorlib /nodefaultlib:msvcrt vccorlib.lib msvcrt.lib %(AdditionalOptions) - - - pch.h - $(IntDir)pch.pch - $(ProjectDir);$(IntermediateOutputPath);..\..\include - /bigobj %(AdditionalOptions) - 4453;28204 - NDEBUG;%(PreprocessorDefinitions) - false - NotUsing - - - - - - - - - - - - - - Designer - - - - - {89e9b32e-a86a-47c3-a948-d2b1622925ce} - - - - - - - - - - - - - - - - true - true - true - true - true - true - true - true - - - false - false - false - false - false - false - false - false - - - - - - - - - - - - - - - diff --git a/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj.filters b/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj.filters deleted file mode 100644 index d41d939d6..000000000 --- a/libs/SDL3/VisualC-WinRT/testdraw/testdraw.vcxproj.filters +++ /dev/null @@ -1,88 +0,0 @@ - - - - - 95943bbe-f378-4068-a3fd-dae1b8309b6e - - - dad3d573-ab33-428d-ae70-6098066c27e7 - bmp;fbx;gif;jpg;jpeg;tga;tiff;tif;png - - - e4caa635-e149-44c2-8915-48ffa6ac48f7 - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - Assets - - - - - Assets - - - - - - - - Content - - - Content - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - Common - - - - - - - - - diff --git a/libs/SDL3/VisualC/SDL.sln b/libs/SDL3/VisualC/SDL.sln index 67484805d..f0492dfb1 100644 --- a/libs/SDL3/VisualC/SDL.sln +++ b/libs/SDL3/VisualC/SDL.sln @@ -12,6 +12,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testatomic", "tests\testato EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testautomation", "tests\testautomation\testautomation.vcxproj", "{9C7E8C03-3130-436D-A97E-E8F8ED1AC4EA}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdialog", "tests\testdialog\testdialog.vcxproj", "{97A3A89b-E023-48CD-905F-CDBDE8D951DE}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testdraw", "tests\testdraw\testdraw.vcxproj", "{8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testfile", "tests\testfile\testfile.vcxproj", "{CAE4F1D0-314F-4B10-805B-0EFD670133A0}" @@ -100,6 +102,14 @@ Global {9C7E8C03-3130-436D-A97E-E8F8ED1AC4EA}.Release|Win32.Build.0 = Release|Win32 {9C7E8C03-3130-436D-A97E-E8F8ED1AC4EA}.Release|x64.ActiveCfg = Release|x64 {9C7E8C03-3130-436D-A97E-E8F8ED1AC4EA}.Release|x64.Build.0 = Release|x64 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Debug|Win32.ActiveCfg = Debug|Win32 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Debug|Win32.Build.0 = Debug|Win32 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Debug|x64.ActiveCfg = Debug|x64 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Debug|x64.Build.0 = Debug|x64 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Release|Win32.ActiveCfg = Release|Win32 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Release|Win32.Build.0 = Release|Win32 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Release|x64.ActiveCfg = Release|x64 + {97A3A89b-E023-48CD-905F-CDBDE8D951DE}.Release|x64.Build.0 = Release|x64 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|Win32.ActiveCfg = Debug|Win32 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|Win32.Build.0 = Debug|Win32 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|x64.ActiveCfg = Debug|x64 @@ -269,6 +279,7 @@ Global {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {66B32F7E-5716-48D0-B5B9-D832FD052DD5} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {9C7E8C03-3130-436D-A97E-E8F8ED1AC4EA} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} + {97A3A89b-E023-48CD-905F-CDBDE8D951DE} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {CAE4F1D0-314F-4B10-805B-0EFD670133A0} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} {8B5CFB38-CCBA-40A8-AD7A-89C57B070884} = {D69D5741-611F-4E14-8541-1FEE94F50B5A} diff --git a/libs/SDL3/VisualC/SDL/SDL.vcxproj b/libs/SDL3/VisualC/SDL/SDL.vcxproj index 7cc840594..a6371238f 100644 --- a/libs/SDL3/VisualC/SDL/SDL.vcxproj +++ b/libs/SDL3/VisualC/SDL/SDL.vcxproj @@ -47,19 +47,15 @@ - - - - @@ -112,7 +108,7 @@ Disabled - $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) + $(ProjectDir)/../../include;$(ProjectDir)/../../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -144,7 +140,7 @@ Disabled - $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) + $(ProjectDir)/../../include;$(ProjectDir)/../../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -178,7 +174,7 @@ .\Release/SDL.tlb - $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) + $(ProjectDir)/../../include;$(ProjectDir)/../../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -211,7 +207,7 @@ .\Release/SDL.tlb - $(ProjectDir)/../../include;%(AdditionalIncludeDirectories) + $(ProjectDir)/../../include;$(ProjectDir)/../../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) DLL_EXPORT;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) false @@ -234,6 +230,11 @@ true + + + $(TreatWarningsAsError) + + @@ -253,6 +254,7 @@ + @@ -282,8 +284,8 @@ + - @@ -305,7 +307,6 @@ - @@ -338,15 +339,19 @@ + + + + @@ -404,10 +409,17 @@ + + + + + + + @@ -451,6 +463,12 @@ + + + + + + @@ -460,6 +478,7 @@ + @@ -468,6 +487,7 @@ + @@ -504,7 +524,6 @@ - @@ -517,11 +536,13 @@ NotUsing NotUsing + + @@ -548,6 +569,7 @@ + @@ -580,6 +602,10 @@ + + + + @@ -591,12 +617,17 @@ + + + + + @@ -637,7 +668,9 @@ NotUsing + + @@ -660,6 +693,12 @@ + + + + + + @@ -685,6 +724,7 @@ + diff --git a/libs/SDL3/VisualC/SDL/SDL.vcxproj.filters b/libs/SDL3/VisualC/SDL/SDL.vcxproj.filters index 77b54b847..ada794006 100644 --- a/libs/SDL3/VisualC/SDL/SDL.vcxproj.filters +++ b/libs/SDL3/VisualC/SDL/SDL.vcxproj.filters @@ -172,6 +172,9 @@ {f48c2b17-1bee-4fec-a7c8-24cf619abe08} + + {653672cc-90ae-4eba-a256-6479f2c31804} + {00001967ea2801028a046a722a070000} @@ -196,6 +199,18 @@ {0000d7fda065b13b0ca4ab262c380000} + + {098fbef9-d8a0-4b3b-b57b-d157d395335d} + + + {00008dfdfa0190856fbf3c7db52d0000} + + + {748cf015-00b8-4e71-ac48-02e947e4d93d} + + + {00009d5ded166cc6c6680ec771a30000} + @@ -333,10 +348,10 @@ API Headers - + API Headers - + API Headers @@ -396,9 +411,6 @@ API Headers - - API Headers - API Headers @@ -489,6 +501,9 @@ dynapi + + events + events @@ -504,6 +519,9 @@ events + + events + events @@ -606,6 +624,9 @@ video + + video + video @@ -669,6 +690,9 @@ video\windows + + video\windows + video\windows @@ -862,6 +886,7 @@ + @@ -871,6 +896,33 @@ render\vulkan + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + API Headers + + + gpu + + + gpu + @@ -883,6 +935,9 @@ camera + + dialog + filesystem @@ -895,6 +950,12 @@ main + + main + + + main\windows + @@ -937,9 +998,6 @@ core - - core - core\windows @@ -961,6 +1019,9 @@ dynapi + + events + events @@ -976,6 +1037,9 @@ events + + events + events @@ -1066,6 +1130,18 @@ libm + + libm + + + libm + + + libm + + + libm + libm @@ -1153,6 +1229,9 @@ joystick\hidapi + + joystick\hidapi + joystick\hidapi @@ -1282,6 +1361,9 @@ video\windows + + video\windows + video\windows @@ -1366,9 +1448,15 @@ stdlib + + stdlib + stdlib + + stdlib + stdlib @@ -1411,6 +1499,15 @@ render\direct3d11 + + render\gpu + + + render\gpu + + + render\gpu + render\opengl @@ -1450,10 +1547,16 @@ power - power\windows + + process + + + process\windows + + render\direct3d12 @@ -1467,6 +1570,7 @@ stdlib + @@ -1476,6 +1580,36 @@ render\vulkan + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + video\offscreen + + + gpu + + + gpu + + + gpu + + + gpu + diff --git a/libs/SDL3/VisualC/SDL_test/SDL_test.vcxproj b/libs/SDL3/VisualC/SDL_test/SDL_test.vcxproj index f69b2e5f6..541f7cb0c 100644 --- a/libs/SDL3/VisualC/SDL_test/SDL_test.vcxproj +++ b/libs/SDL3/VisualC/SDL_test/SDL_test.vcxproj @@ -46,19 +46,15 @@ - - - - @@ -156,6 +152,11 @@ true + + + $(TreatWarningsAsError) + + @@ -167,9 +168,8 @@ - - \ No newline at end of file + diff --git a/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config-version.cmake b/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config-version.cmake index 3c455dc19..e766f1d4a 100644 --- a/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config-version.cmake +++ b/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config-version.cmake @@ -13,10 +13,10 @@ string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re set(_sdl_major "${CMAKE_MATCH_1}") string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_version_h}") set(_sdl_minor "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl_patch_re "${_sdl_version_h}") -set(_sdl_patch "${CMAKE_MATCH_1}") -if(_sdl_major_re AND _sdl_minor_re AND _sdl_patch_re) - set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_patch}") +string(REGEX MATCH "#define[ \t]+SDL_MICRO_VERSION[ \t]+([0-9]+)" _sdl_micro_re "${_sdl_version_h}") +set(_sdl_micro "${CMAKE_MATCH_1}") +if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re) + set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}") else() message(AUTHOR_WARNING "Could not extract version from SDL3/SDL_version.h.") return() @@ -47,8 +47,11 @@ if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "") set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() -# check that the installed version has the same 32/64bit-ness as the one which is currently searching: -if(NOT (CMAKE_SIZEOF_VOID_P STREQUAL "8" OR CMAKE_SIZEOF_VOID_P STREQUAL "4")) - set(PACKAGE_VERSION "${PACKAGE_VERSION} (32+64bit)") +include("${CMAKE_CURRENT_LIST_DIR}/sdlcpu.cmake") +SDL_DetectTargetCPUArchitectures(_detected_archs) + +# check that the installed version has a compatible architecture as the one which is currently searching: +if(NOT(SDL_CPU_X86 OR SDL_CPU_X64 OR SDL_CPU_ARM64 OR SDL_CPU_ARM64EC)) + set(PACKAGE_VERSION "${PACKAGE_VERSION} (X86,X64,ARM64)") set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() diff --git a/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config.cmake b/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config.cmake index fda40b7de..9995847cd 100644 --- a/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config.cmake +++ b/libs/SDL3/VisualC/pkg-support/cmake/sdl3-config.cmake @@ -30,10 +30,12 @@ endmacro() set(SDL3_FOUND TRUE) -if(CMAKE_SIZEOF_VOID_P STREQUAL "4") +if(SDL_CPU_X86) set(_sdl_arch_subdir "x86") -elseif(CMAKE_SIZEOF_VOID_P STREQUAL "8") +elseif(SDL_CPU_X64 OR SDL_CPU_ARM64EC) set(_sdl_arch_subdir "x64") +elseif(SDL_CPU_ARM64) + set(_sdl_arch_subdir "arm64") else() set(SDL3_FOUND FALSE) return() @@ -41,11 +43,11 @@ endif() get_filename_component(_sdl3_prefix "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) set_and_check(_sdl3_prefix "${_sdl3_prefix}") -set(_sdl3_include_dirs "${_sdl3_prefix}/include;${_sdl3_prefix}/include/SDL3") +set(_sdl3_include_dirs "${_sdl3_prefix}/include") -set(_sdl3_library "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.lib") -set(_sdl3_dll_library "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.dll") -set(_sdl3test_library "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3_test.lib") +set(_sdl3_implib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.lib") +set(_sdl3_dll "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3.dll") +set(_sdl3test_lib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/SDL3_test.lib") unset(_sdl_arch_subdir) unset(_sdl3_prefix) @@ -63,14 +65,14 @@ endif() set(SDL3_Headers_FOUND TRUE) unset(_sdl3_include_dirs) -if(EXISTS "${_sdl3_library}" AND EXISTS "${_sdl3_dll_library}") +if(EXISTS "${_sdl3_implib}" AND EXISTS "${_sdl3_dll}") if(NOT TARGET SDL3::SDL3-shared) add_library(SDL3::SDL3-shared SHARED IMPORTED) set_target_properties(SDL3::SDL3-shared PROPERTIES INTERFACE_LINK_LIBRARIES "SDL3::Headers" - IMPORTED_IMPLIB "${_sdl3_library}" - IMPORTED_LOCATION "${_sdl3_dll_library}" + IMPORTED_IMPLIB "${_sdl3_implib}" + IMPORTED_LOCATION "${_sdl3_dll}" COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" INTERFACE_SDL3_SHARED "ON" COMPATIBLE_INTERFACE_STRING "SDL_VERSION" @@ -81,18 +83,18 @@ if(EXISTS "${_sdl3_library}" AND EXISTS "${_sdl3_dll_library}") else() set(SDL3_SDL3-shared_FOUND FALSE) endif() -unset(_sdl3_library) -unset(_sdl3_dll_library) +unset(_sdl3_implib) +unset(_sdl3_dll) set(SDL3_SDL3-static_FOUND FALSE) -if(EXISTS "${_sdl3test_library}") +if(EXISTS "${_sdl3test_lib}") if(NOT TARGET SDL3::SDL3_test) add_library(SDL3::SDL3_test STATIC IMPORTED) set_target_properties(SDL3::SDL3_test PROPERTIES INTERFACE_LINK_LIBRARIES "SDL3::Headers" - IMPORTED_LOCATION "${_sdl3test_library}" + IMPORTED_LOCATION "${_sdl3test_lib}" COMPATIBLE_INTERFACE_STRING "SDL_VERSION" INTERFACE_SDL_VERSION "SDL3" ) @@ -101,7 +103,7 @@ if(EXISTS "${_sdl3test_library}") else() set(SDL3_SDL3_test_FOUND FALSE) endif() -unset(_sdl3test_library) +unset(_sdl3test_lib) if(SDL3_SDL3-shared_FOUND) set(SDL3_SDL3_FOUND TRUE) diff --git a/libs/SDL3/VisualC/tests/checkkeys/checkkeys.vcxproj b/libs/SDL3/VisualC/tests/checkkeys/checkkeys.vcxproj index cb3f0eeea..cc263df07 100644 --- a/libs/SDL3/VisualC/tests/checkkeys/checkkeys.vcxproj +++ b/libs/SDL3/VisualC/tests/checkkeys/checkkeys.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -187,6 +183,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/loopwave/loopwave.vcxproj b/libs/SDL3/VisualC/tests/loopwave/loopwave.vcxproj index d755abe9f..a5912a9a8 100644 --- a/libs/SDL3/VisualC/tests/loopwave/loopwave.vcxproj +++ b/libs/SDL3/VisualC/tests/loopwave/loopwave.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -187,6 +183,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testatomic/testatomic.vcxproj b/libs/SDL3/VisualC/tests/testatomic/testatomic.vcxproj index d8b7bf9a5..5a1efef2d 100644 --- a/libs/SDL3/VisualC/tests/testatomic/testatomic.vcxproj +++ b/libs/SDL3/VisualC/tests/testatomic/testatomic.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testautomation/testautomation.vcxproj b/libs/SDL3/VisualC/tests/testautomation/testautomation.vcxproj index 84539df43..ba737643f 100644 --- a/libs/SDL3/VisualC/tests/testautomation/testautomation.vcxproj +++ b/libs/SDL3/VisualC/tests/testautomation/testautomation.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -93,7 +89,7 @@ Disabled - $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + $(SolutionDir)/../include;$(SolutionDir)/../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDLL @@ -119,7 +115,7 @@ Disabled - $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + $(SolutionDir)/../include;$(SolutionDir)/../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDebugDLL @@ -144,7 +140,7 @@ .\Release/testautomation.tlb - $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + $(SolutionDir)/../include;$(SolutionDir)/../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDLL @@ -167,7 +163,7 @@ .\Release/testautomation.tlb - $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + $(SolutionDir)/../include;$(SolutionDir)/../include/build_config;%(AdditionalIncludeDirectories) %(AdditionalUsingDirectories) WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) MultiThreadedDLL @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} @@ -198,6 +199,7 @@ + @@ -210,12 +212,6 @@ - - $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) - $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) - $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) - $(ProjectDir)\..\..\..\src;%(AdditionalIncludeDirectories) - @@ -236,4 +232,4 @@ - + \ No newline at end of file diff --git a/libs/SDL3/VisualC/tests/testcontroller/testcontroller.vcxproj b/libs/SDL3/VisualC/tests/testcontroller/testcontroller.vcxproj index 5bdcc3b21..94c8629a1 100644 --- a/libs/SDL3/VisualC/tests/testcontroller/testcontroller.vcxproj +++ b/libs/SDL3/VisualC/tests/testcontroller/testcontroller.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testdialog/testdialog.vcxproj b/libs/SDL3/VisualC/tests/testdialog/testdialog.vcxproj new file mode 100644 index 000000000..9961cf25e --- /dev/null +++ b/libs/SDL3/VisualC/tests/testdialog/testdialog.vcxproj @@ -0,0 +1,205 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {97A3A89B-E023-48CD-905F-CDBDE8D951DE} + testdialog + 10.0 + + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + Application + $(DefaultPlatformToolset) + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/testdialog.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Debug/testdialog.tlb + + + Disabled + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + OldStyle + + + _DEBUG;%(PreprocessorDefinitions) + 0x0409 + + + true + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release/testdialog.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + .\Release/testdialog.tlb + + + $(SolutionDir)/../include;%(AdditionalIncludeDirectories) + %(AdditionalUsingDirectories) + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + + + NDEBUG;%(PreprocessorDefinitions) + 0x0409 + + + Windows + + + + + $(TreatWarningsAsError) + + + + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} + false + false + true + + + {da956fd3-e143-46f2-9fe5-c77bebc56b1a} + false + false + true + + + + + + + + + \ No newline at end of file diff --git a/libs/SDL3/VisualC/tests/testdraw/testdraw.vcxproj b/libs/SDL3/VisualC/tests/testdraw/testdraw.vcxproj index 9e985c3c6..5ca57bf08 100644 --- a/libs/SDL3/VisualC/tests/testdraw/testdraw.vcxproj +++ b/libs/SDL3/VisualC/tests/testdraw/testdraw.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testfile/testfile.vcxproj b/libs/SDL3/VisualC/tests/testfile/testfile.vcxproj index f0e138eed..a38880d5e 100644 --- a/libs/SDL3/VisualC/tests/testfile/testfile.vcxproj +++ b/libs/SDL3/VisualC/tests/testfile/testfile.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testgl/testgl.vcxproj b/libs/SDL3/VisualC/tests/testgl/testgl.vcxproj index 02dc5c6f1..b8bc234ec 100644 --- a/libs/SDL3/VisualC/tests/testgl/testgl.vcxproj +++ b/libs/SDL3/VisualC/tests/testgl/testgl.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -185,6 +181,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testgles2/testgles2.vcxproj b/libs/SDL3/VisualC/tests/testgles2/testgles2.vcxproj index 153b64fdd..13d0df290 100644 --- a/libs/SDL3/VisualC/tests/testgles2/testgles2.vcxproj +++ b/libs/SDL3/VisualC/tests/testgles2/testgles2.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testoverlay/testoverlay.vcxproj b/libs/SDL3/VisualC/tests/testoverlay/testoverlay.vcxproj index 851bc2fd9..80c8b0304 100644 --- a/libs/SDL3/VisualC/tests/testoverlay/testoverlay.vcxproj +++ b/libs/SDL3/VisualC/tests/testoverlay/testoverlay.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testpen/testpen.vcxproj b/libs/SDL3/VisualC/tests/testpen/testpen.vcxproj index dc1a28e0b..fdef64f23 100644 --- a/libs/SDL3/VisualC/tests/testpen/testpen.vcxproj +++ b/libs/SDL3/VisualC/tests/testpen/testpen.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testplatform/testplatform.vcxproj b/libs/SDL3/VisualC/tests/testplatform/testplatform.vcxproj index b88aa4f7b..7752f733f 100644 --- a/libs/SDL3/VisualC/tests/testplatform/testplatform.vcxproj +++ b/libs/SDL3/VisualC/tests/testplatform/testplatform.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -111,10 +107,6 @@ true Windows - - true - .\Debug/testplatform.bsc - @@ -144,10 +136,6 @@ true Windows - - true - .\Debug/testplatform.bsc - @@ -174,10 +162,6 @@ Windows - - true - .\Release/testplatform.bsc - @@ -204,10 +188,11 @@ Windows - - true - .\Release/testplatform.bsc - + + + + $(TreatWarningsAsError) + diff --git a/libs/SDL3/VisualC/tests/testpower/testpower.vcxproj b/libs/SDL3/VisualC/tests/testpower/testpower.vcxproj index 308555f53..98ca2b53a 100644 --- a/libs/SDL3/VisualC/tests/testpower/testpower.vcxproj +++ b/libs/SDL3/VisualC/tests/testpower/testpower.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testrendertarget/testrendertarget.vcxproj b/libs/SDL3/VisualC/tests/testrendertarget/testrendertarget.vcxproj index 23f4466ae..eaf719bb2 100644 --- a/libs/SDL3/VisualC/tests/testrendertarget/testrendertarget.vcxproj +++ b/libs/SDL3/VisualC/tests/testrendertarget/testrendertarget.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testrumble/testrumble.vcxproj b/libs/SDL3/VisualC/tests/testrumble/testrumble.vcxproj index 6fab2f944..c0cb1090b 100644 --- a/libs/SDL3/VisualC/tests/testrumble/testrumble.vcxproj +++ b/libs/SDL3/VisualC/tests/testrumble/testrumble.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testscale/testscale.vcxproj b/libs/SDL3/VisualC/tests/testscale/testscale.vcxproj index 4e4c6f53e..3843e57ae 100644 --- a/libs/SDL3/VisualC/tests/testscale/testscale.vcxproj +++ b/libs/SDL3/VisualC/tests/testscale/testscale.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testsensor/testsensor.vcxproj b/libs/SDL3/VisualC/tests/testsensor/testsensor.vcxproj index cf480e586..3f034ad39 100644 --- a/libs/SDL3/VisualC/tests/testsensor/testsensor.vcxproj +++ b/libs/SDL3/VisualC/tests/testsensor/testsensor.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testshape/testshape.vcxproj b/libs/SDL3/VisualC/tests/testshape/testshape.vcxproj index 1c59aa430..33521f684 100644 --- a/libs/SDL3/VisualC/tests/testshape/testshape.vcxproj +++ b/libs/SDL3/VisualC/tests/testshape/testshape.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testsprite/testsprite.vcxproj b/libs/SDL3/VisualC/tests/testsprite/testsprite.vcxproj index fa00f8e3e..f53408ff5 100644 --- a/libs/SDL3/VisualC/tests/testsprite/testsprite.vcxproj +++ b/libs/SDL3/VisualC/tests/testsprite/testsprite.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testsurround/testsurround.vcxproj b/libs/SDL3/VisualC/tests/testsurround/testsurround.vcxproj index 47c5cff3e..657dd1f3d 100644 --- a/libs/SDL3/VisualC/tests/testsurround/testsurround.vcxproj +++ b/libs/SDL3/VisualC/tests/testsurround/testsurround.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -187,6 +183,11 @@ Console + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testvulkan/testvulkan.vcxproj b/libs/SDL3/VisualC/tests/testvulkan/testvulkan.vcxproj index 3fb60d7c9..800aa50ff 100644 --- a/libs/SDL3/VisualC/tests/testvulkan/testvulkan.vcxproj +++ b/libs/SDL3/VisualC/tests/testvulkan/testvulkan.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {da956fd3-e143-46f2-9fe5-c77bebc56b1a} diff --git a/libs/SDL3/VisualC/tests/testwm/testwm.vcxproj b/libs/SDL3/VisualC/tests/testwm/testwm.vcxproj index cbff83797..b16df2434 100644 --- a/libs/SDL3/VisualC/tests/testwm/testwm.vcxproj +++ b/libs/SDL3/VisualC/tests/testwm/testwm.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/VisualC/tests/testyuv/testyuv.vcxproj b/libs/SDL3/VisualC/tests/testyuv/testyuv.vcxproj index 9df29c3d5..e0eefbd74 100644 --- a/libs/SDL3/VisualC/tests/testyuv/testyuv.vcxproj +++ b/libs/SDL3/VisualC/tests/testyuv/testyuv.vcxproj @@ -45,19 +45,15 @@ - - - - @@ -181,6 +177,11 @@ Windows + + + $(TreatWarningsAsError) + + {81ce8daf-ebb2-4761-8e45-b71abcca8c68} diff --git a/libs/SDL3/WhatsNew.txt b/libs/SDL3/WhatsNew.txt index 654997118..63d347580 100644 --- a/libs/SDL3/WhatsNew.txt +++ b/libs/SDL3/WhatsNew.txt @@ -1,33 +1,33 @@ - -This is a list of major changes in SDL's version history. - ---------------------------------------------------------------------------- -3.1.0: ---------------------------------------------------------------------------- - -This is a preview release of the new SDL 3.0 API. - -The ABI hasn't been locked down yet, but it's fairly stable and feedback is welcome! - -Check out [migration guide](docs/README-migration.md) for details on API changes since SDL 2.0, and tips on transitioning your code from SDL2 code to SDL3. - -There have been too many changes to list them all, but here are some of the highlights: -* The API has been significantly reworked to be easier to use and more consistent -* The 2D rendering API now has support for more advanced colorspaces and HDR rendering -* The 2D rendering API now has a Vulkan backend -* An example of hardware accelerated video playback using ffmpeg has been added in test/testffmpeg.c -* The shaped window API has been replaced with transparent windows -* Time and date functions have been added in SDL_time.h -* Support for webcam video capture has been added in SDL_camera.h -* Support for handling pens and tablets has been added in SDL_pen.h -* Support for file open and save dialogs has been added in SDL_dialog.h -* Cross-platform functions for working with files and directories are available in SDL_filesystem.h -* A cross-platform abstraction for working with user and game data has been added in SDL_storage.h -* Handling of main() has been moved to a header library and an optional callback-based program flow is available -* Support for simple object properties has been added in SDL_properties.h. These properties are available on many SDL objects, and can be used for more advanced functionality. - -Please let us know about issues and feedback at: https://github.com/libsdl-org/SDL/issues - -The development team is focused on code, moving towards the final release, and we would love volunteers to help improve the documentation. Please send e-mail to slouken@libsdl.org if you'd like to help out! - -Finally, a giant thank you to all the people who have contributed code and feedback to the SDL 3.0 improvements! + +This is a list of major changes in SDL's version history. + +--------------------------------------------------------------------------- +3.1.0: +--------------------------------------------------------------------------- + +This is a preview release of the new SDL 3.0 API. + +The ABI hasn't been locked down yet, but it's fairly stable and feedback is welcome! + +Check out [migration guide](docs/README-migration.md) for details on API changes since SDL 2.0, and tips on transitioning your code from SDL2 code to SDL3. + +There have been too many changes to list them all, but here are some of the highlights: +* The API has been significantly reworked to be easier to use and more consistent +* The 2D rendering API now has support for more advanced colorspaces and HDR rendering +* The 2D rendering API now has a Vulkan backend +* An example of hardware accelerated video playback using ffmpeg has been added in test/testffmpeg.c +* The shaped window API has been replaced with transparent windows +* Time and date functions have been added in SDL_time.h +* Support for webcam video recording has been added in SDL_camera.h +* Support for handling pens and tablets has been added in SDL_pen.h +* Support for file open and save dialogs has been added in SDL_dialog.h +* Cross-platform functions for working with files and directories are available in SDL_filesystem.h +* A cross-platform abstraction for working with user and game data has been added in SDL_storage.h +* Handling of main() has been moved to a header library and an optional callback-based program flow is available +* Support for simple object properties has been added in SDL_properties.h. These properties are available on many SDL objects, and can be used for more advanced functionality. + +Please let us know about issues and feedback at: https://github.com/libsdl-org/SDL/issues + +The development team is focused on code, moving towards the final release, and we would love volunteers to help improve the documentation. Please send e-mail to slouken@libsdl.org if you'd like to help out! + +Finally, a giant thank you to all the people who have contributed code and feedback to the SDL 3.0 improvements! diff --git a/libs/SDL3/Xcode/SDL/Info-Framework.plist b/libs/SDL3/Xcode/SDL/Info-Framework.plist index e0b0c8b99..5cd967ee3 100644 --- a/libs/SDL3/Xcode/SDL/Info-Framework.plist +++ b/libs/SDL3/Xcode/SDL/Info-Framework.plist @@ -19,10 +19,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.1.1 + 3.1.3 CFBundleSignature SDLX CFBundleVersion - 3.1.1 + 3.1.3 diff --git a/libs/SDL3/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/libs/SDL3/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 4ba76a901..de62829a9 100644 --- a/libs/SDL3/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/libs/SDL3/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 0000140640E77F73F1DF0000 /* SDL_dialog_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000F6C6A072ED4E3D660000 /* SDL_dialog_utils.c */; }; 00001B2471F503DD3C1B0000 /* SDL_camera_dummy.c in Sources */ = {isa = PBXBuildFile; fileRef = 00005BD74B46358B33A20000 /* SDL_camera_dummy.c */; }; 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */; }; 00002B20A48E055EB0350000 /* SDL_camera_coremedia.m in Sources */ = {isa = PBXBuildFile; fileRef = 00008B79BF08CBCEAC460000 /* SDL_camera_coremedia.m */; }; @@ -43,6 +44,7 @@ 000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000641A9BAC11AB3FBE0000 /* SDL_time.c */; }; 000098E9DAA43EF6FF7F0000 /* SDL_camera.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000035D38C3899C7EFD0000 /* SDL_camera.c */; }; 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; + 0000D5B526B85DE7AB1C0000 /* SDL_cocoapen.m in Sources */ = {isa = PBXBuildFile; fileRef = 0000CCA310B73A7B59910000 /* SDL_cocoapen.m */; }; 007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; platformFilters = (macos, ); }; 007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; platformFilters = (ios, maccatalyst, macos, ); }; 00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; platformFilters = (macos, ); }; @@ -60,6 +62,7 @@ 566E26D8246274CC00718109 /* SDL_locale.c in Sources */ = {isa = PBXBuildFile; fileRef = 566E26CD246274CB00718109 /* SDL_locale.c */; }; 566E26E1246274CC00718109 /* SDL_syslocale.h in Headers */ = {isa = PBXBuildFile; fileRef = 566E26CE246274CC00718109 /* SDL_syslocale.h */; }; 56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */; }; + 6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */ = {isa = PBXBuildFile; fileRef = 6312C66C2B42341400A7BB00 /* SDL_murmur3.c */; }; 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A212A7902CF0021E9A6 /* SDL_pen.h */; settings = {ATTRIBUTES = (Public, ); }; }; 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */; }; 63134A262A7902FD0021E9A6 /* SDL_pen.c in Sources */ = {isa = PBXBuildFile; fileRef = 63134A242A7902FD0021E9A6 /* SDL_pen.c */; }; @@ -228,8 +231,6 @@ A7D8B58723E2514300DCD162 /* SDL_joystick_c.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */; }; A7D8B5B723E2514300DCD162 /* controller_type.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7D923E2513E00DCD162 /* controller_type.h */; }; A7D8B5BD23E2514300DCD162 /* SDL_iostream.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */; }; - A7D8B5C323E2514300DCD162 /* SDL_iostreambundlesupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */; }; - A7D8B5C923E2514300DCD162 /* SDL_iostreambundlesupport.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */; }; A7D8B5CF23E2514300DCD162 /* SDL_syspower.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7E123E2513F00DCD162 /* SDL_syspower.m */; }; A7D8B5D523E2514300DCD162 /* SDL_syspower.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D8A7E223E2513F00DCD162 /* SDL_syspower.h */; }; A7D8B5E723E2514300DCD162 /* SDL_power.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A7E723E2513F00DCD162 /* SDL_power.c */; }; @@ -378,10 +379,23 @@ E479118E2BA9555500CE3B7F /* SDL_sysstorage.h in Headers */ = {isa = PBXBuildFile; fileRef = E47911882BA9555500CE3B7F /* SDL_sysstorage.h */; }; E479118F2BA9555500CE3B7F /* SDL_genericstorage.c in Sources */ = {isa = PBXBuildFile; fileRef = E479118A2BA9555500CE3B7F /* SDL_genericstorage.c */; }; E4A568B62AF763940062EEC4 /* SDL_sysmain_callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */; }; + E4F257712C818FE200FCEAFC /* SDL_gpu.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F257702C818FE200FCEAFC /* SDL_gpu.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E4F257912C81903800FCEAFC /* Metal_Blit.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F2577E2C81903800FCEAFC /* Metal_Blit.h */; }; + E4F257922C81903800FCEAFC /* Metal_Blit.metal in Sources */ = {isa = PBXBuildFile; fileRef = E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */; }; + E4F257932C81903800FCEAFC /* SDL_gpu_metal.m in Sources */ = {isa = PBXBuildFile; fileRef = E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */; }; + E4F257942C81903800FCEAFC /* SDL_gpu_vulkan_vkfuncs.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F257822C81903800FCEAFC /* SDL_gpu_vulkan_vkfuncs.h */; }; + E4F257952C81903800FCEAFC /* SDL_gpu_vulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257832C81903800FCEAFC /* SDL_gpu_vulkan.c */; }; + E4F257962C81903800FCEAFC /* SDL_gpu.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F257852C81903800FCEAFC /* SDL_gpu.c */; }; + E4F257972C81903800FCEAFC /* SDL_sysgpu.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F257862C81903800FCEAFC /* SDL_sysgpu.h */; }; E4F7981A2AD8D84800669F54 /* SDL_core_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */; }; E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */ = {isa = PBXBuildFile; fileRef = E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */; }; E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */; }; E4F798202AD8D87F00669F54 /* SDL_video_unsupported.c in Sources */ = {isa = PBXBuildFile; fileRef = E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */; }; + F310138D2C1F2CB700FBE946 /* SDL_getenv_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F310138A2C1F2CB700FBE946 /* SDL_getenv_c.h */; }; + F310138E2C1F2CB700FBE946 /* SDL_random.c in Sources */ = {isa = PBXBuildFile; fileRef = F310138B2C1F2CB700FBE946 /* SDL_random.c */; }; + F310138F2C1F2CB700FBE946 /* SDL_sysstdlib.h in Headers */ = {isa = PBXBuildFile; fileRef = F310138C2C1F2CB700FBE946 /* SDL_sysstdlib.h */; }; + F31013C72C24E98200FBE946 /* SDL_keymap.c in Sources */ = {isa = PBXBuildFile; fileRef = F31013C52C24E98200FBE946 /* SDL_keymap.c */; }; + F31013C82C24E98200FBE946 /* SDL_keymap_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F31013C62C24E98200FBE946 /* SDL_keymap_c.h */; }; F316ABD82B5C3185002EF551 /* SDL_memset.c in Sources */ = {isa = PBXBuildFile; fileRef = F316ABD62B5C3185002EF551 /* SDL_memset.c */; }; F316ABD92B5C3185002EF551 /* SDL_memcpy.c in Sources */ = {isa = PBXBuildFile; fileRef = F316ABD72B5C3185002EF551 /* SDL_memcpy.c */; }; F316ABDB2B5CA721002EF551 /* SDL_memmove.c in Sources */ = {isa = PBXBuildFile; fileRef = F316ABDA2B5CA721002EF551 /* SDL_memmove.c */; }; @@ -391,7 +405,6 @@ F32DDACF2AB795A30041EAA5 /* SDL_audio_channel_converters.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDAC92AB795A30041EAA5 /* SDL_audio_channel_converters.h */; }; F32DDAD02AB795A30041EAA5 /* SDL_audioresample.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDACA2AB795A30041EAA5 /* SDL_audioresample.h */; }; F32DDAD12AB795A30041EAA5 /* SDL_audioqueue.c in Sources */ = {isa = PBXBuildFile; fileRef = F32DDACB2AB795A30041EAA5 /* SDL_audioqueue.c */; }; - F32DDAD22AB795A30041EAA5 /* SDL_audio_resampler_filter.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */; }; F32DDAD32AB795A30041EAA5 /* SDL_audioqueue.h in Headers */ = {isa = PBXBuildFile; fileRef = F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */; }; F32DDAD42AB795A30041EAA5 /* SDL_audioresample.c in Sources */ = {isa = PBXBuildFile; fileRef = F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */; }; F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */; }; @@ -401,6 +414,8 @@ F362B91C2B3349E200D30B94 /* SDL_steam_virtual_gamepad.c in Sources */ = {isa = PBXBuildFile; fileRef = F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */; }; F3681E802B7AA6240002C6FD /* SDL_cocoashape.m in Sources */ = {isa = PBXBuildFile; fileRef = F3681E7E2B7AA6240002C6FD /* SDL_cocoashape.m */; }; F3681E812B7AA6240002C6FD /* SDL_cocoashape.h in Headers */ = {isa = PBXBuildFile; fileRef = F3681E7F2B7AA6240002C6FD /* SDL_cocoashape.h */; }; + F36C34312C0F876500991150 /* SDL_offscreenvulkan.h in Headers */ = {isa = PBXBuildFile; fileRef = F36C342F2C0F876500991150 /* SDL_offscreenvulkan.h */; }; + F36C34322C0F876500991150 /* SDL_offscreenvulkan.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C34302C0F876500991150 /* SDL_offscreenvulkan.c */; }; F36C7AD1294BA009004D61C3 /* SDL_runapp.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C7AD0294BA009004D61C3 /* SDL_runapp.c */; }; F376F6552559B4E300CFC0BC /* SDL_hidapi.c in Sources */ = {isa = PBXBuildFile; fileRef = A7D8A81423E2513F00DCD162 /* SDL_hidapi.c */; }; F37A8E1A28405AA100C38E95 /* CMake in Resources */ = {isa = PBXBuildFile; fileRef = F37A8E1928405AA100C38E95 /* CMake */; }; @@ -431,11 +446,24 @@ F3990E062A788303000D8759 /* SDL_hidapi_ios.h in Headers */ = {isa = PBXBuildFile; fileRef = F3990E032A788303000D8759 /* SDL_hidapi_ios.h */; }; F3990E072A78833C000D8759 /* hid.m in Sources */ = {isa = PBXBuildFile; fileRef = A75FDAA523E2792500529352 /* hid.m */; }; F3A4909E2554D38600E92A8B /* SDL_hidapi_ps5.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */; }; + F3A9AE982C8A13C100AAC390 /* SDL_gpu_util.h in Headers */ = {isa = PBXBuildFile; fileRef = F3A9AE922C8A13C100AAC390 /* SDL_gpu_util.h */; }; + F3A9AE992C8A13C100AAC390 /* SDL_render_gpu.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A9AE932C8A13C100AAC390 /* SDL_render_gpu.c */; }; + F3A9AE9A2C8A13C100AAC390 /* SDL_shaders_gpu.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A9AE942C8A13C100AAC390 /* SDL_shaders_gpu.c */; }; + F3A9AE9B2C8A13C100AAC390 /* SDL_pipeline_gpu.h in Headers */ = {isa = PBXBuildFile; fileRef = F3A9AE952C8A13C100AAC390 /* SDL_pipeline_gpu.h */; }; + F3A9AE9C2C8A13C100AAC390 /* SDL_pipeline_gpu.c in Sources */ = {isa = PBXBuildFile; fileRef = F3A9AE962C8A13C100AAC390 /* SDL_pipeline_gpu.c */; }; + F3A9AE9D2C8A13C100AAC390 /* SDL_shaders_gpu.h in Headers */ = {isa = PBXBuildFile; fileRef = F3A9AE972C8A13C100AAC390 /* SDL_shaders_gpu.h */; }; F3B38CCF296E2E52005DA6D3 /* SDL_main_impl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCA296E2E52005DA6D3 /* SDL_main_impl.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CD3296E2E52005DA6D3 /* SDL_platform_defines.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CD7296E2E52005DA6D3 /* SDL_init.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCC296E2E52005DA6D3 /* SDL_init.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CDB296E2E52005DA6D3 /* SDL_oldnames.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3B38CDF296E2E52005DA6D3 /* SDL_intrin.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3B439482C93595900792030 /* SDL_process.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B439472C93595900792030 /* SDL_process.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F3B439512C935C2400792030 /* SDL_dummyprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B439502C935C2400792030 /* SDL_dummyprocess.c */; }; + F3B439532C935C2C00792030 /* SDL_posixprocess.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B439522C935C2C00792030 /* SDL_posixprocess.c */; }; + F3B439562C937DAB00792030 /* SDL_process.c in Sources */ = {isa = PBXBuildFile; fileRef = F3B439542C937DAB00792030 /* SDL_process.c */; }; + F3B439572C937DAB00792030 /* SDL_sysprocess.h in Headers */ = {isa = PBXBuildFile; fileRef = F3B439552C937DAB00792030 /* SDL_sysprocess.h */; }; + F3C2CB222C5DDDB2004D7998 /* SDL_categories_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */; }; + F3C2CB232C5DDDB2004D7998 /* SDL_categories.c in Sources */ = {isa = PBXBuildFile; fileRef = F3C2CB212C5DDDB2004D7998 /* SDL_categories.c */; }; F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */ = {isa = PBXBuildFile; fileRef = F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */; }; F3DDCC562AFD42B600B0842B /* SDL_clipboard_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */; }; F3DDCC5B2AFD42B600B0842B /* SDL_video_c.h in Headers */ = {isa = PBXBuildFile; fileRef = F3DDCC522AFD42B600B0842B /* SDL_video_c.h */; }; @@ -443,6 +471,11 @@ F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */; }; F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F07D59269640160074468B /* SDL_hidapi_luna.c */; }; + F3F528CB2C29E1C300E6CC26 /* s_isnanf.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F528C62C29E1C300E6CC26 /* s_isnanf.c */; }; + F3F528CC2C29E1C300E6CC26 /* s_isinf.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F528C72C29E1C300E6CC26 /* s_isinf.c */; }; + F3F528CD2C29E1C300E6CC26 /* s_isnan.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F528C82C29E1C300E6CC26 /* s_isnan.c */; }; + F3F528CE2C29E1C300E6CC26 /* s_modf.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F528C92C29E1C300E6CC26 /* s_modf.c */; }; + F3F528CF2C29E1C300E6CC26 /* s_isinff.c in Sources */ = {isa = PBXBuildFile; fileRef = F3F528CA2C29E1C300E6CC26 /* s_isinff.c */; }; F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8AA2933074900816151 /* SDL_audio.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D8F12933074E00816151 /* SDL_platform.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8AB2933074900816151 /* SDL_platform.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D8F52933074E00816151 /* SDL_stdinc.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8AC2933074900816151 /* SDL_stdinc.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -493,7 +526,6 @@ F3F7D9B12933074E00816151 /* SDL_power.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8DB2933074D00816151 /* SDL_power.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8DD2933074D00816151 /* SDL_cpuinfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9BD2933074E00816151 /* SDL_render.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8DE2933074D00816151 /* SDL_render.h */; settings = {ATTRIBUTES = (Public, ); }; }; - F3F7D9C12933074E00816151 /* SDL_quit.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8DF2933074D00816151 /* SDL_quit.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9C52933074E00816151 /* SDL_assert.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E02933074D00816151 /* SDL_assert.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9C92933074E00816151 /* SDL_opengl.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E12933074D00816151 /* SDL_opengl.h */; settings = {ATTRIBUTES = (Public, ); }; }; F3F7D9CD2933074E00816151 /* SDL_rect.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F7D8E22933074D00816151 /* SDL_rect.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -512,6 +544,8 @@ F3FA5A232B59ACE000FEAD97 /* yuv_rgb_lsx.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */; }; F3FA5A242B59ACE000FEAD97 /* yuv_rgb_lsx.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */; }; F3FA5A252B59ACE000FEAD97 /* yuv_rgb_common.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */; }; + F3FD042E2C9B755700824C4C /* SDL_hidapi_nintendo.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */; }; + F3FD042F2C9B755700824C4C /* SDL_hidapi_steam_hori.c in Sources */ = {isa = PBXBuildFile; fileRef = F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */; }; FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; platformFilters = (ios, maccatalyst, macos, tvos, watchos, ); }; /* End PBXBuildFile section */ @@ -541,6 +575,7 @@ /* Begin PBXFileReference section */ 0000035D38C3899C7EFD0000 /* SDL_camera.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_camera.c; sourceTree = ""; }; 00002B010DB1A70931C20000 /* SDL_filesystem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_filesystem.c; sourceTree = ""; }; + 00002F2F5496FA184A0F0000 /* SDL_cocoapen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoapen.h; sourceTree = ""; }; 00003260407E1002EAC10000 /* SDL_main_callbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_main_callbacks.h; sourceTree = ""; }; 00003F472C51CE7DF6160000 /* SDL_systime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systime.c; sourceTree = ""; }; 00005BD74B46358B33A20000 /* SDL_camera_dummy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_camera_dummy.c; sourceTree = ""; }; @@ -553,7 +588,9 @@ 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_main_callbacks.c; sourceTree = ""; }; 0000B6ADCD88CAD6610F0000 /* SDL_hashtable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hashtable.h; sourceTree = ""; }; 0000BB287BA0A0178C1A0000 /* SDL_sysmain_callbacks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_sysmain_callbacks.m; sourceTree = ""; }; + 0000CCA310B73A7B59910000 /* SDL_cocoapen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoapen.m; sourceTree = ""; }; 0000F4E6AA3EF99DA3C80000 /* SDL_sysfsops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysfsops.c; sourceTree = ""; }; + 0000F6C6A072ED4E3D660000 /* SDL_dialog_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dialog_utils.c; sourceTree = ""; }; 0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = System/Library/Frameworks/Carbon.framework; sourceTree = SDKROOT; }; @@ -570,6 +607,7 @@ 566E26CD246274CB00718109 /* SDL_locale.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_locale.c; path = locale/SDL_locale.c; sourceTree = ""; }; 566E26CE246274CC00718109 /* SDL_syslocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_syslocale.h; path = locale/SDL_syslocale.h; sourceTree = ""; }; 56A2373229F9C113003CCA5F /* SDL_sysrwlock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysrwlock.c; sourceTree = ""; }; + 6312C66C2B42341400A7BB00 /* SDL_murmur3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_murmur3.c; sourceTree = ""; }; 63134A212A7902CF0021E9A6 /* SDL_pen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_pen.h; path = SDL3/SDL_pen.h; sourceTree = ""; }; 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pen_c.h; sourceTree = ""; }; 63134A242A7902FD0021E9A6 /* SDL_pen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_pen.c; sourceTree = ""; }; @@ -777,8 +815,6 @@ A7D8A7D023E2513E00DCD162 /* SDL_joystick_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_joystick_c.h; sourceTree = ""; }; A7D8A7D923E2513E00DCD162 /* controller_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_type.h; sourceTree = ""; }; A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_iostream.c; sourceTree = ""; }; - A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_iostreambundlesupport.h; sourceTree = ""; }; - A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_iostreambundlesupport.m; sourceTree = ""; }; A7D8A7E123E2513F00DCD162 /* SDL_syspower.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_syspower.m; sourceTree = ""; }; A7D8A7E223E2513F00DCD162 /* SDL_syspower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_syspower.h; sourceTree = ""; }; A7D8A7E723E2513F00DCD162 /* SDL_power.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_power.c; sourceTree = ""; }; @@ -903,10 +939,23 @@ E47911882BA9555500CE3B7F /* SDL_sysstorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysstorage.h; sourceTree = ""; }; E479118A2BA9555500CE3B7F /* SDL_genericstorage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_genericstorage.c; sourceTree = ""; }; E4A568B52AF763940062EEC4 /* SDL_sysmain_callbacks.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_sysmain_callbacks.c; sourceTree = ""; }; + E4F257702C818FE200FCEAFC /* SDL_gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_gpu.h; path = SDL3/SDL_gpu.h; sourceTree = ""; }; + E4F2577E2C81903800FCEAFC /* Metal_Blit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Metal_Blit.h; sourceTree = ""; }; + E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Metal_Blit.metal; sourceTree = ""; }; + E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_gpu_metal.m; sourceTree = ""; }; + E4F257822C81903800FCEAFC /* SDL_gpu_vulkan_vkfuncs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gpu_vulkan_vkfuncs.h; sourceTree = ""; }; + E4F257832C81903800FCEAFC /* SDL_gpu_vulkan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gpu_vulkan.c; sourceTree = ""; }; + E4F257852C81903800FCEAFC /* SDL_gpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gpu.c; sourceTree = ""; }; + E4F257862C81903800FCEAFC /* SDL_sysgpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysgpu.h; sourceTree = ""; }; E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_core_unsupported.c; sourceTree = ""; }; E4F7981B2AD8D85500669F54 /* SDL_dynapi_unsupported.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dynapi_unsupported.h; sourceTree = ""; }; E4F7981D2AD8D86A00669F54 /* SDL_render_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_unsupported.c; sourceTree = ""; }; E4F7981F2AD8D87F00669F54 /* SDL_video_unsupported.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_video_unsupported.c; sourceTree = ""; }; + F310138A2C1F2CB700FBE946 /* SDL_getenv_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_getenv_c.h; sourceTree = ""; }; + F310138B2C1F2CB700FBE946 /* SDL_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_random.c; sourceTree = ""; }; + F310138C2C1F2CB700FBE946 /* SDL_sysstdlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysstdlib.h; sourceTree = ""; }; + F31013C52C24E98200FBE946 /* SDL_keymap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_keymap.c; sourceTree = ""; }; + F31013C62C24E98200FBE946 /* SDL_keymap_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_keymap_c.h; sourceTree = ""; }; F316ABD62B5C3185002EF551 /* SDL_memset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_memset.c; sourceTree = ""; }; F316ABD72B5C3185002EF551 /* SDL_memcpy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_memcpy.c; sourceTree = ""; }; F316ABDA2B5CA721002EF551 /* SDL_memmove.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_memmove.c; sourceTree = ""; }; @@ -916,7 +965,6 @@ F32DDAC92AB795A30041EAA5 /* SDL_audio_channel_converters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_channel_converters.h; sourceTree = ""; }; F32DDACA2AB795A30041EAA5 /* SDL_audioresample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audioresample.h; sourceTree = ""; }; F32DDACB2AB795A30041EAA5 /* SDL_audioqueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audioqueue.c; sourceTree = ""; }; - F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_resampler_filter.h; sourceTree = ""; }; F32DDACD2AB795A30041EAA5 /* SDL_audioqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audioqueue.h; sourceTree = ""; }; F32DDACE2AB795A30041EAA5 /* SDL_audioresample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audioresample.c; sourceTree = ""; }; F362B9152B3349E200D30B94 /* controller_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = controller_list.h; sourceTree = ""; }; @@ -925,6 +973,8 @@ F362B9182B3349E200D30B94 /* SDL_steam_virtual_gamepad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_steam_virtual_gamepad.c; sourceTree = ""; }; F3681E7E2B7AA6240002C6FD /* SDL_cocoashape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoashape.m; sourceTree = ""; }; F3681E7F2B7AA6240002C6FD /* SDL_cocoashape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoashape.h; sourceTree = ""; }; + F36C342F2C0F876500991150 /* SDL_offscreenvulkan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_offscreenvulkan.h; sourceTree = ""; }; + F36C34302C0F876500991150 /* SDL_offscreenvulkan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_offscreenvulkan.c; sourceTree = ""; }; F36C7AD0294BA009004D61C3 /* SDL_runapp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_runapp.c; sourceTree = ""; }; F376F6182559B29300CFC0BC /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.1.sdk/System/Library/Frameworks/OpenGLES.framework; sourceTree = DEVELOPER_DIR; }; F376F61A2559B2AF00CFC0BC /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; @@ -968,12 +1018,25 @@ F3990E022A788303000D8759 /* SDL_hidapi_mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hidapi_mac.h; sourceTree = ""; }; F3990E032A788303000D8759 /* SDL_hidapi_ios.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hidapi_ios.h; sourceTree = ""; }; F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_ps5.c; sourceTree = ""; }; + F3A9AE922C8A13C100AAC390 /* SDL_gpu_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gpu_util.h; sourceTree = ""; }; + F3A9AE932C8A13C100AAC390 /* SDL_render_gpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_render_gpu.c; sourceTree = ""; }; + F3A9AE942C8A13C100AAC390 /* SDL_shaders_gpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_shaders_gpu.c; sourceTree = ""; }; + F3A9AE952C8A13C100AAC390 /* SDL_pipeline_gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pipeline_gpu.h; sourceTree = ""; }; + F3A9AE962C8A13C100AAC390 /* SDL_pipeline_gpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_pipeline_gpu.c; sourceTree = ""; }; + F3A9AE972C8A13C100AAC390 /* SDL_shaders_gpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_shaders_gpu.h; sourceTree = ""; }; F3ADAB8D2576F0B300A6B1D9 /* SDL_sysurl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_sysurl.m; sourceTree = ""; }; F3B38CCA296E2E52005DA6D3 /* SDL_main_impl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_main_impl.h; path = SDL3/SDL_main_impl.h; sourceTree = ""; }; F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_platform_defines.h; path = SDL3/SDL_platform_defines.h; sourceTree = ""; }; F3B38CCC296E2E52005DA6D3 /* SDL_init.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_init.h; path = SDL3/SDL_init.h; sourceTree = ""; }; F3B38CCD296E2E52005DA6D3 /* SDL_oldnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_oldnames.h; path = SDL3/SDL_oldnames.h; sourceTree = ""; }; F3B38CCE296E2E52005DA6D3 /* SDL_intrin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_intrin.h; path = SDL3/SDL_intrin.h; sourceTree = ""; }; + F3B439472C93595900792030 /* SDL_process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_process.h; path = SDL3/SDL_process.h; sourceTree = ""; }; + F3B439502C935C2400792030 /* SDL_dummyprocess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyprocess.c; sourceTree = ""; }; + F3B439522C935C2C00792030 /* SDL_posixprocess.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_posixprocess.c; sourceTree = ""; }; + F3B439542C937DAB00792030 /* SDL_process.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_process.c; sourceTree = ""; }; + F3B439552C937DAB00792030 /* SDL_sysprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysprocess.h; sourceTree = ""; }; + F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_categories_c.h; sourceTree = ""; }; + F3C2CB212C5DDDB2004D7998 /* SDL_categories.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_categories.c; sourceTree = ""; }; F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_wii.c; sourceTree = ""; }; F3DDCC4D2AFD42B500B0842B /* SDL_clipboard_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard_c.h; sourceTree = ""; }; F3DDCC522AFD42B600B0842B /* SDL_video_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video_c.h; sourceTree = ""; }; @@ -981,6 +1044,11 @@ F3E5A6EA2AD5E0E600293D83 /* SDL_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_properties.c; sourceTree = ""; }; F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_properties.h; path = SDL3/SDL_properties.h; sourceTree = ""; }; F3F07D59269640160074468B /* SDL_hidapi_luna.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_luna.c; sourceTree = ""; }; + F3F528C62C29E1C300E6CC26 /* s_isnanf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_isnanf.c; sourceTree = ""; }; + F3F528C72C29E1C300E6CC26 /* s_isinf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_isinf.c; sourceTree = ""; }; + F3F528C82C29E1C300E6CC26 /* s_isnan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_isnan.c; sourceTree = ""; }; + F3F528C92C29E1C300E6CC26 /* s_modf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_modf.c; sourceTree = ""; }; + F3F528CA2C29E1C300E6CC26 /* s_isinff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_isinff.c; sourceTree = ""; }; F3F7D8AA2933074900816151 /* SDL_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_audio.h; path = SDL3/SDL_audio.h; sourceTree = ""; }; F3F7D8AB2933074900816151 /* SDL_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_platform.h; path = SDL3/SDL_platform.h; sourceTree = ""; }; F3F7D8AC2933074900816151 /* SDL_stdinc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_stdinc.h; path = SDL3/SDL_stdinc.h; sourceTree = ""; }; @@ -1031,7 +1099,6 @@ F3F7D8DB2933074D00816151 /* SDL_power.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_power.h; path = SDL3/SDL_power.h; sourceTree = ""; }; F3F7D8DD2933074D00816151 /* SDL_cpuinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_cpuinfo.h; path = SDL3/SDL_cpuinfo.h; sourceTree = ""; }; F3F7D8DE2933074D00816151 /* SDL_render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_render.h; path = SDL3/SDL_render.h; sourceTree = ""; }; - F3F7D8DF2933074D00816151 /* SDL_quit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_quit.h; path = SDL3/SDL_quit.h; sourceTree = ""; }; F3F7D8E02933074D00816151 /* SDL_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_assert.h; path = SDL3/SDL_assert.h; sourceTree = ""; }; F3F7D8E12933074D00816151 /* SDL_opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_opengl.h; path = SDL3/SDL_opengl.h; sourceTree = ""; }; F3F7D8E22933074D00816151 /* SDL_rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_rect.h; path = SDL3/SDL_rect.h; sourceTree = ""; }; @@ -1050,6 +1117,8 @@ F3FA5A1A2B59ACE000FEAD97 /* yuv_rgb_lsx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = yuv_rgb_lsx.c; sourceTree = ""; }; F3FA5A1B2B59ACE000FEAD97 /* yuv_rgb_lsx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_lsx.h; sourceTree = ""; }; F3FA5A1C2B59ACE000FEAD97 /* yuv_rgb_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = yuv_rgb_common.h; sourceTree = ""; }; + F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDL_hidapi_nintendo.h; sourceTree = ""; }; + F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SDL_hidapi_steam_hori.c; sourceTree = ""; }; F59C710300D5CB5801000001 /* ReadMe.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ReadMe.txt; sourceTree = ""; }; F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; }; F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; }; @@ -1123,6 +1192,7 @@ 00008B5A0CB83D2069E80000 /* ios */, 00009366FB9FBBD54C390000 /* SDL_main_callbacks.c */, 00003260407E1002EAC10000 /* SDL_main_callbacks.h */, + F36C7AD0294BA009004D61C3 /* SDL_runapp.c */, ); path = main; sourceTree = ""; @@ -1174,6 +1244,7 @@ F3F7D8CB2933074B00816151 /* SDL_events.h */, F3F7D8D62933074C00816151 /* SDL_filesystem.h */, F3F7D8D02933074C00816151 /* SDL_gamepad.h */, + E4F257702C818FE200FCEAFC /* SDL_gpu.h */, F3F7D8D12933074C00816151 /* SDL_guid.h */, F3F7D8AD2933074900816151 /* SDL_haptic.h */, F3F7D8CA2933074B00816151 /* SDL_hidapi.h */, @@ -1208,8 +1279,8 @@ F3B38CCB296E2E52005DA6D3 /* SDL_platform_defines.h */, F3F7D8AB2933074900816151 /* SDL_platform.h */, F3F7D8DB2933074D00816151 /* SDL_power.h */, + F3B439472C93595900792030 /* SDL_process.h */, F3E5A6EC2AD5E10800293D83 /* SDL_properties.h */, - F3F7D8DF2933074D00816151 /* SDL_quit.h */, F3F7D8E22933074D00816151 /* SDL_rect.h */, F3F7D8DE2933074D00816151 /* SDL_render.h */, F3F7D8B42933074900816151 /* SDL_revision.h */, @@ -1272,6 +1343,7 @@ A7D8A92923E2514000DCD162 /* events */, A7D8A7DA23E2513E00DCD162 /* file */, A7D8A7F623E2513F00DCD162 /* filesystem */, + E4F257872C81903800FCEAFC /* gpu */, A7D8A5C223E2513D00DCD162 /* haptic */, A7D8A80923E2513F00DCD162 /* hidapi */, A7D8A79D23E2513E00DCD162 /* joystick */, @@ -1281,6 +1353,7 @@ 000082EF09C89B62BD840000 /* main */, 5616CA47252BB278005D5928 /* misc */, A7D8A7DF23E2513F00DCD162 /* power */, + F3B439492C93597500792030 /* process */, A7D8A8DA23E2514000DCD162 /* render */, A7D8A57623E2513D00DCD162 /* sensor */, A7D8A8D223E2514000DCD162 /* stdlib */, @@ -1571,6 +1644,8 @@ F31A92C628D4CB39003BFD6A /* SDL_offscreenopengles.h */, A7D8A5F623E2513D00DCD162 /* SDL_offscreenvideo.c */, A7D8A5F123E2513D00DCD162 /* SDL_offscreenvideo.h */, + F36C34302C0F876500991150 /* SDL_offscreenvulkan.c */, + F36C342F2C0F876500991150 /* SDL_offscreenvulkan.h */, A7D8A5EF23E2513D00DCD162 /* SDL_offscreenwindow.c */, A7D8A5F523E2513D00DCD162 /* SDL_offscreenwindow.h */, ); @@ -1652,6 +1727,8 @@ A7D8A68323E2513E00DCD162 /* SDL_cocoavulkan.m */, A7D8A69223E2513E00DCD162 /* SDL_cocoawindow.h */, A7D8A68423E2513E00DCD162 /* SDL_cocoawindow.m */, + 00002F2F5496FA184A0F0000 /* SDL_cocoapen.h */, + 0000CCA310B73A7B59910000 /* SDL_cocoapen.m */, ); path = cocoa; sourceTree = ""; @@ -1825,25 +1902,27 @@ A7D8A7BE23E2513E00DCD162 /* hidapi */ = { isa = PBXGroup; children = ( - A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */, F32305FE28939F6400E66D30 /* SDL_hidapi_combined.c */, A7D8A7C923E2513E00DCD162 /* SDL_hidapi_gamecube.c */, F3F07D59269640160074468B /* SDL_hidapi_luna.c */, + F3FD042C2C9B755700824C4C /* SDL_hidapi_nintendo.h */, F388C95428B5F6F600661ECF /* SDL_hidapi_ps3.c */, A7D8A7C323E2513E00DCD162 /* SDL_hidapi_ps4.c */, F3A4909D2554D38500E92A8B /* SDL_hidapi_ps5.c */, - A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */, A75FDBC323EA380300529352 /* SDL_hidapi_rumble.h */, + A75FDBC423EA380300529352 /* SDL_hidapi_rumble.c */, 9846B07B287A9020000C35C8 /* SDL_hidapi_shield.c */, F3984CCF25BCC92800374F43 /* SDL_hidapi_stadia.c */, A75FDAAC23E2795C00529352 /* SDL_hidapi_steam.c */, + F3FD042D2C9B755700824C4C /* SDL_hidapi_steam_hori.c */, + A797456F2B2E9D39009D224A /* SDL_hidapi_steamdeck.c */, A7D8A7C623E2513E00DCD162 /* SDL_hidapi_switch.c */, F3D60A8228C16A1800788A3A /* SDL_hidapi_wii.c */, A7D8A7C223E2513E00DCD162 /* SDL_hidapi_xbox360.c */, A7D8A7C823E2513E00DCD162 /* SDL_hidapi_xbox360w.c */, A7D8A7C523E2513E00DCD162 /* SDL_hidapi_xboxone.c */, - A7D8A7C723E2513E00DCD162 /* SDL_hidapijoystick_c.h */, A7D8A7C423E2513E00DCD162 /* SDL_hidapijoystick.c */, + A7D8A7C723E2513E00DCD162 /* SDL_hidapijoystick_c.h */, ); path = hidapi; sourceTree = ""; @@ -1860,21 +1939,11 @@ A7D8A7DA23E2513E00DCD162 /* file */ = { isa = PBXGroup; children = ( - A7D8A7DC23E2513F00DCD162 /* cocoa */, A7D8A7DB23E2513F00DCD162 /* SDL_iostream.c */, ); path = file; sourceTree = ""; }; - A7D8A7DC23E2513F00DCD162 /* cocoa */ = { - isa = PBXGroup; - children = ( - A7D8A7DD23E2513F00DCD162 /* SDL_iostreambundlesupport.h */, - A7D8A7DE23E2513F00DCD162 /* SDL_iostreambundlesupport.m */, - ); - path = cocoa; - sourceTree = ""; - }; A7D8A7DF23E2513F00DCD162 /* power */ = { isa = PBXGroup; children = ( @@ -1983,7 +2052,6 @@ A7D8A87023E2513F00DCD162 /* dummy */, A7D8A87323E2513F00DCD162 /* SDL_audio_c.h */, F32DDAC92AB795A30041EAA5 /* SDL_audio_channel_converters.h */, - F32DDACC2AB795A30041EAA5 /* SDL_audio_resampler_filter.h */, A7D8A8B823E2513F00DCD162 /* SDL_audio.c */, A7D8A8A123E2513F00DCD162 /* SDL_audiocvt.c */, A7D8A87723E2513F00DCD162 /* SDL_audiodev_c.h */, @@ -2031,8 +2099,10 @@ A7D8A8D223E2514000DCD162 /* stdlib */ = { isa = PBXGroup; children = ( + 6312C66C2B42341400A7BB00 /* SDL_murmur3.c */, F3973FA128A59BDD00B84553 /* SDL_crc16.c */, F395BF6425633B2400942BFF /* SDL_crc32.c */, + F310138A2C1F2CB700FBE946 /* SDL_getenv_c.h */, A7D8A8D423E2514000DCD162 /* SDL_getenv.c */, A7D8A8D323E2514000DCD162 /* SDL_iconv.c */, A7D8A8D923E2514000DCD162 /* SDL_malloc.c */, @@ -2040,9 +2110,11 @@ F316ABDA2B5CA721002EF551 /* SDL_memmove.c */, F316ABD62B5C3185002EF551 /* SDL_memset.c */, A7D8A8D723E2514000DCD162 /* SDL_qsort.c */, + F310138B2C1F2CB700FBE946 /* SDL_random.c */, A7D8A8D823E2514000DCD162 /* SDL_stdlib.c */, A7D8A8D523E2514000DCD162 /* SDL_string.c */, A7D8A8D623E2514000DCD162 /* SDL_strtokr.c */, + F310138C2C1F2CB700FBE946 /* SDL_sysstdlib.h */, F3973FA028A59BDD00B84553 /* SDL_vacopy.h */, ); path = stdlib; @@ -2051,6 +2123,7 @@ A7D8A8DA23E2514000DCD162 /* render */ = { isa = PBXGroup; children = ( + F3A9AE912C8A139C00AAC390 /* gpu */, A7D8A8DD23E2514000DCD162 /* metal */, A7D8A90C23E2514000DCD162 /* opengl */, A7D8A90323E2514000DCD162 /* opengles2 */, @@ -2146,6 +2219,11 @@ A7D8A91323E2514000DCD162 /* s_cos.c */, A7D8A91523E2514000DCD162 /* s_fabs.c */, A7D8A92523E2514000DCD162 /* s_floor.c */, + F3F528C72C29E1C300E6CC26 /* s_isinf.c */, + F3F528CA2C29E1C300E6CC26 /* s_isinff.c */, + F3F528C82C29E1C300E6CC26 /* s_isnan.c */, + F3F528C62C29E1C300E6CC26 /* s_isnanf.c */, + F3F528C92C29E1C300E6CC26 /* s_modf.c */, A7D8A91A23E2514000DCD162 /* s_scalbn.c */, A7D8A91223E2514000DCD162 /* s_sin.c */, A7D8A91E23E2514000DCD162 /* s_tan.c */, @@ -2162,6 +2240,8 @@ A7D8A93623E2514000DCD162 /* scancodes_linux.h */, A7D8A92C23E2514000DCD162 /* scancodes_windows.h */, A7D8A94123E2514000DCD162 /* scancodes_xfree86.h */, + F3C2CB202C5DDDB2004D7998 /* SDL_categories_c.h */, + F3C2CB212C5DDDB2004D7998 /* SDL_categories.c */, A7D8A93923E2514000DCD162 /* SDL_clipboardevents_c.h */, A7D8A93A23E2514000DCD162 /* SDL_clipboardevents.c */, A7D8A93123E2514000DCD162 /* SDL_displayevents_c.h */, @@ -2172,6 +2252,8 @@ A7D8A93523E2514000DCD162 /* SDL_events.c */, A7D8A93D23E2514000DCD162 /* SDL_keyboard_c.h */, A7D8A93823E2514000DCD162 /* SDL_keyboard.c */, + F31013C62C24E98200FBE946 /* SDL_keymap_c.h */, + F31013C52C24E98200FBE946 /* SDL_keymap.c */, A7D8A92B23E2514000DCD162 /* SDL_mouse_c.h */, A7D8A92A23E2514000DCD162 /* SDL_mouse.c */, 63134A232A7902FD0021E9A6 /* SDL_pen_c.h */, @@ -2219,11 +2301,40 @@ path = generic; sourceTree = ""; }; + E4F257812C81903800FCEAFC /* metal */ = { + isa = PBXGroup; + children = ( + E4F2577E2C81903800FCEAFC /* Metal_Blit.h */, + E4F2577F2C81903800FCEAFC /* Metal_Blit.metal */, + E4F257802C81903800FCEAFC /* SDL_gpu_metal.m */, + ); + path = metal; + sourceTree = ""; + }; + E4F257842C81903800FCEAFC /* vulkan */ = { + isa = PBXGroup; + children = ( + E4F257822C81903800FCEAFC /* SDL_gpu_vulkan_vkfuncs.h */, + E4F257832C81903800FCEAFC /* SDL_gpu_vulkan.c */, + ); + path = vulkan; + sourceTree = ""; + }; + E4F257872C81903800FCEAFC /* gpu */ = { + isa = PBXGroup; + children = ( + E4F257812C81903800FCEAFC /* metal */, + E4F257842C81903800FCEAFC /* vulkan */, + E4F257852C81903800FCEAFC /* SDL_gpu.c */, + E4F257862C81903800FCEAFC /* SDL_sysgpu.h */, + ); + path = gpu; + sourceTree = ""; + }; F36C7ACF294B9F5E004D61C3 /* core */ = { isa = PBXGroup; children = ( E4F798192AD8D84800669F54 /* SDL_core_unsupported.c */, - F36C7AD0294BA009004D61C3 /* SDL_runapp.c */, ); path = core; sourceTree = ""; @@ -2233,6 +2344,7 @@ children = ( F37E18552BA50ED50098C111 /* cocoa */, F37E18562BA50F2A0098C111 /* dummy */, + 0000F6C6A072ED4E3D660000 /* SDL_dialog_utils.c */, ); path = dialog; sourceTree = ""; @@ -2253,6 +2365,19 @@ path = dummy; sourceTree = ""; }; + F3A9AE912C8A139C00AAC390 /* gpu */ = { + isa = PBXGroup; + children = ( + F3A9AE922C8A13C100AAC390 /* SDL_gpu_util.h */, + F3A9AE962C8A13C100AAC390 /* SDL_pipeline_gpu.c */, + F3A9AE952C8A13C100AAC390 /* SDL_pipeline_gpu.h */, + F3A9AE932C8A13C100AAC390 /* SDL_render_gpu.c */, + F3A9AE942C8A13C100AAC390 /* SDL_shaders_gpu.c */, + F3A9AE972C8A13C100AAC390 /* SDL_shaders_gpu.h */, + ); + path = gpu; + sourceTree = ""; + }; F3ADAB8C2576F08500A6B1D9 /* ios */ = { isa = PBXGroup; children = ( @@ -2261,6 +2386,33 @@ path = ios; sourceTree = ""; }; + F3B439492C93597500792030 /* process */ = { + isa = PBXGroup; + children = ( + F3B4394A2C93599900792030 /* dummy */, + F3B4394B2C9359A500792030 /* posix */, + F3B439542C937DAB00792030 /* SDL_process.c */, + F3B439552C937DAB00792030 /* SDL_sysprocess.h */, + ); + path = process; + sourceTree = ""; + }; + F3B4394A2C93599900792030 /* dummy */ = { + isa = PBXGroup; + children = ( + F3B439502C935C2400792030 /* SDL_dummyprocess.c */, + ); + path = dummy; + sourceTree = ""; + }; + F3B4394B2C9359A500792030 /* posix */ = { + isa = PBXGroup; + children = ( + F3B439522C935C2C00792030 /* SDL_posixprocess.c */, + ); + path = posix; + sourceTree = ""; + }; F59C70FC00D5CB5801000001 /* pkg-support */ = { isa = PBXGroup; children = ( @@ -2288,14 +2440,16 @@ buildActionMask = 2147483647; files = ( F3F7D9812933074E00816151 /* SDL.h in Headers */, + E4F257942C81903800FCEAFC /* SDL_gpu_vulkan_vkfuncs.h in Headers */, + F310138D2C1F2CB700FBE946 /* SDL_getenv_c.h in Headers */, A7D8B39E23E2514200DCD162 /* SDL_RLEaccel_c.h in Headers */, F3F7D9C52933074E00816151 /* SDL_assert.h in Headers */, A7D8B61723E2514300DCD162 /* SDL_assert_c.h in Headers */, F3F7D9292933074E00816151 /* SDL_atomic.h in Headers */, + F3A9AE9D2C8A13C100AAC390 /* SDL_shaders_gpu.h in Headers */, F3F7D8ED2933074E00816151 /* SDL_audio.h in Headers */, A7D8B7A023E2514400DCD162 /* SDL_audio_c.h in Headers */, F32DDACF2AB795A30041EAA5 /* SDL_audio_channel_converters.h in Headers */, - F32DDAD22AB795A30041EAA5 /* SDL_audio_resampler_filter.h in Headers */, A7D8B7B223E2514400DCD162 /* SDL_audiodev_c.h in Headers */, F32DDAD32AB795A30041EAA5 /* SDL_audioqueue.h in Headers */, F32DDAD02AB795A30041EAA5 /* SDL_audioresample.h in Headers */, @@ -2333,8 +2487,10 @@ F3F7D9B92933074E00816151 /* SDL_cpuinfo.h in Headers */, A7D8B98023E2514400DCD162 /* SDL_d3dmath.h in Headers */, A7D8B8A223E2514400DCD162 /* SDL_diskaudio.h in Headers */, + F3B439482C93595900792030 /* SDL_process.h in Headers */, A7D8BB3F23E2514500DCD162 /* SDL_displayevents_c.h in Headers */, A7D8BA1923E2514400DCD162 /* SDL_draw.h in Headers */, + F3C2CB222C5DDDB2004D7998 /* SDL_categories_c.h in Headers */, E479118E2BA9555500CE3B7F /* SDL_sysstorage.h in Headers */, A7D8BA0723E2514400DCD162 /* SDL_drawline.h in Headers */, A7D8B9EF23E2514400DCD162 /* SDL_drawpoint.h in Headers */, @@ -2346,12 +2502,14 @@ A7D8AB1C23E2514100DCD162 /* SDL_dynapi_procs.h in Headers */, E4F7981C2AD8D85500669F54 /* SDL_dynapi_unsupported.h in Headers */, F3F7D9252933074E00816151 /* SDL_egl.h in Headers */, + F3A9AE982C8A13C100AAC390 /* SDL_gpu_util.h in Headers */, A7D8ABD923E2514100DCD162 /* SDL_egl_c.h in Headers */, F3F7D93D2933074E00816151 /* SDL_endian.h in Headers */, F3F7D9352933074E00816151 /* SDL_error.h in Headers */, A7D8A95D23E2514000DCD162 /* SDL_error_c.h in Headers */, F3F7D9712933074E00816151 /* SDL_events.h in Headers */, A7D8BBA523E2514500DCD162 /* SDL_events_c.h in Headers */, + E4F257712C818FE200FCEAFC /* SDL_gpu.h in Headers */, F3F7D99D2933074E00816151 /* SDL_filesystem.h in Headers */, F3F7D9852933074E00816151 /* SDL_gamepad.h in Headers */, F362B91A2B3349E200D30B94 /* SDL_gamepad_c.h in Headers */, @@ -2410,25 +2568,26 @@ F3F7D9392933074E00816151 /* SDL_opengles2_gl2ext.h in Headers */, F3F7D9692933074E00816151 /* SDL_opengles2_gl2platform.h in Headers */, F3F7D9092933074E00816151 /* SDL_opengles2_khrplatform.h in Headers */, + F31013C82C24E98200FBE946 /* SDL_keymap_c.h in Headers */, 63134A222A7902CF0021E9A6 /* SDL_pen.h in Headers */, 63134A252A7902FD0021E9A6 /* SDL_pen_c.h in Headers */, + F36C34312C0F876500991150 /* SDL_offscreenvulkan.h in Headers */, F3F7D9192933074E00816151 /* SDL_pixels.h in Headers */, A7D8B2C023E2514200DCD162 /* SDL_pixels_c.h in Headers */, F3F7D8F12933074E00816151 /* SDL_platform.h in Headers */, F3B38CD3296E2E52005DA6D3 /* SDL_platform_defines.h in Headers */, F3F7D9B12933074E00816151 /* SDL_power.h in Headers */, F3E5A6ED2AD5E10800293D83 /* SDL_properties.h in Headers */, - F3F7D9C12933074E00816151 /* SDL_quit.h in Headers */, F37E18622BAA40090098C111 /* SDL_sysfilesystem.h in Headers */, F3F7D9CD2933074E00816151 /* SDL_rect.h in Headers */, A7D8AC0323E2514100DCD162 /* SDL_rect_c.h in Headers */, F3DDCC5D2AFD42B600B0842B /* SDL_rect_impl.h in Headers */, F3F7D9BD2933074E00816151 /* SDL_render.h in Headers */, A7D8B9FB23E2514400DCD162 /* SDL_render_sw_c.h in Headers */, + E4F257972C81903800FCEAFC /* SDL_sysgpu.h in Headers */, F3F7D9152933074E00816151 /* SDL_revision.h in Headers */, A7D8BA3123E2514400DCD162 /* SDL_rotate.h in Headers */, F3F7D9652933074E00816151 /* SDL_iostream.h in Headers */, - A7D8B5C323E2514300DCD162 /* SDL_iostreambundlesupport.h in Headers */, F3F7D9492933074E00816151 /* SDL_scancode.h in Headers */, F3F7D94D2933074E00816151 /* SDL_sensor.h in Headers */, A7D8A98D23E2514000DCD162 /* SDL_sensor_c.h in Headers */, @@ -2437,6 +2596,7 @@ A7D8B98C23E2514400DCD162 /* SDL_shaders_metal_ios.h in Headers */, A7D8B99B23E2514400DCD162 /* SDL_shaders_metal_macos.h in Headers */, A7D8B9A123E2514400DCD162 /* SDL_shaders_metal_tvos.h in Headers */, + F310138F2C1F2CB700FBE946 /* SDL_sysstdlib.h in Headers */, F3F7D8F52933074E00816151 /* SDL_stdinc.h in Headers */, F362B91B2B3349E200D30B94 /* SDL_steam_virtual_gamepad.h in Headers */, A7D8BBC723E2561500DCD162 /* SDL_steamcontroller.h in Headers */, @@ -2458,6 +2618,8 @@ A7D8AC3F23E2514100DCD162 /* SDL_sysvideo.h in Headers */, F3F7D9792933074E00816151 /* SDL_thread.h in Headers */, A7D8B3EC23E2514300DCD162 /* SDL_thread_c.h in Headers */, + F3B439572C937DAB00792030 /* SDL_sysprocess.h in Headers */, + E4F257912C81903800FCEAFC /* Metal_Blit.h in Headers */, F3F7D90D2933074E00816151 /* SDL_timer.h in Headers */, A7D8AB3123E2514100DCD162 /* SDL_timer_c.h in Headers */, F3F7D9012933074E00816151 /* SDL_touch.h in Headers */, @@ -2515,6 +2677,8 @@ A7D8B26023E2514200DCD162 /* vulkan.h in Headers */, A7D8B2B423E2514200DCD162 /* vulkan_android.h in Headers */, A7D8B2A823E2514200DCD162 /* vulkan_core.h in Headers */, + F3FD042E2C9B755700824C4C /* SDL_hidapi_nintendo.h in Headers */, + F3A9AE9B2C8A13C100AAC390 /* SDL_pipeline_gpu.h in Headers */, E41D20152BA9577D003073FA /* SDL_storage.h in Headers */, F37E18522BA50E760098C111 /* SDL_dialog.h in Headers */, A7D8B27223E2514200DCD162 /* vulkan_fuchsia.h in Headers */, @@ -2629,7 +2793,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "mkdir -p build/dmg-tmp/share/cmake/SDL3\ncp -a build/SDL3.xcframework build/dmg-tmp/\n\ncp pkg-support/resources/License.txt build/dmg-tmp\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\ncp pkg-support/resources/CMake/sdl3-config.cmake build/dmg-tmp/share/cmake/SDL3\ncp pkg-support/resources/CMake/sdl3-config-version.cmake build/dmg-tmp/share/cmake/SDL3\n\nmkdir -p \n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nfind build/dmg-tmp -name .DS_Store -exec rm -f \"{}\" \\;\n\n# for fancy .dmg\nmkdir -p build/dmg-tmp/.logo\ncp pkg-support/resources/SDL_DS_Store build/dmg-tmp/.DS_Store\ncp pkg-support/sdl_logo.pdf build/dmg-tmp/.logo\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname SDL3 -srcfolder build/dmg-tmp build/SDL3.dmg\n\n# clean up\nrm -rf build/dmg-tmp\n"; + shellScript = "set -ex\n\nmkdir -p build/dmg-tmp/share/cmake/SDL3\ncp -a build/SDL3.xcframework build/dmg-tmp/\n\ncp pkg-support/resources/License.txt build/dmg-tmp\ncp pkg-support/resources/ReadMe.txt build/dmg-tmp\ncp pkg-support/resources/share/cmake/SDL3/sdl3-config.cmake build/dmg-tmp/share/cmake/SDL3\ncp pkg-support/resources/share/cmake/SDL3/sdl3-config-version.cmake build/dmg-tmp/share/cmake/SDL3\n\n# remove the .DS_Store files if any (we may want to provide one in the future for fancy .dmgs)\nfind build/dmg-tmp -name .DS_Store -exec rm -f \"{}\" \\;\n\n# for fancy .dmg\nmkdir -p build/dmg-tmp/.logo\ncp pkg-support/resources/SDL_DS_Store build/dmg-tmp/.DS_Store\ncp pkg-support/sdl_logo.pdf build/dmg-tmp/.logo\n\n# create the dmg\nhdiutil create -ov -fs HFS+ -volname SDL3 -srcfolder build/dmg-tmp build/SDL3.dmg\n\n# clean up\nrm -rf build/dmg-tmp\n"; }; F3B38CF0296F63D1005DA6D3 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -2662,10 +2826,13 @@ A7D8BAC723E2514500DCD162 /* e_pow.c in Sources */, A7D8B41C23E2514300DCD162 /* SDL_systls.c in Sources */, 9846B07C287A9020000C35C8 /* SDL_hidapi_shield.c in Sources */, + F31013C72C24E98200FBE946 /* SDL_keymap.c in Sources */, + F3A9AE992C8A13C100AAC390 /* SDL_render_gpu.c in Sources */, A7D8BBD923E2574800DCD162 /* SDL_uikitmessagebox.m in Sources */, F32DDAD42AB795A30041EAA5 /* SDL_audioresample.c in Sources */, F3FA5A212B59ACE000FEAD97 /* yuv_rgb_std.c in Sources */, A7D8AD2923E2514100DCD162 /* SDL_vulkan_utils.c in Sources */, + F36C34322C0F876500991150 /* SDL_offscreenvulkan.c in Sources */, A7D8A95123E2514000DCD162 /* SDL_spinlock.c in Sources */, F34B9895291DEFF500AAC96E /* SDL_hidapi_steam.c in Sources */, A7D8BAAF23E2514400DCD162 /* s_atan.c in Sources */, @@ -2680,15 +2847,19 @@ A7D8B9F523E2514400DCD162 /* SDL_rotate.c in Sources */, A7D8BBE323E2574800DCD162 /* SDL_uikitvideo.m in Sources */, 5616CA4E252BB2A6005D5928 /* SDL_sysurl.m in Sources */, + F3B439562C937DAB00792030 /* SDL_process.c in Sources */, A7D8A97523E2514000DCD162 /* SDL_coremotionsensor.m in Sources */, F382071D284F362F004DD584 /* SDL_guid.c in Sources */, A7D8BB8D23E2514500DCD162 /* SDL_touch.c in Sources */, F31A92D228D4CB39003BFD6A /* SDL_offscreenopengles.c in Sources */, A1626A3E2617006A003F1973 /* SDL_triangle.c in Sources */, A7D8B3F223E2514300DCD162 /* SDL_thread.c in Sources */, + F3F528CF2C29E1C300E6CC26 /* s_isinff.c in Sources */, A7D8B55D23E2514300DCD162 /* SDL_hidapi_xbox360w.c in Sources */, + F3F528CB2C29E1C300E6CC26 /* s_isnanf.c in Sources */, A7D8A95723E2514000DCD162 /* SDL_atomic.c in Sources */, A75FDBCE23EA380300529352 /* SDL_hidapi_rumble.c in Sources */, + E4F257952C81903800FCEAFC /* SDL_gpu_vulkan.c in Sources */, A7D8BB2723E2514500DCD162 /* SDL_displayevents.c in Sources */, A7D8AB2523E2514100DCD162 /* SDL_log.c in Sources */, A7D8AE8823E2514100DCD162 /* SDL_cocoaopengl.m in Sources */, @@ -2699,6 +2870,7 @@ A7D8BABB23E2514400DCD162 /* s_scalbn.c in Sources */, F3973FAB28A59BDD00B84553 /* SDL_crc16.c in Sources */, A7D8AB2B23E2514100DCD162 /* SDL_timer.c in Sources */, + E4F257962C81903800FCEAFC /* SDL_gpu.c in Sources */, F3D60A8328C16A1900788A3A /* SDL_hidapi_wii.c in Sources */, A7D8B9DD23E2514400DCD162 /* SDL_blendpoint.c in Sources */, A7D8B4EE23E2514300DCD162 /* SDL_gamepad.c in Sources */, @@ -2713,6 +2885,7 @@ A7D8ADF223E2514100DCD162 /* SDL_blit_A.c in Sources */, A7D8BBDD23E2574800DCD162 /* SDL_uikitmodes.m in Sources */, A7D8BA3723E2514400DCD162 /* SDL_d3dmath.c in Sources */, + F3A9AE9C2C8A13C100AAC390 /* SDL_pipeline_gpu.c in Sources */, 75E0915A241EA924004729E1 /* SDL_virtualjoystick.c in Sources */, A7D8ABEB23E2514100DCD162 /* SDL_nullvideo.c in Sources */, F3990E072A78833C000D8759 /* hid.m in Sources */, @@ -2727,6 +2900,7 @@ A7D8BA9723E2514400DCD162 /* s_copysign.c in Sources */, F3984CD025BCC92900374F43 /* SDL_hidapi_stadia.c in Sources */, A7D8AAB623E2514100DCD162 /* SDL_haptic.c in Sources */, + E4F257922C81903800FCEAFC /* Metal_Blit.metal in Sources */, A7D8AF2423E2514100DCD162 /* SDL_cocoametalview.m in Sources */, A7D8B86023E2514400DCD162 /* SDL_audiotypecvt.c in Sources */, A7D8BBC523E2561500DCD162 /* SDL_steamcontroller.c in Sources */, @@ -2734,7 +2908,9 @@ A7D8BB7B23E2514500DCD162 /* SDL_dropevents.c in Sources */, A7D8BACD23E2514500DCD162 /* e_atan2.c in Sources */, A7D8BA8B23E2514400DCD162 /* s_sin.c in Sources */, + F3F528CE2C29E1C300E6CC26 /* s_modf.c in Sources */, A7D8BBEB23E2574800DCD162 /* SDL_uikitwindow.m in Sources */, + F3B439532C935C2C00792030 /* SDL_posixprocess.c in Sources */, F395BF6525633B2400942BFF /* SDL_crc32.c in Sources */, A7D8B5E723E2514300DCD162 /* SDL_power.c in Sources */, A7D8AED623E2514100DCD162 /* SDL_cocoakeyboard.m in Sources */, @@ -2766,6 +2942,7 @@ A7D8B95023E2514400DCD162 /* SDL_iconv.c in Sources */, F3E5A6EB2AD5E0E600293D83 /* SDL_properties.c in Sources */, A7D8BA9D23E2514400DCD162 /* s_fabs.c in Sources */, + F3F528CC2C29E1C300E6CC26 /* s_isinf.c in Sources */, F395C1B12569C6A000942BFF /* SDL_mfijoystick.m in Sources */, A7D8B99223E2514400DCD162 /* SDL_shaders_metal.metal in Sources */, F3990DF52A787C10000D8759 /* SDL_sysurl.m in Sources */, @@ -2777,12 +2954,14 @@ A7D8BADF23E2514500DCD162 /* e_fmod.c in Sources */, A7D8B5CF23E2514300DCD162 /* SDL_syspower.m in Sources */, A7D8BAEB23E2514500DCD162 /* e_log10.c in Sources */, + F3B439512C935C2400792030 /* SDL_dummyprocess.c in Sources */, A7D8B76423E2514300DCD162 /* SDL_mixer.c in Sources */, A7D8BB5723E2514500DCD162 /* SDL_events.c in Sources */, A7D8ADE623E2514100DCD162 /* SDL_blit_0.c in Sources */, A7D8BB0923E2514500DCD162 /* k_tan.c in Sources */, A7D8B8A823E2514400DCD162 /* SDL_diskaudio.c in Sources */, 56A2373329F9C113003CCA5F /* SDL_sysrwlock.c in Sources */, + F3A9AE9A2C8A13C100AAC390 /* SDL_shaders_gpu.c in Sources */, 566E26CF246274CC00718109 /* SDL_syslocale.m in Sources */, A7D8AFC023E2514200DCD162 /* SDL_egl.c in Sources */, A7D8AC3323E2514100DCD162 /* SDL_RLEaccel.c in Sources */, @@ -2813,6 +2992,7 @@ A7D8AE9A23E2514100DCD162 /* SDL_cocoaopengles.m in Sources */, A7D8B96823E2514400DCD162 /* SDL_qsort.c in Sources */, F3FA5A222B59ACE000FEAD97 /* yuv_rgb_sse.c in Sources */, + F3C2CB232C5DDDB2004D7998 /* SDL_categories.c in Sources */, A7D8B55123E2514300DCD162 /* SDL_hidapi_switch.c in Sources */, A7D8B96223E2514400DCD162 /* SDL_strtokr.c in Sources */, A7D8BB7523E2514500DCD162 /* SDL_clipboardevents.c in Sources */, @@ -2823,19 +3003,21 @@ A7D8B97423E2514400DCD162 /* SDL_malloc.c in Sources */, A7D8B8C623E2514400DCD162 /* SDL_audio.c in Sources */, A7D8B61D23E2514300DCD162 /* SDL_sysfilesystem.c in Sources */, + E4F257932C81903800FCEAFC /* SDL_gpu_metal.m in Sources */, F3820713284F3609004DD584 /* controller_type.c in Sources */, A7D8AB8B23E2514100DCD162 /* SDL_offscreenvideo.c in Sources */, A7D8B42E23E2514300DCD162 /* SDL_syscond.c in Sources */, A7D8AADA23E2514100DCD162 /* SDL_syshaptic.c in Sources */, A7D8BAE523E2514500DCD162 /* e_exp.c in Sources */, + F3FD042F2C9B755700824C4C /* SDL_hidapi_steam_hori.c in Sources */, A7D8BB8123E2514500DCD162 /* SDL_quit.c in Sources */, F3FA5A232B59ACE000FEAD97 /* yuv_rgb_lsx.c in Sources */, A7D8AEA623E2514100DCD162 /* SDL_cocoawindow.m in Sources */, A7D8B43A23E2514300DCD162 /* SDL_sysmutex.c in Sources */, A7D8AAB023E2514100DCD162 /* SDL_syshaptic.c in Sources */, + F3F528CD2C29E1C300E6CC26 /* s_isnan.c in Sources */, F3F07D5A269640160074468B /* SDL_hidapi_luna.c in Sources */, A7D8BBD523E2574800DCD162 /* SDL_uikitclipboard.m in Sources */, - A7D8B5C923E2514300DCD162 /* SDL_iostreambundlesupport.m in Sources */, F386F6F92884663E001840AA /* SDL_utils.c in Sources */, E4F7981E2AD8D86A00669F54 /* SDL_render_unsupported.c in Sources */, A7D8AC0F23E2514100DCD162 /* SDL_video.c in Sources */, @@ -2866,12 +3048,16 @@ 0000A4DA2F45A31DC4F00000 /* SDL_sysmain_callbacks.m in Sources */, 000028F8113A53F4333E0000 /* SDL_main_callbacks.c in Sources */, 000098E9DAA43EF6FF7F0000 /* SDL_camera.c in Sources */, + F310138E2C1F2CB700FBE946 /* SDL_random.c in Sources */, 00001B2471F503DD3C1B0000 /* SDL_camera_dummy.c in Sources */, 00002B20A48E055EB0350000 /* SDL_camera_coremedia.m in Sources */, 000080903BC03006F24E0000 /* SDL_filesystem.c in Sources */, 0000481D255AF155B42C0000 /* SDL_sysfsops.c in Sources */, 0000494CC93F3E624D3C0000 /* SDL_systime.c in Sources */, 000095FA1BDE436CF3AF0000 /* SDL_time.c in Sources */, + 0000140640E77F73F1DF0000 /* SDL_dialog_utils.c in Sources */, + 0000D5B526B85DE7AB1C0000 /* SDL_cocoapen.m in Sources */, + 6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2893,8 +3079,8 @@ CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; DEPLOYMENT_POSTPROCESSING = YES; - DYLIB_COMPATIBILITY_VERSION = 102.0.0; - DYLIB_CURRENT_VERSION = 102.0.0; + DYLIB_COMPATIBILITY_VERSION = 104.0.0; + DYLIB_CURRENT_VERSION = 104.0.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_ALTIVEC_EXTENSIONS = YES; @@ -2906,6 +3092,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = ( ../../include, + ../../include/build_config, ../../src, ../../src/hidapi/hidapi, ../../src/video/khronos, @@ -2924,7 +3111,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11; - MARKETING_VERSION = 3.1.1; + MARKETING_VERSION = 3.1.3; PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3; PRODUCT_NAME = SDL3; STRIP_STYLE = "non-global"; @@ -2950,8 +3137,8 @@ ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; - DYLIB_COMPATIBILITY_VERSION = 102.0.0; - DYLIB_CURRENT_VERSION = 102.0.0; + DYLIB_COMPATIBILITY_VERSION = 104.0.0; + DYLIB_CURRENT_VERSION = 104.0.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -2963,6 +3150,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = ( ../../include, + ../../include/build_config, ../../src, ../../src/hidapi/hidapi, ../../src/video/khronos, @@ -2981,7 +3169,7 @@ "@loader_path/Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.11; - MARKETING_VERSION = 3.1.1; + MARKETING_VERSION = 3.1.3; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3; PRODUCT_NAME = SDL3; diff --git a/libs/SDL3/Xcode/SDL/pkg-support/SDL.info b/libs/SDL3/Xcode/SDL/pkg-support/SDL.info index ba7ac6644..610ab5e70 100644 --- a/libs/SDL3/Xcode/SDL/pkg-support/SDL.info +++ b/libs/SDL3/Xcode/SDL/pkg-support/SDL.info @@ -1,4 +1,4 @@ -Title SDL 3.1.1 +Title SDL 3.1.3 Version 1 Description SDL Library for macOS (http://www.libsdl.org) DefaultLocation /Library/Frameworks diff --git a/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake b/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake index 21d6f7d7c..74329c438 100644 --- a/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake +++ b/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config-version.cmake @@ -1,39 +1,24 @@ # based on the files generated by CMake's write_basic_package_version_file # SDL CMake version configuration file: -# This file is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework +# This file is meant to be placed in Resources/CMake of a SDL3 framework cmake_minimum_required(VERSION 3.12) -get_filename_component(_sdl3_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3/ -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3/ -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share/cmake -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # / -set(_sdl3_xcframework "${_sdl3_xcframework_parent_path}/SDL3.xcframework") # /SDL3.xcframework -set(_sdl3_framework "${_sdl3_xcframework}/macos-arm64_x86_64/SDL3.framework") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework -set(_sdl3_version_h "${_sdl3_framework}/Headers/SDL_version.h") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/Headers/SDL_version.h - -if(NOT EXISTS "${_sdl3_version_h}") - message(AUTHOR_WARNING "Cannot not find ${_sdl3_framework}. This script is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework") +if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/../../Headers/SDL_version.h") + message(AUTHOR_WARNING "Could not find SDL_version.h. This script is meant to be placed in the Resources/CMake directory of SDL2.framework") return() endif() -file(READ "${_sdl3_version_h}" _sdl_version_h) - -unset(_sdl3_xcframework_parent_path) -unset(_sdl3_framework) -unset(_sdl3_xcframework) -unset(_sdl3_version_h) - +file(READ "${CMAKE_CURRENT_LIST_DIR}/../../Headers/SDL_version.h" _sdl_version_h) string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re "${_sdl_version_h}") set(_sdl_major "${CMAKE_MATCH_1}") string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_version_h}") set(_sdl_minor "${CMAKE_MATCH_1}") -string(REGEX MATCH "#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)" _sdl_patch_re "${_sdl_version_h}") -set(_sdl_patch "${CMAKE_MATCH_1}") -if(_sdl_major_re AND _sdl_minor_re AND _sdl_patch_re) - set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_patch}") +string(REGEX MATCH "#define[ \t]+SDL_MICRO_VERSION[ \t]+([0-9]+)" _sdl_micro_re "${_sdl_version_h}") +set(_sdl_micro "${CMAKE_MATCH_1}") +if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re) + set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}") else() message(AUTHOR_WARNING "Could not extract version from SDL_version.h.") return() @@ -43,8 +28,8 @@ unset(_sdl_major_re) unset(_sdl_major) unset(_sdl_minor_re) unset(_sdl_minor) -unset(_sdl_patch_re) -unset(_sdl_patch) +unset(_sdl_micro_re) +unset(_sdl_micro) if(PACKAGE_FIND_VERSION_RANGE) # Package version must be in the requested version range @@ -70,7 +55,3 @@ endif() if(NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8") set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() - -if(NOT CMAKE_SYSTEM_NAME MATCHES "^(Darwin|iOS|tvOS)$") - set(PACKAGE_VERSION_UNSUITABLE TRUE) -endif() diff --git a/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake b/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake index 1e5151bd1..784d27dbb 100644 --- a/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake +++ b/libs/SDL3/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake @@ -1,5 +1,5 @@ -# SDL CMake configuration file: -# This file is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework +# SDL3 CMake configuration file: +# This file is meant to be placed in Resources/CMake of a SDL3 framework # INTERFACE_LINK_OPTIONS needs CMake 3.12 cmake_minimum_required(VERSION 3.12) @@ -31,49 +31,15 @@ endmacro() set(SDL3_FOUND TRUE) -macro(_check_target_is_simulator) - include(CheckCSourceCompiles) - check_c_source_compiles([===[ - #include - #if defined(TARGET_OS_SIMULATOR) - int target_is_simulator; - #endif - int main(int argc, char *argv[]) { return target_is_simulator; } - ]===] SDL_TARGET_IS_SIMULATOR) -endmacro() - -if(CMAKE_SYSTEM_NAME STREQUAL "iOS") - _check_target_is_simulator() - if(SDL_TARGET_IS_SIMULATOR) - set(_xcfw_target_subdir "ios-arm64_x86_64-simulator") - else() - set(_xcfw_target_subdir "ios-arm64") - endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS") - _check_target_is_simulator() - if(SDL_TARGET_IS_SIMULATOR) - set(_xcfw_target_subdir "tvos-arm64_x86_64-simulator") - else() - set(_xcfw_target_subdir "tvos-arm64") - endif() -elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(_xcfw_target_subdir "macos-arm64_x86_64") -else() - message(WARNING "Unsupported Apple platform (${CMAKE_SYSTEM_NAME}) and broken sdl3-config-version.cmake") - set(SDL3_FOUND FALSE) - return() -endif() - # Compute the installation prefix relative to this file. -get_filename_component(_sdl3_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3/ -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3/ -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share/cmake -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share -get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # / -set_and_check(_sdl3_xcframework_path "${_sdl3_xcframework_parent_path}/SDL3.xcframework") # /SDL3.xcframework -set_and_check(_sdl3_framework_parent_path "${_sdl3_xcframework_path}/${_xcfw_target_subdir}") # /SDL3.xcframework/macos-arm64_x86_64 -set_and_check(_sdl3_framework_path "${_sdl3_framework_parent_path}/SDL3.framework") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework -set_and_check(_sdl3_include_dirs "${_sdl3_framework_path}/Headers") +set(_sdl3_framework_path "${CMAKE_CURRENT_LIST_DIR}") # > /SDL3.framework/Resources/CMake/ +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" REALPATH) # > /SDL3.framework/Versions/Current/Resources/CMake +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" REALPATH) # > /SDL3.framework/Versions/A/Resources/CMake/ +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" PATH) # > /SDL3.framework/Versions/A/Resources/ +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" PATH) # > /SDL3.framework/Versions/A/ +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" PATH) # > /SDL3.framework/Versions/ +get_filename_component(_sdl3_framework_path "${_sdl3_framework_path}" PATH) # > /SDL3.framework/ +get_filename_component(_sdl3_framework_parent_path "${_sdl3_framework_path}" PATH) # > / # All targets are created, even when some might not be requested though COMPONENTS. @@ -84,30 +50,17 @@ if(NOT TARGET SDL3::Headers) set_target_properties(SDL3::Headers PROPERTIES INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${_sdl3_framework_parent_path}\"" - INTERFACE_INCLUDE_DIRECTORIES "${_sdl3_include_dirs}" ) endif() set(SDL3_Headers_FOUND TRUE) if(NOT TARGET SDL3::SDL3-shared) add_library(SDL3::SDL3-shared SHARED IMPORTED) - if(CMAKE_VERSION GREATER_EQUAL "3.28") - set_target_properties(SDL3::SDL3-shared - PROPERTIES - FRAMEWORK "TRUE" - IMPORTED_LOCATION "${_sdl3_xcframework_path}" - INTERFACE_LINK_LIBRARIES "SDL3::Headers" - ) - else() - set_target_properties(SDL3::SDL3-shared - PROPERTIES - FRAMEWORK "TRUE" - IMPORTED_LOCATION "${_sdl3_framework_path}/SDL3" - INTERFACE_LINK_LIBRARIES "SDL3::Headers" - ) - endif() set_target_properties(SDL3::SDL3-shared PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_framework_path}/SDL3" + INTERFACE_LINK_LIBRARIES "SDL3::Headers" COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" INTERFACE_SDL3_SHARED "ON" COMPATIBLE_INTERFACE_STRING "SDL_VERSION" @@ -120,11 +73,8 @@ set(SDL3_SDL3-static FALSE) set(SDL3_SDL3_test FALSE) -unset(_sdl3_xcframework_parent_path) -unset(_sdl3_xcframework_path) unset(_sdl3_framework_parent_path) unset(_sdl3_framework_path) -unset(_sdl3_include_dirs) if(SDL3_SDL3-shared_FOUND) set(SDL3_SDL3_FOUND TRUE) diff --git a/libs/SDL3/Xcode/SDL/pkg-support/resources/ReadMe.txt b/libs/SDL3/Xcode/SDL/pkg-support/resources/ReadMe.txt index 27130884f..6ea93478f 100644 --- a/libs/SDL3/Xcode/SDL/pkg-support/resources/ReadMe.txt +++ b/libs/SDL3/Xcode/SDL/pkg-support/resources/ReadMe.txt @@ -1,29 +1,29 @@ -The Simple DirectMedia Layer (SDL for short) is a cross-platform -library designed to make it easy to write multi-media software, +The Simple DirectMedia Layer (SDL for short) is a cross-platform +library designed to make it easy to write multi-media software, such as games and emulators. -The Simple DirectMedia Layer library source code is available from: +The Simple DirectMedia Layer library source code is available from: http://www.libsdl.org/ -This library is distributed under the terms of the zlib license: +This library is distributed under the terms of the zlib license: http://zlib.net/zlib_license.html -This packages contains the SDL framework for macOS. -Conforming with Apple guidelines, this framework +This packages contains the SDL framework for macOS. +Conforming with Apple guidelines, this framework contains both the SDL runtime component and development header files. To Install: -Copy the SDL3.framework to /Library/Frameworks +Copy "SDL3.xcframework" and "share" to /Library/Frameworks -You may alternatively install it in /Library/Frameworks +You may alternatively install it in /Library/Frameworks if your access privileges are not high enough. Use in CMake projects: -SDL3.framework can be used in CMake projects using the following pattern: -``` +SDL3.xcframework can be used in CMake projects using the following pattern: +```cmake find_package(SDL3 REQUIRED COMPONENTS SDL3) add_executable(my_game ${MY_SOURCES}) target_link_libraries(my_game PRIVATE SDL3::SDL3) @@ -35,10 +35,10 @@ https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search Additional References: - - Screencast tutorials for getting started with OpenSceneGraph/macOS are + - Screencast tutorials for getting started with OpenSceneGraph/macOS are available at: http://www.openscenegraph.org/projects/osg/wiki/Support/Tutorials/MacOSXTips - Though these are OpenSceneGraph centric, the same exact concepts apply to + Though these are OpenSceneGraph centric, the same exact concepts apply to SDL, thus the videos are recommended for everybody getting started with developing on macOS. (You can skim over the PlugIns stuff since SDL doesn't have any PlugIns to worry about.) diff --git a/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config-version.cmake b/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config-version.cmake new file mode 100644 index 000000000..6c833a7f2 --- /dev/null +++ b/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config-version.cmake @@ -0,0 +1,76 @@ +# based on the files generated by CMake's write_basic_package_version_file + +# SDL CMake version configuration file: +# This file is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework + +cmake_minimum_required(VERSION 3.12) + +get_filename_component(_sdl3_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share/cmake +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # / +set(_sdl3_xcframework "${_sdl3_xcframework_parent_path}/SDL3.xcframework") # /SDL3.xcframework +set(_sdl3_framework "${_sdl3_xcframework}/macos-arm64_x86_64/SDL3.framework") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework +set(_sdl3_version_h "${_sdl3_framework}/Headers/SDL_version.h") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/Headers/SDL_version.h + +if(NOT EXISTS "${_sdl3_version_h}") + message(AUTHOR_WARNING "Cannot not find ${_sdl3_framework}. This script is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework") + return() +endif() + +file(READ "${_sdl3_version_h}" _sdl_version_h) + +unset(_sdl3_xcframework_parent_path) +unset(_sdl3_framework) +unset(_sdl3_xcframework) +unset(_sdl3_version_h) + +string(REGEX MATCH "#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)" _sdl_major_re "${_sdl_version_h}") +set(_sdl_major "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)" _sdl_minor_re "${_sdl_version_h}") +set(_sdl_minor "${CMAKE_MATCH_1}") +string(REGEX MATCH "#define[ \t]+SDL_MICRO_VERSION[ \t]+([0-9]+)" _sdl_micro_re "${_sdl_version_h}") +set(_sdl_micro "${CMAKE_MATCH_1}") +if(_sdl_major_re AND _sdl_minor_re AND _sdl_micro_re) + set(PACKAGE_VERSION "${_sdl_major}.${_sdl_minor}.${_sdl_micro}") +else() + message(AUTHOR_WARNING "Could not extract version from SDL_version.h.") + return() +endif() + +unset(_sdl_major_re) +unset(_sdl_major) +unset(_sdl_minor_re) +unset(_sdl_minor) +unset(_sdl_micro_re) +unset(_sdl_micro) + +if(PACKAGE_FIND_VERSION_RANGE) + # Package version must be in the requested version range + if ((PACKAGE_FIND_VERSION_RANGE_MIN STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MIN) + OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_GREATER PACKAGE_FIND_VERSION_MAX) + OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_GREATER_EQUAL PACKAGE_FIND_VERSION_MAX))) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + endif() +else() + if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) + else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() + endif() +endif() + +# The SDL3.xcframework only contains 64-bit archives +if(NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() + +if(NOT CMAKE_SYSTEM_NAME MATCHES "^(Darwin|iOS|tvOS)$") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() diff --git a/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config.cmake b/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config.cmake new file mode 100644 index 000000000..278cd3b20 --- /dev/null +++ b/libs/SDL3/Xcode/SDL/pkg-support/resources/share/cmake/SDL3/sdl3-config.cmake @@ -0,0 +1,154 @@ +# SDL3 CMake configuration file: +# This file is meant to be placed in share/cmake/SDL3, next to SDL3.xcframework + +# INTERFACE_LINK_OPTIONS needs CMake 3.12 +cmake_minimum_required(VERSION 3.12) + +include(FeatureSummary) +set_package_properties(SDL3 PROPERTIES + URL "https://www.libsdl.org/" + DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware" +) + +# Copied from `configure_package_config_file` +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +# Copied from `configure_package_config_file` +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +set(SDL3_FOUND TRUE) + +macro(_check_target_is_simulator) + include(CheckCSourceCompiles) + check_c_source_compiles([===[ + #include + #if defined(TARGET_OS_SIMULATOR) + int target_is_simulator; + #endif + int main(int argc, char *argv[]) { return target_is_simulator; } + ]===] SDL_TARGET_IS_SIMULATOR) +endmacro() + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + _check_target_is_simulator() + if(SDL_TARGET_IS_SIMULATOR) + set(_xcfw_target_subdir "ios-arm64_x86_64-simulator") + else() + set(_xcfw_target_subdir "ios-arm64") + endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS") + _check_target_is_simulator() + if(SDL_TARGET_IS_SIMULATOR) + set(_xcfw_target_subdir "tvos-arm64_x86_64-simulator") + else() + set(_xcfw_target_subdir "tvos-arm64") + endif() +elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(_xcfw_target_subdir "macos-arm64_x86_64") +else() + message(WARNING "Unsupported Apple platform (${CMAKE_SYSTEM_NAME}) and broken sdl3-config-version.cmake") + set(SDL3_FOUND FALSE) + return() +endif() + +# Compute the installation prefix relative to this file. +get_filename_component(_sdl3_xcframework_parent_path "${CMAKE_CURRENT_LIST_DIR}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" REALPATH) # /share/cmake/SDL3/ +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share/cmake +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # /share +get_filename_component(_sdl3_xcframework_parent_path "${_sdl3_xcframework_parent_path}" PATH) # / +set_and_check(_sdl3_xcframework_path "${_sdl3_xcframework_parent_path}/SDL3.xcframework") # /SDL3.xcframework +set_and_check(_sdl3_framework_parent_path "${_sdl3_xcframework_path}/${_xcfw_target_subdir}") # /SDL3.xcframework/macos-arm64_x86_64 +set_and_check(_sdl3_framework_path "${_sdl3_framework_parent_path}/SDL3.framework") # /SDL3.xcframework/macos-arm64_x86_64/SDL3.framework + + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3-target.cmake files. + +if(NOT TARGET SDL3::Headers) + add_library(SDL3::Headers INTERFACE IMPORTED) + set_target_properties(SDL3::Headers + PROPERTIES + INTERFACE_COMPILE_OPTIONS "SHELL:-F \"${_sdl3_framework_parent_path}\"" + ) +endif() +set(SDL3_Headers_FOUND TRUE) + +if(NOT TARGET SDL3::SDL3-shared) + add_library(SDL3::SDL3-shared SHARED IMPORTED) + if(CMAKE_VERSION GREATER_EQUAL "3.28") + set_target_properties(SDL3::SDL3-shared + PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_xcframework_path}" + INTERFACE_LINK_LIBRARIES "SDL3::Headers" + ) + else() + set_target_properties(SDL3::SDL3-shared + PROPERTIES + FRAMEWORK "TRUE" + IMPORTED_LOCATION "${_sdl3_framework_path}/SDL3" + INTERFACE_LINK_LIBRARIES "SDL3::Headers" + ) + endif() + set_target_properties(SDL3::SDL3-shared + PROPERTIES + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) +endif() +set(SDL3_SDL3-shared_FOUND TRUE) + +set(SDL3_SDL3-static FALSE) + +set(SDL3_SDL3_test FALSE) + +unset(_sdl3_xcframework_parent_path) +unset(_sdl3_xcframework_path) +unset(_sdl3_framework_parent_path) +unset(_sdl3_framework_path) +unset(_sdl3_include_dirs) + +if(SDL3_SDL3-shared_FOUND) + set(SDL3_SDL3_FOUND TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3::SDL3 always exists +if(NOT TARGET SDL3::SDL3) + if(TARGET SDL3::SDL3-shared) + _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-shared) + endif() +endif() + +check_required_components(SDL3) + +set(SDL3_LIBRARIES SDL3::SDL3) +set(SDL3_STATIC_LIBRARIES SDL3::SDL3-static) +set(SDL3_STATIC_PRIVATE_LIBS) + +set(SDL3TEST_LIBRARY SDL3::SDL3_test) diff --git a/libs/SDL3/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj b/libs/SDL3/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj index 2069c2229..b1b49715a 100644 --- a/libs/SDL3/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj +++ b/libs/SDL3/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj @@ -89,6 +89,10 @@ 00794EF709D237DE003FC8A1 /* moose.dat in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E5E09D20839003FC8A1 /* moose.dat */; }; 453774A5120915E3002F0F45 /* testshape.c in Sources */ = {isa = PBXBuildFile; fileRef = 453774A4120915E3002F0F45 /* testshape.c */; }; 66E88E8B203B778F0004D44E /* testyuv_cvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 66E88E8A203B778F0004D44E /* testyuv_cvt.c */; }; + A1A8594E2BC72FC20045DD6C /* testautomation_properties.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A859482BC72FC20045DD6C /* testautomation_properties.c */; }; + A1A859502BC72FC20045DD6C /* testautomation_subsystems.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A859492BC72FC20045DD6C /* testautomation_subsystems.c */; }; + A1A859522BC72FC20045DD6C /* testautomation_log.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A8594A2BC72FC20045DD6C /* testautomation_log.c */; }; + A1A859542BC72FC20045DD6C /* testautomation_time.c in Sources */ = {isa = PBXBuildFile; fileRef = A1A8594B2BC72FC20045DD6C /* testautomation_time.c */; }; AAF02FFA1F90092700B9A9FB /* SDL_test_memory.c in Sources */ = {isa = PBXBuildFile; fileRef = AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */; }; BBFC08D0164C6876003E6A99 /* testcontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088E164C6820003E6A99 /* testcontroller.c */; }; BEC566B10761D90300A33029 /* checkkeys.c in Sources */ = {isa = PBXBuildFile; fileRef = 092D6D10FFB30A2C7F000001 /* checkkeys.c */; }; @@ -112,7 +116,6 @@ DB166D9916A1D1A500A1396C /* SDL_test_harness.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166D8A16A1D1A500A1396C /* SDL_test_harness.c */; }; DB166D9F16A1D1A500A1396C /* SDL_test_log.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166D9016A1D1A500A1396C /* SDL_test_log.c */; }; DB166DA016A1D1A500A1396C /* SDL_test_md5.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166D9116A1D1A500A1396C /* SDL_test_md5.c */; }; - DB166DA116A1D1A500A1396C /* SDL_test_random.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166D9216A1D1A500A1396C /* SDL_test_random.c */; }; DB166DD716A1D37800A1396C /* testmessage.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166CBD16A1C74100A1396C /* testmessage.c */; }; DB166DDB16A1D42F00A1396C /* icon.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E5D09D20839003FC8A1 /* icon.bmp */; }; DB166DF016A1D52500A1396C /* testrelative.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166CBF16A1C74100A1396C /* testrelative.c */; }; @@ -131,7 +134,6 @@ DB166E9416A1D7C700A1396C /* teststreaming.c in Sources */ = {isa = PBXBuildFile; fileRef = DB166CC616A1C74100A1396C /* teststreaming.c */; }; DB166E9A16A1D7F700A1396C /* moose.dat in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E5E09D20839003FC8A1 /* moose.dat */; }; DB166E9C16A1D80900A1396C /* icon.bmp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 00794E5D09D20839003FC8A1 /* icon.bmp */; }; - DB166ED016A1D88100A1396C /* shapes in CopyFiles */ = {isa = PBXBuildFile; fileRef = DB166ECF16A1D87000A1396C /* shapes */; }; DB445EFB18184BB600B306B0 /* testdropfile.c in Sources */ = {isa = PBXBuildFile; fileRef = DB445EFA18184BB600B306B0 /* testdropfile.c */; }; DB89958418A19B130092407C /* testhotplug.c in Sources */ = {isa = PBXBuildFile; fileRef = DB89958318A19B130092407C /* testhotplug.c */; }; F35E56CF2983130F00A43A5F /* testautomation_main.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56B62983130A00A43A5F /* testautomation_main.c */; }; @@ -156,6 +158,10 @@ F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CB2983130F00A43A5F /* testautomation_surface.c */; }; F35E56E42983130F00A43A5F /* testautomation.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CC2983130F00A43A5F /* testautomation.c */; }; F35E56E52983130F00A43A5F /* testautomation_mouse.c in Sources */ = {isa = PBXBuildFile; fileRef = F35E56CD2983130F00A43A5F /* testautomation_mouse.c */; }; + F36C34212C0F85DB00991150 /* SDL3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA643093FFD41000C53B3 /* SDL3.framework */; }; + F36C34232C0F85DB00991150 /* SDL3.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA643093FFD41000C53B3 /* SDL3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F36C342D2C0F869B00991150 /* testcamera.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C342C2C0F869B00991150 /* testcamera.c */; }; + F36C342E2C0F869B00991150 /* testcamera.c in Sources */ = {isa = PBXBuildFile; fileRef = F36C342C2C0F869B00991150 /* testcamera.c */; }; F399C64E2A78929400C86979 /* gamepadutils.c in Sources */ = {isa = PBXBuildFile; fileRef = F399C6492A78929400C86979 /* gamepadutils.c */; }; F399C64F2A78929400C86979 /* gamepadutils.c in Sources */ = {isa = PBXBuildFile; fileRef = F399C6492A78929400C86979 /* gamepadutils.c */; }; F399C6512A7892D800C86979 /* testautomation_intrinsics.c in Sources */ = {isa = PBXBuildFile; fileRef = F399C6502A7892D800C86979 /* testautomation_intrinsics.c */; }; @@ -178,6 +184,8 @@ F3C17CEC28E417EB00E1A26D /* testutils.c in Sources */ = {isa = PBXBuildFile; fileRef = F3C17C7328E40ADE00E1A26D /* testutils.c */; }; F3C17D3928E424B800E1A26D /* sample.wav in Resources */ = {isa = PBXBuildFile; fileRef = 00794E6209D20839003FC8A1 /* sample.wav */; }; F3C17D3B28E4252900E1A26D /* icon.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 00794E5D09D20839003FC8A1 /* icon.bmp */; }; + F3C2CAC62C5C8BD6004D7998 /* unifont-15.1.05.hex in Resources */ = {isa = PBXBuildFile; fileRef = F3C2CAC52C5C8BD6004D7998 /* unifont-15.1.05.hex */; }; + F3C2CB072C5D3FB2004D7998 /* icon.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 00794E5D09D20839003FC8A1 /* icon.bmp */; }; F3CB56892A7895F800766177 /* SDL3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA643093FFD41000C53B3 /* SDL3.framework */; }; F3CB568A2A7895F800766177 /* SDL3.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA643093FFD41000C53B3 /* SDL3.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; F3CB568C2A7896BF00766177 /* SDL3.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 003FA643093FFD41000C53B3 /* SDL3.framework */; }; @@ -695,10 +703,20 @@ dstPath = ""; dstSubfolderSpec = 7; files = ( - DB166ED016A1D88100A1396C /* shapes in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; + F36C34222C0F85DB00991150 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + F36C34232C0F85DB00991150 /* SDL3.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; F3CB568B2A7895F800766177 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1256,6 +1274,10 @@ 4537749212091504002F0F45 /* testshape.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testshape.app; sourceTree = BUILT_PRODUCTS_DIR; }; 453774A4120915E3002F0F45 /* testshape.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testshape.c; sourceTree = ""; }; 66E88E8A203B778F0004D44E /* testyuv_cvt.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = testyuv_cvt.c; sourceTree = ""; }; + A1A859482BC72FC20045DD6C /* testautomation_properties.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_properties.c; sourceTree = ""; }; + A1A859492BC72FC20045DD6C /* testautomation_subsystems.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_subsystems.c; sourceTree = ""; }; + A1A8594A2BC72FC20045DD6C /* testautomation_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_log.c; sourceTree = ""; }; + A1A8594B2BC72FC20045DD6C /* testautomation_time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_time.c; sourceTree = ""; }; AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_test_memory.c; sourceTree = ""; }; BBFC088E164C6820003E6A99 /* testcontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testcontroller.c; sourceTree = ""; }; BBFC08CD164C6862003E6A99 /* testcontroller.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testcontroller.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1293,7 +1315,6 @@ DB166D8A16A1D1A500A1396C /* SDL_test_harness.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_test_harness.c; sourceTree = ""; }; DB166D9016A1D1A500A1396C /* SDL_test_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_test_log.c; sourceTree = ""; }; DB166D9116A1D1A500A1396C /* SDL_test_md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_test_md5.c; sourceTree = ""; }; - DB166D9216A1D1A500A1396C /* SDL_test_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_test_random.c; sourceTree = ""; }; DB166DD516A1D36A00A1396C /* testmessage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testmessage.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB166DEE16A1D50C00A1396C /* testrelative.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testrelative.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB166E0516A1D57C00A1396C /* testrendercopyex.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testrendercopyex.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1303,7 +1324,6 @@ DB166E6816A1D6F300A1396C /* testshader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testshader.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB166E7E16A1D78400A1396C /* testspriteminimal.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testspriteminimal.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB166E9116A1D78C00A1396C /* teststreaming.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = teststreaming.app; sourceTree = BUILT_PRODUCTS_DIR; }; - DB166ECF16A1D87000A1396C /* shapes */ = {isa = PBXFileReference; lastKnownFileType = folder; path = shapes; sourceTree = ""; }; DB445EF818184B7000B306B0 /* testdropfile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testdropfile.app; sourceTree = BUILT_PRODUCTS_DIR; }; DB445EFA18184BB600B306B0 /* testdropfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testdropfile.c; sourceTree = ""; }; DB89957E18A19ABA0092407C /* testhotplug.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testhotplug.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1331,6 +1351,8 @@ F35E56CB2983130F00A43A5F /* testautomation_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_surface.c; sourceTree = ""; }; F35E56CC2983130F00A43A5F /* testautomation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation.c; sourceTree = ""; }; F35E56CD2983130F00A43A5F /* testautomation_mouse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_mouse.c; sourceTree = ""; }; + F36C34272C0F85DB00991150 /* testcamera.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testcamera.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F36C342C2C0F869B00991150 /* testcamera.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testcamera.c; sourceTree = ""; }; F399C6492A78929400C86979 /* gamepadutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gamepadutils.c; sourceTree = ""; }; F399C6502A7892D800C86979 /* testautomation_intrinsics.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testautomation_intrinsics.c; sourceTree = ""; }; F399C6542A78933000C86979 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; @@ -1338,6 +1360,7 @@ F3C17C7328E40ADE00E1A26D /* testutils.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = testutils.c; sourceTree = ""; }; F3C17CD628E416AC00E1A26D /* testgeometry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testgeometry.c; sourceTree = ""; }; F3C17CDC28E416CF00E1A26D /* testgeometry.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = testgeometry.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F3C2CAC52C5C8BD6004D7998 /* unifont-15.1.05.hex */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "unifont-15.1.05.hex"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1701,6 +1724,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F36C34202C0F85DB00991150 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F36C34212C0F85DB00991150 /* SDL3.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F3C17CD928E416CF00E1A26D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1728,7 +1759,7 @@ 00794E5F09D20839003FC8A1 /* picture.xbm */, 00794E6109D20839003FC8A1 /* sample.bmp */, 00794E6209D20839003FC8A1 /* sample.wav */, - DB166ECF16A1D87000A1396C /* shapes */, + F3C2CAC52C5C8BD6004D7998 /* unifont-15.1.05.hex */, 00794E6309D20839003FC8A1 /* utf8.txt */, ); name = Resources; @@ -1765,22 +1796,27 @@ F35E56B72983130A00A43A5F /* testautomation_hints.c */, F35E56BF2983130C00A43A5F /* testautomation_images.c */, F399C6502A7892D800C86979 /* testautomation_intrinsics.c */, + F35E56B92983130B00A43A5F /* testautomation_iostream.c */, F35E56C62983130D00A43A5F /* testautomation_joystick.c */, F35E56C72983130E00A43A5F /* testautomation_keyboard.c */, + A1A8594A2BC72FC20045DD6C /* testautomation_log.c */, F35E56B62983130A00A43A5F /* testautomation_main.c */, F35E56BA2983130B00A43A5F /* testautomation_math.c */, F35E56CD2983130F00A43A5F /* testautomation_mouse.c */, F35E56C02983130C00A43A5F /* testautomation_pixels.c */, F35E56C32983130D00A43A5F /* testautomation_platform.c */, + A1A859482BC72FC20045DD6C /* testautomation_properties.c */, F35E56C52983130D00A43A5F /* testautomation_rect.c */, F35E56B82983130A00A43A5F /* testautomation_render.c */, - F35E56B92983130B00A43A5F /* testautomation_iostream.c */, F35E56C82983130E00A43A5F /* testautomation_sdltest.c */, F35E56BE2983130C00A43A5F /* testautomation_stdlib.c */, + A1A859492BC72FC20045DD6C /* testautomation_subsystems.c */, F35E56CB2983130F00A43A5F /* testautomation_surface.c */, + A1A8594B2BC72FC20045DD6C /* testautomation_time.c */, F35E56BD2983130B00A43A5F /* testautomation_timer.c */, F35E56C12983130C00A43A5F /* testautomation_video.c */, F35E56CC2983130F00A43A5F /* testautomation.c */, + F36C342C2C0F869B00991150 /* testcamera.c */, BBFC088E164C6820003E6A99 /* testcontroller.c */, 001797711074320D00F5D044 /* testdraw.c */, DB0F48D717CA51D2008798C5 /* testdrawchessboard.c */, @@ -1881,6 +1917,7 @@ DB445EF818184B7000B306B0 /* testdropfile.app */, F3C17CDC28E416CF00E1A26D /* testgeometry.app */, F35E56AA298312CB00A43A5F /* testautomation.app */, + F36C34272C0F85DB00991150 /* testcamera.app */, ); name = Products; sourceTree = ""; @@ -1898,7 +1935,6 @@ DB166D9016A1D1A500A1396C /* SDL_test_log.c */, DB166D9116A1D1A500A1396C /* SDL_test_md5.c */, AAF02FF41F90089800B9A9FB /* SDL_test_memory.c */, - DB166D9216A1D1A500A1396C /* SDL_test_random.c */, ); name = SDL_Test; path = ../../src/test; @@ -2017,6 +2053,7 @@ 0017977B107432AE00F5D044 /* Sources */, 0017977C107432AE00F5D044 /* Frameworks */, F3CB56C22A78979600766177 /* Embed Frameworks */, + F3C2CAC42C5C8BAF004D7998 /* Resources */, ); buildRules = ( ); @@ -2702,6 +2739,23 @@ productReference = F35E56AA298312CB00A43A5F /* testautomation.app */; productType = "com.apple.product-type.application"; }; + F36C341D2C0F85DB00991150 /* testcamera */ = { + isa = PBXNativeTarget; + buildConfigurationList = F36C34242C0F85DB00991150 /* Build configuration list for PBXNativeTarget "testcamera" */; + buildPhases = ( + F36C341E2C0F85DB00991150 /* Sources */, + F36C34202C0F85DB00991150 /* Frameworks */, + F36C34222C0F85DB00991150 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = testcamera; + productName = testalpha; + productReference = F36C34272C0F85DB00991150 /* testcamera.app */; + productType = "com.apple.product-type.application"; + }; F3C17CDB28E416CF00E1A26D /* testgeometry */ = { isa = PBXNativeTarget; buildConfigurationList = F3C17CE828E416D000E1A26D /* Build configuration list for PBXNativeTarget "testgeometry" */; @@ -2895,6 +2949,7 @@ 0017957410741F7900F5D044 /* testatomic */, 00179595107421BF00F5D044 /* testaudioinfo */, F35E56A2298312CB00A43A5F /* testautomation */, + F36C341D2C0F85DB00991150 /* testcamera */, BBFC08B7164C6862003E6A99 /* testcontroller */, 00179756107431B300F5D044 /* testdraw */, DB0F48D917CA51E5008798C5 /* testdrawchessboard */, @@ -2966,6 +3021,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F3C2CAC42C5C8BAF004D7998 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F3C2CB072C5D3FB2004D7998 /* icon.bmp in Resources */, + F3C2CAC62C5C8BD6004D7998 /* unifont-15.1.05.hex in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -3218,6 +3282,7 @@ files = ( BEC567F00761D90600A33029 /* torturethread.c in Sources */, F399C64F2A78929400C86979 /* gamepadutils.c in Sources */, + F36C342E2C0F869B00991150 /* testcamera.c in Sources */, F399C6522A7892D800C86979 /* testautomation_intrinsics.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3252,7 +3317,6 @@ DB166D9F16A1D1A500A1396C /* SDL_test_log.c in Sources */, DB166DA016A1D1A500A1396C /* SDL_test_md5.c in Sources */, AAF02FFA1F90092700B9A9FB /* SDL_test_memory.c in Sources */, - DB166DA116A1D1A500A1396C /* SDL_test_random.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3354,8 +3418,10 @@ buildActionMask = 2147483647; files = ( F35E56D12983130F00A43A5F /* testautomation_render.c in Sources */, + A1A859502BC72FC20045DD6C /* testautomation_subsystems.c in Sources */, F399C6512A7892D800C86979 /* testautomation_intrinsics.c in Sources */, F35E56D22983130F00A43A5F /* testautomation_iostream.c in Sources */, + A1A859522BC72FC20045DD6C /* testautomation_log.c in Sources */, F35E56E32983130F00A43A5F /* testautomation_surface.c in Sources */, F35E56DB2983130F00A43A5F /* testautomation_platform.c in Sources */, F35E56DD2983130F00A43A5F /* testautomation_rect.c in Sources */, @@ -3371,14 +3437,24 @@ F35E56D32983130F00A43A5F /* testautomation_math.c in Sources */, F35E56E02983130F00A43A5F /* testautomation_sdltest.c in Sources */, F35E56D42983130F00A43A5F /* testautomation_events.c in Sources */, + A1A859542BC72FC20045DD6C /* testautomation_time.c in Sources */, F35E56E12983130F00A43A5F /* testautomation_guid.c in Sources */, F35E56D62983130F00A43A5F /* testautomation_timer.c in Sources */, F35E56DA2983130F00A43A5F /* testautomation_video.c in Sources */, F35E56D02983130F00A43A5F /* testautomation_hints.c in Sources */, + A1A8594E2BC72FC20045DD6C /* testautomation_properties.c in Sources */, F35E56DF2983130F00A43A5F /* testautomation_keyboard.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; + F36C341E2C0F85DB00991150 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F36C342D2C0F869B00991150 /* testcamera.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; F3C17CD828E416CF00E1A26D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -4604,6 +4680,30 @@ }; name = Release; }; + F36C34252C0F85DB00991150 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera recording"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + }; + name = Debug; + }; + F36C34262C0F85DB00991150 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_KEY_NSCameraUsageDescription = "Testing camera recording"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + }; + name = Release; + }; F3C17CE928E416D000E1A26D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -5050,6 +5150,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Debug; }; + F36C34242C0F85DB00991150 /* Build configuration list for PBXNativeTarget "testcamera" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F36C34252C0F85DB00991150 /* Debug */, + F36C34262C0F85DB00991150 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; F3C17CE828E416D000E1A26D /* Build configuration list for PBXNativeTarget "testgeometry" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/libs/SDL3/android-project/app/build.gradle b/libs/SDL3/android-project/app/build.gradle index 8dac6e005..514e594a4 100644 --- a/libs/SDL3/android-project/app/build.gradle +++ b/libs/SDL3/android-project/app/build.gradle @@ -1,16 +1,11 @@ -def buildAsLibrary = project.hasProperty('BUILD_AS_LIBRARY'); -def buildAsApplication = !buildAsLibrary -if (buildAsApplication) { - apply plugin: 'com.android.application' -} -else { - apply plugin: 'com.android.library' +plugins { + id 'com.android.application' } +def buildWithCMake = project.hasProperty('BUILD_WITH_CMAKE'); + android { - if (buildAsApplication) { - namespace "org.libsdl.app" - } + namespace "org.libsdl.app" compileSdkVersion 34 defaultConfig { minSdkVersion 19 @@ -24,7 +19,7 @@ android { abiFilters 'arm64-v8a' } cmake { - arguments "-DANDROID_APP_PLATFORM=android-19", "-DANDROID_STL=c++_static" + arguments "-DANDROID_PLATFORM=android-19", "-DANDROID_STL=c++_static" // abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' abiFilters 'arm64-v8a' } @@ -45,30 +40,21 @@ android { jniLibs.srcDir 'libs' } externalNativeBuild { - ndkBuild { - path 'jni/Android.mk' + if (buildWithCMake) { + cmake { + path 'jni/CMakeLists.txt' + } + } else { + ndkBuild { + path 'jni/Android.mk' + } } - // cmake { - // path 'jni/CMakeLists.txt' - // } } } lint { abortOnError false } - - if (buildAsLibrary) { - libraryVariants.all { variant -> - variant.outputs.each { output -> - def outputFile = output.outputFile - if (outputFile != null && outputFile.name.endsWith(".aar")) { - def fileName = "org.libsdl.app.aar"; - output.outputFile = new File(outputFile.parent, fileName); - } - } - } - } } dependencies { diff --git a/libs/SDL3/android-project/app/jni/CMakeLists.txt b/libs/SDL3/android-project/app/jni/CMakeLists.txt index 3d49cf343..404b87b37 100644 --- a/libs/SDL3/android-project/app/jni/CMakeLists.txt +++ b/libs/SDL3/android-project/app/jni/CMakeLists.txt @@ -2,11 +2,6 @@ cmake_minimum_required(VERSION 3.6) project(GAME) -# armeabi-v7a requires cpufeatures library -# include(AndroidNdkModules) -# android_ndk_import_module_cpufeatures() - - # SDL sources are in a subfolder named "SDL" add_subdirectory(SDL) diff --git a/libs/SDL3/android-project/app/jni/src/Android.mk b/libs/SDL3/android-project/app/jni/src/Android.mk index 982f66170..61672d4f6 100644 --- a/libs/SDL3/android-project/app/jni/src/Android.mk +++ b/libs/SDL3/android-project/app/jni/src/Android.mk @@ -4,15 +4,16 @@ include $(CLEAR_VARS) LOCAL_MODULE := main -SDL_PATH := ../SDL +# Add your application source files here... +LOCAL_SRC_FILES := \ + YourSourceHere.c -LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include +SDL_PATH := ../SDL # SDL -# Add your application source files here... -LOCAL_SRC_FILES := YourSourceHere.c +LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include # SDL LOCAL_SHARED_LIBRARIES := SDL3 -LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid +LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -lOpenSLES -llog -landroid # SDL include $(BUILD_SHARED_LIBRARY) diff --git a/libs/SDL3/android-project/app/jni/src/CMakeLists.txt b/libs/SDL3/android-project/app/jni/src/CMakeLists.txt index aaac0c80d..41a82f2af 100644 --- a/libs/SDL3/android-project/app/jni/src/CMakeLists.txt +++ b/libs/SDL3/android-project/app/jni/src/CMakeLists.txt @@ -1,13 +1,29 @@ cmake_minimum_required(VERSION 3.6) -project(MY_APP) +project(my_app) -find_library(SDL3 SDL3) +if(NOT TARGET SDL3::SDL3) + find_package(SDL3 CONFIG) +endif() -add_library(main SHARED) +if(NOT TARGET SDL3::SDL3) + find_library(SDL3_LIBRARY NAMES "SDL3") + find_path(SDL3_INCLUDE_DIR NAMES "SDL3/SDL.h") + add_library(SDL3::SDL3 UNKNOWN IMPORTED) + set_property(TARGET SDL3::SDL3 PROPERTY IMPORTED_LOCATION "${SDL3_LIBRARY}") + set_property(TARGET SDL3::SDL3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${SDL3_INCLUDE_DIR}") +endif() -target_sources(main PRIVATE YourSourceHere.c) - -target_link_libraries(main SDL3) +if(NOT TARGET SDL3::SDL3) + message(FATAL_ERROR "Cannot find SDL3. +Possible ways to fix this: +- Use a SDL3 Android aar archive, and configure gradle to use it: prefab is required. +- Add add_subdirectory(path/to/SDL) to your CMake script, and make sure a vendored SDL is present there. +") +endif() +add_library(main SHARED + YourSourceHere.c +) +target_link_libraries(main PRIVATE SDL3::SDL3) diff --git a/libs/SDL3/android-project/app/jni/src/YourSourceHere.c b/libs/SDL3/android-project/app/jni/src/YourSourceHere.c new file mode 100644 index 000000000..87b829736 --- /dev/null +++ b/libs/SDL3/android-project/app/jni/src/YourSourceHere.c @@ -0,0 +1,26 @@ +#include +#include + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* */ +/* Remove this source, and replace with your SDL sources */ +/* */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +int main(int argc, char *argv[]) { + (void)argc; + (void)argv; + if (!SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init failed (%s)", SDL_GetError()); + return 1; + } + + if (!SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Hello World", + "!! Your SDL project successfully runs on Android !!", NULL)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_ShowSimpleMessageBox failed (%s)", SDL_GetError()); + return 1; + } + + SDL_Quit(); + return 0; +} diff --git a/libs/SDL3/android-project/app/proguard-rules.pro b/libs/SDL3/android-project/app/proguard-rules.pro index 0cb79dc8e..fc0a4f5c9 100644 --- a/libs/SDL3/android-project/app/proguard-rules.pro +++ b/libs/SDL3/android-project/app/proguard-rules.pro @@ -5,7 +5,7 @@ # directive in build.gradle. # # For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html +# https://developer.android.com/build/shrink-code # Add any project specific keep options here: @@ -17,69 +17,59 @@ #} -keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLActivity { - void manualBackButton(); - boolean setActivityTitle(java.lang.String); - void setWindowStyle(boolean); - void setOrientation(int, int, boolean, java.lang.String); - void minimizeWindow(); - boolean shouldMinimizeOnFocusLoss(); - boolean isScreenKeyboardShown(); - boolean supportsRelativeMouse(); - boolean setRelativeMouseEnabled(boolean); - boolean sendMessage(int, int); + java.lang.String nativeGetHint(java.lang.String); # Java-side doesn't use this, so it gets minified, but C-side still tries to register it + java.lang.String clipboardGetText(); + boolean clipboardHasText(); + void clipboardSetText(java.lang.String); + int createCustomCursor(int[], int, int, int, int); + void destroyCustomCursor(int); android.content.Context getContext(); - boolean isAndroidTV(); - boolean isTablet(); - boolean isChromebook(); - boolean isDeXMode(); boolean getManifestEnvironmentVariables(); - boolean showTextInput(int, int, int, int); android.view.Surface getNativeSurface(); void initTouch(); + boolean isAndroidTV(); + boolean isChromebook(); + boolean isDeXMode(); + boolean isScreenKeyboardShown(); + boolean isTablet(); + void manualBackButton(); int messageboxShowMessageBox(int, java.lang.String, java.lang.String, int[], int[], java.lang.String[], int[]); - boolean clipboardHasText(); - java.lang.String clipboardGetText(); - void clipboardSetText(java.lang.String); - int createCustomCursor(int[], int, int, int, int); - void destroyCustomCursor(int); + void minimizeWindow(); + boolean openURL(java.lang.String); + void requestPermission(java.lang.String, int); + boolean showToast(java.lang.String, int, int, int, int); + boolean sendMessage(int, int); + boolean setActivityTitle(java.lang.String); boolean setCustomCursor(int); + void setOrientation(int, int, boolean, java.lang.String); + boolean setRelativeMouseEnabled(boolean); boolean setSystemCursor(int); - void requestPermission(java.lang.String, int); - int openURL(java.lang.String); - int showToast(java.lang.String, int, int, int, int); - native java.lang.String nativeGetHint(java.lang.String); + void setWindowStyle(boolean); + boolean shouldMinimizeOnFocusLoss(); + boolean showTextInput(int, int, int, int, int); + boolean supportsRelativeMouse(); + int openFileDescriptor(java.lang.String, java.lang.String); + boolean showFileDialog(java.lang.String[], boolean, boolean, int); } -keep,includedescriptorclasses,allowoptimization class org.libsdl.app.HIDDeviceManager { + void closeDevice(int); boolean initialize(boolean, boolean); boolean openDevice(int); - int writeReport(int, byte[], boolean); boolean readReport(int, byte[], boolean); - void closeDevice(int); + int writeReport(int, byte[], boolean); } -keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLAudioManager { void registerAudioDeviceCallback(); void unregisterAudioDeviceCallback(); - int[] audioOpen(int, int, int, int, int); - void audioWriteFloatBuffer(float[]); - void audioWriteShortBuffer(short[]); - void audioWriteByteBuffer(byte[]); - int[] captureOpen(int, int, int, int, int); - int captureReadFloatBuffer(float[], boolean); - int captureReadShortBuffer(short[], boolean); - int captureReadByteBuffer(byte[], boolean); - void audioClose(); - void captureClose(); void audioSetThreadPriority(boolean, int); - int nativeSetupJNI(); - void removeAudioDevice(boolean, int); - void addAudioDevice(boolean, java.lang.String, int); } -keep,includedescriptorclasses,allowoptimization class org.libsdl.app.SDLControllerManager { void pollInputDevices(); void pollHapticDevices(); void hapticRun(int, float, int); + void hapticRumble(int, float, float, int); void hapticStop(int); } diff --git a/libs/SDL3/android-project/app/src/main/AndroidManifest.xml b/libs/SDL3/android-project/app/src/main/AndroidManifest.xml index 9b0a816d2..acefc495d 100644 --- a/libs/SDL3/android-project/app/src/main/AndroidManifest.xml +++ b/libs/SDL3/android-project/app/src/main/AndroidManifest.xml @@ -32,7 +32,7 @@ android:required="false" /> - + @@ -55,7 +55,7 @@ - + - - diff --git a/libs/SDL3/build-scripts/SDL_migration.cocci b/libs/SDL3/build-scripts/SDL_migration.cocci index ca06ac65a..8e2dcc10a 100644 --- a/libs/SDL3/build-scripts/SDL_migration.cocci +++ b/libs/SDL3/build-scripts/SDL_migration.cocci @@ -30,7 +30,6 @@ // // So this file is a set of many semantic patches, mostly independent. - @ rule_audio_open @ expression e1, e2; @@ @@ -175,6 +174,12 @@ expression e; + /* FIXME MIGRATION: SDL_Has3DNow() has been removed; there is no replacement. */ 0 - SDL_Has3DNow() +// SDL_HasRDTSC() has been removed; there is no replacement. +@@ +@@ ++ /* FIXME MIGRATION: SDL_HasRDTSC() has been removed; there is no replacement. */ 0 +- SDL_HasRDTSC() + // SDL_HINT_VIDEO_X11_XINERAMA (Xinerama no longer supported by the X11 backend) @@ @@ @@ -852,7 +857,7 @@ typedef SDL_ControllerTouchpadEvent, SDL_GamepadTouchpadEvent; @@ @@ - SDL_CONTROLLER_AXIS_MAX -+ SDL_GAMEPAD_AXIS_MAX ++ SDL_GAMEPAD_AXIS_COUNT @@ @@ - SDL_CONTROLLER_AXIS_RIGHTX @@ -888,11 +893,11 @@ typedef SDL_ControllerTouchpadEvent, SDL_GamepadTouchpadEvent; @@ @@ - SDL_CONTROLLER_BUTTON_A -+ SDL_GAMEPAD_BUTTON_A ++ SDL_GAMEPAD_BUTTON_SOUTH @@ @@ - SDL_CONTROLLER_BUTTON_B -+ SDL_GAMEPAD_BUTTON_B ++ SDL_GAMEPAD_BUTTON_EAST @@ @@ - SDL_CONTROLLER_BUTTON_BACK @@ -932,7 +937,7 @@ typedef SDL_ControllerTouchpadEvent, SDL_GamepadTouchpadEvent; @@ @@ - SDL_CONTROLLER_BUTTON_MAX -+ SDL_GAMEPAD_BUTTON_MAX ++ SDL_GAMEPAD_BUTTON_COUNT @@ @@ - SDL_CONTROLLER_BUTTON_MISC1 @@ -972,11 +977,11 @@ typedef SDL_ControllerTouchpadEvent, SDL_GamepadTouchpadEvent; @@ @@ - SDL_CONTROLLER_BUTTON_X -+ SDL_GAMEPAD_BUTTON_X ++ SDL_GAMEPAD_BUTTON_WEST @@ @@ - SDL_CONTROLLER_BUTTON_Y -+ SDL_GAMEPAD_BUTTON_Y ++ SDL_GAMEPAD_BUTTON_NORTH @@ @@ - SDL_CONTROLLER_TYPE_AMAZON_LUNA @@ -1292,13 +1297,8 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; + SDL_JOYSTICK_TYPE_GAMEPAD @@ @@ -- SDL_JoystickAttachVirtual -+ SDL_AttachVirtualJoystick - (...) -@@ -@@ - SDL_JoystickAttachVirtualEx -+ SDL_AttachVirtualJoystickEx ++ SDL_AttachVirtualJoystick (...) @@ @@ @@ -1358,12 +1358,7 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; @@ @@ - SDL_JoystickGetGUIDFromString -+ SDL_GetJoystickGUIDFromString - (...) -@@ -@@ -- SDL_JoystickGetGUIDString -+ SDL_GetJoystickGUIDString ++ SDL_StringToGUID (...) @@ @@ @@ -1549,10 +1544,6 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; + SDL_KMOD_RCTRL @@ @@ -- KMOD_RESERVED -+ SDL_KMOD_RESERVED -@@ -@@ - KMOD_RGUI + SDL_KMOD_RGUI @@ @@ -1575,7 +1566,7 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; @@ @@ - SDL_AllocFormat -+ SDL_CreatePixelFormat ++ SDL_GetPixelFormatDetails (...) @@ @@ @@ -1584,23 +1575,18 @@ typedef SDL_GameControllerButton, SDL_GamepadButton; (...) @@ @@ -- SDL_FreeFormat -+ SDL_DestroyPixelFormat - (...) -@@ -@@ - SDL_FreePalette + SDL_DestroyPalette (...) @@ @@ - SDL_MasksToPixelFormatEnum -+ SDL_GetPixelFormatEnumForMasks ++ SDL_GetPixelFormatForMasks (...) @@ @@ - SDL_PixelFormatEnumToMasks -+ SDL_GetMasksForPixelFormatEnum ++ SDL_GetMasksForPixelFormat (...) @@ @@ @@ -1781,10 +1767,10 @@ expression e2; @@ ( - SDL_RenderSetLogicalSize(renderer, 0, 0) -+ SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED, SDL_ScaleModeNearest) ++ SDL_SetRenderLogicalPresentation(renderer, 0, 0, SDL_LOGICAL_PRESENTATION_DISABLED) | - SDL_RenderSetLogicalSize(renderer, e1, e2) -+ SDL_SetRenderLogicalPresentation(renderer, e1, e2, SDL_LOGICAL_PRESENTATION_LETTERBOX, SDL_ScaleModeLinear) ++ SDL_SetRenderLogicalPresentation(renderer, e1, e2, SDL_LOGICAL_PRESENTATION_LETTERBOX) ) @@ @@ @@ -2076,7 +2062,7 @@ expression e; @@ @@ - SDL_WINDOWEVENT_TAKE_FOCUS -+ SDL_EVENT_WINDOW_TAKE_FOCUS ++ /* FIXME MIGRATION: SDL_WINDOWEVENT_TAKE_FOCUS has been removed; there is no replacement. */ 0 @@ @@ - SDL_WINDOWEVENT_HIT_TEST @@ -2283,11 +2269,6 @@ symbol SDL_ScaleModeLinear; - SDL_ScaleModeLinear + SDL_SCALEMODE_LINEAR @@ -symbol SDL_ScaleModeBest; -@@ -- SDL_ScaleModeBest -+ SDL_SCALEMODE_BEST -@@ @@ - SDL_RenderCopy + SDL_RenderTexture @@ -2497,11 +2478,6 @@ expression e1, e2, e3, e4; - SDL_CreateWindow(e1, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, e2, e3, e4) + SDL_CreateWindow(e1, e2, e3, e4) @@ -expression e1, e2, e3, e4, e5, e6; -@@ -- SDL_CreateWindow(e1, e2, e3, e4, e5, e6) -+ SDL_CreateWindowWithPosition(e1, e2, e3, e4, e5, e6) -@@ expression e1, e2, e3, e4; constant c1, c2; @@ @@ -2530,7 +2506,7 @@ typedef SDL_atomic_t, SDL_AtomicInt; @@ @@ - SDL_SemPost -+ SDL_PostSemaphore ++ SDL_SignalSemaphore (...) @@ @@ @@ -2644,11 +2620,6 @@ typedef SDL_cond, SDL_Condition; + SDL_WINDOW_HIGH_PIXEL_DENSITY @@ @@ -- SDL_TLSCreate -+ SDL_CreateTLS - (...) -@@ -@@ - SDL_TLSGet + SDL_GetTLS (...) @@ -2673,14 +2644,30 @@ typedef SDL_cond, SDL_Condition; + SDL_WINDOW_UTILITY @@ @@ -- SDL_PIXELFORMAT_RGB888 -+ SDL_PIXELFORMAT_XRGB8888 +- SDL_PIXELFORMAT_BGR444 ++ SDL_PIXELFORMAT_XBGR4444 +@@ +@@ +- SDL_PIXELFORMAT_BGR555 ++ SDL_PIXELFORMAT_XBGR1555 @@ @@ - SDL_PIXELFORMAT_BGR888 + SDL_PIXELFORMAT_XBGR8888 @@ @@ +- SDL_PIXELFORMAT_RGB444 ++ SDL_PIXELFORMAT_XRGB4444 +@@ +@@ +- SDL_PIXELFORMAT_RGB555 ++ SDL_PIXELFORMAT_XRGB1555 +@@ +@@ +- SDL_PIXELFORMAT_RGB888 ++ SDL_PIXELFORMAT_XRGB8888 +@@ +@@ - SDL_strtokr + SDL_strtok_r (...) @@ -2921,12 +2908,37 @@ expression e1, e2, e3, e4; @@ @@ - SDL_AtomicCAS -+ SDL_AtomicCompareAndSwap ++ SDL_CompareAndSwapAtomicInt + (...) +@@ +@@ +- SDL_AtomicSet ++ SDL_SetAtomicInt + (...) +@@ +@@ +- SDL_AtomicGet ++ SDL_GetAtomicInt + (...) +@@ +@@ +- SDL_AtomicAdd ++ SDL_AddAtomicInt (...) @@ @@ - SDL_AtomicCASPtr -+ SDL_AtomicCompareAndSwapPointer ++ SDL_CompareAndSwapAtomicPointer + (...) +@@ +@@ +- SDL_AtomicSetPtr ++ SDL_SetAtomicPointer + (...) +@@ +@@ +- SDL_AtomicGetPtr ++ SDL_GetAtomicPointer (...) @@ @@ @@ -2994,11 +3006,6 @@ SDL_GamepadBinding *e1; - e1->outputType + e1->output_type @@ -typedef SDL_version, SDL_Version; -@@ -- SDL_version -+ SDL_Version -@@ @@ - SDL_HINT_ALLOW_TOPMOST + SDL_HINT_WINDOW_ALLOW_TOPMOST @@ -3119,3 +3126,591 @@ typedef SDL_RWops, SDL_IOStream; - SDL_LogSetOutputFunction + SDL_SetLogOutputFunction (...) +@@ +typedef SDL_eventaction, SDL_EventAction; +@@ +- SDL_eventaction ++ SDL_EventAction +@@ +typedef SDL_RendererFlip, SDL_FlipMode; +@@ +- SDL_RendererFlip ++ SDL_FlipMode +@@ +typedef SDL_Colour, SDL_Color; +@@ +- SDL_Colour ++ SDL_Color +@@ +@@ +- SDL_iPhoneSetAnimationCallback ++ SDL_SetiOSAnimationCallback + (...) +@@ +@@ +- SDL_iPhoneSetEventPump ++ SDL_SetiOSEventPump + (...) +@@ +@@ +- SDL_COMPILEDVERSION ++ SDL_VERSION +@@ +@@ +- SDL_PATCHLEVEL ++ SDL_MICRO_VERSION +@@ +@@ +- SDL_TABLESIZE ++ SDL_arraysize +@@ +@@ +- SDLK_QUOTE ++ SDLK_APOSTROPHE +@@ +@@ +- SDLK_BACKQUOTE ++ SDLK_GRAVE +@@ +@@ +- SDLK_QUOTEDBL ++ SDLK_DBLAPOSTROPHE +@@ +@@ +- SDL_LogSetAllPriority ++ SDL_SetLogPriorities + (...) +@@ +@@ +- SDL_LogSetPriority ++ SDL_SetLogPriority + (...) +@@ +@@ +- SDL_LogGetPriority ++ SDL_GetLogPriority + (...) +@@ +@@ +- SDL_LogResetPriorities ++ SDL_ResetLogPriorities + (...) +@@ +@@ +- SDL_SIMDGetAlignment ++ SDL_GetSIMDAlignment + (...) +@@ +@@ +- SDL_MixAudioFormat ++ SDL_MixAudio + (...) +@@ +@@ +- SDL_BlitScaled ++ SDL_BlitSurfaceScaled + (...) +@@ +@@ +- SDL_SYSTEM_CURSOR_ARROW ++ SDL_SYSTEM_CURSOR_DEFAULT +@@ +@@ +- SDL_SYSTEM_CURSOR_IBEAM ++ SDL_SYSTEM_CURSOR_TEXT +@@ +@@ +- SDL_SYSTEM_CURSOR_WAITARROW ++ SDL_SYSTEM_CURSOR_PROGRESS +@@ +@@ +- SDL_SYSTEM_CURSOR_SIZENWSE ++ SDL_SYSTEM_CURSOR_NWSE_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_SIZENESW ++ SDL_SYSTEM_CURSOR_NESW_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_SIZEWE ++ SDL_SYSTEM_CURSOR_EW_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_SIZENS ++ SDL_SYSTEM_CURSOR_NS_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_SIZEALL ++ SDL_SYSTEM_CURSOR_MOVE +@@ +@@ +- SDL_SYSTEM_CURSOR_NO ++ SDL_SYSTEM_CURSOR_NOT_ALLOWED +@@ +@@ +- SDL_SYSTEM_CURSOR_HAND ++ SDL_SYSTEM_CURSOR_POINTER +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT ++ SDL_SYSTEM_CURSOR_NW_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_TOP ++ SDL_SYSTEM_CURSOR_N_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT ++ SDL_SYSTEM_CURSOR_NE_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_RIGHT ++ SDL_SYSTEM_CURSOR_E_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT ++ SDL_SYSTEM_CURSOR_SE_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_BOTTOM ++ SDL_SYSTEM_CURSOR_S_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT ++ SDL_SYSTEM_CURSOR_SW_RESIZE +@@ +@@ +- SDL_SYSTEM_CURSOR_WINDOW_LEFT ++ SDL_SYSTEM_CURSOR_W_RESIZE +@@ +@@ +- SDL_SwapLE16 ++ SDL_Swap16LE + (...) +@@ +@@ +- SDL_SwapLE32 ++ SDL_Swap32LE + (...) +@@ +@@ +- SDL_SwapBE16 ++ SDL_Swap16BE + (...) +@@ +@@ +- SDL_SwapBE32 ++ SDL_Swap32BE + (...) +@@ +@@ +- SDL_SwapLE64 ++ SDL_Swap64LE + (...) +@@ +@@ +- SDL_SwapBE64 ++ SDL_Swap64BE + (...) +@@ +@@ +- SDL_SCANCODE_AUDIOMUTE ++ SDL_SCANCODE_MUTE +@@ +@@ +- SDLK_AUDIOMUTE ++ SDLK_MUTE +@@ +@@ +- SDL_SCANCODE_EJECT ++ SDL_SCANCODE_MEDIA_EJECT +@@ +@@ +- SDLK_EJECT ++ SDLK_MEDIA_EJECT +@@ +@@ +- SDL_SCANCODE_AUDIONEXT ++ SDL_SCANCODE_MEDIA_NEXT_TRACK +@@ +@@ +- SDLK_AUDIONEXT ++ SDLK_MEDIA_NEXT_TRACK +@@ +@@ +- SDL_SCANCODE_AUDIOPREV ++ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK +@@ +@@ +- SDLK_AUDIOPREV ++ SDLK_MEDIA_PREVIOUS_TRACK +@@ +@@ +- SDL_SCANCODE_AUDIOSTOP ++ SDL_SCANCODE_MEDIA_STOP +@@ +@@ +- SDLK_AUDIOSTOP ++ SDLK_MEDIA_STOP +@@ +@@ +- SDL_SCANCODE_AUDIOPLAY ++ SDL_SCANCODE_MEDIA_PLAY +@@ +@@ +- SDLK_AUDIOPLAY ++ SDLK_MEDIA_PLAY +@@ +@@ +- SDL_SCANCODE_AUDIOREWIND ++ SDL_SCANCODE_MEDIA_REWIND +@@ +@@ +- SDLK_AUDIOREWIND ++ SDLK_MEDIA_REWIND +@@ +@@ +- SDL_SCANCODE_AUDIOFASTFORWARD ++ SDL_SCANCODE_MEDIA_FAST_FORWARD +@@ +@@ +- SDLK_AUDIOFASTFORWARD ++ SDLK_MEDIA_FAST_FORWARD +@@ +@@ +- SDL_SCANCODE_MEDIASELECT ++ SDL_SCANCODE_MEDIA_SELECT +@@ +@@ +- SDLK_MEDIASELECT ++ SDLK_MEDIA_SELECT +@@ +@@ +- SDLK_a ++ SDLK_A +@@ +@@ +- SDLK_b ++ SDLK_B +@@ +@@ +- SDLK_c ++ SDLK_C +@@ +@@ +- SDLK_d ++ SDLK_D +@@ +@@ +- SDLK_e ++ SDLK_E +@@ +@@ +- SDLK_f ++ SDLK_F +@@ +@@ +- SDLK_g ++ SDLK_G +@@ +@@ +- SDLK_h ++ SDLK_H +@@ +@@ +- SDLK_i ++ SDLK_I +@@ +@@ +- SDLK_j ++ SDLK_J +@@ +@@ +- SDLK_k ++ SDLK_K +@@ +@@ +- SDLK_l ++ SDLK_L +@@ +@@ +- SDLK_m ++ SDLK_M +@@ +@@ +- SDLK_n ++ SDLK_N +@@ +@@ +- SDLK_o ++ SDLK_O +@@ +@@ +- SDLK_p ++ SDLK_P +@@ +@@ +- SDLK_q ++ SDLK_Q +@@ +@@ +- SDLK_r ++ SDLK_R +@@ +@@ +- SDLK_s ++ SDLK_S +@@ +@@ +- SDLK_t ++ SDLK_T +@@ +@@ +- SDLK_u ++ SDLK_U +@@ +@@ +- SDLK_v ++ SDLK_V +@@ +@@ +- SDLK_w ++ SDLK_W +@@ +@@ +- SDLK_x ++ SDLK_X +@@ +@@ +- SDLK_y ++ SDLK_Y +@@ +@@ +- SDLK_z ++ SDLK_Z +@@ +@@ +- SDL_ConvertSurfaceFormat ++ SDL_ConvertSurface + (...) +@@ +@@ +- SDL_PREALLOC ++ SDL_SURFACE_PREALLOCATED +@@ +@@ +- SDL_SIMD_ALIGNED ++ SDL_SURFACE_SIMD_ALIGNED +@@ +@@ +- SDL_GL_DeleteContext ++ SDL_GL_DestroyContext + (...) +@@ +@@ +- SDL_AndroidGetActivity ++ SDL_GetAndroidActivity + (...) +@@ +@@ +- SDL_AndroidGetExternalStoragePath ++ SDL_GetAndroidExternalStoragePath + (...) +@@ +@@ +- SDL_AndroidGetExternalStorageState ++ SDL_GetAndroidExternalStorageState + (...) +@@ +@@ +- SDL_AndroidGetInternalStoragePath ++ SDL_GetAndroidInternalStoragePath + (...) +@@ +@@ +- SDL_AndroidGetJNIEnv ++ SDL_GetAndroidJNIEnv + (...) +@@ +@@ +- SDL_Direct3D9GetAdapterIndex ++ SDL_GetDirect3D9AdapterIndex + (...) +@@ +@@ +- SDL_GDKGetDefaultUser ++ SDL_GetGDKDefaultUser + (...) +@@ +@@ +- SDL_GDKGetTaskQueue ++ SDL_GetGDKTaskQueue + (...) +@@ +@@ +- SDL_LinuxSetThreadPriority ++ SDL_SetLinuxThreadPriority + (...) +@@ +@@ +- SDL_LinuxSetThreadPriorityAndPolicy ++ SDL_SetLinuxThreadPriorityAndPolicy + (...) +@@ +@@ +- SDL_DXGIGetOutputInfo ++ SDL_GetDXGIOutputInfo + (...) +@@ +@@ +- SDL_AndroidBackButton ++ SDL_TriggerAndroidBackButton + (...) +@@ +@@ +- SDL_AndroidRequestPermission ++ SDL_RequestAndroidPermission + (...) +@@ +@@ +- SDL_AndroidRequestPermissionCallback ++ SDL_RequestAndroidPermissionCallback + (...) +@@ +@@ +- SDL_AndroidShowToast ++ SDL_ShowAndroidToast + (...) +@@ +@@ +- SDL_AndroidSendMessage ++ SDL_SendAndroidMessage + (...) +@@ +typedef SDL_JoystickGUID, SDL_GUID; +@@ +- SDL_JoystickGUID ++ SDL_GUID +@@ +@@ +- SDL_GUIDFromString ++ SDL_StringToGUID + (...) +@@ +@@ +- SDL_OnApplicationWillResignActive ++ SDL_OnApplicationWillEnterBackground + (...) +@@ +@@ +- SDL_OnApplicationDidBecomeActive ++ SDL_OnApplicationDidEnterForeground + (...) +@@ +@@ +- SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP ++ SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE +@@ +@@ +- SDL_DelEventWatch ++ SDL_RemoveEventWatch + (...) +@@ +@@ +- SDL_DelHintCallback ++ SDL_RemoveHintCallback + (...) +@@ +@@ +- SDL_size_mul_overflow ++ SDL_size_mul_check_overflow + (...) +@@ +@@ +- SDL_size_add_overflow ++ SDL_size_add_check_overflow + (...) +@@ +@@ +- SDL_PRESSED ++ SDL_TRUE +@@ +@@ +- SDL_RELEASED ++ SDL_FALSE + +// This should be the last rule in the file, since it works on SDL3 functions and previous rules may have renamed old functions. +@ bool_return_type @ +identifier func =~ "^(SDL_AddEventWatch|SDL_AddHintCallback|SDL_AddSurfaceAlternateImage|SDL_AddVulkanRenderSemaphores|SDL_BindAudioStream|SDL_BindAudioStreams|SDL_BlitSurface|SDL_BlitSurface9Grid|SDL_BlitSurfaceScaled|SDL_BlitSurfaceTiled|SDL_BlitSurfaceTiledWithScale|SDL_BlitSurfaceUnchecked|SDL_BlitSurfaceUncheckedScaled|SDL_CaptureMouse|SDL_ClearAudioStream|SDL_ClearClipboardData|SDL_ClearComposition|SDL_ClearError|SDL_ClearProperty|SDL_ClearSurface|SDL_CloseIO|SDL_CloseStorage|SDL_ConvertAudioSamples|SDL_ConvertEventToRenderCoordinates|SDL_ConvertPixels|SDL_ConvertPixelsAndColorspace|SDL_CopyFile|SDL_CopyProperties|SDL_CopyStorageFile|SDL_CreateDirectory|SDL_CreateStorageDirectory|SDL_CreateWindowAndRenderer|SDL_DateTimeToTime|SDL_DestroyWindowSurface|SDL_DetachVirtualJoystick|SDL_DisableScreenSaver|SDL_EnableScreenSaver|SDL_EnumerateDirectory|SDL_EnumerateProperties|SDL_EnumerateStorageDirectory|SDL_FillSurfaceRect|SDL_FillSurfaceRects|SDL_FlashWindow|SDL_FlipSurface|SDL_FlushAudioStream|SDL_FlushRenderer|SDL_GL_DestroyContext|SDL_GL_GetAttribute|SDL_GL_GetSwapInterval|SDL_GL_LoadLibrary|SDL_GL_MakeCurrent|SDL_GL_SetAttribute|SDL_GL_SetSwapInterval|SDL_GL_SwapWindow|SDL_GetAudioDeviceFormat|SDL_GetAudioStreamFormat|SDL_GetCameraFormat|SDL_GetClosestFullscreenDisplayMode|SDL_GetCurrentRenderOutputSize|SDL_GetCurrentTime|SDL_GetDXGIOutputInfo|SDL_GetDateTimeLocalePreferences|SDL_GetDisplayBounds|SDL_GetDisplayUsableBounds|SDL_GetGDKDefaultUser|SDL_GetGDKTaskQueue|SDL_GetGamepadSensorData|SDL_GetGamepadTouchpadFinger|SDL_GetHapticEffectStatus|SDL_GetJoystickBall|SDL_GetMasksForPixelFormat|SDL_GetPathInfo|SDL_GetRectUnion|SDL_GetRectUnionFloat|SDL_GetRenderClipRect|SDL_GetRenderColorScale|SDL_GetRenderDrawBlendMode|SDL_GetRenderDrawColor|SDL_GetRenderDrawColorFloat|SDL_GetRenderLogicalPresentation|SDL_GetRenderLogicalPresentationRect|SDL_GetRenderOutputSize|SDL_GetRenderSafeArea|SDL_GetRenderScale|SDL_GetRenderVSync|SDL_GetRenderViewport|SDL_GetSensorData|SDL_GetStorageFileSize|SDL_GetStoragePathInfo|SDL_GetSurfaceAlphaMod|SDL_GetSurfaceBlendMode|SDL_GetSurfaceClipRect|SDL_GetSurfaceColorKey|SDL_GetSurfaceColorMod|SDL_GetTextInputArea|SDL_GetTextureAlphaMod|SDL_GetTextureAlphaModFloat|SDL_GetTextureBlendMode|SDL_GetTextureColorMod|SDL_GetTextureColorModFloat|SDL_GetTextureScaleMode|SDL_GetTextureSize|SDL_GetWindowAspectRatio|SDL_GetWindowBordersSize|SDL_GetWindowMaximumSize|SDL_GetWindowMinimumSize|SDL_GetWindowPosition|SDL_GetWindowRelativeMouseMode|SDL_GetWindowSafeArea|SDL_GetWindowSize|SDL_GetWindowSizeInPixels|SDL_GetWindowSurfaceVSync|SDL_HideCursor|SDL_HideWindow|SDL_Init|SDL_InitHapticRumble|SDL_InitSubSystem|SDL_LoadWAV|SDL_LoadWAV_IO|SDL_LockAudioStream|SDL_LockProperties|SDL_LockSurface|SDL_LockTexture|SDL_LockTextureToSurface|SDL_MaximizeWindow|SDL_MinimizeWindow|SDL_MixAudio|SDL_OpenURL|SDL_OutOfMemory|SDL_PauseAudioDevice|SDL_PauseAudioStreamDevice|SDL_PauseHaptic|SDL_PlayHapticRumble|SDL_PremultiplyAlpha|SDL_PremultiplySurfaceAlpha|SDL_PushEvent|SDL_PutAudioStreamData|SDL_RaiseWindow|SDL_ReadStorageFile|SDL_ReadSurfacePixel|SDL_ReadSurfacePixelFloat|SDL_RegisterApp|SDL_ReloadGamepadMappings|SDL_RemovePath|SDL_RemoveStoragePath|SDL_RemoveTimer|SDL_RenamePath|SDL_RenameStoragePath|SDL_RenderClear|SDL_RenderCoordinatesFromWindow|SDL_RenderCoordinatesToWindow|SDL_RenderFillRect|SDL_RenderFillRects|SDL_RenderGeometry|SDL_RenderGeometryRaw|SDL_RenderLine|SDL_RenderLines|SDL_RenderPoint|SDL_RenderPoints|SDL_RenderPresent|SDL_RenderRect|SDL_RenderRects|SDL_RenderTexture|SDL_RenderTexture9Grid|SDL_RenderTextureRotated|SDL_RenderTextureTiled|SDL_RequestAndroidPermission|SDL_RestoreWindow|SDL_ResumeAudioDevice|SDL_ResumeAudioStreamDevice|SDL_ResumeHaptic|SDL_RumbleGamepad|SDL_RumbleGamepadTriggers|SDL_RumbleJoystick|SDL_RumbleJoystickTriggers|SDL_RunHapticEffect|SDL_SaveBMP|SDL_SaveBMP_IO|SDL_SendAndroidMessage|SDL_SendGamepadEffect|SDL_SendJoystickEffect|SDL_SendJoystickVirtualSensorData|SDL_SetAppMetadata|SDL_SetAppMetadataProperty|SDL_SetAudioDeviceGain|SDL_SetAudioPostmixCallback|SDL_SetAudioStreamFormat|SDL_SetAudioStreamFrequencyRatio|SDL_SetAudioStreamGain|SDL_SetAudioStreamGetCallback|SDL_SetAudioStreamInputChannelMap|SDL_SetAudioStreamOutputChannelMap|SDL_SetAudioStreamPutCallback|SDL_SetBooleanProperty|SDL_SetClipboardData|SDL_SetClipboardText|SDL_SetCursor|SDL_SetFloatProperty|SDL_SetGamepadLED|SDL_SetGamepadMapping|SDL_SetGamepadPlayerIndex|SDL_SetGamepadSensorEnabled|SDL_SetHapticAutocenter|SDL_SetHapticGain|SDL_SetJoystickLED|SDL_SetJoystickPlayerIndex|SDL_SetJoystickVirtualAxis|SDL_SetJoystickVirtualBall|SDL_SetJoystickVirtualButton|SDL_SetJoystickVirtualHat|SDL_SetJoystickVirtualTouchpad|SDL_SetLinuxThreadPriority|SDL_SetLinuxThreadPriorityAndPolicy|SDL_SetLogPriorityPrefix|SDL_SetMemoryFunctions|SDL_SetNumberProperty|SDL_SetPaletteColors|SDL_SetPointerProperty|SDL_SetPointerPropertyWithCleanup|SDL_SetPrimarySelectionText|SDL_SetRenderClipRect|SDL_SetRenderColorScale|SDL_SetRenderDrawBlendMode|SDL_SetRenderDrawColor|SDL_SetRenderDrawColorFloat|SDL_SetRenderLogicalPresentation|SDL_SetRenderScale|SDL_SetRenderTarget|SDL_SetRenderVSync|SDL_SetRenderViewport|SDL_SetScancodeName|SDL_SetStringProperty|SDL_SetSurfaceAlphaMod|SDL_SetSurfaceBlendMode|SDL_SetSurfaceColorKey|SDL_SetSurfaceColorMod|SDL_SetSurfaceColorspace|SDL_SetSurfacePalette|SDL_SetSurfaceRLE|SDL_SetTLS|SDL_SetTextInputArea|SDL_SetTextureAlphaMod|SDL_SetTextureAlphaModFloat|SDL_SetTextureBlendMode|SDL_SetTextureColorMod|SDL_SetTextureColorModFloat|SDL_SetTextureScaleMode|SDL_SetThreadPriority|SDL_SetWindowAlwaysOnTop|SDL_SetWindowAspectRatio|SDL_SetWindowBordered|SDL_SetWindowFocusable|SDL_SetWindowFullscreen|SDL_SetWindowFullscreenMode|SDL_SetWindowHitTest|SDL_SetWindowIcon|SDL_SetWindowKeyboardGrab|SDL_SetWindowMaximumSize|SDL_SetWindowMinimumSize|SDL_SetWindowModalFor|SDL_SetWindowMouseGrab|SDL_SetWindowMouseRect|SDL_SetWindowOpacity|SDL_SetWindowPosition|SDL_SetWindowRelativeMouseMode|SDL_SetWindowResizable|SDL_SetWindowShape|SDL_SetWindowSize|SDL_SetWindowSurfaceVSync|SDL_SetWindowTitle|SDL_SetiOSAnimationCallback|SDL_ShowAndroidToast|SDL_ShowCursor|SDL_ShowMessageBox|SDL_ShowSimpleMessageBox|SDL_ShowWindow|SDL_ShowWindowSystemMenu|SDL_StartTextInput|SDL_StartTextInputWithProperties|SDL_StopHapticEffect|SDL_StopHapticEffects|SDL_StopHapticRumble|SDL_StopTextInput|SDL_SyncWindow|SDL_TimeToDateTime|SDL_TryLockMutex|SDL_TryLockRWLockForReading|SDL_TryLockRWLockForWriting|SDL_TryWaitSemaphore|SDL_UnlockAudioStream|SDL_UpdateHapticEffect|SDL_UpdateNVTexture|SDL_UpdateTexture|SDL_UpdateWindowSurface|SDL_UpdateWindowSurfaceRects|SDL_UpdateYUVTexture|SDL_Vulkan_CreateSurface|SDL_Vulkan_LoadLibrary|SDL_WaitConditionTimeout|SDL_WaitSemaphoreTimeout|SDL_WarpMouseGlobal|SDL_WriteStorageFile|SDL_WriteSurfacePixel|SDL_WriteSurfacePixelFloat|SDL_size_mul_check_overflow|SDL_size_add_check_overflow|TTF_GlyphMetrics|TTF_GlyphMetrics32|TTF_Init|TTF_MeasureText|TTF_MeasureUNICODE|TTF_MeasureUTF8|TTF_SetFontDirection|TTF_SetFontLanguage|TTF_SetFontScriptName|TTF_SetFontSDF|TTF_SetFontSize|TTF_SetFontSizeDPI|TTF_SizeText|TTF_SizeUNICODE|TTF_SizeUTF8|IMG_SaveAVIF|IMG_SaveAVIF_IO|IMG_SaveJPG|IMG_SaveJPG_IO|IMG_SavePNG|IMG_SavePNG_IO|Mix_FadeInMusic|Mix_FadeInMusicPos|Mix_GroupChannels|Mix_ModMusicJumpToOrder|Mix_OpenAudio|Mix_PlayMusic|Mix_SetMusicCMD|Mix_SetMusicPosition|Mix_SetSoundFonts|Mix_StartTrack)$"; +@@ +( + func( + ... + ) +- == 0 +| +- func( ++ !func( + ... + ) +- < 0 +| +- func( ++ !func( + ... + ) +- != 0 +| +- func( ++ !func( + ... + ) +- == -1 +) +@@ +@@ +- SDL_NUM_LOG_PRIORITIES ++ SDL_LOG_PRIORITY_COUNT +@@ +@@ +- SDL_MESSAGEBOX_COLOR_MAX ++ SDL_MESSAGEBOX_COLOR_COUNT +@@ +@@ +- SDL_NUM_SYSTEM_CURSORS ++ SDL_SYSTEM_CURSOR_COUNT +@@ +@@ +- SDL_NUM_SCANCODES ++ SDL_SCANCODE_COUNT +@@ +@@ +- SDL_GetCPUCount ++ SDL_GetNumLogicalCPUCores + (...) +@@ +@@ +- SDL_bool ++ bool +@@ +@@ +- SDL_TRUE ++ true +@@ +@@ +- SDL_FALSE ++ false +@@ +@@ +- SDL_IsAndroidTV ++ SDL_IsTV + (...) +@@ +@@ +- SDL_SetThreadPriority ++ SDL_SetCurrentThreadPriority + (...) +@@ +@@ +- SDL_BUTTON ++ SDL_BUTTON_MASK diff --git a/libs/SDL3/build-scripts/add-source-to-projects.pl b/libs/SDL3/build-scripts/add-source-to-projects.pl index 6d703dc36..5ba0a6975 100644 --- a/libs/SDL3/build-scripts/add-source-to-projects.pl +++ b/libs/SDL3/build-scripts/add-source-to-projects.pl @@ -591,7 +591,6 @@ sub process_visualstudio { process_xcode($arg, 'Xcode/SDL/SDL.xcodeproj/project.pbxproj'); process_visualstudio($arg, 'VisualC/SDL/SDL.vcxproj'); process_visualstudio($arg, 'VisualC-GDK/SDL/SDL.vcxproj'); - process_visualstudio($arg, 'VisualC-WinRT/SDL-UWP.vcxproj'); } print("Done. Please run `git diff` and make sure this looks okay!\n"); diff --git a/libs/SDL3/build-scripts/android-prefab.sh b/libs/SDL3/build-scripts/android-prefab.sh deleted file mode 100644 index 586054204..000000000 --- a/libs/SDL3/build-scripts/android-prefab.sh +++ /dev/null @@ -1,315 +0,0 @@ -#!/bin/bash - -set -e - -if ! [ "x$ANDROID_NDK_HOME" != "x" -a -d "$ANDROID_NDK_HOME" ]; then - echo "ANDROID_NDK_HOME environment variable is not set" - exit 1 -fi - -if ! [ "x$ANDROID_HOME" != "x" -a -d "$ANDROID_HOME" ]; then - echo "ANDROID_HOME environment variable is not set" - exit 1 -fi - -if [ "x$ANDROID_API" = "x" ]; then - ANDROID_API="$(ls "$ANDROID_HOME/platforms" | grep -E "^android-[0-9]+$" | sed 's/android-//' | sort -n -r | head -1)" - if [ "x$ANDROID_API" = "x" ]; then - echo "No Android platform found in $ANDROID_HOME/platforms" - exit 1 - fi -else - if ! [ -d "$ANDROID_HOME/platforms/android-$ANDROID_API" ]; then - echo "Android api version $ANDROID_API is not available ($ANDROID_HOME/platforms/android-$ANDROID_API does not exist)" >2 - exit 1 - fi -fi - -android_platformdir="$ANDROID_HOME/platforms/android-$ANDROID_API" - -echo "Building for android api version $ANDROID_API" -echo "android_platformdir=$android_platformdir" - -scriptdir=$(cd -P -- "$(dirname -- "$0")" && printf '%s\n' "$(pwd -P)") -sdl_root=$(cd -P -- "$(dirname -- "$0")/.." && printf '%s\n' "$(pwd -P)") - -build_root="${sdl_root}/build-android-prefab" - -android_abis="armeabi-v7a arm64-v8a x86 x86_64" -android_api=19 -android_ndk=21 -android_stl="c++_shared" - -sdl_major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' "${sdl_root}/include/SDL3/SDL_version.h") -sdl_minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' "${sdl_root}/include/SDL3/SDL_version.h") -sdl_patch=$(sed -ne 's/^#define SDL_PATCHLEVEL *//p' "${sdl_root}/include/SDL3/SDL_version.h") -sdl_version="${sdl_major}.${sdl_minor}.${sdl_patch}" -echo "Building Android prefab package for SDL version $sdl_version" - -prefabhome="${build_root}/prefab-${sdl_version}" -rm -rf "$prefabhome" -mkdir -p "${prefabhome}" - -build_cmake_projects() { - for android_abi in $android_abis; do - echo "Configuring CMake project for $android_abi" - cmake -S "$sdl_root" -B "${build_root}/build_${android_abi}" \ - -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ - -DANDROID_PLATFORM=${android_platform} \ - -DANDROID_ABI=${android_abi} \ - -DSDL_SHARED=ON \ - -DSDL_STATIC=ON \ - -DSDL_STATIC_PIC=ON \ - -DSDL_TEST=ON \ - -DSDL_DISABLE_INSTALL=OFF \ - -DCMAKE_INSTALL_PREFIX="${build_root}/build_${android_abi}/prefix" \ - -DCMAKE_INSTALL_INCLUDEDIR=include \ - -DCMAKE_INSTALL_LIBDIR=lib \ - -DCMAKE_BUILD_TYPE=Release \ - -GNinja - - rm -rf "${build_root}/build_${android_abi}/prefix" - - echo "Building CMake project for $android_abi" - cmake --build "${build_root}/build_${android_abi}" - - echo "Installing CMake project for $android_abi" - cmake --install "${build_root}/build_${android_abi}" - done -} - -classes_sources_jar_path="${prefabhome}/classes-sources.jar" -classes_jar_path="${prefabhome}/classes.jar" -compile_java() { - classes_sources_root="${prefabhome}/classes-sources" - - rm -rf "${classes_sources_root}" - mkdir -p "${classes_sources_root}/META-INF" - - echo "Copying LICENSE.txt to java build folder" - cp "$sdl_root/LICENSE.txt" "${classes_sources_root}/META-INF" - - echo "Copy JAVA sources to java build folder" - cp -r "$sdl_root/android-project/app/src/main/java/org" "${classes_sources_root}" - - java_sourceslist_path="${prefabhome}/java_sources.txt" - pushd "${classes_sources_root}" - echo "Collecting sources for classes-sources.jar" - find "." -name "*.java" >"${java_sourceslist_path}" - find "META-INF" -name "*" >>"${java_sourceslist_path}" - - echo "Creating classes-sources.jar" - jar -cf "${classes_sources_jar_path}" "@${java_sourceslist_path}" - popd - - classes_root="${prefabhome}/classes" - mkdir -p "${classes_root}/META-INF" - cp "$sdl_root/LICENSE.txt" "${classes_root}/META-INF" - java_sourceslist_path="${prefabhome}/java_sources.txt" - - echo "Collecting sources for classes.jar" - find "$sdl_root/android-project/app/src/main/java" -name "*.java" >"${java_sourceslist_path}" - - echo "Compiling classes" - javac -encoding utf-8 -classpath "$android_platformdir/android.jar" -d "${classes_root}" "@${java_sourceslist_path}" - - java_classeslist_path="${prefabhome}/java_classes.txt" - pushd "${classes_root}" - find "." -name "*.class" >"${java_classeslist_path}" - find "META-INF" -name "*" >>"${java_classeslist_path}" - echo "Creating classes.jar" - jar -cf "${classes_jar_path}" "@${java_classeslist_path}" - popd -} - -pom_filename="SDL${sdl_major}-${sdl_version}.pom" -pom_filepath="${prefabhome}/${pom_filename}" -create_pom_xml() { - echo "Creating ${pom_filename}" - cat >"${pom_filepath}" < - 4.0.0 - org.libsdl.android - SDL${sdl_major} - ${sdl_version} - aar - SDL${sdl_major} - The AAR for SDL${sdl_major} - https://libsdl.org/ - - - zlib License - https://github.com/libsdl-org/SDL/blob/main/LICENSE.txt - repo - - - - scm:git:https://github.com/libsdl-org/SDL - https://github.com/libsdl-org/SDL - - -EOF -} - -create_aar_androidmanifest() { - echo "Creating AndroidManifest.xml" - cat >"${aar_root}/AndroidManifest.xml" < - - -EOF -} - -echo "Creating AAR root directory" -aar_root="${prefabhome}/SDL${sdl_major}-${sdl_version}" -mkdir -p "${aar_root}" - -aar_metainfdir_path=${aar_root}/META-INF -mkdir -p "${aar_metainfdir_path}" -cp "${sdl_root}/LICENSE.txt" "${aar_metainfdir_path}" - -prefabworkdir="${aar_root}/prefab" -mkdir -p "${prefabworkdir}" - -cat >"${prefabworkdir}/prefab.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" <"${sdl_moduleworkdir}/module.json" <"${abi_sdllibdir}/abi.json" </dev/null ; - mv "${aar_filename}" "${prefabhome}" -popd - -maven_filename="SDL${sdl_major}-${sdl_version}.zip" - -pushd "${prefabhome}" - zip_filename="SDL${sdl_major}-${sdl_version}.zip" - zip "${maven_filename}" "${aar_filename}" "${pom_filename}" 2>/dev/null; - zip -Tv "${zip_filename}" 2>/dev/null; -popd - -echo "Prefab zip is ready at ${prefabhome}/${aar_filename}" -echo "Maven archive is ready at ${prefabhome}/${zip_filename}" diff --git a/libs/SDL3/build-scripts/androidbuild.sh b/libs/SDL3/build-scripts/androidbuild.sh deleted file mode 100644 index 1a107e27d..000000000 --- a/libs/SDL3/build-scripts/androidbuild.sh +++ /dev/null @@ -1,101 +0,0 @@ -#!/bin/bash - -SOURCES=() -MKSOURCES="" -CURDIR=`pwd -P` - -# Fetch sources -if [[ $# -ge 2 ]]; then - for src in ${@:2} - do - SOURCES+=($src) - MKSOURCES="$MKSOURCES $(basename $src)" - done -else - if [ -n "$1" ]; then - while read src - do - SOURCES+=($src) - MKSOURCES="$MKSOURCES $(basename $src)" - done - fi -fi - -if [ -z "$1" ] || [ -z "$SOURCES" ]; then - echo "Usage: androidbuild.sh com.yourcompany.yourapp < sources.list" - echo "Usage: androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c" - echo "To copy SDL source instead of symlinking: COPYSOURCE=1 androidbuild.sh ... " - exit 1 -fi - -SDLPATH="$( cd "$(dirname "$0")/.." ; pwd -P )" - -if [ -z "$ANDROID_HOME" ];then - echo "Please set the ANDROID_HOME directory to the path of the Android SDK" - exit 1 -fi - -if [ ! -d "$ANDROID_HOME/ndk-bundle" -a -z "$ANDROID_NDK_HOME" ]; then - echo "Please set the ANDROID_NDK_HOME directory to the path of the Android NDK" - exit 1 -fi - -APP="$1" -APPARR=(${APP//./ }) -BUILDPATH="$SDLPATH/build/$APP" - -# Start Building - -rm -rf $BUILDPATH -mkdir -p $BUILDPATH - -cp -r $SDLPATH/android-project/* $BUILDPATH - -# Copy SDL sources -mkdir -p $BUILDPATH/app/jni/SDL -if [ -z "$COPYSOURCE" ]; then - ln -s $SDLPATH/src $BUILDPATH/app/jni/SDL - ln -s $SDLPATH/include $BUILDPATH/app/jni/SDL -else - cp -r $SDLPATH/src $BUILDPATH/app/jni/SDL - cp -r $SDLPATH/include $BUILDPATH/app/jni/SDL -fi - -cp -r $SDLPATH/Android.mk $BUILDPATH/app/jni/SDL -sed -i -e "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/app/jni/src/Android.mk -sed -i -e "s|org\.libsdl\.app|$APP|g" $BUILDPATH/app/build.gradle -sed -i -e "s|org\.libsdl\.app|$APP|g" $BUILDPATH/app/src/main/AndroidManifest.xml - -# Copy user sources -for src in "${SOURCES[@]}" -do - cp $src $BUILDPATH/app/jni/src -done - -# Create an inherited Activity -cd $BUILDPATH/app/src/main/java -for folder in "${APPARR[@]}" -do - mkdir -p $folder - cd $folder -done - -# Uppercase the first char in the activity class name because it's Java -ACTIVITY="$(echo $folder | awk '{$1=toupper(substr($1,0,1))substr($1,2)}1')Activity" -sed -i -e "s|\"SDLActivity\"|\"$ACTIVITY\"|g" $BUILDPATH/app/src/main/AndroidManifest.xml - -# Fill in a default Activity -cat >"$ACTIVITY.java" <<__EOF__ -package $APP; - -import org.libsdl.app.SDLActivity; - -public class $ACTIVITY extends SDLActivity -{ -} -__EOF__ - -# Update project and build -echo "To build and install to a device for testing, run the following:" -echo "cd $BUILDPATH" -echo "./gradlew installDebug" diff --git a/libs/SDL3/build-scripts/build-release.py b/libs/SDL3/build-scripts/build-release.py index b85b0635f..e84dcd5fd 100644 --- a/libs/SDL3/build-scripts/build-release.py +++ b/libs/SDL3/build-scripts/build-release.py @@ -4,6 +4,7 @@ import collections import contextlib import datetime +import glob import io import json import logging @@ -23,21 +24,18 @@ logger = logging.getLogger(__name__) -VcArchDevel = collections.namedtuple("VcArchDevel", ("dll", "imp", "test")) +VcArchDevel = collections.namedtuple("VcArchDevel", ("dll", "pdb", "imp", "test")) GIT_HASH_FILENAME = ".git-hash" - -def itertools_batched(iterator: typing.Iterable, count: int): - iterator = iter(iterator) - while True: - items = [] - for _ in range(count): - obj = next(iterator, None) - if obj is None: - yield tuple(items) - return - items.append(obj) - yield tuple(items) +ANDROID_AVAILABLE_ABIS = [ + "armeabi-v7a", + "arm64-v8a", + "x86", + "x86_64", +] +ANDROID_MINIMUM_API = 19 +ANDROID_TARGET_API = 29 +ANDROID_MINIMUM_NDK = 21 class Executer: @@ -84,7 +82,7 @@ def __init__(self, executer: Executer, year: typing.Optional[str]=None): self.msbuild = self.find_msbuild() @property - def dry(self): + def dry(self) -> bool: return self.executer.dry VS_YEAR_TO_VERSION = { @@ -99,7 +97,7 @@ def find_vsdevcmd(self, year: typing.Optional[str]=None) -> typing.Optional[Path vswhere_spec = ["-latest"] if year is not None: try: - version = cls.VS_YEAR_TO_VERSION[year] + version = self.VS_YEAR_TO_VERSION[year] except KeyError: logger.error("Invalid Visual Studio year") return None @@ -117,7 +115,7 @@ def find_vsdevcmd(self, year: typing.Optional[str]=None) -> typing.Optional[Path return vsdevcmd_path def find_msbuild(self) -> typing.Optional[Path]: - vswhere_cmd = ["vswhere", "-latest", "-requires", "Microsoft.Component.MSBuild", "-find", "MSBuild\**\Bin\MSBuild.exe"] + vswhere_cmd = ["vswhere", "-latest", "-requires", "Microsoft.Component.MSBuild", "-find", r"MSBuild\**\Bin\MSBuild.exe"] msbuild_path = Path(self.executer.run(vswhere_cmd, stdout=True, dry_out="/tmp/MSBuild.exe").stdout.strip()) logger.info("MSBuild path = %s", msbuild_path) if self.dry: @@ -152,90 +150,39 @@ def __init__(self, project: str, commit: str, root: Path, dist_path: Path, secti self.executer = executer self.cmake_generator = cmake_generator - self.artifacts = {} + self.artifacts: dict[str, Path] = {} @property - def dry(self): + def dry(self) -> bool: return self.executer.dry def prepare(self): logger.debug("Creating dist folder") self.dist_path.mkdir(parents=True, exist_ok=True) - GitLsTreeResult = collections.namedtuple("GitLsTreeResult", ("path", "mode", "object_type", "object_name")) - def _git_ls_tree(self, commit) -> dict[str, GitLsTreeResult]: - logger.debug("Getting source listing from git") - dry_out = textwrap.dedent("""\ - "CMakeLists.txt": {"object_name": "9e5e4bcf094bfbde94f19c3f314808031ec8f141", "mode": "100644", "type": "blob"}, - """) - - last_key = "zzzzzz" - dict_tree_items = "{" + self.executer.run(["git", "ls-tree", "-r", """--format="%(path)": {"object_name": "%(objectname)", "mode": "%(objectmode)", "type": "%(objecttype)"},""", commit], stdout=True, dry_out=dry_out).stdout + f'"{last_key}": null' + "}" - with open("/tmp/a.txt", "w") as f: - f.write(dict_tree_items) - f.write("\n") - dict_tree_items = json.loads(dict_tree_items) - del dict_tree_items[last_key] - - tree_items = {path: self.GitLsTreeResult(path=path, mode=int(v["mode"], 8), object_type=v["type"], object_name=v["object_name"]) for path, v in dict_tree_items.items()} - assert all(item.object_type == "blob" for item in tree_items.values()) - return tree_items - - def _git_cat_file(self, tree_items: dict[str, GitLsTreeResult]) -> dict[str, bytes]: - logger.debug("Getting source binary data from git") - if self.dry: - return { - "CMakeLists.txt": b"cmake_minimum_required(VERSION 3.20)\nproject(SDL)\n", - } - git_cat = subprocess.Popen(["git", "cat-file", "--batch"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=False, bufsize=50 * 1024 * 1024) - data_tree = {} - batch_size = 60 - for batch in itertools_batched(tree_items.items(), batch_size): - for object_path, tree_item in batch: - logger.debug("Requesting data of file '%s' (object=%s)...", object_path, tree_item.object_name) - git_cat.stdin.write(f"{tree_item.object_name}\n".encode()) - git_cat.stdin.flush() - for object_path, tree_item in batch: - header = git_cat.stdout.readline().decode() - object_name, object_type, obj_size = header.strip().split(maxsplit=3) - assert tree_item.object_name == object_name - assert tree_item.object_type == object_type - obj_size = int(obj_size) - data_tree[object_path] = git_cat.stdout.read(obj_size) - logger.debug("File data received '%s'", object_path) - assert git_cat.stdout.readline() == b"\n" - - assert len(data_tree) == len(tree_items) - - logger.debug("No more file!") - git_cat.stdin.close() - git_cat.wait() - assert git_cat.returncode == 0 - logger.debug("All data received!") - return data_tree - - def _get_file_times(self, tree_items: dict[str, GitLsTreeResult]) -> dict[str, datetime.datetime]: + TreeItem = collections.namedtuple("TreeItem", ("path", "mode", "data", "time")) + def _get_file_times(self, paths: tuple[str, ...]) -> dict[str, datetime.datetime]: dry_out = textwrap.dedent("""\ time=2024-03-14T15:40:25-07:00 M\tCMakeLists.txt """) - git_log_out = self.executer.run(["git", "log", "--name-status", '--pretty=time=%cI'], stdout=True, dry_out=dry_out).stdout.splitlines(keepends=False) + git_log_out = self.executer.run(["git", "log", "--name-status", '--pretty=time=%cI', self.commit], stdout=True, dry_out=dry_out).stdout.splitlines(keepends=False) current_time = None - tree_paths = {item.path for item in tree_items.values()} - path_times = {} + set_paths = set(paths) + path_times: dict[str, datetime.datetime] = {} for line in git_log_out: if not line: continue if line.startswith("time="): current_time = datetime.datetime.fromisoformat(line.removeprefix("time=")) continue - mod_type, paths = line.split(maxsplit=1) + mod_type, file_paths = line.split(maxsplit=1) assert current_time is not None - for path in paths.split(): - if path in tree_paths and path not in path_times: - path_times[path] = current_time - assert set(path_times.keys()) == tree_paths + for file_path in file_paths.split("\t"): + if file_path in set_paths and file_path not in path_times: + path_times[file_path] = current_time + assert set(path_times.keys()) == set_paths return path_times @staticmethod @@ -244,16 +191,25 @@ def _path_filter(path: str): return False return True - TreeItem = collections.namedtuple("TreeItem", ("path", "mode", "data", "time")) - - def _get_git_contents(self) -> dict[str, (TreeItem, bytes, datetime.datetime)]: - commit_file_tree = self._git_ls_tree(self.commit) - git_datas = self._git_cat_file(commit_file_tree) - git_times = self._get_file_times(commit_file_tree) - git_contents = {path: self.TreeItem(path=path, data=git_datas[path], mode=item.mode, time=git_times[path]) for path, item in commit_file_tree.items() if self._path_filter(path)} + def _get_git_contents(self) -> dict[str, TreeItem]: + contents_tgz = subprocess.check_output(["git", "archive", "--format=tar.gz", self.commit, "-o", "/dev/stdout"], text=False) + contents = tarfile.open(fileobj=io.BytesIO(contents_tgz), mode="r:gz") + filenames = tuple(m.name for m in contents if m.isfile()) + assert "src/SDL.c" in filenames + assert "include/SDL3/SDL.h" in filenames + file_times = self._get_file_times(filenames) + git_contents = {} + for ti in contents: + if not ti.isfile(): + continue + if not self._path_filter(ti.name): + continue + contents_file = contents.extractfile(ti.name) + assert contents_file, f"{ti.name} is not a file" + git_contents[ti.name] = self.TreeItem(path=ti.name, mode=ti.mode, data=contents_file.read(), time=file_times[ti.name]) return git_contents - def create_source_archives(self): + def create_source_archives(self) -> None: archive_base = f"{self.project}-{self.version}" git_contents = self._get_git_contents() @@ -307,10 +263,10 @@ def create_source_archives(self): self.artifacts[f"src-tar-{comp}"] = tar_path - def create_xcframework(self, configuration: str="Release"): - dmg_in = self.root / f"Xcode/SDL/build/SDL3.dmg" + def create_xcframework(self, configuration: str="Release") -> None: + dmg_in = self.root / f"Xcode/SDL/build/{self.project}.dmg" dmg_in.unlink(missing_ok=True) - self.executer.run(["xcodebuild", "-project", self.root / "Xcode/SDL/SDL.xcodeproj", "-target", "SDL3.dmg", "-configuration", configuration]) + self.executer.run(["xcodebuild", "-project", str(self.root / "Xcode/SDL/SDL.xcodeproj"), "-target", "SDL3.dmg", "-configuration", configuration]) if self.dry: dmg_in.parent.mkdir(parents=True, exist_ok=True) dmg_in.touch() @@ -322,7 +278,7 @@ def create_xcframework(self, configuration: str="Release"): self.artifacts["dmg"] = dmg_out @property - def git_hash_data(self): + def git_hash_data(self) -> bytes: return f"{self.commit}\n".encode() def _tar_add_git_hash(self, tar_object: tarfile.TarFile, root: typing.Optional[str]=None, time: typing.Optional[datetime.datetime]=None): @@ -335,7 +291,7 @@ def _tar_add_git_hash(self, tar_object: tarfile.TarFile, root: typing.Optional[s tar_info = tarfile.TarInfo(path) tar_info.mode = 0o100644 tar_info.size = len(self.git_hash_data) - tar_info.mtime = time.timestamp() + tar_info.mtime = int(time.timestamp()) tar_object.addfile(tar_info, fileobj=io.BytesIO(self.git_hash_data)) def _zip_add_git_hash(self, zip_file: zipfile.ZipFile, root: typing.Optional[str]=None, time: typing.Optional[datetime.datetime]=None): @@ -351,7 +307,7 @@ def _zip_add_git_hash(self, zip_file: zipfile.ZipFile, root: typing.Optional[str zip_info.compress_type = zipfile.ZIP_DEFLATED zip_file.writestr(zip_info, data=self.git_hash_data) - def create_mingw_archives(self): + def create_mingw_archives(self) -> None: build_type = "Release" mingw_archs = ("i686", "x86_64") build_parent_dir = self.root / "build-mingw" @@ -373,6 +329,8 @@ def create_mingw_archives(self): self.executer.run([ "cmake", "-S", str(self.root), "-B", str(build_path), "--fresh", + f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', "-DSDL_SHARED=ON", "-DSDL_STATIC=ON", "-DSDL_DISABLE_INSTALL_DOCS=ON", @@ -393,18 +351,19 @@ def create_mingw_archives(self): self.executer.run(["cmake", "--install", str(build_path), "--strip", "--config", build_type]) arch_files[arch] = list(Path(r) / f for r, _, files in os.walk(install_path) for f in files) - extra_files = [ - ("mingw/pkg-support/INSTALL.txt", ""), - ("mingw/pkg-support/Makefile", ""), - ("mingw/pkg-support/cmake/sdl3-config.cmake", "cmake/"), - ("mingw/pkg-support/cmake/sdl3-config-version.cmake", "cmake/"), + extra_files = ( + ("build-scripts/pkg-support/mingw/INSTALL.txt", ""), + ("build-scripts/pkg-support/mingw/Makefile", ""), + ("build-scripts/pkg-support/mingw/cmake/SDL3Config.cmake", "cmake/"), + ("build-scripts/pkg-support/mingw/cmake/SDL3ConfigVersion.cmake", "cmake/"), ("BUGS.txt", ""), ("CREDITS.md", ""), ("README-SDL.txt", ""), ("WhatsNew.txt", ""), ("LICENSE.txt", ""), ("README.md", ""), - ] + ("docs/*", "docs/"), + ) test_files = list(Path(r) / f for r, _, files in os.walk(self.root / "test") for f in files) # FIXME: split SDL3.dll debug information into debug library @@ -416,10 +375,12 @@ def create_mingw_archives(self): logger.info("Creating %s...", tar_paths[comp]) with tarfile.open(tar_paths[comp], f"w:{comp}") as tar_object: arc_root = f"{self.project}-{self.version}" - for file_path, arcdirname in extra_files: + for file_path_glob, arcdirname in extra_files: assert not arcdirname or arcdirname[-1] == "/" - arcname = f"{arc_root}/{arcdirname}{Path(file_path).name}" - tar_object.add(self.root / file_path, arcname=arcname) + for file_path in glob.glob(file_path_glob, root_dir=self.root): + file_path = self.root / file_path + arcname = f"{arc_root}/{arcdirname}{Path(file_path).name}" + tar_object.add(file_path, arcname=arcname) for arch in mingw_archs: install_path = arch_install_paths[arch] arcname_parent = f"{arc_root}/{arch}-w64-mingw32" @@ -433,12 +394,14 @@ def create_mingw_archives(self): self.artifacts[f"mingw-devel-tar-{comp}"] = tar_paths[comp] - def build_vs(self, arch: str, platform: str, vs: VisualStudio, configuration: str="Release"): + def build_vs(self, arch: str, platform: str, vs: VisualStudio, configuration: str="Release") -> VcArchDevel: dll_path = self.root / f"VisualC/SDL/{platform}/{configuration}/{self.project}.dll" + pdb_path = self.root / f"VisualC/SDL/{platform}/{configuration}/{self.project}.pdb" imp_path = self.root / f"VisualC/SDL/{platform}/{configuration}/{self.project}.lib" test_path = self.root / f"VisualC/SDL_test/{platform}/{configuration}/{self.project}_test.lib" dll_path.unlink(missing_ok=True) + pdb_path.unlink(missing_ok=True) imp_path.unlink(missing_ok=True) test_path.unlink(missing_ok=True) @@ -447,16 +410,89 @@ def build_vs(self, arch: str, platform: str, vs: VisualStudio, configuration: st self.root / "VisualC/SDL_test/SDL_test.vcxproj", ] - vs.build(arch=arch, platform=platform, configuration=configuration, projects=projects) + with self.section_printer.group(f"Build {arch} VS binary"): + vs.build(arch=arch, platform=platform, configuration=configuration, projects=projects) if self.dry: dll_path.parent.mkdir(parents=True, exist_ok=True) dll_path.touch() + pdb_path.touch() imp_path.touch() test_path.parent.mkdir(parents=True, exist_ok=True) test_path.touch() assert dll_path.is_file(), "SDL3.dll has not been created" + assert pdb_path.is_file(), "SDL3.pdb has not been created" + assert imp_path.is_file(), "SDL3.lib has not been created" + assert test_path.is_file(), "SDL3_test.lib has not been created" + + zip_path = self.dist_path / f"{self.project}-{self.version}-win32-{arch}.zip" + zip_path.unlink(missing_ok=True) + logger.info("Creating %s", zip_path) + with zipfile.ZipFile(zip_path, mode="w", compression=zipfile.ZIP_DEFLATED) as zf: + logger.debug("Adding %s", dll_path.name) + zf.write(dll_path, arcname=dll_path.name) + logger.debug("Adding %s", "README-SDL.txt") + zf.write(self.root / "README-SDL.txt", arcname="README-SDL.txt") + self._zip_add_git_hash(zip_file=zf) + self.artifacts[f"VC-{arch}"] = zip_path + + return VcArchDevel(dll=dll_path, pdb=pdb_path, imp=imp_path, test=test_path) + + def build_vs_cmake(self, arch: str, arch_cmake: str) -> VcArchDevel: + build_path = self.root / f"build-vs-{arch}" + install_path = build_path / "prefix" + dll_path = install_path / f"bin/{self.project}.dll" + pdb_path = install_path / f"bin/{self.project}.pdb" + imp_path = install_path / f"lib/{self.project}.lib" + test_path = install_path / f"lib/{self.project}_test.lib" + + dll_path.unlink(missing_ok=True) + pdb_path.unlink(missing_ok=True) + imp_path.unlink(missing_ok=True) + test_path.unlink(missing_ok=True) + + build_type = "Release" + + shutil.rmtree(install_path, ignore_errors=True) + build_path.mkdir(parents=True, exist_ok=True) + with self.section_printer.group(f"Configure VC CMake project for {arch}"): + self.executer.run([ + "cmake", "-S", str(self.root), "-B", str(build_path), + "--fresh", + "-A", arch_cmake, + "-DSDL_SHARED=ON", + "-DSDL_STATIC=OFF", + "-DSDL_DISABLE_INSTALL_DOCS=ON", + "-DSDL_TEST_LIBRARY=ON", + "-DSDL_TESTS=OFF", + "-DCMAKE_INSTALL_BINDIR=bin", + "-DCMAKE_INSTALL_DATAROOTDIR=share", + "-DCMAKE_INSTALL_INCLUDEDIR=include", + "-DCMAKE_INSTALL_LIBDIR=lib", + f"-DCMAKE_BUILD_TYPE={build_type}", + f"-DCMAKE_INSTALL_PREFIX={install_path}", + # MSVC debug information format flags are selected by an abstraction + "-DCMAKE_POLICY_DEFAULT_CMP0141=NEW", + # MSVC debug information format + "-DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=ProgramDatabase", + # Linker flags for executables + "-DCMAKE_EXE_LINKER_FLAGS=-DEBUG", + # Linker flag for shared libraries + "-DCMAKE_SHARED_LINKER_FLAGS=-INCREMENTAL:NO -DEBUG -OPT:REF -OPT:ICF", + # MSVC runtime library flags are selected by an abstraction + "-DCMAKE_POLICY_DEFAULT_CMP0091=NEW", + # Use statically linked runtime (-MT) (ideally, should be "MultiThreaded$<$:Debug>") + "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", + ]) + + with self.section_printer.group(f"Build VC CMake project for {arch}"): + self.executer.run(["cmake", "--build", str(build_path), "--verbose", "--config", build_type]) + with self.section_printer.group(f"Install VC CMake project for {arch}"): + self.executer.run(["cmake", "--install", str(build_path), "--config", build_type]) + + assert dll_path.is_file(), "SDL3.dll has not been created" + assert pdb_path.is_file(), "SDL3.pdb has not been created" assert imp_path.is_file(), "SDL3.lib has not been created" assert test_path.is_file(), "SDL3_test.lib has not been created" @@ -471,9 +507,9 @@ def build_vs(self, arch: str, platform: str, vs: VisualStudio, configuration: st self._zip_add_git_hash(zip_file=zf) self.artifacts[f"VC-{arch}"] = zip_path - return VcArchDevel(dll=dll_path, imp=imp_path, test=test_path) + return VcArchDevel(dll=dll_path, pdb=pdb_path, imp=imp_path, test=test_path) - def build_vs_devel(self, arch_vc: dict[str, VcArchDevel]): + def build_vs_devel(self, arch_vc: dict[str, VcArchDevel]) -> None: zip_path = self.dist_path / f"{self.project}-devel-{self.version}-VC.zip" archive_prefix = f"{self.project}-{self.version}" @@ -493,11 +529,13 @@ def zip_directory(zf: zipfile.ZipFile, directory: Path, arcrelpath: str): for arch, binaries in arch_vc.items(): zip_file(zf, path=binaries.dll, arcrelpath=f"lib/{arch}/{binaries.dll.name}") zip_file(zf, path=binaries.imp, arcrelpath=f"lib/{arch}/{binaries.imp.name}") + zip_file(zf, path=binaries.pdb, arcrelpath=f"lib/{arch}/{binaries.pdb.name}") zip_file(zf, path=binaries.test, arcrelpath=f"lib/{arch}/{binaries.test.name}") zip_directory(zf, directory=self.root / "include/SDL3", arcrelpath="include/SDL3") zip_directory(zf, directory=self.root / "docs", arcrelpath="docs") zip_directory(zf, directory=self.root / "VisualC/pkg-support/cmake", arcrelpath="cmake") + zip_file(zf, path=self.root / "cmake/sdlcpu.cmake", arcrelpath="cmake/sdlcpu.cmake") for txt in ("BUGS.txt", "README-SDL.txt", "WhatsNew.txt"): zip_file(zf, path=self.root / txt, arcrelpath=txt) @@ -507,26 +545,215 @@ def zip_directory(zf: zipfile.ZipFile, directory: Path, arcrelpath: str): self._zip_add_git_hash(zip_file=zf, root=archive_prefix) self.artifacts["VC-devel"] = zip_path + def detect_android_api(self, android_home: str) -> typing.Optional[int]: + platform_dirs = list(Path(p) for p in glob.glob(f"{android_home}/platforms/android-*")) + re_platform = re.compile("android-([0-9]+)") + platform_versions = [] + for platform_dir in platform_dirs: + logger.debug("Found Android Platform SDK: %s", platform_dir) + if m:= re_platform.match(platform_dir.name): + platform_versions.append(int(m.group(1))) + platform_versions.sort() + logger.info("Available platform versions: %s", platform_versions) + platform_versions = list(filter(lambda v: v >= ANDROID_MINIMUM_API, platform_versions)) + logger.info("Valid platform versions (>=%d): %s", ANDROID_MINIMUM_API, platform_versions) + if not platform_versions: + return None + android_api = platform_versions[0] + logger.info("Selected API version %d", android_api) + return android_api + + def get_prefab_json_text(self) -> str: + return textwrap.dedent(f"""\ + {{ + "schema_version": 2, + "name": "{self.project}", + "version": "{self.version}", + "dependencies": [] + }} + """) + + def get_prefab_module_json_text(self, library_name: str, extra_libs: list[str]) -> str: + export_libraries_str = ", ".join(f"\"-l{lib}\"" for lib in extra_libs) + return textwrap.dedent(f"""\ + {{ + "export_libraries": [{export_libraries_str}], + "library_name": "lib{library_name}" + }} + """) + + def get_prefab_abi_json_text(self, abi: str, cpp: bool, shared: bool) -> str: + return textwrap.dedent(f"""\ + {{ + "abi": "{abi}", + "api": {ANDROID_MINIMUM_API}, + "ndk": {ANDROID_MINIMUM_NDK}, + "stl": "{'c++_shared' if cpp else 'none'}", + "static": {'true' if not shared else 'false'} + }} + """) + + def get_android_manifest_text(self) -> str: + return textwrap.dedent(f"""\ + + + + """) + + def create_android_archives(self, android_api: int, android_home: Path, android_ndk_home: Path, android_abis: list[str]) -> None: + cmake_toolchain_file = Path(android_ndk_home) / "build/cmake/android.toolchain.cmake" + if not cmake_toolchain_file.exists(): + logger.error("CMake toolchain file does not exist (%s)", cmake_toolchain_file) + raise SystemExit(1) + aar_path = self.dist_path / f"{self.project}-{self.version}.aar" + added_global_files = False + with zipfile.ZipFile(aar_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_object: + def configure_file(path: Path) -> str: + text = path.read_text() + text = text.replace("@PROJECT_VERSION@", self.version) + text = text.replace("@PROJECT_NAME@", self.project) + return text + + install_txt = configure_file(self.root / "build-scripts/pkg-support/android/INSTALL.md.in") + zip_object.writestr("INSTALL.md", install_txt) + + project_description = { + "name": self.project, + "version": self.version, + "git-hash": self.commit, + } + zip_object.writestr("description.json", json.dumps(project_description, indent=0)) + main_py = configure_file(self.root / "build-scripts/pkg-support/android/__main__.py.in") + zip_object.writestr("__main__.py", main_py) + + zip_object.writestr("AndroidManifest.xml", self.get_android_manifest_text()) + zip_object.write(self.root / "android-project/app/proguard-rules.pro", arcname="proguard.txt") + zip_object.write(self.root / "LICENSE.txt", arcname="META-INF/LICENSE.txt") + zip_object.write(self.root / "cmake/sdlcpu.cmake", arcname="cmake/sdlcpu.cmake") + zip_object.write(self.root / "build-scripts/pkg-support/android/cmake/SDL3Config.cmake", arcname="cmake/SDL3Config.cmake") + zip_object.write(self.root / "build-scripts/pkg-support/android/cmake/SDL3ConfigVersion.cmake", arcname="cmake/SDL3ConfigVersion.cmake") + zip_object.writestr("prefab/prefab.json", self.get_prefab_json_text()) + self._zip_add_git_hash(zip_file=zip_object) + + for android_abi in android_abis: + with self.section_printer.group(f"Building for Android {android_api} {android_abi}"): + build_dir = self.root / "build-android" / f"{android_abi}-build" + install_dir = self.root / "install-android" / f"{android_abi}-install" + shutil.rmtree(install_dir, ignore_errors=True) + assert not install_dir.is_dir(), f"{install_dir} should not exist prior to build" + cmake_args = [ + "cmake", + "-S", str(self.root), + "-B", str(build_dir), + "--fresh", + f'''-DCMAKE_C_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + f'''-DCMAKE_CXX_FLAGS="-ffile-prefix-map={self.root}=/src/{self.project}"''', + "-DCMAKE_BUILD_TYPE=RelWithDebInfo", + f"-DCMAKE_TOOLCHAIN_FILE={cmake_toolchain_file}", + f"-DANDROID_PLATFORM={android_api}", + f"-DANDROID_ABI={android_abi}", + "-DCMAKE_POSITION_INDEPENDENT_CODE=ON", + "-DSDL_SHARED=ON", + "-DSDL_STATIC=OFF", + "-DSDL_TEST_LIBRARY=ON", + "-DSDL_DISABLE_ANDROID_JAR=OFF", + "-DSDL_TESTS=OFF", + f"-DCMAKE_INSTALL_PREFIX={install_dir}", + "-DSDL_DISABLE_INSTALL=OFF", + "-DSDL_DISABLE_INSTALL_DOCS=OFF", + "-DCMAKE_INSTALL_INCLUDEDIR=include ", + "-DCMAKE_INSTALL_LIBDIR=lib", + "-DCMAKE_INSTALL_DATAROOTDIR=share", + "-DCMAKE_BUILD_TYPE=Release", + f"-DSDL_ANDROID_HOME={android_home}", + f"-G{self.cmake_generator}", + ] + build_args = [ + "cmake", + "--build", str(build_dir), + "--config", "RelWithDebInfo", + ] + install_args = [ + "cmake", + "--install", str(build_dir), + "--config", "RelWithDebInfo", + ] + self.executer.run(cmake_args) + self.executer.run(build_args) + self.executer.run(install_args) + + main_so_library = install_dir / "lib" / f"lib{self.project}.so" + logger.debug("Expecting library %s", main_so_library) + assert main_so_library.is_file(), "CMake should have built a shared library (e.g. libSDL3.so)" + + test_library = install_dir / "lib" / f"lib{self.project}_test.a" + logger.debug("Expecting library %s", test_library) + assert test_library.is_file(), "CMake should have built a static test library (e.g. libSDL3_test.a)" + + java_jar = install_dir / f"share/java/{self.project}/{self.project}-{self.version}.jar" + logger.debug("Expecting java archive: %s", java_jar) + assert java_jar.is_file(), "CMake should have compiled the java sources and archived them into a JAR" + + javasources_jar = install_dir / f"share/java/{self.project}/{self.project}-{self.version}-sources.jar" + logger.debug("Expecting java sources archive %s", javasources_jar) + assert javasources_jar.is_file(), "CMake should have archived the java sources into a JAR" + + javadoc_dir = install_dir / "share/javadoc" / self.project + logger.debug("Expecting javadoc archive %s", javadoc_dir) + assert javadoc_dir.is_dir(), "CMake should have built javadoc documentation for the java sources" + if not added_global_files: + zip_object.write(java_jar, arcname="classes.jar") + zip_object.write(javasources_jar, arcname="classes-sources.jar", ) + doc_jar_path = install_dir / "classes-doc.jar" + + javadoc_jar_args = ["jar", "--create", "--file", str(doc_jar_path)] + for fn in javadoc_dir.iterdir(): + javadoc_jar_args.extend(["-C", str(javadoc_dir), fn.name]) + self.executer.run(javadoc_jar_args) + zip_object.write(doc_jar_path, arcname="classes-doc.jar") + + for header in (install_dir / "include" / self.project).iterdir(): + zip_object.write(header, arcname=f"prefab/modules/{self.project}/include/{self.project}/{header.name}") + + zip_object.writestr(f"prefab/modules/{self.project}/module.json", self.get_prefab_module_json_text(library_name=self.project, extra_libs=[])) + zip_object.writestr(f"prefab/modules/{self.project}_test/module.json", self.get_prefab_module_json_text(library_name=f"{self.project}_test", extra_libs=list())) + added_global_files = True + + zip_object.write(main_so_library, arcname=f"prefab/modules/{self.project}/libs/android.{android_abi}/lib{self.project}.so") + zip_object.writestr(f"prefab/modules/{self.project}/libs/android.{android_abi}/abi.json", self.get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=True)) + zip_object.write(test_library, arcname=f"prefab/modules/{self.project}_test/libs/android.{android_abi}/lib{self.project}_test.a") + zip_object.writestr(f"prefab/modules/{self.project}_test/libs/android.{android_abi}/abi.json", self.get_prefab_abi_json_text(abi=android_abi, cpp=False, shared=False)) + + self.artifacts[f"android-aar"] = aar_path + @classmethod - def extract_sdl_version(cls, root: Path, project: str): + def extract_sdl_version(cls, root: Path, project: str) -> str: with open(root / f"include/{project}/SDL_version.h", "r") as f: text = f.read() major = next(re.finditer(r"^#define SDL_MAJOR_VERSION\s+([0-9]+)$", text, flags=re.M)).group(1) minor = next(re.finditer(r"^#define SDL_MINOR_VERSION\s+([0-9]+)$", text, flags=re.M)).group(1) - patch = next(re.finditer(r"^#define SDL_PATCHLEVEL\s+([0-9]+)$", text, flags=re.M)).group(1) - return f"{major}.{minor}.{patch}" + micro = next(re.finditer(r"^#define SDL_MICRO_VERSION\s+([0-9]+)$", text, flags=re.M)).group(1) + return f"{major}.{minor}.{micro}" -def main(argv=None): +def main(argv=None) -> int: parser = argparse.ArgumentParser(allow_abbrev=False, description="Create SDL release artifacts") - parser.add_argument("--root", metavar="DIR", type=Path, default=Path(__file__).resolve().parents[1], help="Root of SDL") + parser.add_argument("--root", metavar="DIR", type=Path, default=Path(__file__).absolute().parents[1], help="Root of SDL") parser.add_argument("--out", "-o", metavar="DIR", dest="dist_path", type=Path, default="dist", help="Output directory") parser.add_argument("--github", action="store_true", help="Script is running on a GitHub runner") parser.add_argument("--commit", default="HEAD", help="Git commit/tag of which a release should be created") - parser.add_argument("--project", required=True, help="Name of the project") - parser.add_argument("--create", choices=["source", "mingw", "win32", "xcframework"], required=True,action="append", dest="actions", help="SDL version") + parser.add_argument("--project", required=True, help="Name of the project (e.g. SDL3") + parser.add_argument("--create", choices=["source", "mingw", "win32", "xcframework", "android"], required=True, action="append", dest="actions", help="What to do") parser.set_defaults(loglevel=logging.INFO) parser.add_argument('--vs-year', dest="vs_year", help="Visual Studio year") + parser.add_argument('--android-api', type=int, dest="android_api", help="Android API version") + parser.add_argument('--android-home', dest="android_home", default=os.environ.get("ANDROID_HOME"), help="Android Home folder") + parser.add_argument('--android-ndk-home', dest="android_ndk_home", default=os.environ.get("ANDROID_NDK_HOME"), help="Android NDK Home folder") + parser.add_argument('--android-abis', dest="android_abis", nargs="*", choices=ANDROID_AVAILABLE_ABIS, default=list(ANDROID_AVAILABLE_ABIS), help="Android NDK Home folder") parser.add_argument('--cmake-generator', dest="cmake_generator", default="Ninja", help="CMake Generator") parser.add_argument('--debug', action='store_const', const=logging.DEBUG, dest="loglevel", help="Print script debug information") parser.add_argument('--dry-run', action='store_true', dest="dry", help="Don't execute anything") @@ -535,14 +762,14 @@ def main(argv=None): args = parser.parse_args(argv) logging.basicConfig(level=args.loglevel, format='[%(levelname)s] %(message)s') args.actions = set(args.actions) - args.dist_path = args.dist_path.resolve() - args.root = args.root.resolve() - args.dist_path = args.dist_path.resolve() + args.dist_path = args.dist_path.absolute() + args.root = args.root.absolute() + args.dist_path = args.dist_path.absolute() if args.dry: args.dist_path = args.dist_path / "dry" if args.github: - section_printer = GitHubSectionPrinter() + section_printer: SectionPrinter = GitHubSectionPrinter() else: section_printer = SectionPrinter() @@ -554,7 +781,7 @@ def main(argv=None): logger.warning("%s detected: Building from archive", GIT_HASH_FILENAME) archive_commit = root_git_hash_path.read_text().strip() if args.commit != archive_commit: - logger.warn("Commit argument is %s, but archive commit is %s. Using %s.", args.commit, archive_commit, archive_commit) + logger.warning("Commit argument is %s, but archive commit is %s. Using %s.", args.commit, archive_commit, archive_commit) args.commit = archive_commit else: args.commit = executer.run(["git", "rev-parse", args.commit], stdout=True, dry_out="e5812a9fd2cda317b503325a702ba3c1c37861d9").stdout.strip() @@ -571,7 +798,7 @@ def main(argv=None): ) if root_is_maybe_archive: - logger.warn("Building from archive. Skipping clean git tree check.") + logger.warning("Building from archive. Skipping clean git tree check.") else: porcelain_status = executer.run(["git", "status", "--ignored", "--porcelain"], stdout=True, dry_out="\n").stdout.strip() if porcelain_status: @@ -581,14 +808,14 @@ def main(argv=None): raise Exception("The git repo contains modified and/or non-committed files. Run with --force to ignore.") with section_printer.group("Arguments"): - print(f"project = {args.project}") - print(f"version = {releaser.version}") - print(f"commit = {args.commit}") - print(f"out = {args.dist_path}") - print(f"actions = {args.actions}") - print(f"dry = {args.dry}") - print(f"force = {args.force}") - print(f"cmake_generator = {args.cmake_generator}") + print(f"project = {args.project}") + print(f"version = {releaser.version}") + print(f"commit = {args.commit}") + print(f"out = {args.dist_path}") + print(f"actions = {args.actions}") + print(f"dry = {args.dry}") + print(f"force = {args.force}") + print(f"cmake_generator = {args.cmake_generator}") releaser.prepare() @@ -609,20 +836,45 @@ def main(argv=None): parser.error("win32 artifact(s) can only be built on Windows") with section_printer.group("Find Visual Studio"): vs = VisualStudio(executer=executer) - with section_printer.group("Build x86 VS binary"): - x86 = releaser.build_vs(arch="x86", platform="Win32", vs=vs) - with section_printer.group("Build x64 VS binary"): - x64 = releaser.build_vs(arch="x64", platform="x64", vs=vs) + arm64 = releaser.build_vs_cmake(arch="arm64", arch_cmake="ARM64") + x86 = releaser.build_vs(arch="x86", platform="Win32", vs=vs) + x64 = releaser.build_vs(arch="x64", platform="x64", vs=vs) with section_printer.group("Create SDL VC development zip"): arch_vc = { "x86": x86, "x64": x64, + "arm64": arm64, } releaser.build_vs_devel(arch_vc) if "mingw" in args.actions: releaser.create_mingw_archives() + if "android" in args.actions: + if args.android_home is None or not Path(args.android_home).is_dir(): + parser.error("Invalid $ANDROID_HOME or --android-home: must be a directory containing the Android SDK") + if args.android_ndk_home is None or not Path(args.android_ndk_home).is_dir(): + parser.error("Invalid $ANDROID_NDK_HOME or --android_ndk_home: must be a directory containing the Android NDK") + if args.android_api is None: + with section_printer.group("Detect Android APIS"): + args.android_api = releaser.detect_android_api(android_home=args.android_home) + if args.android_api is None or not (Path(args.android_home) / f"platforms/android-{args.android_api}").is_dir(): + parser.error("Invalid --android-api, and/or could not be detected") + if not args.android_abis: + parser.error("Need at least one Android ABI") + with section_printer.group("Android arguments"): + print(f"android_home = {args.android_home}") + print(f"android_ndk_home = {args.android_ndk_home}") + print(f"android_api = {args.android_api}") + print(f"android_abis = {args.android_abis}") + releaser.create_android_archives( + android_api=args.android_api, + android_home=args.android_home, + android_ndk_home=args.android_ndk_home, + android_abis=args.android_abis, + ) + + with section_printer.group("Summary"): print(f"artifacts = {releaser.artifacts}") diff --git a/libs/SDL3/build-scripts/build-web-examples.pl b/libs/SDL3/build-scripts/build-web-examples.pl new file mode 100644 index 000000000..0053295e9 --- /dev/null +++ b/libs/SDL3/build-scripts/build-web-examples.pl @@ -0,0 +1,226 @@ +#!/usr/bin/perl -w + +# Simple DirectMedia Layer +# Copyright (C) 1997-2024 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. + +use warnings; +use strict; +use File::Basename; +use File::Copy; +use Cwd qw(abs_path); +use IPC::Open2; + +my $examples_dir = abs_path(dirname(__FILE__) . "/../examples"); +my $project = undef; +my $emsdk_dir = undef; +my $compile_dir = undef; +my $cmake_flags = undef; +my $output_dir = undef; + +sub usage { + die("USAGE: $0 \n\n"); +} + +sub do_system { + my $cmd = shift; + $cmd = "exec /bin/bash -c \"$cmd\""; + print("$cmd\n"); + return system($cmd); +} + +sub do_mkdir { + my $d = shift; + if ( ! -d $d ) { + print("mkdir '$d'\n"); + mkdir($d) or die("Couldn't mkdir('$d'): $!\n"); + } +} + +sub do_copy { + my $src = shift; + my $dst = shift; + print("cp '$src' '$dst'\n"); + copy($src, $dst) or die("Failed to copy '$src' to '$dst': $!\n"); +} + +sub build_latest { + # Try to build just the latest without re-running cmake, since that is SLOW. + print("Building latest version of $project ...\n"); + if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && cd '$compile_dir' && ninja") != 0) { + # Build failed? Try nuking the build dir and running CMake from scratch. + print("\n\nBuilding latest version of $project FROM SCRATCH ...\n"); + if (do_system("EMSDK_QUIET=1 source '$emsdk_dir/emsdk_env.sh' && rm -rf '$compile_dir' && mkdir '$compile_dir' && cd '$compile_dir' && emcmake cmake -G Ninja -DCMAKE_BUILD_TYPE=MinSizeRel $cmake_flags '$examples_dir/..' && ninja") != 0) { + die("Failed to build latest version of $project!\n"); # oh well. + } + } +} + +sub handle_example_dir { + my $category = shift; + my $example = shift; + + my @files = (); + my $files_str = ''; + opendir(my $dh, "$examples_dir/$category/$example") or die("Couldn't opendir '$examples_dir/$category/$example': $!\n"); + my $spc = ''; + while (readdir($dh)) { + my $path = "$examples_dir/$category/$example/$_"; + next if not -f $path; # only care about files. + push @files, $path if /\.[ch]\Z/; # add .c and .h files to source code. + if (/\.c\Z/) { # only care about .c files for compiling. + $files_str .= "$spc$path"; + $spc = ' '; + } + } + closedir($dh); + + my $dst = "$output_dir/$category/$example"; + + print("Building $category/$example ...\n"); + + my $basefname = "$example"; + $basefname =~ s/\A\d+\-//; + $basefname = "$category-$basefname"; + my $jsfname = "$basefname.js"; + my $wasmfname = "$basefname.wasm"; + my $jssrc = "$compile_dir/examples/$jsfname"; + my $wasmsrc = "$compile_dir/examples/$wasmfname"; + my $jsdst = "$dst/$jsfname"; + my $wasmdst = "$dst/$wasmfname"; + + my $description = ''; + if (open(my $readmetxth, '<', "$examples_dir/$category/$example/README.txt")) { + while (<$readmetxth>) { + chomp; + s/\A\s+//; + s/\s+\Z//; + $description .= "$_
"; + } + close($readmetxth); + } + + do_mkdir($dst); + do_copy($jssrc, $jsdst); + do_copy($wasmsrc, $wasmdst); + + my $highlight_cmd = "highlight '--outdir=$dst' --style-outfile=highlight.css --fragment --enclose-pre --stdout --syntax=c '--plug-in=$examples_dir/highlight-plugin.lua'"; + print("$highlight_cmd\n"); + my $pid = open2(my $child_out, my $child_in, $highlight_cmd); + + my $htmlified_source_code = ''; + foreach (sort(@files)) { + my $path = $_; + open my $srccode, '<', $path or die("Couldn't open '$path': $!\n"); + my $fname = "$path"; + $fname =~ s/\A.*\///; + print $child_in "/* $fname ... */\n\n"; + while (<$srccode>) { + print $child_in $_; + } + print $child_in "\n\n\n"; + close($srccode); + } + + close($child_in); + + while (<$child_out>) { + $htmlified_source_code .= $_; + } + close($child_out); + + waitpid($pid, 0); + + + my $html = ''; + open my $htmltemplate, '<', "$examples_dir/template.html" or die("Couldn't open '$examples_dir/template.html': $!\n"); + while (<$htmltemplate>) { + s/\@project_name\@/$project/g; + s/\@category_name\@/$category/g; + s/\@example_name\@/$example/g; + s/\@javascript_file\@/$jsfname/g; + s/\@htmlified_source_code\@/$htmlified_source_code/g; + s/\@description\@/$description/g; + $html .= $_; + } + close($htmltemplate); + + open my $htmloutput, '>', "$dst/index.html" or die("Couldn't open '$dst/index.html': $!\n"); + print $htmloutput $html; + close($htmloutput); +} + +sub handle_category_dir { + my $category = shift; + + # !!! FIXME: this needs to generate a preview page for all the examples things in the category. + + print("Category $category ...\n"); + + do_mkdir("$output_dir/$category"); + + opendir(my $dh, "$examples_dir/$category") or die("Couldn't opendir '$examples_dir/$category': $!\n"); + + while (readdir($dh)) { + next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries. + next if not -d "$examples_dir/$category/$_"; # only care about subdirectories. + handle_example_dir($category, $_); + } + + closedir($dh); +} + + +# Mainline! + +foreach (@ARGV) { + $project = $_, next if not defined $project; + $emsdk_dir = $_, next if not defined $emsdk_dir; + $compile_dir = $_, next if not defined $compile_dir; + $cmake_flags = $_, next if not defined $cmake_flags; + $output_dir = $_, next if not defined $output_dir; + usage(); # too many arguments. +} + +usage() if not defined $output_dir; + +print("Examples dir: $examples_dir\n"); +print("emsdk dir: $emsdk_dir\n"); +print("Compile dir: $compile_dir\n"); +print("CMake flags: $cmake_flags\n"); +print("Output dir: $output_dir\n"); + +do_system("rm -rf '$output_dir'"); +do_mkdir($output_dir); + +build_latest(); + +opendir(my $dh, $examples_dir) or die("Couldn't opendir '$examples_dir': $!\n"); + +while (readdir($dh)) { + next if ($_ eq '.') || ($_ eq '..'); # obviously skip current and parent entries. + next if not -d "$examples_dir/$_"; # only care about subdirectories. + # !!! FIXME: this needs to generate a preview page for all the categories. + handle_category_dir($_); +} + +closedir($dh); + +print("All examples built successfully!\n"); +exit(0); # success! + diff --git a/libs/SDL3/build-scripts/check_android_jni.py b/libs/SDL3/build-scripts/check_android_jni.py new file mode 100644 index 000000000..9e519fb2d --- /dev/null +++ b/libs/SDL3/build-scripts/check_android_jni.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python + +import argparse +import dataclasses +import os +import pathlib +import re + +ROOT = pathlib.Path(__file__).resolve().parents[1] +SDL_ANDROID_C = ROOT / "src/core/android/SDL_android.c" +METHOD_SOURCE_PATHS = ( + SDL_ANDROID_C, + ROOT / "src/hidapi/android/hid.cpp", +) +JAVA_ROOT = ROOT / "android-project/app/src/main/java" + + +BASIC_TYPE_SPEC_LUT = { + "char": "C", + "byte": "B", + "short": "S", + "int": "I", + "long": "J", + "float": "F", + "double": "D", + "void": "V", + "boolean": "Z", + "Object": "Ljava/lang/Object;", + "String": "Ljava/lang/String;", +} + + +@dataclasses.dataclass(frozen=True) +class JniType: + typ: str + array: int + + +def java_type_to_jni_spec_internal(type_str: str) -> tuple[int, str]: + for basic_type_str, basic_type_spec in BASIC_TYPE_SPEC_LUT.items(): + if type_str.startswith(basic_type_str): + return len(basic_type_str), basic_type_spec + raise ValueError(f"Don't know how to convert {repr(type_str)} to its equivalent jni spec") + + +def java_type_to_jni_spec(type_str: str) -> str: + end, type_spec = java_type_to_jni_spec_internal(type_str) + suffix_str = type_str[end:] + assert(all(c in "[] \t" for c in suffix_str)) + suffix_str = "".join(filter(lambda v: v in "[]", suffix_str)) + assert len(suffix_str) % 2 == 0 + array_spec = "[" * (len(suffix_str) // 2) + return array_spec + type_spec + + +def java_method_to_jni_spec(ret: str, args: list[str]) -> str: + return "(" + "".join(java_type_to_jni_spec(a) for a in args) +")" + java_type_to_jni_spec(ret) + + +@dataclasses.dataclass(frozen=True) +class JniMethodBinding: + name: str + spec: str + + +def collect_jni_bindings_from_c() -> dict[str, set[JniMethodBinding]]: + bindings = {} + + sdl_android_text = SDL_ANDROID_C.read_text() + for m in re.finditer(r"""register_methods\((?:[A-Za-z0-9]+),\s*"(?P[a-zA-Z0-9_/]+)",\s*(?P[a-zA-Z0-9_]+),\s*SDL_arraysize\((?P=table)\)\)""", sdl_android_text): + kls = m["class"] + table = m["table"] + methods = set() + in_struct = False + for method_source_path in METHOD_SOURCE_PATHS: + method_source = method_source_path.read_text() + for line in method_source.splitlines(keepends=False): + if re.match(f"(static )?JNINativeMethod {table}" + r"\[([0-9]+)?\] = \{", line): + in_struct = True + continue + if in_struct: + if re.match(r"\};", line): + in_struct = False + break + n = re.match(r"""\s*\{\s*"(?P[a-zA-Z0-9_]+)"\s*,\s*"(?P[()A-Za-z0-9_/;[]+)"\s*,\s*(\(void\*\))?(HID|SDL)[_A-Z]*_JAVA_[_A-Z]*INTERFACE[_A-Z]*\((?P=method)\)\s*\},?""", line) + assert n, f"'{line}' does not match regex" + methods.add(JniMethodBinding(name=n["method"], spec=n["spec"])) + continue + if methods: + break + if methods: + break + assert methods, f"Could not find methods for {kls} (table={table})" + + assert not in_struct + + assert kls not in bindings, f"{kls} must be unique in C sources" + bindings[kls] = methods + return bindings + +def collect_jni_bindings_from_java() -> dict[str, set[JniMethodBinding]]: + bindings = {} + + for root, _, files in os.walk(JAVA_ROOT): + for file in files: + file_path = pathlib.Path(root) / file + java_text = file_path.read_text() + methods = set() + for m in re.finditer(r"(?:(?:public|private)\s+)?(?:static\s+)?native\s+(?P[A-Za-z0-9_]+)\s+(?P[a-zA-Z0-9_]+)\s*\(\s*(?P[^)]*)\);", java_text): + name = m["method"] + ret = m["ret"] + args = [] + args_str = m["args"].strip() + if args_str: + for a_s in args_str.split(","): + atype_str, _ = a_s.strip().rsplit(" ") + args.append(atype_str.strip()) + + spec = java_method_to_jni_spec(ret=ret, args=args) + methods.add(JniMethodBinding(name=name, spec=spec)) + if methods: + relative_java_path = file_path.relative_to(JAVA_ROOT) + relative_java_path_without_suffix = relative_java_path.with_suffix("") + kls = "/".join(relative_java_path_without_suffix.parts) + assert kls not in bindings, f"{kls} must be unique in JAVA sources" + bindings[kls] = methods + return bindings + + +def print_error(*args): + print("ERROR:", *args) + + +def main(): + parser = argparse.ArgumentParser(allow_abbrev=False, description="Verify Android JNI bindings") + args = parser.parse_args() + + bindings_from_c = collect_jni_bindings_from_c() + bindings_from_java = collect_jni_bindings_from_java() + + all_ok = bindings_from_c == bindings_from_java + if all_ok: + print("OK") + else: + print("NOT OK") + kls_c = set(bindings_from_c.keys()) + kls_java = set(bindings_from_java.keys()) + if kls_c != kls_java: + only_c = kls_c - kls_java + for c in only_c: + print_error(f"Missing class in JAVA sources: {c}") + only_java = kls_java - kls_c + for c in only_java: + print_error(f"Missing class in C sources: {c}") + + klasses = kls_c.union(kls_java) + for kls in klasses: + m_c = bindings_from_c.get(kls) + m_j = bindings_from_java.get(kls) + if m_c and m_j and m_c != m_j: + m_only_c = m_c - m_j + for c in m_only_c: + print_error(f"{kls}: Binding only in C source: {c.name} {c.spec}") + m_only_j = m_j - m_c + for c in m_only_j: + print_error(f"{kls}: Binding only in JAVA source: {c.name} {c.spec}") + + return 0 if all_ok else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/libs/SDL3/build-scripts/check_stdlib_usage.py b/libs/SDL3/build-scripts/check_stdlib_usage.py index 8dea74e14..525b58a83 100644 --- a/libs/SDL3/build-scripts/check_stdlib_usage.py +++ b/libs/SDL3/build-scripts/check_stdlib_usage.py @@ -29,7 +29,7 @@ SDL_ROOT = pathlib.Path(__file__).resolve().parents[1] -words = [ +STDLIB_SYMBOLS = [ 'abs', 'acos', 'acosf', @@ -146,15 +146,13 @@ 'wcslen', 'wcsncasecmp', 'wcsncmp', - 'wcsstr' ] + 'wcsstr', +] +RE_STDLIB_SYMBOL = re.compile(rf"\b(?P{'|'.join(STDLIB_SYMBOLS)})\b\(") -reg_comment_remove_content = re.compile('\/\*.*\*/') -reg_comment_remove_content2 = re.compile('".*"') -reg_comment_remove_content3 = re.compile(':strlen') -reg_comment_remove_content4 = re.compile('->free') - -def find_symbols_in_file(file, regex): +def find_symbols_in_file(file: pathlib.Path) -> int: + match_count = 0 allowed_extensions = [ ".c", ".cpp", ".m", ".h", ".hpp", ".cc" ] @@ -165,99 +163,99 @@ def find_symbols_in_file(file, regex): "src/video/khronos", "include/SDL3", "build-scripts/gen_audio_resampler_filter.c", - "build-scripts/gen_audio_channel_conversion.c" ] + "build-scripts/gen_audio_channel_conversion.c", + "test/win32/sdlprocdump.c", + ] filename = pathlib.Path(file) for ep in excluded_paths: if ep in filename.as_posix(): # skip - return + return 0 if filename.suffix not in allowed_extensions: # skip - return + return 0 # print("Parse %s" % file) try: with file.open("r", encoding="UTF-8", newline="") as rfp: parsing_comment = False - for l in rfp: - l = l.strip() + for line_i, original_line in enumerate(rfp, start=1): + line = original_line.strip() + + line_comment = "" # Get the comment block /* ... */ across several lines - match_start = "/*" in l - match_end = "*/" in l - if match_start and match_end: - continue - if match_start: - parsing_comment = True - continue - if match_end: - parsing_comment = False - continue + while True: + if parsing_comment: + pos_end_comment = line.find("*/") + if pos_end_comment >= 0: + line = line[pos_end_comment+2:] + parsing_comment = False + else: + break + else: + pos_start_comment = line.find("/*") + if pos_start_comment >= 0: + pos_end_comment = line.find("*/", pos_start_comment+2) + if pos_end_comment >= 0: + line_comment += line[pos_start_comment:pos_end_comment+2] + line = line[:pos_start_comment] + line[pos_end_comment+2:] + else: + line_comment += line[pos_start_comment:] + line = line[:pos_start_comment] + parsing_comment = True + break + else: + break if parsing_comment: continue + pos_line_comment = line.find("//") + if pos_line_comment >= 0: + line_comment += line[pos_line_comment:] + line = line[:pos_line_comment] - if regex.match(l): - - # free() allowed here - if "This should NOT be SDL_" in l: - continue - - # double check - # Remove one line comment /* ... */ - # eg: extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */); - l = reg_comment_remove_content.sub('', l) - - # Remove strings " ... " - l = reg_comment_remove_content2.sub('', l) - - # :strlen - l = reg_comment_remove_content3.sub('', l) - - # ->free - l = reg_comment_remove_content4.sub('', l) - - if regex.match(l): - print("File %s" % filename) - print(" %s" % l) - print("") + if m := RE_STDLIB_SYMBOL.match(line): + override_string = f"This should NOT be SDL_{m['symbol']}()" + if override_string not in line_comment: + print(f"{filename}:{line_i}") + print(f" {line}") + print(f"") + match_count += 1 except UnicodeDecodeError: - print("%s is not text, skipping" % file) - except Exception as err: - print("%s" % err) + print(f"{file} is not text, skipping", file=sys.stderr) -def find_symbols_in_dir(path, regex): + return match_count +def find_symbols_in_dir(path: pathlib.Path) -> int: + match_count = 0 for entry in path.glob("*"): if entry.is_dir(): - find_symbols_in_dir(entry, regex) + match_count += find_symbols_in_dir(entry) else: - find_symbols_in_file(entry, regex) + match_count += find_symbols_in_file(entry) + return match_count def main(): - str = ".*\\b(" - for w in words: - str += w + "|" - str = str[:-1] - str += ")\(" - regex = re.compile(str) - find_symbols_in_dir(SDL_ROOT, regex) - -if __name__ == "__main__": - - parser = argparse.ArgumentParser(fromfile_prefix_chars='@') + parser = argparse.ArgumentParser(fromfile_prefix_chars="@") + parser.add_argument("path", default=SDL_ROOT, nargs="?", type=pathlib.Path, help="Path to look for stdlib symbols") args = parser.parse_args() - try: - main() - except Exception as e: - print(e) - exit(-1) + print(f"Looking for stdlib usage in {args.path}...") - exit(0) + match_count = find_symbols_in_dir(args.path) + if match_count: + print("If the stdlib usage is intentional, add a '// This should NOT be SDL_()' line comment.") + print("") + print("NOT OK") + else: + print("OK") + return 1 if match_count else 0 +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/libs/SDL3/build-scripts/clang-format-src.sh b/libs/SDL3/build-scripts/clang-format-src.sh index c4af9a591..bc0defc7c 100644 --- a/libs/SDL3/build-scripts/clang-format-src.sh +++ b/libs/SDL3/build-scripts/clang-format-src.sh @@ -18,15 +18,22 @@ git checkout \ stdlib/SDL_malloc.c \ stdlib/SDL_qsort.c \ stdlib/SDL_strtokr.c \ - video/arm \ video/khronos \ + video/x11/edid.h \ video/x11/edid-parse.c \ + video/x11/xsettings-client.* \ video/yuv2rgb clang-format -i hidapi/SDL_hidapi.c # Revert generated code -git checkout dynapi/SDL_dynapi_overrides.h -git checkout dynapi/SDL_dynapi_procs.h -git checkout render/metal/SDL_shaders_metal_*.h +git checkout \ + dynapi/SDL_dynapi_overrides.h \ + dynapi/SDL_dynapi_procs.h \ + render/*/*Shader*.h \ + render/metal/SDL_shaders_metal_*.h \ + render/vitagxm/SDL_render_vita_gxm_shaders.h \ + video/directx/SDL_d3d12_xbox_cmacros.h \ + video/directx/d3d12.h \ + video/directx/d3d12sdklayers.h \ echo "clang-format complete!" diff --git a/libs/SDL3/build-scripts/create-android-project.py b/libs/SDL3/build-scripts/create-android-project.py new file mode 100644 index 000000000..76ad853d2 --- /dev/null +++ b/libs/SDL3/build-scripts/create-android-project.py @@ -0,0 +1,238 @@ +#!/usr/bin/env python3 +import os +from argparse import ArgumentParser +from pathlib import Path +import re +import shutil +import sys +import textwrap + + +SDL_ROOT = Path(__file__).resolve().parents[1] + +def extract_sdl_version() -> str: + """ + Extract SDL version from SDL3/SDL_version.h + """ + + with open(SDL_ROOT / "include/SDL3/SDL_version.h") as f: + data = f.read() + + major = int(next(re.finditer(r"#define\s+SDL_MAJOR_VERSION\s+([0-9]+)", data)).group(1)) + minor = int(next(re.finditer(r"#define\s+SDL_MINOR_VERSION\s+([0-9]+)", data)).group(1)) + micro = int(next(re.finditer(r"#define\s+SDL_MICRO_VERSION\s+([0-9]+)", data)).group(1)) + return f"{major}.{minor}.{micro}" + +def replace_in_file(path: Path, regex_what: str, replace_with: str) -> None: + with path.open("r") as f: + data = f.read() + + new_data, count = re.subn(regex_what, replace_with, data) + + assert count > 0, f"\"{regex_what}\" did not match anything in \"{path}\"" + + with open(path, "w") as f: + f.write(new_data) + + +def android_mk_use_prefab(path: Path) -> None: + """ + Replace relative SDL inclusion with dependency on prefab package + """ + + with path.open() as f: + data = "".join(line for line in f.readlines() if "# SDL" not in line) + + data, _ = re.subn("[\n]{3,}", "\n\n", data) + + newdata = data + textwrap.dedent(""" + # https://google.github.io/prefab/build-systems.html + + # Add the prefab modules to the import path. + $(call import-add-path,/out) + + # Import SDL3 so we can depend on it. + $(call import-module,prefab/SDL3) + """) + + with path.open("w") as f: + f.write(newdata) + + +def cmake_mk_no_sdl(path: Path) -> None: + """ + Don't add the source directories of SDL/SDL_image/SDL_mixer/... + """ + + with path.open() as f: + lines = f.readlines() + + newlines: list[str] = [] + for line in lines: + if "add_subdirectory(SDL" in line: + while newlines[-1].startswith("#"): + newlines = newlines[:-1] + continue + newlines.append(line) + + newdata, _ = re.subn("[\n]{3,}", "\n\n", "".join(newlines)) + + with path.open("w") as f: + f.write(newdata) + + +def gradle_add_prefab_and_aar(path: Path, aar: str) -> None: + with path.open() as f: + data = f.read() + + data, count = re.subn("android {", textwrap.dedent(""" + android { + buildFeatures { + prefab true + }"""), data) + assert count == 1 + + data, count = re.subn("dependencies {", textwrap.dedent(f""" + dependencies {{ + implementation files('libs/{aar}')"""), data) + assert count == 1 + + with path.open("w") as f: + f.write(data) + + +def gradle_add_package_name(path: Path, package_name: str) -> None: + with path.open() as f: + data = f.read() + + data, count = re.subn("org.libsdl.app", package_name, data) + assert count >= 1 + + with path.open("w") as f: + f.write(data) + + +def main() -> int: + description = "Create a simple Android gradle project from input sources." + epilog = textwrap.dedent("""\ + You need to manually copy a prebuilt SDL3 Android archive into the project tree when using the aar variant. + + Any changes you have done to the sources in the Android project will be lost + """) + parser = ArgumentParser(description=description, epilog=epilog, allow_abbrev=False) + parser.add_argument("package_name", metavar="PACKAGENAME", help="Android package name (e.g. com.yourcompany.yourapp)") + parser.add_argument("sources", metavar="SOURCE", nargs="*", help="Source code of your application. The files are copied to the output directory.") + parser.add_argument("--variant", choices=["copy", "symlink", "aar"], default="copy", help="Choose variant of SDL project (copy: copy SDL sources, symlink: symlink SDL sources, aar: use Android aar archive)") + parser.add_argument("--output", "-o", default=SDL_ROOT / "build", type=Path, help="Location where to store the Android project") + parser.add_argument("--version", default=None, help="SDL3 version to use as aar dependency (only used for aar variant)") + + args = parser.parse_args() + if not args.sources: + print("Reading source file paths from stdin (press CTRL+D to stop)") + args.sources = [path for path in sys.stdin.read().strip().split() if path] + if not args.sources: + parser.error("No sources passed") + + if not os.getenv("ANDROID_HOME"): + print("WARNING: ANDROID_HOME environment variable not set", file=sys.stderr) + if not os.getenv("ANDROID_NDK_HOME"): + print("WARNING: ANDROID_NDK_HOME environment variable not set", file=sys.stderr) + + args.sources = [Path(src) for src in args.sources] + + build_path = args.output / args.package_name + + # Remove the destination folder + shutil.rmtree(build_path, ignore_errors=True) + + # Copy the Android project + shutil.copytree(SDL_ROOT / "android-project", build_path) + + # Add the source files to the ndk-build and cmake projects + replace_in_file(build_path / "app/jni/src/Android.mk", r"YourSourceHere\.c", " \\\n ".join(src.name for src in args.sources)) + replace_in_file(build_path / "app/jni/src/CMakeLists.txt", r"YourSourceHere\.c", "\n ".join(src.name for src in args.sources)) + + # Remove placeholder source "YourSourceHere.c" + (build_path / "app/jni/src/YourSourceHere.c").unlink() + + # Copy sources to output folder + for src in args.sources: + if not src.is_file(): + parser.error(f"\"{src}\" is not a file") + shutil.copyfile(src, build_path / "app/jni/src" / src.name) + + sdl_project_files = ( + SDL_ROOT / "src", + SDL_ROOT / "include", + SDL_ROOT / "LICENSE.txt", + SDL_ROOT / "README.md", + SDL_ROOT / "Android.mk", + SDL_ROOT / "CMakeLists.txt", + SDL_ROOT / "cmake", + ) + if args.variant == "copy": + (build_path / "app/jni/SDL").mkdir(exist_ok=True, parents=True) + for sdl_project_file in sdl_project_files: + # Copy SDL project files and directories + if sdl_project_file.is_dir(): + shutil.copytree(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) + elif sdl_project_file.is_file(): + shutil.copyfile(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) + elif args.variant == "symlink": + (build_path / "app/jni/SDL").mkdir(exist_ok=True, parents=True) + # Create symbolic links for all SDL project files + for sdl_project_file in sdl_project_files: + os.symlink(sdl_project_file, build_path / "app/jni/SDL" / sdl_project_file.name) + elif args.variant == "aar": + if not args.version: + args.version = extract_sdl_version() + + major = args.version.split(".")[0] + aar = f"SDL{ major }-{ args.version }.aar" + + # Remove all SDL java classes + shutil.rmtree(build_path / "app/src/main/java") + + # Use prefab to generate include-able files + gradle_add_prefab_and_aar(build_path / "app/build.gradle", aar=aar) + + # Make sure to use the prefab-generated files and not SDL sources + android_mk_use_prefab(build_path / "app/jni/src/Android.mk") + cmake_mk_no_sdl(build_path / "app/jni/CMakeLists.txt") + + aar_libs_folder = build_path / "app/libs" + aar_libs_folder.mkdir(parents=True) + with (aar_libs_folder / "copy-sdl-aars-here.txt").open("w") as f: + f.write(f"Copy {aar} to this folder.\n") + + print(f"WARNING: copy { aar } to { aar_libs_folder }", file=sys.stderr) + + # Add the package name to build.gradle + gradle_add_package_name(build_path / "app/build.gradle", args.package_name) + + # Create entry activity, subclassing SDLActivity + activity = args.package_name[args.package_name.rfind(".") + 1:].capitalize() + "Activity" + activity_path = build_path / "app/src/main/java" / args.package_name.replace(".", "/") / f"{activity}.java" + activity_path.parent.mkdir(parents=True) + with activity_path.open("w") as f: + f.write(textwrap.dedent(f""" + package {args.package_name}; + + import org.libsdl.app.SDLActivity; + + public class {activity} extends SDLActivity + {{ + }} + """)) + + # Add the just-generated activity to the Android manifest + replace_in_file(build_path / "app/src/main/AndroidManifest.xml", 'name="SDLActivity"', f'name="{activity}"') + + # Update project and build + print("To build and install to a device for testing, run the following:") + print(f"cd {build_path}") + print("./gradlew installDebug") + return 0 + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/libs/SDL3/build-scripts/fnsince.pl b/libs/SDL3/build-scripts/fnsince.pl index 9e95886db..684f4cc80 100644 --- a/libs/SDL3/build-scripts/fnsince.pl +++ b/libs/SDL3/build-scripts/fnsince.pl @@ -88,11 +88,6 @@ close(PIPEFH); } -# these are incorrect in the dynapi header, because we forgot to add them -# until a later release, but are available in the older release. -$funcs{'SDL_WinRTGetFSPathUNICODE'} = '2.0.3'; -$funcs{'SDL_WinRTGetFSPathUTF8'} = '2.0.3'; - if (not defined $wikipath) { foreach my $release (@releases) { foreach my $fn (sort keys %funcs) { @@ -105,7 +100,7 @@ foreach my $fn (keys %funcs) { my $revision = $funcs{$fn}; $revision = $next_release if $revision eq 'HEAD'; - my $fname = "$fn.mediawiki"; + my $fname = "$fn.md"; if ( ! -f $fname ) { #print STDERR "No such file: $fname\n"; next; @@ -117,21 +112,21 @@ while () { chomp; if ((/\A\-\-\-\-/) && (!$added)) { - push @lines, "== Version =="; + push @lines, "## Version"; push @lines, ""; push @lines, "This function is available since SDL $revision."; push @lines, ""; $added = 1; } push @lines, $_; - next if not /\A\=\=\s+Version\s+\=\=/; + next if not /\A\#\#\s+Version/; $added = 1; push @lines, ""; push @lines, "This function is available since SDL $revision."; push @lines, ""; while () { chomp; - next if not (/\A\=\=\s+/ || /\A\-\-\-\-/); + next if not (/\A\#\#\s+/ || /\A\-\-\-\-/); push @lines, $_; last; } @@ -139,7 +134,7 @@ close(FH); if (!$added) { - push @lines, "== Version =="; + push @lines, "## Version"; push @lines, ""; push @lines, "This function is available since SDL $revision."; push @lines, ""; diff --git a/libs/SDL3/build-scripts/gen_audio_resampler_filter.c b/libs/SDL3/build-scripts/gen_audio_resampler_filter.c deleted file mode 100644 index c115484a9..000000000 --- a/libs/SDL3/build-scripts/gen_audio_resampler_filter.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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. -*/ - -/* - -Built with: - -gcc -o genfilter build-scripts/gen_audio_resampler_filter.c -lm && ./genfilter > src/audio/SDL_audio_resampler_filter.h - -*/ - -/* - SDL's resampler uses a "bandlimited interpolation" algorithm: - https://ccrma.stanford.edu/~jos/resample/ - - This code pre-generates the kaiser tables so we don't have to do this at - run time, at a cost of about 20 kilobytes of static data in SDL. This code - used to be part of SDL itself and generated the tables on the first use, - but that was expensive to produce on platforms without floating point - hardware. -*/ - -#include -#include - -#ifndef M_PI - #define M_PI 3.14159265358979323846 -#endif - -#define RESAMPLER_ZERO_CROSSINGS 5 -#define RESAMPLER_BITS_PER_SAMPLE 16 -#define RESAMPLER_BITS_PER_ZERO_CROSSING ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1) -#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << RESAMPLER_BITS_PER_ZERO_CROSSING) -#define RESAMPLER_FILTER_SIZE (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) - -/* This is a "modified" bessel function, so you can't use POSIX j0() */ -static double -bessel(const double x) -{ - const double xdiv2 = x / 2.0; - double i0 = 1.0; - double f = 1.0; - int i = 1; - - while (1) { - const double diff = pow(xdiv2, i * 2) / pow(f, 2); - if (diff < 1.0e-21) { - break; - } - i0 += diff; - i++; - f *= (double) i; - } - - return i0; -} - -/* build kaiser table with cardinal sine applied to it, and array of differences between elements. */ -static void -kaiser_and_sinc(double *table, const int tablelen, const double beta) -{ - const double bessel_beta = bessel(beta); - int i; - - table[0] = 1.0; - - for (i = 1; i < tablelen; i++) { - const double kaiser = bessel(beta * sqrt(1.0 - pow((double)i / (double)(tablelen), 2.0))) / bessel_beta; - const double x = (((double) i) / ((double) RESAMPLER_SAMPLES_PER_ZERO_CROSSING)) * M_PI; - table[i] = kaiser * (sin(x) / x); - } -} - -static double ResamplerFilter[RESAMPLER_FILTER_SIZE]; - -static void -PrepareResampleFilter(void) -{ - /* if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. */ - const double dB = 80.0; - const double beta = 0.1102 * (dB - 8.7); - kaiser_and_sinc(ResamplerFilter, RESAMPLER_FILTER_SIZE, beta); -} - -int main(void) -{ - int i, j; - - PrepareResampleFilter(); - - printf( - "/*\n" - " Simple DirectMedia Layer\n" - " Copyright (C) 1997-2024 Sam Lantinga \n" - "\n" - " This software is provided 'as-is', without any express or implied\n" - " warranty. In no event will the authors be held liable for any damages\n" - " arising from the use of this software.\n" - "\n" - " Permission is granted to anyone to use this software for any purpose,\n" - " including commercial applications, and to alter it and redistribute it\n" - " freely, subject to the following restrictions:\n" - "\n" - " 1. The origin of this software must not be misrepresented; you must not\n" - " claim that you wrote the original software. If you use this software\n" - " in a product, an acknowledgment in the product documentation would be\n" - " appreciated but is not required.\n" - " 2. Altered source versions must be plainly marked as such, and must not be\n" - " misrepresented as being the original software.\n" - " 3. This notice may not be removed or altered from any source distribution.\n" - "*/\n" - "\n" - "// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c\n" - "\n" - "#define RESAMPLER_ZERO_CROSSINGS %d\n" - "#define RESAMPLER_BITS_PER_SAMPLE %d\n" - "#define RESAMPLER_BITS_PER_ZERO_CROSSING ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1)\n" - "#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << RESAMPLER_BITS_PER_ZERO_CROSSING)\n" - "#define RESAMPLER_FILTER_SIZE (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS)\n" - "\n", RESAMPLER_ZERO_CROSSINGS, RESAMPLER_BITS_PER_SAMPLE - ); - - printf("static const float ResamplerFilter[RESAMPLER_FILTER_SIZE] = {"); - for (i = 0; i < RESAMPLER_FILTER_SIZE; i++) { - j = (i % RESAMPLER_ZERO_CROSSINGS) * RESAMPLER_SAMPLES_PER_ZERO_CROSSING + (i / RESAMPLER_ZERO_CROSSINGS); - printf("%s%12.9ff,", (i % RESAMPLER_ZERO_CROSSINGS) ? "" : "\n ", ResamplerFilter[j]); - } - printf("\n};\n\n"); - - return 0; -} diff --git a/libs/SDL3/build-scripts/pkg-support/android/INSTALL.md.in b/libs/SDL3/build-scripts/pkg-support/android/INSTALL.md.in new file mode 100644 index 000000000..7c06ddb1e --- /dev/null +++ b/libs/SDL3/build-scripts/pkg-support/android/INSTALL.md.in @@ -0,0 +1,58 @@ + +This Android archive allows use of @PROJECT_NAME@ in your Android project, without needing to copy any SDL source. +For integration with CMake/ndk-build, it uses [prefab](https://google.github.io/prefab/). + +Copy this archive (@PROJECT_NAME@-@PROJECT_VERSION@.aar) to a `app/libs` directory of your project. + +In `app/build.gradle` of your Android project, add: +``` +android { + /* ... */ + buildFeatures { + prefab true + } +} +dependencies { + implementation files('libs/@PROJECT_NAME@-@PROJECT_VERSION@.aar') + /* ... */ +} +``` + +If you're using CMake, add the following to your CMakeLists.txt: +``` +find_package(@PROJECT_NAME@ REQUIRED CONFIG) +target_link_libraries(yourgame PRIVATE @PROJECT_NAME@::@PROJECT_NAME@) +``` + +If you're using ndk-build, add the following somewhere after `LOCAL_MODULE := yourgame` to your `Android.mk` or `Application.mk`: +``` +# https://google.github.io/prefab/build-systems.html + +# Add the prefab modules to the import path. +$(call import-add-path,/out) + +# Import @PROJECT_NAME@ so we can depend on it. +$(call import-module,prefab/@PROJECT_NAME@) +``` + +--- + +For advanced users: + +If you want to build a 3rd party library outside Gradle, +running the following command will extract the Android archive into a more common directory structure. +``` +python @PROJECT_NAME@-@PROJECT_VERSION@.aar -o android_prefix +``` +Add `--help` for a list of all available options. + + +Look at the example programs in ./test (of the source archive), and check out online documentation: + https://wiki.libsdl.org/SDL3/FrontPage + +Join the SDL discourse server if you want to join the community: + https://discourse.libsdl.org/ + + +That's it! +Sam Lantinga diff --git a/libs/SDL3/build-scripts/pkg-support/android/__main__.py.in b/libs/SDL3/build-scripts/pkg-support/android/__main__.py.in new file mode 100644 index 000000000..c40ac0112 --- /dev/null +++ b/libs/SDL3/build-scripts/pkg-support/android/__main__.py.in @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +""" +Create a @PROJECT_NAME@ SDK prefix from an Android archive +This file is meant to be placed in a the root of an android .aar archive + +Example usage: +```sh +python @PROJECT_NAME@-@PROJECT_VERSION@.aar -o /usr/opt/android-sdks +cmake -S my-project \ + -DCMAKE_PREFIX_PATH=/usr/opt/android-sdks \ + -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ + -B build-arm64 -DANDROID_ABI=arm64-v8a \ + -DCMAKE_BUILD_TYPE=Releaase +cmake --build build-arm64 +``` +""" +import argparse +import io +import json +import os +import pathlib +import re +import stat +import zipfile + + +AAR_PATH = pathlib.Path(__file__).resolve().parent +ANDROID_ARCHS = { "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } + + +def main(): + parser = argparse.ArgumentParser( + description="Convert a @PROJECT_NAME@ Android .aar archive into a SDK", + allow_abbrev=False, + ) + parser.add_argument("-o", dest="output", type=pathlib.Path, required=True, help="Folder where to store the SDK") + args = parser.parse_args() + + print(f"Creating a @PROJECT_NAME@ SDK at {args.output}...") + + prefix = args.output + incdir = prefix / "include" + libdir = prefix / "lib" + + RE_LIB_MODULE_ARCH = re.compile(r"prefab/modules/(?P[A-Za-z0-9_-]+)/libs/android\.(?P[a-zA-Z0-9_-]+)/(?Plib[A-Za-z0-9_]+\.(?:so|a))") + RE_INC_MODULE_ARCH = re.compile(r"prefab/modules/(?P[A-Za-z0-9_-]+)/include/(?P
[a-zA-Z0-9_./-]+)") + RE_LICENSE = re.compile(r"(?:.*/)?(?P(?:license|copying)(?:\.md|\.txt)?)", flags=re.I) + RE_PROGUARD = re.compile(r"(?:.*/)?(?Pproguard.*\.(?:pro|txt))", flags=re.I) + RE_CMAKE = re.compile(r"(?:.*/)?(?P.*\.cmake)", flags=re.I) + + with zipfile.ZipFile(AAR_PATH) as zf: + project_description = json.loads(zf.read("description.json")) + project_name = project_description["name"] + project_version = project_description["version"] + licensedir = prefix / "share/licenses" / project_name + cmakedir = libdir / "cmake" / project_name + javadir = prefix / "share/java" / project_name + javadocdir = prefix / "share/javadoc" / project_name + + def read_zipfile_and_write(path: pathlib.Path, zippath: str): + data = zf.read(zippath) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(data) + + for zip_info in zf.infolist(): + zippath = zip_info.filename + if m := RE_LIB_MODULE_ARCH.match(zippath): + lib_path = libdir / m["arch"] / m["filename"] + read_zipfile_and_write(lib_path, zippath) + if m["filename"].endswith(".so"): + os.chmod(lib_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + + elif m := RE_INC_MODULE_ARCH.match(zippath): + header_path = incdir / m["header"] + read_zipfile_and_write(header_path, zippath) + elif m:= RE_LICENSE.match(zippath): + license_path = licensedir / m["filename"] + read_zipfile_and_write(license_path, zippath) + elif m:= RE_PROGUARD.match(zippath): + proguard_path = javadir / m["filename"] + read_zipfile_and_write(proguard_path, zippath) + elif m:= RE_CMAKE.match(zippath): + cmake_path = cmakedir / m["filename"] + read_zipfile_and_write(cmake_path, zippath) + elif zippath == "classes.jar": + versioned_jar_path = javadir / f"{project_name}-{project_version}.jar" + unversioned_jar_path = javadir / f"{project_name}.jar" + read_zipfile_and_write(versioned_jar_path, zippath) + os.symlink(src=versioned_jar_path.name, dst=unversioned_jar_path) + elif zippath == "classes-sources.jar": + jarpath = javadir / f"{project_name}-{project_version}-sources.jar" + read_zipfile_and_write(jarpath, zippath) + elif zippath == "classes-doc.jar": + data = zf.read(zippath) + with zipfile.ZipFile(io.BytesIO(data)) as doc_zf: + doc_zf.extractall(javadocdir) + + print("... done") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/libs/SDL3/build-scripts/pkg-support/android/cmake/SDL3Config.cmake b/libs/SDL3/build-scripts/pkg-support/android/cmake/SDL3Config.cmake new file mode 100644 index 000000000..a41275dc4 --- /dev/null +++ b/libs/SDL3/build-scripts/pkg-support/android/cmake/SDL3Config.cmake @@ -0,0 +1,148 @@ +# SDL CMake configuration file: +# This file is meant to be placed in lib/cmake/SDL3 subfolder of a reconstructed Android SDL3 SDK + +cmake_minimum_required(VERSION 3.0...3.5) + +include(FeatureSummary) +set_package_properties(SDL3 PROPERTIES + URL "https://www.libsdl.org/" + DESCRIPTION "low level access to audio, keyboard, mouse, joystick, and graphics hardware" +) + +# Copied from `configure_package_config_file` +macro(set_and_check _var _file) + set(${_var} "${_file}") + if(NOT EXISTS "${_file}") + message(FATAL_ERROR "File or directory ${_file} referenced by variable ${_var} does not exist !") + endif() +endmacro() + +# Copied from `configure_package_config_file` +macro(check_required_components _NAME) + foreach(comp ${${_NAME}_FIND_COMPONENTS}) + if(NOT ${_NAME}_${comp}_FOUND) + if(${_NAME}_FIND_REQUIRED_${comp}) + set(${_NAME}_FOUND FALSE) + endif() + endif() + endforeach() +endmacro() + +set(SDL3_FOUND TRUE) + +if(SDL_CPU_X86) + set(_sdl_arch_subdir "x86") +elseif(SDL_CPU_X64) + set(_sdl_arch_subdir "x86_64") +elseif(SDL_CPU_ARM32) + set(_sdl_arch_subdir "armeabi-v7a") +elseif(SDL_CPU_ARM64) + set(_sdl_arch_subdir "arm64-v8a") +else() + set(SDL3_FOUND FALSE) + return() +endif() + +get_filename_component(_sdl3_prefix "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE) +get_filename_component(_sdl3_prefix "${_sdl3_prefix}/.." ABSOLUTE) +get_filename_component(_sdl3_prefix "${_sdl3_prefix}/.." ABSOLUTE) +set_and_check(_sdl3_prefix "${_sdl3_prefix}") +set_and_check(_sdl3_include_dirs "${_sdl3_prefix}/include") + +set_and_check(_sdl3_lib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/libSDL3.so") +set_and_check(_sdl3test_lib "${_sdl3_prefix}/lib/${_sdl_arch_subdir}/libSDL3_test.a") +set_and_check(_sdl3_jar "${_sdl3_prefix}/share/java/SDL3/SDL3-${SDL3_VERSION}.jar") + +unset(_sdl_arch_subdir) +unset(_sdl3_prefix) + +# All targets are created, even when some might not be requested though COMPONENTS. +# This is done for compatibility with CMake generated SDL3-target.cmake files. + +if(NOT TARGET SDL3::Headers) + add_library(SDL3::Headers INTERFACE IMPORTED) + set_target_properties(SDL3::Headers + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_sdl3_include_dirs}" + ) +endif() +set(SDL3_Headers_FOUND TRUE) +unset(_sdl3_include_dirs) + +if(EXISTS "${_sdl3_lib}") + if(NOT TARGET SDL3::SDL3-shared) + add_library(SDL3::SDL3-shared SHARED IMPORTED) + set_target_properties(SDL3::SDL3-shared + PROPERTIES + INTERFACE_LINK_LIBRARIES "SDL3::Headers" + IMPORTED_LOCATION "${_sdl3_lib}" + COMPATIBLE_INTERFACE_BOOL "SDL3_SHARED" + INTERFACE_SDL3_SHARED "ON" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) + endif() + set(SDL3_SDL3-shared_FOUND TRUE) +else() + set(SDL3_SDL3-shared_FOUND FALSE) +endif() +unset(_sdl3_lib) + +set(SDL3_SDL3-static_FOUND FALSE) + +if(EXISTS "${_sdl3test_lib}") + if(NOT TARGET SDL3::SDL3_test) + add_library(SDL3::SDL3_test STATIC IMPORTED) + set_target_properties(SDL3::SDL3_test + PROPERTIES + INTERFACE_LINK_LIBRARIES "SDL3::Headers" + IMPORTED_LOCATION "${_sdl3test_lib}" + COMPATIBLE_INTERFACE_STRING "SDL_VERSION" + INTERFACE_SDL_VERSION "SDL3" + ) + endif() + set(SDL3_SDL3_test_FOUND TRUE) +else() + set(SDL3_SDL3_test_FOUND FALSE) +endif() +unset(_sdl3test_lib) + +if(SDL3_SDL3-shared_FOUND) + set(SDL3_SDL3_FOUND TRUE) +endif() + +function(_sdl_create_target_alias_compat NEW_TARGET TARGET) + if(CMAKE_VERSION VERSION_LESS "3.18") + # Aliasing local targets is not supported on CMake < 3.18, so make it global. + add_library(${NEW_TARGET} INTERFACE IMPORTED) + set_target_properties(${NEW_TARGET} PROPERTIES INTERFACE_LINK_LIBRARIES "${TARGET}") + else() + add_library(${NEW_TARGET} ALIAS ${TARGET}) + endif() +endfunction() + +# Make sure SDL3::SDL3 always exists +if(NOT TARGET SDL3::SDL3) + if(TARGET SDL3::SDL3-shared) + _sdl_create_target_alias_compat(SDL3::SDL3 SDL3::SDL3-shared) + endif() +endif() + +if(EXISTS "${_sdl3_jar}") + if(NOT TARGET SDL3::Jar) + add_library(SDL3::Jar INTERFACE IMPORTED) + set_property(TARGET SDL3::Jar PROPERTY JAR_FILE "${_sdl3_jar}") + endif() + set(SDL3_Jar_FOUND TRUE) +else() + set(SDL3_Jar_FOUND FALSE) +endif() +unset(_sdl3_jar) + +check_required_components(SDL3) + +set(SDL3_LIBRARIES SDL3::SDL3) +set(SDL3_STATIC_LIBRARIES SDL3::SDL3-static) +set(SDL3_STATIC_PRIVATE_LIBS) + +set(SDL3TEST_LIBRARY SDL3::SDL3_test) diff --git a/libs/SDL3/build-scripts/pkg-support/mingw/INSTALL.txt b/libs/SDL3/build-scripts/pkg-support/mingw/INSTALL.txt new file mode 100644 index 000000000..41025e073 --- /dev/null +++ b/libs/SDL3/build-scripts/pkg-support/mingw/INSTALL.txt @@ -0,0 +1,25 @@ + +The 32-bit files are in i686-w64-mingw32 +The 64-bit files are in x86_64-w64-mingw32 + +To install SDL for 32-bit x86 executables (i686): + make install-i686 + +To install SDL for 64-bit x86 executables (x86_64): + make install-x86_64 + +To install both: + make install-all + +Use DESTDIR to change the target location + mkdir $HOME/mingw32-prefix + make install-i686 DESTDIR=$HOME/mingw32-prefix + +Look at the example programs in ./test, and check out online documentation: + https://wiki.libsdl.org/SDL3/FrontPage + +Join the SDL discourse server if you want to join the community: + https://discourse.libsdl.org/ + +That's it! +Sam Lantinga diff --git a/libs/SDL3/build-scripts/pkg-support/mingw/Makefile b/libs/SDL3/build-scripts/pkg-support/mingw/Makefile new file mode 100644 index 000000000..ff8d01f81 --- /dev/null +++ b/libs/SDL3/build-scripts/pkg-support/mingw/Makefile @@ -0,0 +1,37 @@ +# +# Makefile for installing the mingw32 version of the SDL library + +DESTDIR = /usr/local +ARCHITECTURES := i686-w64-mingw32 x86_64-w64-mingw32 + +default: + @echo "Run \"make install-i686\" to install 32-bit" + @echo "Run \"make install-x86_64\" to install 64-bit" + @echo "Run \"make install-all\" to install both" + @echo "Add DESTDIR=/custom/path to change the destination folder" + +install: + @if test -d $(ARCH) && test -d $(DESTDIR); then \ + (cd $(ARCH) && cp -rv bin include lib share $(DESTDIR)/); \ + else \ + echo "*** ERROR: $(ARCH) or $(DESTDIR) does not exist!"; \ + exit 1; \ + fi + +install-i686: + $(MAKE) install ARCH=i686-w64-mingw32 + +install-x86_64: + $(MAKE) install ARCH=x86_64-w64-mingw32 + +install-all: + @if test -d $(DESTDIR); then \ + for arch in $(ARCHITECTURES); do \ + $(MAKE) install ARCH=$$arch DESTDIR=$(DESTDIR)/$$arch; \ + done \ + else \ + echo "*** ERROR: $(DESTDIR) does not exist!"; \ + exit 1; \ + fi + +.PHONY: default install install-i686 install-x86_64 install-all diff --git a/libs/SDL3/mingw/pkg-support/cmake/sdl3-config.cmake b/libs/SDL3/build-scripts/pkg-support/mingw/cmake/SDL3Config.cmake similarity index 100% rename from libs/SDL3/mingw/pkg-support/cmake/sdl3-config.cmake rename to libs/SDL3/build-scripts/pkg-support/mingw/cmake/SDL3Config.cmake diff --git a/libs/SDL3/build-scripts/rename_api.py b/libs/SDL3/build-scripts/rename_api.py index 7c02b9e94..605ffa0f3 100644 --- a/libs/SDL3/build-scripts/rename_api.py +++ b/libs/SDL3/build-scripts/rename_api.py @@ -24,7 +24,7 @@ def main(): # Check whether we can still modify the ABI version_header = pathlib.Path( SDL_INCLUDE_DIR / "SDL_version.h" ).read_text() - if not re.search("SDL_MINOR_VERSION\s+[01]\s", version_header): + if not re.search(r"SDL_MINOR_VERSION\s+[01]\s", version_header): raise Exception("ABI is frozen, symbols cannot be renamed") # Find the symbol in the headers @@ -57,7 +57,7 @@ def main(): i += 2 regex = create_regex_from_replacements(replacements) - for dir in ["src", "test", "include", "docs", "cmake/test"]: + for dir in ["src", "test", "examples", "include", "docs", "cmake/test"]: replace_symbols_in_path(SDL_ROOT / dir, regex, replacements) # Replace the symbols in documentation @@ -239,8 +239,8 @@ def add_symbol_to_migration(header, symbol_type, oldname, newname): parser = argparse.ArgumentParser(fromfile_prefix_chars='@') parser.add_argument("--skip-header-check", action="store_true") - parser.add_argument("header"); - parser.add_argument("type", choices=["enum", "function", "hint", "structure", "symbol"]); + parser.add_argument("header") + parser.add_argument("type", choices=["enum", "function", "hint", "structure", "symbol"]) parser.add_argument("args", nargs="*") args = parser.parse_args() diff --git a/libs/SDL3/build-scripts/rename_macros.py b/libs/SDL3/build-scripts/rename_macros.py index 913b10e5f..ba386cd41 100644 --- a/libs/SDL3/build-scripts/rename_macros.py +++ b/libs/SDL3/build-scripts/rename_macros.py @@ -129,7 +129,6 @@ def main(): "__VITA__": "SDL_PLATFORM_VITA", "__3DS__": "SDL_PLATFORM_3DS", # "__unix__": "SDL_PLATFORM_UNIX, - "__WINRT__": "SDL_PLATFORM_WINRT", "__XBOXSERIES__": "SDL_PLATFORM_XBOXSERIES", "__XBOXONE__": "SDL_PLATFORM_XBOXONE", "__WINDOWS__": "SDL_PLATFORM_WINDOWS", @@ -145,6 +144,7 @@ def main(): "__NACL__", "__PNACL__", "__WINDOWS__", + "__WINRT__", "SDL_ALTIVEC_BLITTERS", "SDL_ARM_NEON_BLITTERS", "SDL_ARM_SIMD_BLITTERS", diff --git a/libs/SDL3/build-scripts/rename_types.py b/libs/SDL3/build-scripts/rename_types.py new file mode 100644 index 000000000..137b40960 --- /dev/null +++ b/libs/SDL3/build-scripts/rename_types.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# +# This script renames symbols in the specified paths + +import argparse +import os +import pathlib +import re +import sys + + +def main(): + if len(args.args) < 1: + print("Usage: %s files_or_directories ..." % sys.argv[0]) + exit(1) + + replacements = { + "SDL_bool": "bool", + "SDL_TRUE": "true", + "SDL_FALSE": "false", + } + entries = args.args[0:] + + regex = create_regex_from_replacements(replacements) + + for entry in entries: + path = pathlib.Path(entry) + if not path.exists(): + print("%s doesn't exist, skipping" % entry) + continue + + replace_symbols_in_path(path, regex, replacements) + +def create_regex_from_replacements(replacements): + return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys()))) + +def replace_symbols_in_file(file, regex, replacements): + try: + with file.open("r", encoding="UTF-8", newline="") as rfp: + original = rfp.read() + contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], original) + if contents != original: + with file.open("w", encoding="UTF-8", newline="") as wfp: + wfp.write(contents) + except UnicodeDecodeError: + print("%s is not text, skipping" % file) + except Exception as err: + print("%s" % err) + + +def replace_symbols_in_dir(path, regex, replacements): + for entry in path.glob("*"): + if entry.is_dir(): + replace_symbols_in_dir(entry, regex, replacements) + else: + print("Processing %s" % entry) + replace_symbols_in_file(entry, regex, replacements) + + +def replace_symbols_in_path(path, regex, replacements): + if path.is_dir(): + replace_symbols_in_dir(path, regex, replacements) + else: + replace_symbols_in_file(path, regex, replacements) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser(fromfile_prefix_chars='@') + parser.add_argument("args", nargs="*") + args = parser.parse_args() + + try: + main() + except Exception as e: + print(e) + exit(-1) + + exit(0) + diff --git a/libs/SDL3/build-scripts/setup-gdk-desktop.py b/libs/SDL3/build-scripts/setup-gdk-desktop.py new file mode 100644 index 000000000..d2309a0e3 --- /dev/null +++ b/libs/SDL3/build-scripts/setup-gdk-desktop.py @@ -0,0 +1,303 @@ +#!/usr/bin/env python + +import argparse +import functools +import logging +import os +from pathlib import Path +import re +import shutil +import subprocess +import tempfile +import textwrap +import urllib.request +import zipfile + +# Update both variables when updating the GDK +GIT_REF = "June_2024_Update_1" +GDK_EDITION = "240601" # YYMMUU + +logger = logging.getLogger(__name__) + +class GdDesktopConfigurator: + def __init__(self, gdk_path, arch, vs_folder, vs_version=None, vs_toolset=None, temp_folder=None, git_ref=None, gdk_edition=None): + self.git_ref = git_ref or GIT_REF + self.gdk_edition = gdk_edition or GDK_EDITION + self.gdk_path = gdk_path + self.temp_folder = temp_folder or Path(tempfile.gettempdir()) + self.dl_archive_path = Path(self.temp_folder) / f"{ self.git_ref }.zip" + self.gdk_extract_path = Path(self.temp_folder) / f"GDK-{ self.git_ref }" + self.arch = arch + self.vs_folder = vs_folder + self._vs_version = vs_version + self._vs_toolset = vs_toolset + + def download_archive(self) -> None: + gdk_url = f"https://github.com/microsoft/GDK/archive/refs/tags/{ GIT_REF }.zip" + logger.info("Downloading %s to %s", gdk_url, self.dl_archive_path) + urllib.request.urlretrieve(gdk_url, self.dl_archive_path) + assert self.dl_archive_path.is_file() + + def extract_zip_archive(self) -> None: + extract_path = self.gdk_extract_path.parent + assert self.dl_archive_path.is_file() + logger.info("Extracting %s to %s", self.dl_archive_path, extract_path) + with zipfile.ZipFile(self.dl_archive_path) as zf: + zf.extractall(extract_path) + assert self.gdk_extract_path.is_dir(), f"{self.gdk_extract_path} must exist" + + def extract_development_kit(self) -> None: + extract_dks_cmd = self.gdk_extract_path / "SetupScripts/ExtractXboxOneDKs.cmd" + assert extract_dks_cmd.is_file() + logger.info("Extracting GDK Development Kit: running %s", extract_dks_cmd) + cmd = ["cmd.exe", "/C", str(extract_dks_cmd), str(self.gdk_extract_path), str(self.gdk_path)] + logger.debug("Running %r", cmd) + subprocess.check_call(cmd) + + def detect_vs_version(self) -> str: + vs_regex = re.compile("VS([0-9]{4})") + supported_vs_versions = [] + for p in self.gaming_grdk_build_path.iterdir(): + if not p.is_dir(): + continue + if m := vs_regex.match(p.name): + supported_vs_versions.append(m.group(1)) + logger.info(f"Supported Visual Studio versions: {supported_vs_versions}") + vs_versions = set(self.vs_folder.parts).intersection(set(supported_vs_versions)) + if not vs_versions: + raise RuntimeError("Visual Studio version is incompatible") + if len(vs_versions) > 1: + raise RuntimeError(f"Too many compatible VS versions found ({vs_versions})") + vs_version = vs_versions.pop() + logger.info(f"Used Visual Studio version: {vs_version}") + return vs_version + + def detect_vs_toolset(self) -> str: + toolset_paths = [] + for ts_path in self.gdk_toolset_parent_path.iterdir(): + if not ts_path.is_dir(): + continue + ms_props = ts_path / "Microsoft.Cpp.props" + if not ms_props.is_file(): + continue + toolset_paths.append(ts_path.name) + logger.info("Detected Visual Studio toolsets: %s", toolset_paths) + assert toolset_paths, "Have we detected at least one toolset?" + + def toolset_number(toolset: str) -> int: + if m:= re.match("[^0-9]*([0-9]+).*", toolset): + return int(m.group(1)) + return -9 + + return max(toolset_paths, key=toolset_number) + + @property + def vs_version(self) -> str: + if self._vs_version is None: + self._vs_version = self.detect_vs_version() + return self._vs_version + + @property + def vs_toolset(self) -> str: + if self._vs_toolset is None: + self._vs_toolset = self.detect_vs_toolset() + return self._vs_toolset + + @staticmethod + def copy_files_and_merge_into(srcdir: Path, dstdir: Path) -> None: + logger.info(f"Copy {srcdir} to {dstdir}") + for root, _, files in os.walk(srcdir): + dest_root = dstdir / Path(root).relative_to(srcdir) + if not dest_root.is_dir(): + dest_root.mkdir() + for file in files: + srcfile = Path(root) / file + dstfile = dest_root / file + shutil.copy(srcfile, dstfile) + + def copy_msbuild(self) -> None: + vc_toolset_parent_path = self.vs_folder / "MSBuild/Microsoft/VC" + if 1: + logger.info(f"Detected compatible Visual Studio version: {self.vs_version}") + srcdir = vc_toolset_parent_path + dstdir = self.gdk_toolset_parent_path + assert srcdir.is_dir(), "Source directory must exist" + assert dstdir.is_dir(), "Destination directory must exist" + + self.copy_files_and_merge_into(srcdir=srcdir, dstdir=dstdir) + + @property + def game_dk_path(self) -> Path: + return self.gdk_path / "Microsoft GDK" + + @property + def game_dk_latest_path(self) -> Path: + return self.game_dk_path / self.gdk_edition + + @property + def windows_sdk_path(self) -> Path: + return self.gdk_path / "Windows Kits/10" + + @property + def gaming_grdk_build_path(self) -> Path: + return self.game_dk_latest_path / "GRDK" + + @property + def gdk_toolset_parent_path(self) -> Path: + return self.gaming_grdk_build_path / f"VS{self.vs_version}/flatDeployment/MSBuild/Microsoft/VC" + + @property + def env(self) -> dict[str, str]: + game_dk = self.game_dk_path + game_dk_latest = self.game_dk_latest_path + windows_sdk_dir = self.windows_sdk_path + gaming_grdk_build = self.gaming_grdk_build_path + + return { + "GRDKEDITION": f"{self.gdk_edition}", + "GameDK": f"{game_dk}\\", + "GameDKLatest": f"{ game_dk_latest }\\", + "WindowsSdkDir": f"{ windows_sdk_dir }\\", + "GamingGRDKBuild": f"{ gaming_grdk_build }\\", + "VSInstallDir": f"{ self.vs_folder }\\", + } + + def create_user_props(self, path: Path) -> None: + vc_targets_path = self.gaming_grdk_build_path / f"VS{ self.vs_version }/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" + vc_targets_path16 = self.gaming_grdk_build_path / f"VS2019/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" + vc_targets_path17 = self.gaming_grdk_build_path / f"VS2022/flatDeployment/MSBuild/Microsoft/VC/{ self.vs_toolset }" + additional_include_directories = ";".join(str(p) for p in self.gdk_include_paths) + additional_library_directories = ";".join(str(p) for p in self.gdk_library_paths) + durango_xdk_install_path = self.gdk_path / "Microsoft GDK" + with path.open("w") as f: + f.write(textwrap.dedent(f"""\ + + + + { vc_targets_path }\\ + { vc_targets_path16 }\\ + { vc_targets_path17 }\\ + { self.gaming_grdk_build_path }\\ + Gaming.Desktop.x64 + Debug + { self.gdk_edition } + { durango_xdk_install_path } + + $(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2019\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\ + $(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2019\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\ + $(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2022\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\ + $(DurangoXdkInstallPath)\\{self.gdk_edition}\\GRDK\\VS2022\\flatDeployment\\MSBuild\\Microsoft\\VC\\{self.vs_toolset}\\Platforms\\$(Platform)\\ + + true + true + true + + + + { additional_include_directories };%(AdditionalIncludeDirectories) + + + { additional_library_directories };%(AdditionalLibraryDirectories) + + + + """)) + + @property + def gdk_include_paths(self) -> list[Path]: + return [ + self.gaming_grdk_build_path / "gamekit/include", + ] + + @property + def gdk_library_paths(self) -> list[Path]: + return [ + self.gaming_grdk_build_path / f"gamekit/lib/{self.arch}", + ] + + @property + def gdk_binary_path(self) -> list[Path]: + return [ + self.gaming_grdk_build_path / "bin", + self.game_dk_path / "bin", + ] + + @property + def build_env(self) -> dict[str, str]: + gdk_include = ";".join(str(p) for p in self.gdk_include_paths) + gdk_lib = ";".join(str(p) for p in self.gdk_library_paths) + gdk_path = ";".join(str(p) for p in self.gdk_binary_path) + return { + "GDK_INCLUDE": gdk_include, + "GDK_LIB": gdk_lib, + "GDK_PATH": gdk_path, + } + + def print_env(self) -> None: + for k, v in self.env.items(): + print(f"set \"{k}={v}\"") + print() + for k, v in self.build_env.items(): + print(f"set \"{k}={v}\"") + print() + print(f"set \"PATH=%GDK_PATH%;%PATH%\"") + print(f"set \"LIB=%GDK_LIB%;%LIB%\"") + print(f"set \"INCLUDE=%GDK_INCLUDE%;%INCLUDE%\"") + + +def main(): + logging.basicConfig(level=logging.INFO) + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument("--arch", choices=["amd64"], default="amd64", help="Architecture") + parser.add_argument("--download", action="store_true", help="Download GDK") + parser.add_argument("--extract", action="store_true", help="Extract downloaded GDK") + parser.add_argument("--copy-msbuild", action="store_true", help="Copy MSBuild files") + parser.add_argument("--temp-folder", help="Temporary folder where to download and extract GDK") + parser.add_argument("--gdk-path", required=True, type=Path, help="Folder where to store the GDK") + parser.add_argument("--ref-edition", type=str, help="Git ref and GDK edition separated by comma") + parser.add_argument("--vs-folder", required=True, type=Path, help="Installation folder of Visual Studio") + parser.add_argument("--vs-version", required=False, type=int, help="Visual Studio version") + parser.add_argument("--vs-toolset", required=False, help="Visual Studio toolset (e.g. v150)") + parser.add_argument("--props-folder", required=False, type=Path, default=Path(), help="Visual Studio toolset (e.g. v150)") + parser.add_argument("--no-user-props", required=False, dest="user_props", action="store_false", help="Don't ") + args = parser.parse_args() + + logging.basicConfig(level=logging.INFO) + + git_ref = None + gdk_edition = None + if args.ref_edition is not None: + git_ref, gdk_edition = args.ref_edition.split(",", 1) + try: + int(gdk_edition) + except ValueError: + parser.error("Edition should be an integer (YYMMUU) (Y=year M=month U=update)") + + configurator = GdDesktopConfigurator( + arch=args.arch, + git_ref=git_ref, + gdk_edition=gdk_edition, + vs_folder=args.vs_folder, + vs_version=args.vs_version, + vs_toolset=args.vs_toolset, + gdk_path=args.gdk_path, + temp_folder=args.temp_folder, + ) + + if args.download: + configurator.download_archive() + + if args.extract: + configurator.extract_zip_archive() + + configurator.extract_development_kit() + + if args.copy_msbuild: + configurator.copy_msbuild() + + if args.user_props: + configurator.print_env() + configurator.create_user_props(args.props_folder / "Directory.Build.props") + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/libs/SDL3/build-scripts/showrev.sh b/libs/SDL3/build-scripts/showrev.sh index 98bb335b2..764d3a431 100644 --- a/libs/SDL3/build-scripts/showrev.sh +++ b/libs/SDL3/build-scripts/showrev.sh @@ -12,7 +12,7 @@ fi major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' include/SDL3/SDL_version.h) minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' include/SDL3/SDL_version.h) -micro=$(sed -ne 's/^#define SDL_PATCHLEVEL *//p' include/SDL3/SDL_version.h) +micro=$(sed -ne 's/^#define SDL_MICRO_VERSION *//p' include/SDL3/SDL_version.h) version="${major}.${minor}.${micro}" if [ -x "$(command -v git)" ]; then diff --git a/libs/SDL3/build-scripts/test-versioning.sh b/libs/SDL3/build-scripts/test-versioning.sh index a887a9cc8..55e29a301 100644 --- a/libs/SDL3/build-scripts/test-versioning.sh +++ b/libs/SDL3/build-scripts/test-versioning.sh @@ -8,7 +8,7 @@ cd `dirname $0`/.. ref_major=$(sed -ne 's/^#define SDL_MAJOR_VERSION *//p' include/SDL3/SDL_version.h) ref_minor=$(sed -ne 's/^#define SDL_MINOR_VERSION *//p' include/SDL3/SDL_version.h) -ref_micro=$(sed -ne 's/^#define SDL_PATCHLEVEL *//p' include/SDL3/SDL_version.h) +ref_micro=$(sed -ne 's/^#define SDL_MICRO_VERSION *//p' include/SDL3/SDL_version.h) ref_version="${ref_major}.${ref_minor}.${ref_micro}" tests=0 @@ -25,6 +25,14 @@ not_ok () { failed=1 } +version=$(sed -Ene 's/^.* version ([0-9.]*)$/\1/p' include/SDL3/SDL.h) + +if [ "$ref_version" = "$version" ]; then + ok "SDL.h $version" +else + not_ok "SDL.h $version disagrees with SDL_version.h $ref_version" +fi + version=$(sed -Ene 's/^project\(SDL[0-9]+ LANGUAGES C VERSION "([0-9.]*)"\)$/\1/p' CMakeLists.txt) if [ "$ref_version" = "$version" ]; then diff --git a/libs/SDL3/build-scripts/update-version.sh b/libs/SDL3/build-scripts/update-version.sh index 395aa62b2..86ae81634 100644 --- a/libs/SDL3/build-scripts/update-version.sh +++ b/libs/SDL3/build-scripts/update-version.sh @@ -22,11 +22,13 @@ fi MAJOR="$1" MINOR="$2" -PATCH="$3" -NEWVERSION="$MAJOR.$MINOR.$PATCH" +MICRO="$3" +NEWVERSION="$MAJOR.$MINOR.$MICRO" echo "Updating version to '$NEWVERSION' ..." +perl -w -pi -e 's/\A(.* version )[0-9.]+/${1}'$NEWVERSION'/;' include/SDL3/SDL.h + # !!! FIXME: This first one is a kinda scary search/replace that might fail later if another X.Y.Z version is added to the file. perl -w -pi -e 's/(\)\d+\.\d+\.\d+/${1}'$NEWVERSION'/;' Xcode/SDL/Info-Framework.plist @@ -41,33 +43,33 @@ perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/; perl -w -pi -e 's/(DYLIB_COMPATIBILITY_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj # non-zero patch? -if [ "x$PATCH" != "x0" ]; then +if [ "x$MICRO" != "x0" ]; then if [ `expr $MINOR % 2` = "0" ]; then # If patch is not zero, but minor is even, it's a bugfix release. - perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.'$PATCH'.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj + perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.'$MICRO'.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj else # If patch is not zero, but minor is odd, it's a development prerelease. - DYVER=`expr $MINOR \* 100 + $PATCH + 1` + DYVER=`expr $MINOR \* 100 + $MICRO + 1` perl -w -pi -e 's/(DYLIB_CURRENT_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj perl -w -pi -e 's/(DYLIB_COMPATIBILITY_VERSION\s*=\s*)\d+\.\d+\.\d+/${1}'$DYVER'.0.0/;' Xcode/SDL/SDL.xcodeproj/project.pbxproj fi fi -perl -w -pi -e 's/\A(project\(SDL[0-9]+ LANGUAGES C CXX VERSION ")[0-9.]+/${1}'$NEWVERSION'/;' CMakeLists.txt +perl -w -pi -e 's/\A(project\(SDL[0-9]+ LANGUAGES C VERSION ")[0-9.]+/${1}'$NEWVERSION'/;' CMakeLists.txt perl -w -pi -e 's/\A(.* SDL_MAJOR_VERSION = )\d+/${1}'$MAJOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java perl -w -pi -e 's/\A(.* SDL_MINOR_VERSION = )\d+/${1}'$MINOR'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java -perl -w -pi -e 's/\A(.* SDL_MICRO_VERSION = )\d+/${1}'$PATCH'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +perl -w -pi -e 's/\A(.* SDL_MICRO_VERSION = )\d+/${1}'$MICRO'/;' android-project/app/src/main/java/org/libsdl/app/SDLActivity.java perl -w -pi -e 's/(\#define SDL_MAJOR_VERSION\s+)\d+/${1}'$MAJOR'/;' include/SDL3/SDL_version.h perl -w -pi -e 's/(\#define SDL_MINOR_VERSION\s+)\d+/${1}'$MINOR'/;' include/SDL3/SDL_version.h -perl -w -pi -e 's/(\#define SDL_PATCHLEVEL\s+)\d+/${1}'$PATCH'/;' include/SDL3/SDL_version.h +perl -w -pi -e 's/(\#define SDL_MICRO_VERSION\s+)\d+/${1}'$MICRO'/;' include/SDL3/SDL_version.h -perl -w -pi -e 's/(FILEVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$PATCH'/;' src/core/windows/version.rc -perl -w -pi -e 's/(PRODUCTVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$PATCH'/;' src/core/windows/version.rc -perl -w -pi -e 's/(VALUE "FileVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$PATCH'/;' src/core/windows/version.rc -perl -w -pi -e 's/(VALUE "ProductVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$PATCH'/;' src/core/windows/version.rc +perl -w -pi -e 's/(FILEVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$MICRO'/;' src/core/windows/version.rc +perl -w -pi -e 's/(PRODUCTVERSION\s+)\d+,\d+,\d+/${1}'$MAJOR','$MINOR','$MICRO'/;' src/core/windows/version.rc +perl -w -pi -e 's/(VALUE "FileVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$MICRO'/;' src/core/windows/version.rc +perl -w -pi -e 's/(VALUE "ProductVersion", ")\d+, \d+, \d+/${1}'$MAJOR', '$MINOR', '$MICRO'/;' src/core/windows/version.rc echo "Running build-scripts/test-versioning.sh to verify changes..." ./build-scripts/test-versioning.sh diff --git a/libs/SDL3/build-scripts/wikiheaders.pl b/libs/SDL3/build-scripts/wikiheaders.pl index 598216a87..071e4695d 100644 --- a/libs/SDL3/build-scripts/wikiheaders.pl +++ b/libs/SDL3/build-scripts/wikiheaders.pl @@ -1,5 +1,24 @@ #!/usr/bin/perl -w +# Simple DirectMedia Layer +# Copyright (C) 1997-2024 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. + use warnings; use strict; use File::Path; @@ -16,7 +35,7 @@ my $versionfname = 'include/SDL_version.h'; my $versionmajorregex = '\A\#define\s+SDL_MAJOR_VERSION\s+(\d+)\Z'; my $versionminorregex = '\A\#define\s+SDL_MINOR_VERSION\s+(\d+)\Z'; -my $versionpatchregex = '\A\#define\s+SDL_PATCHLEVEL\s+(\d+)\Z'; +my $versionmicroregex = '\A\#define\s+SDL_MICRO_VERSION\s+(\d+)\Z'; my $mainincludefname = 'SDL.h'; my $selectheaderregex = '\ASDL.*?\.h\Z'; my $projecturl = 'https://libsdl.org/'; @@ -31,6 +50,7 @@ my $wikipreamble = undef; my $wikiheaderfiletext = 'Defined in %fname%'; my $manpageheaderfiletext = 'Defined in %fname%'; +my $headercategoryeval = undef; my $changeformat = undef; my $manpath = undef; my $gitrev = undef; @@ -41,6 +61,8 @@ $copy_direction = 1, next if $_ eq '--copy-to-header'; $copy_direction = -1, next if $_ eq '--copy-to-wiki'; $copy_direction = -2, next if $_ eq '--copy-to-manpages'; + $copy_direction = -3, next if $_ eq '--report-coverage-gaps'; + $copy_direction = -4, next if $_ eq '--copy-to-latex'; if (/\A--options=(.*)\Z/) { $optionsfname = $1; next; @@ -68,6 +90,8 @@ if (defined $optionsfname) { open OPTIONS, '<', $optionsfname or die("Failed to open options file '$optionsfname': $!\n"); while () { + next if /\A\s*\#/; # Skip lines that start with (optional whitespace, then) '#' as comments. + chomp; if (/\A(.*?)\=(.*)\Z/) { my $key = $1; @@ -87,7 +111,7 @@ $readmesubdir = $val, next if $key eq 'readmesubdir'; $versionmajorregex = $val, next if $key eq 'versionmajorregex'; $versionminorregex = $val, next if $key eq 'versionminorregex'; - $versionpatchregex = $val, next if $key eq 'versionpatchregex'; + $versionmicroregex = $val, next if $key eq 'versionmicroregex'; $versionfname = $val, next if $key eq 'versionfname'; $mainincludefname = $val, next if $key eq 'mainincludefname'; $selectheaderregex = $val, next if $key eq 'selectheaderregex'; @@ -97,11 +121,18 @@ $wikipreamble = $val, next if $key eq 'wikipreamble'; $wikiheaderfiletext = $val, next if $key eq 'wikiheaderfiletext'; $manpageheaderfiletext = $val, next if $key eq 'manpageheaderfiletext'; + $headercategoryeval = $val, next if $key eq 'headercategoryeval'; } } close(OPTIONS); } +sub escLaTeX { + my $str = shift; + $str =~ s/([_\#\&\^])/\\$1/g; + return $str; +} + my $wordwrap_mode = 'mediawiki'; sub wordwrap_atom { # don't call this directly. my $str = shift; @@ -178,6 +209,8 @@ sub wordwrap_one_paragraph { # don't call this directly. if ($item ne '') { $retval .= wordwrap_with_bullet_indent($bullet, $item); } + } elsif ($p =~ /\A\s*\|.*\|\s*\n/) { # Markdown table + $retval = "$p\n"; # don't wrap it (!!! FIXME: but maybe parse by lines until we run out of table...) } else { $retval = wordwrap_atom($p) . "\n"; } @@ -243,14 +276,14 @@ sub wikify_chunk { $codedstr .= wikify_chunk($wikitype, $1, undef, undef); if (defined $apiprefixregex) { # Convert obvious API things to wikilinks, even inside `code` blocks. - $codeblock =~ s/\b($apiprefixregex[a-zA-Z0-9_]+)/[[$1]]/gms; + $codeblock =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[\[$2\]\]/gms; } $codedstr .= "$codeblock"; } # Convert obvious API things to wikilinks. if (defined $apiprefixregex) { - $str =~ s/\b($apiprefixregex[a-zA-Z0-9_]+)/[[$1]]/gms; + $str =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[\[$2\]\]/gms; } # Make some Markdown things into MediaWiki... @@ -295,13 +328,13 @@ sub wikify_chunk { # Convert obvious API things to wikilinks. if (defined $apiprefixregex) { - $str =~ s/\b($apiprefixregex[a-zA-Z0-9_]+)/[$1]($1)/gms; + $str =~ s/(\A|[^\/a-zA-Z0-9_])($apiprefixregex[a-zA-Z0-9_]+)/$1\[$2\]\($2\)/gms; } $str = $codedstr . $str; if (defined $code) { - $str .= "```$codelang$code```"; + $str .= "```$codelang\n$code\n```\n"; } } @@ -317,7 +350,7 @@ sub wikify { #print("WIKIFY WHOLE:\n\n$str\n\n\n"); - while ($str =~ s/\A(.*?)\`\`\`(c\+\+|c)(.*?)\`\`\`//ms) { + while ($str =~ s/\A(.*?)\`\`\`(.*?)\n(.*?)\n\`\`\`(\n|\Z)//ms) { $retval .= wikify_chunk($wikitype, $1, $2, $3); } $retval .= wikify_chunk($wikitype, $str, undef, undef); @@ -374,7 +407,7 @@ sub dewikify_chunk { } if (defined $code) { - $str .= "```$codelang$code```"; + $str .= "\n```$codelang\n$code\n```\n"; } } elsif ($dewikify_mode eq 'manpage') { $str =~ s/\./\\[char46]/gms; # make sure these can't become control codes. @@ -424,9 +457,6 @@ sub dewikify_chunk { # bullets $str =~ s/^\- /\n\\\(bu /gm; - - } else { - die("Unexpected wikitype when converting to manpages\n"); # !!! FIXME: need to handle Markdown wiki pages. } if (defined $code) { @@ -439,8 +469,80 @@ sub dewikify_chunk { } $str .= ".EX\n$code\n.EE\n.PP\n"; } + } elsif ($dewikify_mode eq 'LaTeX') { + if ($wikitype eq 'mediawiki') { + # Dump obvious wikilinks. + if (defined $apiprefixregex) { + $str =~ s/\s*\[\[($apiprefixregex[a-zA-Z0-9_]+)\]\]/$1/gms; + } + + # links + $str =~ s/\[(https?\:\/\/.*?)\s+(.*?)\]/\\href{$1}{$2}/g; + + # is also popular. :/ + $str =~ s/\s*\(.*?)<\/code>/ \\texttt{$1}/gms; + + # bold+italic + $str =~ s/\s*'''''(.*?)'''''/ \\textbf{\\textit{$1}}/gms; + + # bold + $str =~ s/\s*'''(.*?)'''/ \\textbf{$1}/gms; + + # italic + $str =~ s/\s*''(.*?)''/ \\textit{$1}/gms; + + # bullets + $str =~ s/^\*\s+/ \\item /gm; + } elsif ($wikitype eq 'md') { + # Dump obvious wikilinks. + if (defined $apiprefixregex) { + $str =~ s/\[(\`?$apiprefixregex[a-zA-Z0-9_]+\`?)\]\($apiprefixregex[a-zA-Z0-9_]+\)/$1/gms; + } + + # links + $str =~ s/\[(.*?)]\((https?\:\/\/.*?)\)/\\href{$2}{$1}/g; + + # is also popular. :/ + $str =~ s/\s*\`(.*?)\`/ \\texttt{$1}/gms; + + # bold+italic + $str =~ s/\s*\*\*\*(.*?)\*\*\*/ \\textbf{\\textit{$1}}/gms; + + # bold + $str =~ s/\s*\*\*(.*?)\*\*/ \\textbf{$1}/gms; + + # italic + $str =~ s/\s*\*(.*?)\*/ \\textit{$1}/gms; + + # bullets + $str =~ s/^\-\s+/ \\item /gm; + } + + # Wrap bullet lists in itemize blocks... + $str =~ s/^(\s*\\item .*?)(\n\n|\Z)/\n\\begin{itemize}\n$1$2\n\\end{itemize}\n\n/gms; + + $str = escLaTeX($str); + + if (defined $code) { + $code =~ s/\A\n+//gms; + $code =~ s/\n+\Z//gms; + + if (($codelang eq '') || ($codelang eq 'output')) { + $str .= "\\begin{verbatim}\n$code\n\\end{verbatim}\n"; + } else { + if ($codelang eq 'c') { + $codelang = 'C'; + } elsif ($codelang eq 'c++') { + $codelang = 'C++'; + } else { + die("Unexpected codelang '$codelang'"); + } + $str .= "\n\\lstset{language=$codelang}\n"; + $str .= "\\begin{lstlisting}\n$code\n\\end{lstlisting}\n"; + } + } } else { - die("Unexpected dewikify_mode\n"); + die("Unexpected dewikify_mode"); } #print("\n\nDEWIKIFY CHUNK DONE:\n\n$str\n\n\n"); @@ -459,8 +561,14 @@ sub dewikify { $str =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; my $retval = ''; - while ($str =~ s/\A(.*?)(.*?)<\/syntaxhighlight\>//ms) { - $retval .= dewikify_chunk($wikitype, $1, $2, $3); + if ($wikitype eq 'mediawiki') { + while ($str =~ s/\A(.*?)(.*?)<\/syntaxhighlight\>//ms) { + $retval .= dewikify_chunk($wikitype, $1, $2, $3); + } + } elsif ($wikitype eq 'md') { + while ($str =~ s/\A(.*?)\n```(.*?)\n(.*?)\n```\n//ms) { + $retval .= dewikify_chunk($wikitype, $1, $2, $3); + } } $retval .= dewikify_chunk($wikitype, $str, undef, undef); @@ -505,12 +613,15 @@ sub usage { 'Header File', 'Syntax', 'Function Parameters', + 'Macro Parameters', + 'Fields', + 'Values', 'Return Value', 'Remarks', 'Thread Safety', 'Version', 'Code Examples', - 'Related Functions' + 'See Also' ); # Sections that only ever exist in the wiki and shouldn't be deleted when @@ -523,11 +634,91 @@ sub usage { my %headers = (); # $headers{"SDL_audio.h"} -> reference to an array of all lines of text in SDL_audio.h. -my %headerfuncs = (); # $headerfuncs{"SDL_OpenAudio"} -> string of header documentation for SDL_OpenAudio, with comment '*' bits stripped from the start. Newlines embedded! +my %headersyms = (); # $headersyms{"SDL_OpenAudio"} -> string of header documentation for SDL_OpenAudio, with comment '*' bits stripped from the start. Newlines embedded! my %headerdecls = (); -my %headerfuncslocation = (); # $headerfuncslocation{"SDL_OpenAudio"} -> name of header holding SDL_OpenAudio define ("SDL_audio.h" in this case). -my %headerfuncschunk = (); # $headerfuncschunk{"SDL_OpenAudio"} -> offset in array in %headers that should be replaced for this function. -my %headerfuncshasdoxygen = (); # $headerfuncschunk{"SDL_OpenAudio"} -> 1 if there was no existing doxygen for this function. +my %headersymslocation = (); # $headersymslocation{"SDL_OpenAudio"} -> name of header holding SDL_OpenAudio define ("SDL_audio.h" in this case). +my %headersymschunk = (); # $headersymschunk{"SDL_OpenAudio"} -> offset in array in %headers that should be replaced for this symbol. +my %headersymshasdoxygen = (); # $headersymshasdoxygen{"SDL_OpenAudio"} -> 1 if there was no existing doxygen for this function. +my %headersymstype = (); # $headersymstype{"SDL_OpenAudio"} -> 1 (function), 2 (macro), 3 (struct), 4 (enum), 5 (other typedef) +my %headersymscategory = (); # $headersymscategory{"SDL_OpenAudio"} -> 'Audio' ... this is set with a `/* WIKI CATEGEORY: Audio */` comment in the headers that sets it on all symbols until a new comment changes it. So usually, once at the top of the header file. +my %headercategorydocs = (); # $headercategorydocs{"Audio"} -> (fake) symbol for this category's documentation. Undefined if not documented. +my %headersymsparaminfo = (); # $headersymsparaminfo{"SDL_OpenAudio"} -> reference to array of parameters, pushed by name, then C type string, repeating. Undef'd if void params, or not a function. +my %headersymsrettype = (); # $headersymsrettype{"SDL_OpenAudio"} -> string of C datatype of return value. Undef'd if not a function. +my %wikitypes = (); # contains string of wiki page extension, like $wikitypes{"SDL_OpenAudio"} == 'mediawiki' +my %wikisyms = (); # contains references to hash of strings, each string being the full contents of a section of a wiki page, like $wikisyms{"SDL_OpenAudio"}{"Remarks"}. +my %wikisectionorder = (); # contains references to array, each array item being a key to a wikipage section in the correct order, like $wikisectionorder{"SDL_OpenAudio"}[2] == 'Remarks' + +my %referenceonly = (); # $referenceonly{"Y"} -> symbol name that this symbol is bound to. This makes wiki pages that say "See X" where "X" is a typedef and "Y" is a define attached to it. These pages are generated in the wiki only and do not bridge to the headers or manpages. + +my @coverage_gap = (); # array of strings that weren't part of documentation, or blank, or basic preprocessor logic. Lets you see what this script is missing! + +sub add_coverage_gap { + if ($copy_direction == -3) { # --report-coverage-gaps + my $text = shift; + my $dent = shift; + my $lineno = shift; + return if $text =~ /\A\s*\Z/; # skip blank lines + return if $text =~ /\A\s*\#\s*(if|el|endif|include)/; # skip preprocessor floof. + push @coverage_gap, "$dent:$lineno: $text"; + } +} + +sub print_undocumented_section { + my $fh = shift; + my $typestr = shift; + my $typeval = shift; + + print $fh "## $typestr defined in the headers, but not in the wiki\n\n"; + my $header_only_sym = 0; + foreach (sort keys %headersyms) { + my $sym = $_; + if ((not defined $wikisyms{$sym}) && ($headersymstype{$sym} == $typeval)) { + print $fh "- [$sym]($sym)\n"; + $header_only_sym = 1; + } + } + if (!$header_only_sym) { + print $fh "(none)\n"; + } + print $fh "\n"; + + if (0) { # !!! FIXME: this lists things that _shouldn't_ be in the headers, like MigrationGuide, etc, but also we don't know if they're functions, macros, etc at this point (can we parse that from the wiki page, though?) + print $fh "## $typestr defined in the wiki, but not in the headers\n\n"; + + my $wiki_only_sym = 0; + foreach (sort keys %wikisyms) { + my $sym = $_; + if ((not defined $headersyms{$sym}) && ($headersymstype{$sym} == $typeval)) { + print $fh "- [$sym]($sym)\n"; + $wiki_only_sym = 1; + } + } + if (!$wiki_only_sym) { + print $fh "(none)\n"; + } + print $fh "\n"; + } +} + +sub strip_fn_declaration_metadata { + my $decl = shift; + $decl =~ s/SDL_(PRINTF|SCANF)_FORMAT_STRING\s*//; # don't want this metadata as part of the documentation. + $decl =~ s/SDL_ALLOC_SIZE2?\(.*?\)\s*//; # don't want this metadata as part of the documentation. + $decl =~ s/SDL_MALLOC\s*//; # don't want this metadata as part of the documentation. + $decl =~ s/SDL_(IN|OUT|INOUT)_.*?CAP\s*\(.*?\)\s*//g; # don't want this metadata as part of the documentation. + $decl =~ s/\)(\s*SDL_[a-zA-Z_]+(\(.*?\)|))*;/);/; # don't want this metadata as part of the documentation. + return $decl; +} + +sub sanitize_c_typename { + my $str = shift; + $str =~ s/\A\s+//; + $str =~ s/\s+\Z//; + $str =~ s/const\s*(\*+)/const $1/g; # one space between `const` and pointer stars: `char const* const *` becomes `char const * const *`. + $str =~ s/\*\s+\*/**/g; # drop spaces between pointers: `void * *` becomes `void **`. + $str =~ s/\s*(\*+)\Z/ $1/; # one space between pointer stars and what it points to: `void**` becomes `void **`. + return $str; +} my $incpath = "$srcpath"; $incpath .= "/$incsubdir" if $incsubdir ne ''; @@ -544,32 +735,88 @@ sub usage { next if not $dent =~ /$selectheaderregex/; # just selected headers. open(FH, '<', "$incpath/$dent") or die("Can't open '$incpath/$dent': $!\n"); - my @contents = (); + # You can optionally set a wiki category with Perl code in .wikiheaders-options that gets eval()'d per-header, + # and also if you put `/* WIKI CATEGORY: blah */` on a line by itself, it'll change the category for any symbols + # below it in the same file. If no category is set, one won't be added for the symbol (beyond the standard CategoryFunction, etc) + my $current_wiki_category = undef; + if (defined $headercategoryeval) { + $_ = $dent; + $current_wiki_category = eval($headercategoryeval); + if (($current_wiki_category eq '') || ($current_wiki_category eq '-')) { + $current_wiki_category = undef; + } + #print("CATEGORY FOR '$dent' IS " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); + } + my @contents = (); + my $ignoring_lines = 0; + my $header_comment = -1; + my $saw_category_doxygen = -1; + my $lineno = 0; while () { chomp; + $lineno++; + my $symtype = 0; # nothing, yet. my $decl; my @templines; my $str; my $has_doxygen = 1; - if (/\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC/) { # a function declaration without a doxygen comment? + + # Since a lot of macros are just preprocessor logic spam and not all macros are worth documenting anyhow, we only pay attention to them when they have a Doxygen comment attached. + # Functions and other things are a different story, though! + + if ($header_comment == -1) { + $header_comment = /\A\/\*\s*\Z/ ? 1 : 0; + } elsif (($header_comment == 1) && (/\A\*\/\s*\Z/)) { + $header_comment = 0; + } + + if ($ignoring_lines && /\A\s*\#\s*endif\s*\Z/) { + $ignoring_lines = 0; + push @contents, $_; + next; + } elsif ($ignoring_lines) { + push @contents, $_; + next; + } elsif (/\A\s*\#\s*ifndef\s+SDL_WIKI_DOCUMENTATION_SECTION\s*\Z/) { + $ignoring_lines = 1; + push @contents, $_; + next; + } elsif (/\A\s*\/\*\s*WIKI CATEGORY:\s*(.*?)\s*\*\/\s*\Z/) { + $current_wiki_category = (($1 eq '') || ($1 eq '-')) ? undef : $1; + #print("CATEGORY FOR '$dent' CHANGED TO " . (defined($current_wiki_category) ? "'$current_wiki_category'" : '(undef)') . "\n"); + push @contents, $_; + next; + } elsif (/\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { # a function declaration without a doxygen comment? + $symtype = 1; # function declaration + @templines = (); + $decl = $_; + $str = ''; + $has_doxygen = 0; + } elsif (/\A\s*SDL_FORCE_INLINE/) { # a (forced-inline) function declaration without a doxygen comment? + $symtype = 1; # function declaration @templines = (); $decl = $_; $str = ''; $has_doxygen = 0; } elsif (not /\A\/\*\*\s*\Z/) { # not doxygen comment start? push @contents, $_; + add_coverage_gap($_, $dent, $lineno) if ($header_comment == 0); next; } else { # Start of a doxygen comment, parse it out. + my $is_category_doxygen = 0; + @templines = ( $_ ); while () { chomp; + $lineno++; push @templines, $_; last if /\A\s*\*\/\Z/; if (s/\A\s*\*\s*\`\`\`/```/) { # this is a hack, but a lot of other code relies on the whitespace being trimmed, but we can't trim it in code blocks... $str .= "$_\n"; while () { chomp; + $lineno++; push @templines, $_; s/\A\s*\*\s?//; if (s/\A\s*\`\`\`/```/) { @@ -580,97 +827,482 @@ sub usage { } } } else { - s/\A\s*\*\s*//; + s/\A\s*\*\s*//; # Strip off the " * " at the start of the comment line. + + # To add documentation to Category Pages, the rule is it has to + # be the first Doxygen comment in the header, and it must start with `# CategoryX` + # (otherwise we'll treat it as documentation for whatever's below it). `X` is + # the category name, which doesn't _necessarily_ have to match + # $current_wiki_category, but it probably should. + # + # For compatibility with Doxygen, if there's a `\file` here instead of + # `# CategoryName`, we'll accept it and use the $current_wiki_category if set. + if ($saw_category_doxygen == -1) { + $saw_category_doxygen = defined($current_wiki_category) && /\A\\file\s+/; + if ($saw_category_doxygen) { + $_ = "# Category$current_wiki_category"; + } else { + $saw_category_doxygen = /\A\# Category/; + } + $is_category_doxygen = $saw_category_doxygen; + } + $str .= "$_\n"; } } - $decl = ; - $decl = '' if not defined $decl; - chomp($decl); - if (not $decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC/) { + if ($is_category_doxygen) { + $str =~ s/\s*\Z//; + $decl = ''; + $symtype = -1; # not a symbol at all. + } else { + $decl = ; + $lineno++ if defined $decl; + $decl = '' if not defined $decl; + chomp($decl); + if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC/) { + $symtype = 1; # function declaration + } elsif ($decl =~ /\A\s*SDL_FORCE_INLINE/) { + $symtype = 1; # (forced-inline) function declaration + } elsif ($decl =~ /\A\s*\#\s*define\s+/) { + $symtype = 2; # macro + } elsif ($decl =~ /\A\s*(typedef\s+|)(struct|union)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { + $symtype = 3; # struct or union + } elsif ($decl =~ /\A\s*(typedef\s+|)enum\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\Z)/) { + $symtype = 4; # enum + } elsif ($decl =~ /\A\s*typedef\s+.*\Z/) { + $symtype = 5; # other typedef + } else { + #print "Found doxygen but no function sig:\n$str\n\n"; + foreach (@templines) { + push @contents, $_; + add_coverage_gap($_, $dent, $lineno); + } + push @contents, $decl; + add_coverage_gap($decl, $dent, $lineno); + next; + } + } + } + + my @paraminfo = (); + my $rettype = undef; + my @decllines = ( $decl ); + my $sym = ''; + + if ($symtype == -1) { # category documentation with no symbol attached. + @decllines = (); + if ($str =~ /^#\s*Category(.*?)\s*$/m) { + $sym = "[category documentation] $1"; # make a fake, unique symbol that's not valid C. + } else { + die("Unexpected category documentation line '$str' in '$incpath/$dent' ...?"); + } + $headercategorydocs{$current_wiki_category} = $sym; + } elsif ($symtype == 1) { # a function + my $is_forced_inline = ($decl =~ /\A\s*SDL_FORCE_INLINE/); + + if ($is_forced_inline) { + if (not $decl =~ /\)\s*(\{.*|)\s*\Z/) { + while () { + chomp; + $lineno++; + push @decllines, $_; + s/\A\s+//; + s/\s+\Z//; + $decl .= " $_"; + last if /\)\s*(\{.*|)\s*\Z/; + } + } + $decl =~ s/\s*\)\s*(\{.*|)\s*\Z/);/; + } else { + if (not $decl =~ /;/) { + while () { + chomp; + $lineno++; + push @decllines, $_; + s/\A\s+//; + s/\s+\Z//; + $decl .= " $_"; + last if /;/; + } + } + $decl =~ s/\s+\);\Z/);/; + $decl =~ s/\s+;\Z/;/; + } + + $decl =~ s/\s+\Z//; + + $decl = strip_fn_declaration_metadata($decl); + + my $paramsstr = undef; + + if (!$is_forced_inline && $decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(\*?)\s*SDLCALL\s+(.*?)\s*\((.*?)\);/) { + $sym = $8; + $rettype = "$3$4$5$6"; + $paramsstr = $9; + } elsif ($is_forced_inline && $decl =~ /\A\s*SDL_FORCE_INLINE\s+(SDL_DEPRECATED\s+|)(const\s+|)(unsigned\s+|)(.*?)([\*\s]+)(.*?)\s*\((.*?)\);/) { + $sym = $6; + $rettype = "$2$3$4$5"; + $paramsstr = $7; + } else { #print "Found doxygen but no function sig:\n$str\n\n"; foreach (@templines) { push @contents, $_; } - push @contents, $decl; + foreach (@decllines) { + push @contents, $_; + } next; } - } - my @decllines = ( $decl ); + $rettype = sanitize_c_typename($rettype); + + if ($paramsstr =~ /\(/) { + die("\n\n$0 FAILURE!\n" . + "There's a '(' in the parameters for function '$sym' '$incpath/$dent'.\n" . + "This usually means there's a parameter that's a function pointer type.\n" . + "This causes problems for wikiheaders.pl and is less readable, too.\n" . + "Please put that function pointer into a typedef,\n" . + "and use the new type in this function's signature instead!\n\n"); + } + + my @params = split(/,/, $paramsstr); + my $dotdotdot = 0; + foreach (@params) { + my $p = $_; + $p =~ s/\A\s+//; + $p =~ s/\s+\Z//; + if (($p eq 'void') || ($p eq '')) { + die("Void parameter in a function with multiple params?! ('$sym' in '$incpath/$dent')") if (scalar(@params) != 1); + } elsif ($p eq '...') { + die("Mutiple '...' params?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); + $dotdotdot = 1; + push @paraminfo, '...'; + push @paraminfo, '...'; + } elsif ($p =~ /\A(.*)\s+([a-zA-Z0-9_\*\[\]]+)\Z/) { + die("Parameter after '...' param?! ('$sym' in '$incpath/$dent')") if ($dotdotdot); + my $t = $1; + my $n = $2; + if ($n =~ s/\A(\*+)//) { + $t .= $1; # move any `*` that stuck to the name over. + } + if ($n =~ s/\[\]\Z//) { + $t = "$t*"; # move any `[]` that stuck to the name over, as a pointer. + } + $t = sanitize_c_typename($t); + #print("$t\n"); + #print("$n\n"); + push @paraminfo, $n; + push @paraminfo, $t; + } else { + die("Unexpected parameter '$p' in function '$sym' in '$incpath/$dent'!"); + } + } + + if (!$is_forced_inline) { # don't do with forced-inline because we don't want the implementation inserted in the wiki. + my $shrink_length = 0; + + $decl = ''; # rebuild this with the line breaks, since it looks better for syntax highlighting. + foreach (@decllines) { + if ($decl eq '') { + my $temp; + + $decl = $_; + $temp = $decl; + $temp =~ s/\Aextern\s+(SDL_DEPRECATED\s+|)(SDLMAIN_|SDL_)?DECLSPEC\w*\s+(.*?)\s+(\*?)SDLCALL\s+/$3$4 /; + $shrink_length = length($decl) - length($temp); + $decl = $temp; + } else { + my $trimmed = $_; + $trimmed =~ s/\A\s{$shrink_length}//; # shrink to match the removed "extern SDL_DECLSPEC SDLCALL " + $decl .= $trimmed; + } + $decl .= "\n"; + } + } - if (not $decl =~ /\)\s*;/) { + $decl = strip_fn_declaration_metadata($decl); + + # !!! FIXME: code duplication with typedef processing, below. + # We assume any `#define`s directly after the function are related to it: probably bitflags for an integer typedef. + # We'll also allow some other basic preprocessor lines. + # Blank lines are allowed, anything else, even comments, are not. + my $blank_lines = 0; + my $lastpos = tell(FH); + my $lastlineno = $lineno; + my $additional_decl = ''; + my $saw_define = 0; while () { chomp; - push @decllines, $_; - s/\A\s+//; - s/\s+\Z//; - $decl .= " $_"; - last if /\)\s*;/; + + $lineno++; + + if (/\A\s*\Z/) { + $blank_lines++; + } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { + if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { + $referenceonly{$1} = $sym; + $saw_define = 1; + } elsif (!$saw_define) { + # if the first non-blank thing isn't a #define, assume we're done. + seek(FH, $lastpos, 0); # re-read eaten lines again next time. + $lineno = $lastlineno; + last; + } + + # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. + + # At Sam's request, don't list property defines with functions. (See #9440) + my $is_property = /\A\s*\#\s*define\s+SDL_PROP_/; + if (!$is_property) { + if ($blank_lines > 0) { + while ($blank_lines > 0) { + $additional_decl .= "\n"; + push @decllines, ''; + $blank_lines--; + } + } + $additional_decl .= "\n$_"; + push @decllines, $_; + $lastpos = tell(FH); + } + } else { + seek(FH, $lastpos, 0); # re-read eaten lines again next time. + $lineno = $lastlineno; + last; + } } - } + $decl .= $additional_decl; - $decl =~ s/\s+\);\Z/);/; - $decl =~ s/\s+\Z//; - #print("DECL: [$decl]\n"); + } elsif ($symtype == 2) { # a macro + if ($decl =~ /\A\s*\#\s*define\s+(.*?)(\(.*?\)|)\s+/) { + $sym = $1; + } else { + #print "Found doxygen but no macro:\n$str\n\n"; + foreach (@templines) { + push @contents, $_; + } + foreach (@decllines) { + push @contents, $_; + } + next; + } - my $fn = ''; - if ($decl =~ /\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC\s+(const\s+|)(unsigned\s+|)(.*?)\s*(\*?)\s*SDLCALL\s+(.*?)\s*\((.*?)\);/) { - $fn = $6; - #$decl =~ s/\A\s*extern\s+DECLSPEC\s+(.*?)\s+SDLCALL/$1/; - } else { - #print "Found doxygen but no function sig:\n$str\n\n"; - foreach (@templines) { - push @contents, $_; + while ($decl =~ /\\\Z/) { + my $l = ; + last if not $l; + $lineno++; + chomp($l); + push @decllines, $l; + #$l =~ s/\A\s+//; + $l =~ s/\s+\Z//; + $decl .= "\n$l"; } - foreach (@decllines) { - push @contents, $_; + } elsif (($symtype == 3) || ($symtype == 4)) { # struct or union or enum + my $has_definition = 0; + if ($decl =~ /\A\s*(typedef\s+|)(struct|union|enum)\s*([a-zA-Z0-9_]*?)\s*(\n|\{|\;|\Z)/) { + my $ctype = $2; + my $origsym = $3; + my $ending = $4; + $sym = $origsym; + if ($sym =~ s/\A(.*?)(\s+)(.*?)\Z/$1/) { + die("Failed to parse '$origsym' correctly!") if ($sym ne $1); # Thought this was "typedef struct MySym MySym;" ... it was not. :( This is a hack! + } + if ($sym eq '') { + die("\n\n$0 FAILURE!\n" . + "There's a 'typedef $ctype' in $incpath/$dent without a name at the top.\n" . + "Instead of `typedef $ctype {} x;`, this should be `typedef $ctype x {} x;`.\n" . + "This causes problems for wikiheaders.pl and scripting language bindings.\n" . + "Please fix it!\n\n"); + } + $has_definition = ($ending ne ';'); + } else { + #print "Found doxygen but no datatype:\n$str\n\n"; + foreach (@templines) { + push @contents, $_; + } + foreach (@decllines) { + push @contents, $_; + } + next; } - next; - } - $decl = ''; # build this with the line breaks, since it looks better for syntax highlighting. - foreach (@decllines) { - if ($decl eq '') { - $decl = $_; - $decl =~ s/\Aextern\s+(SDL_DEPRECATED\s+|)DECLSPEC\s+(.*?)\s+(\*?)SDLCALL\s+/$2$3 /; + # This block attempts to find the whole struct/union/enum definition by counting matching brackets. Kind of yucky. + # It also "parses" enums enough to find out the elements of it. + if ($has_definition) { + my $started = 0; + my $brackets = 0; + my $pending = $decl; + my $skipping_comment = 0; + + $decl = ''; + while (!$started || ($brackets != 0)) { + foreach my $seg (split(/([{}])/, $pending)) { # (this will pick up brackets in comments! Be careful!) + $decl .= $seg; + if ($seg eq '{') { + $started = 1; + $brackets++; + } elsif ($seg eq '}') { + die("Something is wrong with header $incpath/$dent while parsing $sym; is a bracket missing?\n") if ($brackets <= 0); + $brackets--; + } + } + + if ($skipping_comment) { + if ($pending =~ s/\A.*?\*\///) { + $skipping_comment = 0; + } + } + + if (!$skipping_comment && $started && ($symtype == 4)) { # Pick out elements of an enum. + my $stripped = "$pending"; + $stripped =~ s/\/\*.*?\*\///g; # dump /* comments */ that exist fully on one line. + if ($stripped =~ /\/\*/) { # uhoh, a /* comment */ that crosses newlines. + $skipping_comment = 1; + } elsif ($stripped =~ /\A\s*([a-zA-Z0-9_]+)(.*)\Z/) { #\s*(\=\s*.*?|)\s*,?(.*?)\Z/) { + if ($1 ne 'typedef') { # make sure we didn't just eat the first line by accident. :/ + #print("ENUM [$1] $incpath/$dent:$lineno\n"); + $referenceonly{$1} = $sym; + } + } + } + + if (!$started || ($brackets != 0)) { + $pending = ; + die("EOF/error reading $incpath/$dent while parsing $sym\n") if not $pending; + $lineno++; + chomp($pending); + push @decllines, $pending; + $decl .= "\n"; + } + } + # this currently assumes the struct/union/enum ends on the line with the final bracket. I'm not writing a C parser here, fix the header! + } + } elsif ($symtype == 5) { # other typedef + if ($decl =~ /\A\s*typedef\s+(.*)\Z/) { + my $tdstr = $1; + + if (not $decl =~ /;/) { + while () { + chomp; + $lineno++; + push @decllines, $_; + s/\A\s+//; + s/\s+\Z//; + $decl .= " $_"; + last if /;/; + } + } + $decl =~ s/\s+(\))?;\Z/$1;/; + + $tdstr =~ s/;\s*\Z//; + + #my $datatype; + if ($tdstr =~ /\A(.*?)\s*\((.*?)\s*\*\s*(.*?)\)\s*\((.*?)(\))?/) { # a function pointer type + $sym = $3; + #$datatype = "$1 ($2 *$sym)($4)"; + } elsif ($tdstr =~ /\A(.*[\s\*]+)(.*?)\s*\Z/) { + $sym = $2; + #$datatype = $1; + } else { + die("Failed to parse typedef '$tdstr' in $incpath/$dent!\n"); # I'm hitting a C grammar nail with a regexp hammer here, y'all. + } + + $sym =~ s/\A\s+//; + $sym =~ s/\s+\Z//; + #$datatype =~ s/\A\s+//; + #$datatype =~ s/\s+\Z//; } else { - my $trimmed = $_; - # !!! FIXME: trim space for SDL_DEPRECATED if it was used, too. - $trimmed =~ s/\A\s{24}//; # 24 for shrinking to match the removed "extern DECLSPEC SDLCALL " - $decl .= $trimmed; + #print "Found doxygen but no datatype:\n$str\n\n"; + foreach (@templines) { + push @contents, $_; + } + foreach (@decllines) { + push @contents, $_; + } + next; + } + + # We assume any `#define`s directly after the typedef are related to it: probably bitflags for an integer typedef. + # We'll also allow some other basic preprocessor lines. + # Blank lines are allowed, anything else, even comments, are not. + my $blank_lines = 0; + my $lastpos = tell(FH); + my $lastlineno = $lineno; + my $additional_decl = ''; + my $saw_define = 0; + while () { + chomp; + + $lineno++; + + if (/\A\s*\Z/) { + $blank_lines++; + } elsif (/\A\s*\#\s*(define|if|else|elif|endif)(\s+|\Z)/) { + if (/\A\s*\#\s*define\s+([a-zA-Z0-9_]*)/) { + $referenceonly{$1} = $sym; + $saw_define = 1; + } elsif (!$saw_define) { + # if the first non-blank thing isn't a #define, assume we're done. + seek(FH, $lastpos, 0); # re-read eaten lines again next time. + $lineno = $lastlineno; + last; + } + # update strings now that we know everything pending is to be applied to this declaration. Add pending blank lines and the new text. + if ($blank_lines > 0) { + while ($blank_lines > 0) { + $additional_decl .= "\n"; + push @decllines, ''; + $blank_lines--; + } + } + $additional_decl .= "\n$_"; + push @decllines, $_; + $lastpos = tell(FH); + } else { + seek(FH, $lastpos, 0); # re-read eaten lines again next time. + $lineno = $lastlineno; + last; + } } - $decl .= "\n"; + $decl .= $additional_decl; + } else { + die("Unexpected symtype $symtype"); } - #print("$fn:\n$str\n\n"); + #print("DECL: [$decl]\n"); + + #print("$sym:\n$str\n\n"); # There might be multiple declarations of a function due to #ifdefs, # and only one of them will have documentation. If we hit an # undocumented one before, delete the placeholder line we left for # it so it doesn't accumulate a new blank line on each run. - my $skipfn = 0; - if (defined $headerfuncshasdoxygen{$fn}) { - if ($headerfuncshasdoxygen{$fn} == 0) { # An undocumented declaration already exists, nuke its placeholder line. - delete $contents[$headerfuncschunk{$fn}]; # delete DOES NOT RENUMBER existing elements! + my $skipsym = 0; + if (defined $headersymshasdoxygen{$sym}) { + if ($headersymshasdoxygen{$sym} == 0) { # An undocumented declaration already exists, nuke its placeholder line. + delete $contents[$headersymschunk{$sym}]; # delete DOES NOT RENUMBER existing elements! } else { # documented function already existed? - $skipfn = 1; # don't add this copy to the list of functions. + $skipsym = 1; # don't add this copy to the list of functions. if ($has_doxygen) { - print STDERR "WARNING: Function '$fn' appears to be documented in multiple locations. Only keeping the first one we saw!\n"; + print STDERR "WARNING: Symbol '$sym' appears to be documented in multiple locations. Only keeping the first one we saw!\n"; } - push @contents, join("\n", @decllines); # just put the existing declation in as-is. + push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); # just put the existing declation in as-is. } } - if (!$skipfn) { - $headerfuncs{$fn} = $str; - $headerdecls{$fn} = $decl; - $headerfuncslocation{$fn} = $dent; - $headerfuncschunk{$fn} = scalar(@contents); - $headerfuncshasdoxygen{$fn} = $has_doxygen; + if (!$skipsym) { + $headersymscategory{$sym} = $current_wiki_category if defined $current_wiki_category; + $headersyms{$sym} = $str; + $headerdecls{$sym} = $decl; + $headersymslocation{$sym} = $dent; + $headersymschunk{$sym} = scalar(@contents); + $headersymshasdoxygen{$sym} = $has_doxygen; + $headersymstype{$sym} = $symtype; + $headersymsparaminfo{$sym} = \@paraminfo if (scalar(@paraminfo) > 0); + $headersymsrettype{$sym} = $rettype if (defined($rettype)); push @contents, join("\n", @templines); - push @contents, join("\n", @decllines); + push @contents, join("\n", @decllines) if (scalar(@decllines) > 0); } } @@ -681,12 +1313,6 @@ sub usage { closedir(DH); -# !!! FIXME: we need to parse enums and typedefs and structs and defines and and and and and... -# !!! FIXME: (but functions are good enough for now.) - -my %wikitypes = (); # contains string of wiki page extension, like $wikitypes{"SDL_OpenAudio"} == 'mediawiki' -my %wikifuncs = (); # contains references to hash of strings, each string being the full contents of a section of a wiki page, like $wikifuncs{"SDL_OpenAudio"}{"Remarks"}. -my %wikisectionorder = (); # contains references to array, each array item being a key to a wikipage section in the correct order, like $wikisectionorder{"SDL_OpenAudio"}[2] == 'Remarks' opendir(DH, $wikipath) or die("Can't opendir '$wikipath': $!\n"); while (my $d = readdir(DH)) { my $dent = $d; @@ -697,17 +1323,48 @@ sub usage { next; # only dealing with wiki pages. } - my $fn = $dent; - $fn =~ s/\..*\Z//; + my $sym = $dent; + $sym =~ s/\..*\Z//; + # (There are other pages to ignore, but these are known ones to not bother parsing.) # Ignore FrontPage. - next if $fn eq 'FrontPage'; - - # Ignore "Category*" pages. - next if ($fn =~ /\ACategory/); + next if $sym eq 'FrontPage'; open(FH, '<', "$wikipath/$dent") or die("Can't open '$wikipath/$dent': $!\n"); + if ($sym =~ /\ACategory(.*?)\Z/) { # Special case for Category pages. + # Find the end of the category documentation in the existing file and append everything else to the new file. + my $cat = $1; + my $docstr = ''; + my $notdocstr = ''; + my $docs = 1; + while () { + chomp; + if ($docs) { + $docs = 0 if /\A\-\-\-\-\Z/; # Hit a footer? We're done. + $docs = 0 if /\A', $path) or die("Can't open '$path': $!\n"); - - print FH "# Undocumented\n\n"; - - print FH "## Functions defined in the headers, but not in the wiki\n\n"; - my $header_only_func = 0; - foreach (sort keys %headerfuncs) { - my $fn = $_; - if (not defined $wikifuncs{$fn}) { - print FH "- [$fn]($fn)\n"; - $header_only_func = 1; - } - } - if (!$header_only_func) { - print FH "(none)\n"; - } - print FH "\n"; - - print FH "## Functions defined in the wiki, but not in the headers\n\n"; + open(my $fh, '>', $path) or die("Can't open '$path': $!\n"); - my $wiki_only_func = 0; - foreach (sort keys %wikifuncs) { - my $fn = $_; - if (not defined $headerfuncs{$fn}) { - print FH "- [$fn]($fn)\n"; - $wiki_only_func = 1; - } - } - if (!$wiki_only_func) { - print FH "(none)\n"; - } - print FH "\n"; + print $fh "# Undocumented\n\n"; + print_undocumented_section($fh, 'Functions', 1); + #print_undocumented_section($fh, 'Macros', 2); - close(FH); + close($fh); } if ($warn_about_missing) { - foreach (keys %wikifuncs) { - my $fn = $_; - if (not defined $headerfuncs{$fn}) { - print("WARNING: $fn defined in the wiki but not the headers!\n"); + foreach (keys %wikisyms) { + my $sym = $_; + if (not defined $headersyms{$sym}) { + print STDERR "WARNING: $sym defined in the wiki but not the headers!\n"; } } - foreach (keys %headerfuncs) { - my $fn = $_; - if (not defined $wikifuncs{$fn}) { - print("WARNING: $fn defined in the headers but not the wiki!\n"); + foreach (keys %headersyms) { + my $sym = $_; + if (not defined $wikisyms{$sym}) { + print STDERR "WARNING: $sym defined in the headers but not the wiki!\n"; } } } @@ -860,24 +1498,45 @@ sub usage { $dewikify_mode = 'md'; $wordwrap_mode = 'md'; # the headers use Markdown format. - foreach (keys %headerfuncs) { - my $fn = $_; - next if not defined $wikifuncs{$fn}; # don't have a page for that function, skip it. - my $wikitype = $wikitypes{$fn}; - my $sectionsref = $wikifuncs{$fn}; + foreach (keys %headersyms) { + my $sym = $_; + next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. + my $symtype = $headersymstype{$sym}; + my $wikitype = $wikitypes{$sym}; + my $sectionsref = $wikisyms{$sym}; my $remarks = $sectionsref->{'Remarks'}; - my $params = $sectionsref->{'Function Parameters'}; my $returns = $sectionsref->{'Return Value'}; my $threadsafety = $sectionsref->{'Thread Safety'}; my $version = $sectionsref->{'Version'}; - my $related = $sectionsref->{'Related Functions'}; + my $related = $sectionsref->{'See Also'}; my $deprecated = $sectionsref->{'Deprecated'}; my $brief = $sectionsref->{'[Brief]'}; my $addblank = 0; my $str = ''; - $headerfuncshasdoxygen{$fn} = 1; # Added/changed doxygen for this header. - + my $params = undef; + my $paramstr = undef; + + if ($symtype == -1) { # category documentation block. + # nothing to be done here. + } elsif (($symtype == 1) || (($symtype == 5))) { # we'll assume a typedef (5) with a \param is a function pointer typedef. + $params = $sectionsref->{'Function Parameters'}; + $paramstr = '\param'; + } elsif ($symtype == 2) { + $params = $sectionsref->{'Macro Parameters'}; + $paramstr = '\param'; + } elsif ($symtype == 3) { + $params = $sectionsref->{'Fields'}; + $paramstr = '\field'; + } elsif ($symtype == 4) { + $params = $sectionsref->{'Values'}; + $paramstr = '\value'; + } else { + die("Unexpected symtype $symtype"); + } + + $headersymshasdoxygen{$sym} = 1; # Added/changed doxygen for this header. + $brief = dewikify($wikitype, $brief); $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. my @briefsplit = split /\n/, $brief; @@ -918,21 +1577,32 @@ sub usage { if ($wikitype eq 'mediawiki') { die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start while (scalar(@lines) >= 3) { + my $c_datatype = shift @lines; my $name = shift @lines; my $desc = shift @lines; - my $terminator = shift @lines; # the '|-' or '|}' line. + my $terminator; # the '|-' or '|}' line. + + if (($desc eq '|-') or ($desc eq '|}') or (not $desc =~ /\A\|/)) { # we seem to be out of cells, which means there was no datatype column on this one. + $terminator = $desc; + $desc = $name; + $name = $c_datatype; + $c_datatype = ''; + } else { + $terminator = shift @lines; + } + last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. $name =~ s/\A\|\s*//; $name =~ s/\A\*\*(.*?)\*\*/$1/; $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; $desc =~ s/\A\|\s*//; - #print STDERR "FN: $fn NAME: $name DESC: $desc TERM: $terminator\n"; + #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; my $whitespacelen = length($name) + 8; my $whitespace = ' ' x $whitespacelen; $desc = wordwrap($desc, -$whitespacelen); my @desclines = split /\n/, $desc; my $firstline = shift @desclines; - $str .= "\\param $name $firstline\n"; + $str .= "$paramstr $name $firstline\n"; foreach (@desclines) { $str .= "${whitespace}$_\n"; } @@ -940,29 +1610,36 @@ sub usage { } elsif ($wikitype eq 'md') { my $l; $l = shift @lines; - die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*\|\s*\|\s*\|\s*\Z/); + die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); $l = shift @lines; - die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); + die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); while (scalar(@lines) >= 1) { $l = shift @lines; - if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { - my $name = $1; - my $desc = $2; - $name =~ s/\A\*\*(.*?)\*\*/$1/; - $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; - #print STDERR "FN: $fn NAME: $name DESC: $desc\n"; - my $whitespacelen = length($name) + 8; - my $whitespace = ' ' x $whitespacelen; - $desc = wordwrap($desc, -$whitespacelen); - my @desclines = split /\n/, $desc; - my $firstline = shift @desclines; - $str .= "\\param $name $firstline\n"; - foreach (@desclines) { - $str .= "${whitespace}$_\n"; - } + my $name; + my $desc; + if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + # c datatype is $1, but we don't care about it here. + $name = $2; + $desc = $3; + } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + $name = $1; + $desc = $2; } else { last; # we seem to have run out of table. } + + $name =~ s/\A\*\*(.*?)\*\*/$1/; + $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; + #print STDERR "SYM: $sym NAME: $name DESC: $desc\n"; + my $whitespacelen = length($name) + 8; + my $whitespace = ' ' x $whitespacelen; + $desc = wordwrap($desc, -$whitespacelen); + my @desclines = split /\n/, $desc; + my $firstline = shift @desclines; + $str .= "$paramstr $name $firstline\n"; + foreach (@desclines) { + $str .= "${whitespace}$_\n"; + } } } else { die("write me"); @@ -972,8 +1649,9 @@ sub usage { if (defined $returns) { $str .= "\n" if $addblank; $addblank = 1; my $r = dewikify($wikitype, $returns); + $r =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. my $retstr = "\\returns"; - if ($r =~ s/\AReturn(s?) //) { + if ($r =~ s/\AReturn(s?)\s+//) { $retstr = "\\return$1"; } @@ -1024,18 +1702,20 @@ sub usage { my $v = dewikify($wikitype, $related); my @desclines = split /\n/, $v; foreach (@desclines) { - s/\A(\:|\* )//; s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. s/\A\/*//; + s/\A\s*[\:\*\-]\s*//; + s/\A\s+//; + s/\s+\Z//; $str .= "\\sa $_\n"; } } - my $header = $headerfuncslocation{$fn}; + my $header = $headersymslocation{$sym}; my $contentsref = $headers{$header}; - my $chunk = $headerfuncschunk{$fn}; + my $chunk = $headersymschunk{$sym}; my @lines = split /\n/, $str; @@ -1053,10 +1733,10 @@ sub usage { } $output .= " */"; - #print("$fn:\n$output\n\n"); + #print("$sym:\n[$output]\n\n"); $$contentsref[$chunk] = $output; - #$$contentsref[$chunk+1] = $headerdecls{$fn}; + #$$contentsref[$chunk+1] = $headerdecls{$sym}; $changed_headers{$header} = 1; } @@ -1066,12 +1746,12 @@ sub usage { # this is kinda inefficient, but oh well. my @removelines = (); - foreach (keys %headerfuncslocation) { - my $fn = $_; - next if $headerfuncshasdoxygen{$fn}; - next if $headerfuncslocation{$fn} ne $header; + foreach (keys %headersymslocation) { + my $sym = $_; + next if $headersymshasdoxygen{$sym}; + next if $headersymslocation{$sym} ne $header; # the index of the blank line we put before the function declaration in case we needed to replace it with new content from the wiki. - push @removelines, $headerfuncschunk{$fn}; + push @removelines, $headersymschunk{$sym}; } my $contentsref = $headers{$header}; @@ -1102,6 +1782,7 @@ sub usage { closedir(DH); } } + } elsif ($copy_direction == -1) { # --copy-to-wiki if (defined $changeformat) { @@ -1109,18 +1790,20 @@ sub usage { $wordwrap_mode = $changeformat; } - foreach (keys %headerfuncs) { - my $fn = $_; - next if not $headerfuncshasdoxygen{$fn}; - my $origwikitype = defined $wikitypes{$fn} ? $wikitypes{$fn} : 'md'; # default to MarkDown for new stuff. + foreach (keys %headersyms) { + my $sym = $_; + next if not $headersymshasdoxygen{$sym}; + next if $sym =~ /\A\[category documentation\]/; # not real symbols, we handle this elsewhere. + my $symtype = $headersymstype{$sym}; + my $origwikitype = defined $wikitypes{$sym} ? $wikitypes{$sym} : 'md'; # default to MarkDown for new stuff. my $wikitype = (defined $changeformat) ? $changeformat : $origwikitype; - die("Unexpected wikitype '$wikitype'\n") if (($wikitype ne 'mediawiki') and ($wikitype ne 'md') and ($wikitype ne 'manpage')); + die("Unexpected wikitype '$wikitype'") if (($wikitype ne 'mediawiki') and ($wikitype ne 'md') and ($wikitype ne 'manpage')); - #print("$fn\n"); next; + #print("$sym\n"); next; $wordwrap_mode = $wikitype; - my $raw = $headerfuncs{$fn}; # raw doxygen text with comment characters stripped from start/end and start of each line. + my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. next if not defined $raw; $raw =~ s/\A\s*\\brief\s+//; # Technically we don't need \brief (please turn on JAVADOC_AUTOBRIEF if you use Doxygen), so just in case one is present, strip it. @@ -1136,27 +1819,20 @@ sub usage { $brief .= "$l "; } + $brief =~ s/\s+\Z//; $brief =~ s/\A(.*?\.) /$1\n\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. my @briefsplit = split /\n/, $brief; + + next if not defined $briefsplit[0]; # No brief text? Probably a bogus Doxygen comment, skip it. + $brief = wikify($wikitype, shift @briefsplit) . "\n"; @doxygenlines = (@briefsplit, @doxygenlines); my $remarks = ''; - # !!! FIXME: wordwrap and wikify might handle this, now. while (@doxygenlines) { last if $doxygenlines[0] =~ /\A\\/; # some sort of doxygen command, assume we're past the general remarks. my $l = shift @doxygenlines; - if ($l =~ /\A\`\`\`/) { # syntax highlighting, don't reformat. - $remarks .= "$l\n"; - while ((@doxygenlines) && (not $l =~ /\`\`\`\Z/)) { - $l = shift @doxygenlines; - $remarks .= "$l\n"; - } - } else { - $l =~ s/\A\s*//; - $l =~ s/\s*\Z//; - $remarks .= "$l\n"; - } + $remarks .= "$l\n"; } #print("REMARKS:\n\n $remarks\n\n"); @@ -1165,29 +1841,32 @@ sub usage { $remarks =~ s/\A\s*//; $remarks =~ s/\s*\Z//; - my $decl = $headerdecls{$fn}; - #$decl =~ s/\*\s+SDLCALL/ *SDLCALL/; # Try to make "void * Function" become "void *Function" - #$decl =~ s/\A\s*extern\s+(SDL_DEPRECATED\s+|)DECLSPEC\s+(.*?)\s+(\*?)SDLCALL/$2$3/; + my $decl = $headerdecls{$sym}; my $syntax = ''; if ($wikitype eq 'mediawiki') { $syntax = "\n$decl\n"; } elsif ($wikitype eq 'md') { + $decl =~ s/\n+\Z//; $syntax = "```c\n$decl\n```\n"; - } else { die("Expected wikitype '$wikitype'\n"); } + } else { die("Expected wikitype '$wikitype'"); } my %sections = (); $sections{'[Brief]'} = $brief; # include this section even if blank so we get a title line. $sections{'Remarks'} = "$remarks\n" if $remarks ne ''; $sections{'Syntax'} = $syntax; - my @params = (); # have to parse these and build up the wiki tables after, since Markdown needs to know the length of the largest string. :/ + my %params = (); # have to parse these and build up the wiki tables after, since Markdown needs to know the length of the largest string. :/ + my @paramsorder = (); + my $fnsigparams = $headersymsparaminfo{$sym}; + my $has_returns = 0; while (@doxygenlines) { my $l = shift @doxygenlines; - if ($l =~ /\A\\param\s+(.*?)\s+(.*)\Z/) { - my $arg = $1; - my $desc = $2; + # We allow param/field/value interchangeably, even if it doesn't make sense. The next --copy-to-headers will correct it anyhow. + if ($l =~ /\A\\(param|field|value)\s+(.*?)\s+(.*)\Z/) { + my $arg = $2; + my $desc = $3; while (@doxygenlines) { my $subline = $doxygenlines[0]; $subline =~ s/\A\s*//; @@ -1202,12 +1881,40 @@ sub usage { $desc =~ s/[\s\n]+\Z//ms; + if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. + if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { + print STDERR "WARNING: $sym\'s '\\param $arg' text starts with a capital letter: '$desc'. Fixing.\n"; + $desc = lcfirst($desc); + } + } + + if (not $desc =~ /[\.\!]\Z/) { + print STDERR "WARNING: $sym\'s '\\param $arg' text doesn't end with punctuation: '$desc'. Fixing.\n"; + $desc .= '.'; + } + + # Validate this param. + if (defined($params{$arg})) { + print STDERR "WARNING: Symbol '$sym' has multiple '\\param $arg' declarations! Only keeping the first one!\n"; + } elsif (defined $fnsigparams) { + my $found = 0; + for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { + $found = 1, last if (@$fnsigparams[$i] eq $arg); + } + if (!$found) { + print STDERR "WARNING: Symbol '$sym' has a '\\param $arg' for a param that doesn't exist. It will be removed!\n"; + } + } + # We need to know the length of the longest string to make Markdown tables, so we just store these off until everything is parsed. - push @params, $arg; - push @params, $desc; + $params{$arg} = $desc; + push @paramsorder, $arg; } elsif ($l =~ /\A\\r(eturns?)\s+(.*)\Z/) { + $has_returns = 1; + # !!! FIXME: complain if this isn't a function or macro. my $retstr = "R$1"; # "Return" or "Returns" my $desc = $2; + while (@doxygenlines) { my $subline = $doxygenlines[0]; $subline =~ s/\A\s*//; @@ -1220,7 +1927,32 @@ sub usage { } } $desc =~ s/[\s\n]+\Z//ms; - $sections{'Return Value'} = wordwrap("$retstr " . wikify($wikitype, $desc)) . "\n"; + + if (0) { # !!! FIXME: disabled because it's not currently suitable for general use, but for manually inspecting the output, it can be useful. + if (($desc =~ /\A[A-Z]/) && (not $desc =~ /\ASDL_/)) { + print STDERR "WARNING: $sym\'s '\\returns' text starts with a capital letter: '$desc'. Fixing.\n"; + $desc = lcfirst($desc); + } + } + + if (not $desc =~ /[\.\!]\Z/) { + print STDERR "WARNING: $sym\'s '\\returns' text doesn't end with punctuation: '$desc'. Fixing.\n"; + $desc .= '.'; + } + + # Make sure the \returns info is valid. + my $rettype = $headersymsrettype{$sym}; + die("Don't have a rettype for '$sym' for some reason!") if (($symtype == 1) && (not defined($rettype))); + if (defined($sections{'Return Value'})) { + print STDERR "WARNING: Symbol '$sym' has multiple '\\return' declarations! Only keeping the first one!\n"; + } elsif (($symtype != 1) && ($symtype != 2) && ($symtype != 5)) { # !!! FIXME: if 5, make sure it's a function pointer typedef! + print STDERR "WARNING: Symbol '$sym' has a '\\return' declaration but isn't a function or macro! Removing it!\n"; + } elsif (($symtype == 1) && ($headersymsrettype{$sym} eq 'void')) { + print STDERR "WARNING: Function '$sym' has a '\\returns' declaration but function returns void! Removing it!\n"; + } else { + my $rettypestr = defined($rettype) ? ('(' . wikify($wikitype, $rettype) . ') ') : ''; + $sections{'Return Value'} = wordwrap("$rettypestr$retstr ". wikify($wikitype, $desc)) . "\n"; + } } elsif ($l =~ /\A\\deprecated\s+(.*)\Z/) { my $desc = $1; while (@doxygenlines) { @@ -1269,43 +2001,108 @@ sub usage { } elsif ($l =~ /\A\\sa\s+(.*)\Z/) { my $sa = $1; $sa =~ s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" - $sections{'Related Functions'} = '' if not defined $sections{'Related Functions'}; + $sections{'See Also'} = '' if not defined $sections{'See Also'}; if ($wikitype eq 'mediawiki') { - $sections{'Related Functions'} .= ":[[$sa]]\n"; + $sections{'See Also'} .= ":[[$sa]]\n"; } elsif ($wikitype eq 'md') { - $sections{'Related Functions'} .= "* [$sa]($sa)\n"; - } else { die("Expected wikitype '$wikitype'\n"); } + $sections{'See Also'} .= "- [$sa]($sa)\n"; + } else { die("Expected wikitype '$wikitype'"); } + } + } + + if (($symtype == 1) && ($headersymsrettype{$sym} ne 'void') && !$has_returns) { + print STDERR "WARNING: Function '$sym' has a non-void return type but no '\\returns' declaration\n"; + } + + # Make sure %params is in the same order as the actual function signature and add C datatypes... + my $params_has_c_datatype = 0; + my @final_params = (); + if (($symtype == 1) && (defined($headersymsparaminfo{$sym}))) { # is a function and we have param info for it... + my $fnsigparams = $headersymsparaminfo{$sym}; + for (my $i = 0; $i < scalar(@$fnsigparams); $i += 2) { + my $paramname = @$fnsigparams[$i]; + my $paramdesc = $params{$paramname}; + if (defined($paramdesc)) { + push @final_params, $paramname; # name + push @final_params, @$fnsigparams[$i+1]; # C datatype + push @final_params, $paramdesc; # description + $params_has_c_datatype = 1 if (defined(@$fnsigparams[$i+1])); + } else { + print STDERR "WARNING: Symbol '$sym' is missing a '\\param $paramname' declaration!\n"; + } + } + } else { + foreach (@paramsorder) { + my $paramname = $_; + my $paramdesc = $params{$paramname}; + if (defined($paramdesc)) { + push @final_params, $_; + push @final_params, undef; + push @final_params, $paramdesc; + } } } my $hfiletext = $wikiheaderfiletext; - $hfiletext =~ s/\%fname\%/$headerfuncslocation{$fn}/g; + $hfiletext =~ s/\%fname\%/$headersymslocation{$sym}/g; $sections{'Header File'} = "$hfiletext\n"; # Make sure this ends with a double-newline. - $sections{'Related Functions'} .= "\n" if defined $sections{'Related Functions'}; + $sections{'See Also'} .= "\n" if defined $sections{'See Also'}; + + if (0) { # !!! FIXME: this was a useful hack, but this needs to be generalized if we're going to do this always. + # Plug in a \since section if one wasn't listed. + if (not defined $sections{'Version'}) { + my $symtypename; + if ($symtype == 1) { + $symtypename = 'function'; + } elsif ($symtype == 2) { + $symtypename = 'macro'; + } elsif ($symtype == 3) { + $symtypename = 'struct'; + } elsif ($symtype == 4) { + $symtypename = 'enum'; + } elsif ($symtype == 5) { + $symtypename = 'datatype'; + } else { + die("Unexpected symbol type $symtype!"); + } + my $str = "This $symtypename is available since SDL 3.0.0."; + $sections{'Version'} = wordwrap(wikify($wikitype, $str)) . "\n"; + } + } # We can build the wiki table now that we have all the data. - if (scalar(@params) > 0) { + if (scalar(@final_params) > 0) { my $str = ''; if ($wikitype eq 'mediawiki') { - while (scalar(@params) > 0) { - my $arg = shift @params; - my $desc = wikify($wikitype, shift @params); + while (scalar(@final_params) > 0) { + my $arg = shift @final_params; + my $c_datatype = shift @final_params; + my $desc = wikify($wikitype, shift @final_params); + $c_datatype = '' if not defined $c_datatype; $str .= ($str eq '') ? "{|\n" : "|-\n"; + $str .= "|$c_datatype\n" if $params_has_c_datatype; $str .= "|'''$arg'''\n"; $str .= "|$desc\n"; } $str .= "|}\n"; } elsif ($wikitype eq 'md') { my $longest_arg = 0; + my $longest_c_datatype = 0; my $longest_desc = 0; my $which = 0; - foreach (@params) { + foreach (@final_params) { if ($which == 0) { - my $len = length($_) + 4; + my $len = length($_); $longest_arg = $len if ($len > $longest_arg); $which = 1; + } elsif ($which == 1) { + if (defined($_)) { + my $len = length(wikify($wikitype, $_)); + $longest_c_datatype = $len if ($len > $longest_c_datatype); + } + $which = 2; } else { my $len = length(wikify($wikitype, $_)); $longest_desc = $len if ($len > $longest_desc); @@ -1314,24 +2111,33 @@ sub usage { } # Markdown tables are sort of obnoxious. - $str .= '| ' . (' ' x ($longest_arg+4)) . ' | ' . (' ' x $longest_desc) . " |\n"; - $str .= '| ' . ('-' x ($longest_arg+4)) . ' | ' . ('-' x $longest_desc) . " |\n"; - - while (@params) { - my $arg = shift @params; - my $desc = wikify($wikitype, shift @params); - $str .= "| **$arg** " . (' ' x ($longest_arg - length($arg))) . "| $desc" . (' ' x ($longest_desc - length($desc))) . " |\n"; + my $c_datatype_cell; + $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . (' ' x ($longest_c_datatype)) . ' ') : ''; + $str .= $c_datatype_cell . '| ' . (' ' x ($longest_arg+4)) . ' | ' . (' ' x $longest_desc) . " |\n"; + $c_datatype_cell = ($longest_c_datatype > 0) ? ('| ' . ('-' x ($longest_c_datatype)) . ' ') : ''; + $str .= $c_datatype_cell . '| ' . ('-' x ($longest_arg+4)) . ' | ' . ('-' x $longest_desc) . " |\n"; + + while (@final_params) { + my $arg = shift @final_params; + my $c_datatype = shift @final_params; + $c_datatype_cell = ''; + if ($params_has_c_datatype) { + $c_datatype = defined($c_datatype) ? wikify($wikitype, $c_datatype) : ''; + $c_datatype_cell = ($longest_c_datatype > 0) ? ("| $c_datatype " . (' ' x ($longest_c_datatype - length($c_datatype)))) : ''; + } + my $desc = wikify($wikitype, shift @final_params); + $str .= $c_datatype_cell . "| **$arg** " . (' ' x ($longest_arg - length($arg))) . "| $desc" . (' ' x ($longest_desc - length($desc))) . " |\n"; } } else { - die("Unexpected wikitype!\n"); # should have checked this elsewhere. + die("Unexpected wikitype!"); # should have checked this elsewhere. } $sections{'Function Parameters'} = $str; } - my $path = "$wikipath/$_.${wikitype}.tmp"; + my $path = "$wikipath/$sym.${wikitype}.tmp"; open(FH, '>', $path) or die("Can't open '$path': $!\n"); - my $sectionsref = $wikifuncs{$fn}; + my $sectionsref = $wikisyms{$sym}; foreach (@standard_wiki_sections) { # drop sections we either replaced or removed from the original wiki's contents. @@ -1340,7 +2146,7 @@ sub usage { } } - my $wikisectionorderref = $wikisectionorder{$fn}; + my $wikisectionorderref = $wikisectionorder{$sym}; # Make sure there's a footer in the wiki that puts this function in CategoryAPI... if (not $$sectionsref{'[footer]'}) { @@ -1364,25 +2170,46 @@ sub usage { } } - # !!! FIXME: This won't be CategoryAPI if we eventually handle things other than functions. - my $footer = $$sectionsref{'[footer]'}; - - if ($wikitype eq 'mediawiki') { - $footer =~ s/\[\[CategoryAPI\]\],?\s*//g; - $footer = '[[CategoryAPI]]' . (($footer eq '') ? "\n" : ", $footer"); - } elsif ($wikitype eq 'md') { - $footer =~ s/\[CategoryAPI\]\(CategoryAPI\),?\s*//g; - $footer = '[CategoryAPI](CategoryAPI)' . (($footer eq '') ? '' : ', ') . $footer; - } else { die("Unexpected wikitype '$wikitype'\n"); } - $$sectionsref{'[footer]'} = $footer; + if ($symtype != -1) { # Don't do these in category documentation block + my $footer = $$sectionsref{'[footer]'}; + + my $symtypename; + if ($symtype == 1) { + $symtypename = 'Function'; + } elsif ($symtype == 2) { + $symtypename = 'Macro'; + } elsif ($symtype == 3) { + $symtypename = 'Struct'; + } elsif ($symtype == 4) { + $symtypename = 'Enum'; + } elsif ($symtype == 5) { + $symtypename = 'Datatype'; + } else { + die("Unexpected symbol type $symtype!"); + } - if (defined $wikipreamble) { - my $wikified_preamble = wikify($wikitype, $wikipreamble); + my $symcategory = $headersymscategory{$sym}; if ($wikitype eq 'mediawiki') { - print FH "====== $wikified_preamble ======\n"; + $footer =~ s/\[\[CategoryAPI\]\],?\s*//g; + $footer =~ s/\[\[CategoryAPI${symtypename}\]\],?\s*//g; + $footer =~ s/\[\[Category${symcategory}\]\],?\s*//g if defined $symcategory; + $footer = "[[CategoryAPI]], [[CategoryAPI$symtypename]]" . (defined $symcategory ? ", [[Category$symcategory]]" : '') . (($footer eq '') ? "\n" : ", $footer"); } elsif ($wikitype eq 'md') { - print FH "###### $wikified_preamble\n"; - } else { die("Unexpected wikitype '$wikitype'\n"); } + $footer =~ s/\[CategoryAPI\]\(CategoryAPI\),?\s*//g; + $footer =~ s/\[CategoryAPI${symtypename}\]\(CategoryAPI${symtypename}\),?\s*//g; + $footer =~ s/\[Category${symcategory}\]\(Category${symcategory}\),?\s*//g if defined $symcategory; + $footer = "[CategoryAPI](CategoryAPI), [CategoryAPI$symtypename](CategoryAPI$symtypename)" . (defined $symcategory ? ", [Category$symcategory](Category$symcategory)" : '') . (($footer eq '') ? '' : ', ') . $footer; + } else { die("Unexpected wikitype '$wikitype'"); } + $$sectionsref{'[footer]'} = $footer; + + if (defined $wikipreamble) { + my $wikified_preamble = wikify($wikitype, $wikipreamble); + if ($wikitype eq 'mediawiki') { + print FH "====== $wikified_preamble ======\n"; + } elsif ($wikitype eq 'md') { + print FH "###### $wikified_preamble\n"; + } else { die("Unexpected wikitype '$wikitype'"); } + } } my $prevsectstr = ''; @@ -1392,6 +2219,7 @@ sub usage { next if $sect eq '[start]'; next if (not defined $sections{$sect} and not defined $$sectionsref{$sect}); my $section = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; + if ($sect eq '[footer]') { # Make sure previous section ends with two newlines. if (substr($prevsectstr, -1) ne "\n") { @@ -1402,16 +2230,32 @@ sub usage { print FH "----\n"; # It's the same in Markdown and MediaWiki. } elsif ($sect eq '[Brief]') { if ($wikitype eq 'mediawiki') { - print FH "= $fn =\n\n"; + print FH "= $sym =\n\n"; } elsif ($wikitype eq 'md') { - print FH "# $fn\n\n"; - } else { die("Unexpected wikitype '$wikitype'\n"); } + print FH "# $sym\n\n"; + } else { die("Unexpected wikitype '$wikitype'"); } } else { - if ($wikitype eq 'mediawiki') { - print FH "\n== $sect ==\n\n"; - } elsif ($wikitype eq 'md') { - print FH "\n## $sect\n\n"; - } else { die("Unexpected wikitype '$wikitype'\n"); } + my $sectname = $sect; + if ($sectname eq 'Function Parameters') { # We use this same table for different things depending on what we're documenting, so rename it now. + if (($symtype == 1) || ($symtype == 5)) { # function (or typedef, in case it's a function pointer type). + } elsif ($symtype == 2) { # macro + $sectname = 'Macro Parameters'; + } elsif ($symtype == 3) { # struct/union + $sectname = 'Fields'; + } elsif ($symtype == 4) { # enum + $sectname = 'Values'; + } else { + die("Unexpected symtype $symtype"); + } + } + + if ($symtype != -1) { # Not for category documentation block + if ($wikitype eq 'mediawiki') { + print FH "\n== $sectname ==\n\n"; + } elsif ($wikitype eq 'md') { + print FH "\n## $sectname\n\n"; + } else { die("Unexpected wikitype '$wikitype'"); } + } } my $sectstr = defined $sections{$sect} ? $sections{$sect} : $$sectionsref{$sect}; @@ -1435,6 +2279,99 @@ sub usage { rename($path, "$wikipath/$_.${wikitype}") or die("Can't rename '$path' to '$wikipath/$_.${wikitype}': $!\n"); } + # Write out simple redirector pages if they don't already exist. + foreach (keys %referenceonly) { + my $sym = $_; + my $refersto = $referenceonly{$sym}; + my $path = "$wikipath/$sym.md"; # we only do Markdown for these. + next if (-f $path); # don't overwrite if it already exists. Delete the file if you need a rebuild! + open(FH, '>', $path) or die("Can't open '$path': $!\n"); + + if (defined $wikipreamble) { + my $wikified_preamble = wikify('md', $wikipreamble); + print FH "###### $wikified_preamble\n"; + } + + my $category = 'CategoryAPIMacro'; + if ($headersymstype{$refersto} == 4) { + $category = 'CategoryAPIEnumerators'; # NOT CategoryAPIEnum! + } + + print FH "# $sym\n\nPlease refer to [$refersto]($refersto) for details.\n\n"; + print FH "----\n"; + print FH "[CategoryAPI](CategoryAPI), [$category]($category)\n\n"; + + close(FH); + } + + # Write out Category pages... + foreach (keys %headercategorydocs) { + my $cat = $_; + my $sym = $headercategorydocs{$cat}; # fake symbol + my $raw = $headersyms{$sym}; # raw doxygen text with comment characters stripped from start/end and start of each line. + my $wikitype = defined($wikitypes{$sym}) ? $wikitypes{$sym} : 'md'; + my $path = "$wikipath/Category$cat.$wikitype"; + + $raw = wordwrap(wikify($wikitype, $raw)); + + my $tmppath = "$path.tmp"; + open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); + print FH "$raw\n\n"; + + if (! -f $path) { # Doesn't exist at all? Write out a template file. + # If writing from scratch, it's always a Markdown file. + die("Unexpected wikitype '$wikitype'!") if $wikitype ne 'md'; + print FH <<__EOF__ + + + +## Functions + + + + + +## Datatypes + + + + + +## Structs + + + + + +## Enums + + + + + +## Macros + + + + + +---- +[CategoryAPICategory](CategoryAPICategory) + +__EOF__ +; + } else { + my $endstr = $wikisyms{$sym}->{'[footer]'}; + if (defined($endstr)) { + print FH $endstr; + } + } + + close(FH); + rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); + } + + # Write out READMEs... if (defined $readmepath) { if ( -d $readmepath ) { mkdir($wikireadmepath); # just in case @@ -1474,8 +2411,7 @@ sub usage { } elsif ($copy_direction == -2) { # --copy-to-manpages # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. - $manpath .= "/man3"; - File::Path::make_path($manpath); + File::Path::make_path("$manpath/man3"); $dewikify_mode = 'manpage'; $wordwrap_mode = 'manpage'; @@ -1499,39 +2435,53 @@ sub usage { open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); my $majorver = 0; my $minorver = 0; - my $patchver = 0; + my $microver = 0; while () { chomp; if (/$versionmajorregex/) { $majorver = int($1); } elsif (/$versionminorregex/) { $minorver = int($1); - } elsif (/$versionpatchregex/) { - $patchver = int($1); + } elsif (/$versionmicroregex/) { + $microver = int($1); } } close(FH); - my $fullversion = "$majorver.$minorver.$patchver"; - - foreach (keys %headerfuncs) { - my $fn = $_; - next if not defined $wikifuncs{$fn}; # don't have a page for that function, skip it. - my $wikitype = $wikitypes{$fn}; - my $sectionsref = $wikifuncs{$fn}; + my $fullversion = "$majorver.$minorver.$microver"; + + foreach (keys %headersyms) { + my $sym = $_; + next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. + next if $sym =~ /\A\[category documentation\]/; # not real symbols + my $symtype = $headersymstype{$sym}; + my $wikitype = $wikitypes{$sym}; + my $sectionsref = $wikisyms{$sym}; my $remarks = $sectionsref->{'Remarks'}; my $params = $sectionsref->{'Function Parameters'}; my $returns = $sectionsref->{'Return Value'}; my $version = $sectionsref->{'Version'}; my $threadsafety = $sectionsref->{'Thread Safety'}; - my $related = $sectionsref->{'Related Functions'}; + my $related = $sectionsref->{'See Also'}; my $examples = $sectionsref->{'Code Examples'}; my $deprecated = $sectionsref->{'Deprecated'}; my $headerfile = $manpageheaderfiletext; - $headerfile =~ s/\%fname\%/$headerfuncslocation{$fn}/g; + $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; $headerfile .= "\n"; + my $mansection; + my $mansectionname; + if (($symtype == 1) || ($symtype == 2)) { # functions or macros + $mansection = '3'; + $mansectionname = 'FUNCTIONS'; + } elsif (($symtype >= 3) && ($symtype <= 5)) { # struct/union/enum/typedef + $mansection = '3type'; + $mansectionname = 'DATATYPES'; + } else { + die("Unexpected symtype $symtype"); + } + my $brief = $sectionsref->{'[Brief]'}; - my $decl = $headerdecls{$fn}; + my $decl = $headerdecls{$sym}; my $str = ''; $brief = "$brief"; @@ -1551,14 +2501,14 @@ sub usage { $str .= ".\\\" This manpage content is licensed under Creative Commons\n"; $str .= ".\\\" Attribution 4.0 International (CC BY 4.0)\n"; $str .= ".\\\" https://creativecommons.org/licenses/by/4.0/\n"; - $str .= ".\\\" This manpage was generated from ${projectshortname}'s wiki page for $fn:\n"; - $str .= ".\\\" $wikiurl/$fn\n"; + $str .= ".\\\" This manpage was generated from ${projectshortname}'s wiki page for $sym:\n"; + $str .= ".\\\" $wikiurl/$sym\n"; $str .= ".\\\" Generated with SDL/build-scripts/wikiheaders.pl\n"; $str .= ".\\\" revision $gitrev\n" if $gitrev ne ''; $str .= ".\\\" Please report issues in this manpage's content at:\n"; $str .= ".\\\" $bugreporturl\n"; $str .= ".\\\" Please report issues in the generation of this manpage from the wiki at:\n"; - $str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$fn\n"; + $str .= ".\\\" https://github.com/libsdl-org/SDL/issues/new?title=Misgenerated%20manpage%20for%20$sym\n"; $str .= ".\\\" $projectshortname can be found at $projecturl\n"; # Define a .URL macro. The "www.tmac" thing decides if we're using GNU roff (which has a .URL macro already), and if so, overrides the macro we just created. @@ -1568,10 +2518,10 @@ sub usage { $str .= "..\n"; $str .= '.if \n[.g] .mso www.tmac' . "\n"; - $str .= ".TH $fn 3 \"$projectshortname $fullversion\" \"$projectfullname\" \"$projectshortname$majorver FUNCTIONS\"\n"; + $str .= ".TH $sym $mansection \"$projectshortname $fullversion\" \"$projectfullname\" \"$projectshortname$majorver $mansectionname\"\n"; $str .= ".SH NAME\n"; - $str .= "$fn"; + $str .= "$sym"; $str .= " \\- $brief" if (defined $brief); $str .= "\n"; @@ -1602,21 +2552,43 @@ sub usage { } if (defined $params) { - $str .= ".SH FUNCTION PARAMETERS\n"; + if (($symtype == 1) || ($symtype == 5)) { + $str .= ".SH FUNCTION PARAMETERS\n"; + } elsif ($symtype == 2) { # macro + $str .= ".SH MACRO PARAMETERS\n"; + } elsif ($symtype == 3) { # struct/union + $str .= ".SH FIELDS\n"; + } elsif ($symtype == 4) { # enum + $str .= ".SH VALUES\n"; + } else { + die("Unexpected symtype $symtype"); + } + my @lines = split /\n/, $params; if ($wikitype eq 'mediawiki') { die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start while (scalar(@lines) >= 3) { + my $c_datatype = shift @lines; my $name = shift @lines; my $desc = shift @lines; - my $terminator = shift @lines; # the '|-' or '|}' line. + my $terminator; # the '|-' or '|}' line. + + if (($desc eq '|-') or ($desc eq '|}') or (not $desc =~ /\A\|/)) { # we seem to be out of cells, which means there was no datatype column on this one. + $terminator = $desc; + $desc = $name; + $name = $c_datatype; + $c_datatype = ''; + } else { + $terminator = shift @lines; + } + last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. $name =~ s/\A\|\s*//; $name =~ s/\A\*\*(.*?)\*\*/$1/; $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; $desc =~ s/\A\|\s*//; $desc = dewikify($wikitype, $desc); - #print STDERR "FN: $fn NAME: $name DESC: $desc TERM: $terminator\n"; + #print STDERR "SYM: $sym CDATATYPE: $c_datatype NAME: $name DESC: $desc TERM: $terminator\n"; $str .= ".TP\n"; $str .= ".I $name\n"; @@ -1625,24 +2597,31 @@ sub usage { } elsif ($wikitype eq 'md') { my $l; $l = shift @lines; - die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*\|\s*\|\s*\|\s*\Z/); + die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); $l = shift @lines; - die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); + die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); while (scalar(@lines) >= 1) { $l = shift @lines; - if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { - my $name = $1; - my $desc = $2; - $name =~ s/\A\*\*(.*?)\*\*/$1/; - $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; - $desc = dewikify($wikitype, $desc); - - $str .= ".TP\n"; - $str .= ".I $name\n"; - $str .= "$desc\n"; + my $name; + my $desc; + if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + # c datatype is $1, but we don't care about it here. + $name = $2; + $desc = $3; + } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + $name = $1; + $desc = $2; } else { last; # we seem to have run out of table. } + + $name =~ s/\A\*\*(.*?)\*\*/$1/; + $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; + $desc = dewikify($wikitype, $desc); + + $str .= ".TP\n"; + $str .= ".I $name\n"; + $str .= "$desc\n"; } } else { die("write me"); @@ -1650,8 +2629,10 @@ sub usage { } if (defined $returns) { + $returns = dewikify($wikitype, $returns); + $returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. $str .= ".SH RETURN VALUE\n"; - $str .= dewikify($wikitype, $returns) . "\n"; + $str .= "$returns\n"; } if (defined $examples) { @@ -1678,7 +2659,6 @@ sub usage { my @desclines = split /\n/, $v; my $nextstr = ''; foreach (@desclines) { - s/\A(\:|\* )//; s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. @@ -1686,10 +2666,16 @@ sub usage { s/\A\/*//; s/\A\.BR\s+//; # dewikify added this, but we want to handle it. s/\A\.I\s+//; # dewikify added this, but we want to handle it. + s/\A\s*[\:\*\-]\s*//; s/\A\s+//; s/\s+\Z//; next if $_ eq ''; - $str .= "$nextstr.BR $_ (3)"; + my $seealso_symtype = $headersymstype{$_}; + my $seealso_mansection = '3'; + if (defined($seealso_symtype) && ($seealso_symtype >= 3) && ($seealso_symtype <= 5)) { # struct/union/enum/typedef + $seealso_mansection = '3type'; + } + $str .= "$nextstr.BR $_ ($seealso_mansection)"; $nextstr = ",\n"; } $str .= "\n"; @@ -1703,7 +2689,7 @@ sub usage { $str .= ".UE\n"; $str .= ".PP\n"; $str .= "This manpage was generated from\n"; - $str .= ".UR $wikiurl/$fn\n"; + $str .= ".UR $wikiurl/$sym\n"; $str .= "${projectshortname}'s wiki\n"; $str .= ".UE\n"; $str .= "using SDL/build-scripts/wikiheaders.pl"; @@ -1715,11 +2701,349 @@ sub usage { $str .= ".UE\n"; } - my $path = "$manpath/$_.3.tmp"; - open(FH, '>', $path) or die("Can't open '$path': $!\n"); + my $path = "$manpath/man3/$_.$mansection"; + my $tmppath = "$path.tmp"; + open(FH, '>', $tmppath) or die("Can't open '$tmppath': $!\n"); print FH $str; close(FH); - rename($path, "$manpath/$_.3") or die("Can't rename '$path' to '$manpath/$_.3': $!\n"); + rename($tmppath, $path) or die("Can't rename '$tmppath' to '$path': $!\n"); + } + +} elsif ($copy_direction == -4) { # --copy-to-latex + # This only takes from the wiki data, since it has sections we omit from the headers, like code examples. + + print STDERR "\n(The --copy-to-latex code is known to not be ready for serious use; send patches, not bug reports, please.)\n\n"; + + $dewikify_mode = 'LaTeX'; + $wordwrap_mode = 'LaTeX'; + + # !!! FIXME: code duplication with --copy-to-manpages section. + + my $introtxt = ''; + if (0) { + open(FH, '<', "$srcpath/LICENSE.txt") or die("Can't open '$srcpath/LICENSE.txt': $!\n"); + while () { + chomp; + $introtxt .= ".\\\" $_\n"; + } + close(FH); + } + + if (!$gitrev) { + $gitrev = `cd "$srcpath" ; git rev-list HEAD~..`; + chomp($gitrev); + } + + # !!! FIXME + open(FH, '<', "$srcpath/$versionfname") or die("Can't open '$srcpath/$versionfname': $!\n"); + my $majorver = 0; + my $minorver = 0; + my $microver = 0; + while () { + chomp; + if (/$versionmajorregex/) { + $majorver = int($1); + } elsif (/$versionminorregex/) { + $minorver = int($1); + } elsif (/$versionmicroregex/) { + $microver = int($1); + } + } + close(FH); + my $fullversion = "$majorver.$minorver.$microver"; + + my $latex_fname = "$srcpath/$projectshortname.tex"; + my $latex_tmpfname = "$latex_fname.tmp"; + open(TEXFH, '>', "$latex_tmpfname") or die("Can't open '$latex_tmpfname' for writing: $!\n"); + + print TEXFH <<__EOF__ +\\documentclass{book} + +\\usepackage{listings} +\\usepackage{color} +\\usepackage{hyperref} + +\\definecolor{dkgreen}{rgb}{0,0.6,0} +\\definecolor{gray}{rgb}{0.5,0.5,0.5} +\\definecolor{mauve}{rgb}{0.58,0,0.82} + +\\setcounter{secnumdepth}{0} + +\\lstset{frame=tb, + language=C, + aboveskip=3mm, + belowskip=3mm, + showstringspaces=false, + columns=flexible, + basicstyle={\\small\\ttfamily}, + numbers=none, + numberstyle=\\tiny\\color{gray}, + keywordstyle=\\color{blue}, + commentstyle=\\color{dkgreen}, + stringstyle=\\color{mauve}, + breaklines=true, + breakatwhitespace=true, + tabsize=3 +} + +\\begin{document} +\\frontmatter + +\\title{$projectfullname $majorver.$minorver.$microver Reference Manual} +\\author{The $projectshortname Developers} +\\maketitle + +\\mainmatter + +__EOF__ +; + + # !!! FIXME: Maybe put this in the book intro? print TEXFH $introtxt; + + # Sort symbols by symbol type, then alphabetically. + my @headersymskeys = sort { + my $symtypea = $headersymstype{$a}; + my $symtypeb = $headersymstype{$b}; + $symtypea = 3 if ($symtypea > 3); + $symtypeb = 3 if ($symtypeb > 3); + my $rc = $symtypea <=> $symtypeb; + if ($rc == 0) { + $rc = lc($a) cmp lc($b); + } + return $rc; + } keys %headersyms; + + my $current_symtype = 0; + my $current_chapter = ''; + + foreach (@headersymskeys) { + my $sym = $_; + next if not defined $wikisyms{$sym}; # don't have a page for that function, skip it. + next if $sym =~ /\A\[category documentation\]/; # not real symbols. + my $symtype = $headersymstype{$sym}; + my $wikitype = $wikitypes{$sym}; + my $sectionsref = $wikisyms{$sym}; + my $remarks = $sectionsref->{'Remarks'}; + my $params = $sectionsref->{'Function Parameters'}; + my $returns = $sectionsref->{'Return Value'}; + my $version = $sectionsref->{'Version'}; + my $threadsafety = $sectionsref->{'Thread Safety'}; + my $related = $sectionsref->{'See Also'}; + my $examples = $sectionsref->{'Code Examples'}; + my $deprecated = $sectionsref->{'Deprecated'}; + my $headerfile = $manpageheaderfiletext; + $headerfile =~ s/\%fname\%/$headersymslocation{$sym}/g; + $headerfile .= "\n"; + + my $brief = $sectionsref->{'[Brief]'}; + my $decl = $headerdecls{$sym}; + my $str = ''; + + if ($current_symtype != $symtype) { + my $newchapter = ''; + if ($symtype == 1) { + $newchapter = 'Functions'; + } elsif ($symtype == 2) { + $newchapter = 'Macros'; + } else { + $newchapter = 'Datatypes'; + } + + if ($current_chapter ne $newchapter) { + $str .= "\n\n\\chapter{$projectshortname $newchapter}\n\n\\clearpage\n\n"; + $current_chapter = $newchapter; + } + $current_symtype = $symtype; + } + + $brief = "$brief"; + $brief =~ s/\A[\s\n]*\= .*? \=\s*?\n+//ms; + $brief =~ s/\A[\s\n]*\=\= .*? \=\=\s*?\n+//ms; + $brief =~ s/\A(.*?\.) /$1\n/; # \brief should only be one sentence, delimited by a period+space. Split if necessary. + my @briefsplit = split /\n/, $brief; + $brief = shift @briefsplit; + $brief = dewikify($wikitype, $brief); + + if (defined $remarks) { + $remarks = dewikify($wikitype, join("\n", @briefsplit) . $remarks); + } + + my $escapedsym = escLaTeX($sym); + $str .= "\\hypertarget{$sym}{%\n\\section{$escapedsym}\\label{$sym}}\n\n"; + $str .= $brief if (defined $brief); + $str .= "\n\n"; + + if (defined $deprecated) { + $str .= "\\subsection{Deprecated}\n\n"; + $str .= dewikify($wikitype, $deprecated) . "\n"; + } + + if (defined $headerfile) { + $str .= "\\subsection{Header File}\n\n"; + $str .= dewikify($wikitype, $headerfile) . "\n"; + } + + $str .= "\\subsection{Syntax}\n\n"; + $str .= "\\begin{lstlisting}\n$decl\n\\end{lstlisting}\n"; + + if (defined $params) { + if (($symtype == 1) || ($symtype == 5)) { + $str .= "\\subsection{Function Parameters}\n\n"; + } elsif ($symtype == 2) { # macro + $str .= "\\subsection{Macro Parameters}\n\n"; + } elsif ($symtype == 3) { # struct/union + $str .= "\\subsection{Fields}\n\n"; + } elsif ($symtype == 4) { # enum + $str .= "\\subsection{Values}\n\n"; + } else { + die("Unexpected symtype $symtype"); + } + + $str .= "\\begin{center}\n"; + $str .= " \\begin{tabular}{ | l | p{0.75\\textwidth} |}\n"; + $str .= " \\hline\n"; + + # !!! FIXME: this table parsing has gotten complicated and is pasted three times in this file; move it to a subroutine! + my @lines = split /\n/, $params; + if ($wikitype eq 'mediawiki') { + die("Unexpected data parsing MediaWiki table") if (shift @lines ne '{|'); # Dump the '{|' start + while (scalar(@lines) >= 3) { + my $name = shift @lines; + my $desc = shift @lines; + my $terminator = shift @lines; # the '|-' or '|}' line. + last if ($terminator ne '|-') and ($terminator ne '|}'); # we seem to have run out of table. + $name =~ s/\A\|\s*//; + $name =~ s/\A\*\*(.*?)\*\*/$1/; + $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; + $name = escLaTeX($name); + $desc =~ s/\A\|\s*//; + $desc = dewikify($wikitype, $desc); + #print STDERR "FN: $sym NAME: $name DESC: $desc TERM: $terminator\n"; + $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; + } + } elsif ($wikitype eq 'md') { + my $l; + $l = shift @lines; + die("Unexpected data parsing Markdown table") if (not $l =~ /\A(\s*\|)?\s*\|\s*\|\s*\|\s*\Z/); + $l = shift @lines; + die("Unexpected data parsing Markdown table") if (not $l =~ /\A\s*(\|\s*\-*\s*)?\|\s*\-*\s*\|\s*\-*\s*\|\s*\Z/); + while (scalar(@lines) >= 1) { + $l = shift @lines; + my $name; + my $desc; + if ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + # c datatype is $1, but we don't care about it here. + $name = $2; + $desc = $3; + } elsif ($l =~ /\A\s*\|\s*(.*?)\s*\|\s*(.*?)\s*\|\s*\Z/) { + $name = $1; + $desc = $2; + } else { + last; # we seem to have run out of table. + } + + $name =~ s/\A\*\*(.*?)\*\*/$1/; + $name =~ s/\A\'\'\'(.*?)\'\'\'/$1/; + $name = escLaTeX($name); + $desc = dewikify($wikitype, $desc); + $str .= " \\textbf{$name} & $desc \\\\ \\hline\n"; + } + } else { + die("write me"); + } + + $str .= " \\end{tabular}\n"; + $str .= "\\end{center}\n"; + } + + if (defined $returns) { + $returns = dewikify($wikitype, $returns); + $returns =~ s/\A\(.*?\)\s*//; # Chop datatype in parentheses off the front. + $str .= "\\subsection{Return Value}\n\n"; + $str .= "$returns\n"; + } + + if (defined $remarks) { + $str .= "\\subsection{Remarks}\n\n"; + $str .= $remarks . "\n"; + } + + if (defined $examples) { + $str .= "\\subsection{Code Examples}\n\n"; + $dewikify_manpage_code_indent = 0; + $str .= dewikify($wikitype, $examples) . "\n"; + $dewikify_manpage_code_indent = 1; + } + + if (defined $threadsafety) { + $str .= "\\subsection{Thread Safety}\n\n"; + $str .= dewikify($wikitype, $threadsafety) . "\n"; + } + + if (defined $version) { + $str .= "\\subsection{Version}\n\n"; + $str .= dewikify($wikitype, $version) . "\n"; + } + + if (defined $related) { + $str .= "\\subsection{See Also}\n\n"; + $str .= "\\begin{itemize}\n"; + # !!! FIXME: lots of code duplication in all of these. + my $v = dewikify($wikitype, $related); + my @desclines = split /\n/, $v; + my $nextstr = ''; + foreach (@desclines) { + s/\(\)\Z//; # Convert "SDL_Func()" to "SDL_Func" + s/\[\[(.*?)\]\]/$1/; # in case some wikilinks remain. + s/\[(.*?)\]\(.*?\)/$1/; # in case some wikilinks remain. + s/\A\*\s*\Z//; + s/\A\s*\\item\s*//; + s/\A\/*//; + s/\A\s*[\:\*\-]\s*//; + s/\A\s+//; + s/\s+\Z//; + next if $_ eq ''; + next if $_ eq '\begin{itemize}'; + next if $_ eq '\end{itemize}'; + $str .= " \\item $_\n"; + } + $str .= "\\end{itemize}\n"; + $str .= "\n"; + } + + # !!! FIXME: Maybe put copyright in the book intro? + if (0) { + $str .= ".SH COPYRIGHT\n"; + $str .= "This manpage is licensed under\n"; + $str .= ".UR https://creativecommons.org/licenses/by/4.0/\n"; + $str .= "Creative Commons Attribution 4.0 International (CC BY 4.0)\n"; + $str .= ".UE\n"; + $str .= ".PP\n"; + $str .= "This manpage was generated from\n"; + $str .= ".UR $wikiurl/$sym\n"; + $str .= "${projectshortname}'s wiki\n"; + $str .= ".UE\n"; + $str .= "using SDL/build-scripts/wikiheaders.pl"; + $str .= " revision $gitrev" if $gitrev ne ''; + $str .= ".\n"; + $str .= "Please report issues in this manpage at\n"; + $str .= ".UR $bugreporturl\n"; + $str .= "our bugtracker!\n"; + $str .= ".UE\n"; + } + + $str .= "\\clearpage\n\n"; + + print TEXFH $str; + } + + print TEXFH "\\end{document}\n\n"; + close(TEXFH); + rename($latex_tmpfname, $latex_fname) or die("Can't rename '$latex_tmpfname' to '$latex_fname': $!\n"); + +} elsif ($copy_direction == -3) { # --report-coverage-gaps + foreach (@coverage_gap) { + print("$_\n"); } } diff --git a/libs/SDL3/cmake/3rdparty.cmake b/libs/SDL3/cmake/3rdparty.cmake index 37ac30b70..8b38a5ded 100644 --- a/libs/SDL3/cmake/3rdparty.cmake +++ b/libs/SDL3/cmake/3rdparty.cmake @@ -25,10 +25,6 @@ function(get_clang_tidy_ignored_files OUTVAR) # HIDAPI Steam controller "controller_constants.h" "controller_structs.h" - # Nokia Pixman - "pixman-arm-asm.h" - "pixman-arm-neon-asm.h" - "pixman-arm-simd-asm.h" # YUV2RGB "yuv_rgb.c" "yuv_rgb_lsx_func.h" @@ -98,14 +94,16 @@ function(get_clang_tidy_ignored_files OUTVAR) "vulkan_static_assertions.hpp" "vulkan_structs.hpp" "vulkan_to_string.hpp" - "vulkan.hpp" # HIDAPI "hid.c" "hid.cpp" "hid.m" "hidraw.cpp" "hidusb.cpp" - "hidapi.h") + "hidapi.h" + # XSETTINGS + "xsettings-client.c" + "xsettings-client.h") foreach(SOURCE_FILE ${3RD_PARTY_SOURCES}) list(APPEND IGNORED_LIST "{\"name\":\"${SOURCE_FILE}\",\"lines\":[[1,1]]}") diff --git a/libs/SDL3/cmake/CheckCPUArchitecture.cmake b/libs/SDL3/cmake/CheckCPUArchitecture.cmake deleted file mode 100644 index 8e2954b93..000000000 --- a/libs/SDL3/cmake/CheckCPUArchitecture.cmake +++ /dev/null @@ -1,48 +0,0 @@ -include(CheckCSourceCompiles) -include(CMakePushCheckState) - -function(_internal_check_cpu_architecture macro_check NAME VARIABLE) - cmake_push_check_state() - string(TOUPPER "${NAME}" UPPER_NAME) - set(CACHE_VARIABLE "CHECK_CPU_ARCHITECTURE_${UPPER_NAME}") - set(test_src " -int main(int argc, char *argv[]) { -#if ${macro_check} - return 0; -#else - choke -#endif -} -") - check_c_source_compiles("${test_src}" "${CACHE_VARIABLE}") - cmake_pop_check_state() - if(${CACHE_VARIABLE}) - set(${VARIABLE} "TRUE" PARENT_SCOPE) - else() - set(${VARIABLE} "FALSE" PARENT_SCOPE) - endif() -endfunction() - -function(check_cpu_architecture ARCH VARIABLE) - if(ARCH STREQUAL "x86") - _internal_check_cpu_architecture("defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)" x86 ${VARIABLE}) - elseif(ARCH STREQUAL "x64") - _internal_check_cpu_architecture("defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)" x64 ${VARIABLE}) - elseif(ARCH STREQUAL "arm32") - _internal_check_cpu_architecture("defined(__arm__) || defined(_M_ARM)" arm32 ${VARIABLE}) - elseif(ARCH STREQUAL "arm64") - _internal_check_cpu_architecture("defined(__aarch64__) || defined(_M_ARM64)" arm64 ${VARIABLE}) - elseif(ARCH STREQUAL "loongarch64") - _internal_check_cpu_architecture("defined(__loongarch64)" loongarch64 ${VARIABLE}) - elseif(ARCH STREQUAL "emscripten") - _internal_check_cpu_architecture("defined(__EMSCRIPTEN__)" emscripten ${VARIABLE}) - elseif(ARCH STREQUAL "powerpc64") - _internal_check_cpu_architecture("defined(__PPC64__) || defined(__powerpc64__)" powerpc64 ${VARIABLE}) - elseif(ARCH STREQUAL "powerpc32") - _internal_check_cpu_architecture("(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)" powerpc32 ${VARIABLE}) - else() - message(WARNING "Unknown CPU architectures (${ARCH}).") - set("${VARIABLE}" FALSE) - endif() - set("${VARIABLE}" "${${VARIABLE}}" PARENT_SCOPE) -endfunction() diff --git a/libs/SDL3/cmake/PreseedEmscriptenCache.cmake b/libs/SDL3/cmake/PreseedEmscriptenCache.cmake new file mode 100644 index 000000000..5a34ab5ac --- /dev/null +++ b/libs/SDL3/cmake/PreseedEmscriptenCache.cmake @@ -0,0 +1,178 @@ +if(EMSCRIPTEN) + function(SDL_Preseed_CMakeCache) + set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS") + set(HAVE_ALLOCA_H "1" CACHE INTERNAL "Have include alloca.h") + set(HAVE_LIBM "1" CACHE INTERNAL "Have library m") + set(HAVE_MALLOC "1" CACHE INTERNAL "Have include malloc.h") + set(LIBC_HAS_ABS "1" CACHE INTERNAL "Have symbol abs") + set(LIBC_HAS_ACOS "1" CACHE INTERNAL "Have symbol acos") + set(LIBC_HAS_ACOSF "1" CACHE INTERNAL "Have symbol acosf") + set(LIBC_HAS_ASIN "1" CACHE INTERNAL "Have symbol asin") + set(LIBC_HAS_ASINF "1" CACHE INTERNAL "Have symbol asinf") + set(LIBC_HAS_ATAN "1" CACHE INTERNAL "Have symbol atan") + set(LIBC_HAS_ATAN2 "1" CACHE INTERNAL "Have symbol atan2") + set(LIBC_HAS_ATAN2F "1" CACHE INTERNAL "Have symbol atan2f") + set(LIBC_HAS_ATANF "1" CACHE INTERNAL "Have symbol atanf") + set(LIBC_HAS_ATOF "1" CACHE INTERNAL "Have symbol atof") + set(LIBC_HAS_ATOI "1" CACHE INTERNAL "Have symbol atoi") + set(LIBC_HAS_BCOPY "1" CACHE INTERNAL "Have symbol bcopy") + set(LIBC_HAS_CALLOC "1" CACHE INTERNAL "Have symbol calloc") + set(LIBC_HAS_CEIL "1" CACHE INTERNAL "Have symbol ceil") + set(LIBC_HAS_CEILF "1" CACHE INTERNAL "Have symbol ceilf") + set(LIBC_HAS_COPYSIGN "1" CACHE INTERNAL "Have symbol copysign") + set(LIBC_HAS_COPYSIGNF "1" CACHE INTERNAL "Have symbol copysignf") + set(LIBC_HAS_COS "1" CACHE INTERNAL "Have symbol cos") + set(LIBC_HAS_COSF "1" CACHE INTERNAL "Have symbol cosf") + set(LIBC_HAS_EXP "1" CACHE INTERNAL "Have symbol exp") + set(LIBC_HAS_EXPF "1" CACHE INTERNAL "Have symbol expf") + set(LIBC_HAS_FABS "1" CACHE INTERNAL "Have symbol fabs") + set(LIBC_HAS_FABSF "1" CACHE INTERNAL "Have symbol fabsf") + set(LIBC_HAS_FLOAT_H "1" CACHE INTERNAL "Have include float.h") + set(LIBC_HAS_FLOOR "1" CACHE INTERNAL "Have symbol floor") + set(LIBC_HAS_FLOORF "1" CACHE INTERNAL "Have symbol floorf") + set(LIBC_HAS_FMOD "1" CACHE INTERNAL "Have symbol fmod") + set(LIBC_HAS_FMODF "1" CACHE INTERNAL "Have symbol fmodf") + set(LIBC_HAS_FOPEN64 "1" CACHE INTERNAL "Have symbol fopen64") + set(LIBC_HAS_FREE "1" CACHE INTERNAL "Have symbol free") + set(LIBC_HAS_FSEEKO "1" CACHE INTERNAL "Have symbol fseeko") + set(LIBC_HAS_FSEEKO64 "1" CACHE INTERNAL "Have symbol fseeko64") + set(LIBC_HAS_GETENV "1" CACHE INTERNAL "Have symbol getenv") + set(LIBC_HAS_ICONV_H "1" CACHE INTERNAL "Have include iconv.h") + set(LIBC_HAS_INDEX "1" CACHE INTERNAL "Have symbol index") + set(LIBC_HAS_INTTYPES_H "1" CACHE INTERNAL "Have include inttypes.h") + set(LIBC_HAS_ISINF "1" CACHE INTERNAL "Have include isinf(double)") + set(LIBC_ISINF_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isinf(float)") + set(LIBC_HAS_ISINFF "1" CACHE INTERNAL "Have include isinff(float)") + set(LIBC_HAS_ISNAN "1" CACHE INTERNAL "Have include isnan(double)") + set(LIBC_ISNAN_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isnan(float)") + set(LIBC_HAS_ISNANF "1" CACHE INTERNAL "Have include isnanf(float)") + set(LIBC_HAS_ITOA "" CACHE INTERNAL "Have symbol itoa") + set(LIBC_HAS_LIMITS_H "1" CACHE INTERNAL "Have include limits.h") + set(LIBC_HAS_LOG "1" CACHE INTERNAL "Have symbol log") + set(LIBC_HAS_LOG10 "1" CACHE INTERNAL "Have symbol log10") + set(LIBC_HAS_LOG10F "1" CACHE INTERNAL "Have symbol log10f") + set(LIBC_HAS_LOGF "1" CACHE INTERNAL "Have symbol logf") + set(LIBC_HAS_LROUND "1" CACHE INTERNAL "Have symbol lround") + set(LIBC_HAS_LROUNDF "1" CACHE INTERNAL "Have symbol lroundf") + set(LIBC_HAS_MALLOC "1" CACHE INTERNAL "Have symbol malloc") + set(LIBC_HAS_MALLOC_H "1" CACHE INTERNAL "Have include malloc.h") + set(LIBC_HAS_MATH_H "1" CACHE INTERNAL "Have include math.h") + set(LIBC_HAS_MEMCMP "1" CACHE INTERNAL "Have symbol memcmp") + set(LIBC_HAS_MEMCPY "1" CACHE INTERNAL "Have symbol memcpy") + set(LIBC_HAS_MEMMOVE "1" CACHE INTERNAL "Have symbol memmove") + set(LIBC_HAS_MEMORY_H "1" CACHE INTERNAL "Have include memory.h") + set(LIBC_HAS_MEMSET "1" CACHE INTERNAL "Have symbol memset") + set(LIBC_HAS_MODF "1" CACHE INTERNAL "Have symbol modf") + set(LIBC_HAS_MODFF "1" CACHE INTERNAL "Have symbol modff") + set(LIBC_HAS_POW "1" CACHE INTERNAL "Have symbol pow") + set(LIBC_HAS_POWF "1" CACHE INTERNAL "Have symbol powf") + set(LIBC_HAS_PUTENV "1" CACHE INTERNAL "Have symbol putenv") + set(LIBC_HAS_REALLOC "1" CACHE INTERNAL "Have symbol realloc") + set(LIBC_HAS_RINDEX "1" CACHE INTERNAL "Have symbol rindex") + set(LIBC_HAS_ROUND "1" CACHE INTERNAL "Have symbol round") + set(LIBC_HAS_ROUNDF "1" CACHE INTERNAL "Have symbol roundf") + set(LIBC_HAS_SCALBN "1" CACHE INTERNAL "Have symbol scalbn") + set(LIBC_HAS_SCALBNF "1" CACHE INTERNAL "Have symbol scalbnf") + set(LIBC_HAS_SETENV "1" CACHE INTERNAL "Have symbol setenv") + set(LIBC_HAS_SIGNAL_H "1" CACHE INTERNAL "Have include signal.h") + set(LIBC_HAS_SIN "1" CACHE INTERNAL "Have symbol sin") + set(LIBC_HAS_SINF "1" CACHE INTERNAL "Have symbol sinf") + set(LIBC_HAS_SQR "" CACHE INTERNAL "Have symbol sqr") + set(LIBC_HAS_SQRT "1" CACHE INTERNAL "Have symbol sqrt") + set(LIBC_HAS_SQRTF "1" CACHE INTERNAL "Have symbol sqrtf") + set(LIBC_HAS_SSCANF "1" CACHE INTERNAL "Have symbol sscanf") + set(LIBC_HAS_STDARG_H "1" CACHE INTERNAL "Have include stdarg.h") + set(LIBC_HAS_STDBOOL_H "1" CACHE INTERNAL "Have include stdbool.h") + set(LIBC_HAS_STDDEF_H "1" CACHE INTERNAL "Have include stddef.h") + set(LIBC_HAS_STDINT_H "1" CACHE INTERNAL "Have include stdint.h") + set(LIBC_HAS_STDIO_H "1" CACHE INTERNAL "Have include stdio.h") + set(LIBC_HAS_STDLIB_H "1" CACHE INTERNAL "Have include stdlib.h") + set(LIBC_HAS_STRCASESTR "1" CACHE INTERNAL "Have symbol strcasestr") + set(LIBC_HAS_STRCHR "1" CACHE INTERNAL "Have symbol strchr") + set(LIBC_HAS_STRCMP "1" CACHE INTERNAL "Have symbol strcmp") + set(LIBC_HAS_STRINGS_H "1" CACHE INTERNAL "Have include strings.h") + set(LIBC_HAS_STRING_H "1" CACHE INTERNAL "Have include string.h") + set(LIBC_HAS_STRLCAT "1" CACHE INTERNAL "Have symbol strlcat") + set(LIBC_HAS_STRLCPY "1" CACHE INTERNAL "Have symbol strlcpy") + set(LIBC_HAS_STRLEN "1" CACHE INTERNAL "Have symbol strlen") + set(LIBC_HAS_STRNCMP "1" CACHE INTERNAL "Have symbol strncmp") + set(LIBC_HAS_STRNLEN "1" CACHE INTERNAL "Have symbol strnlen") + set(LIBC_HAS_STRNSTR "" CACHE INTERNAL "Have symbol strnstr") + set(LIBC_HAS_STRPBRK "1" CACHE INTERNAL "Have symbol strpbrk") + set(LIBC_HAS_STRRCHR "1" CACHE INTERNAL "Have symbol strrchr") + set(LIBC_HAS_STRSTR "1" CACHE INTERNAL "Have symbol strstr") + set(LIBC_HAS_STRTOD "1" CACHE INTERNAL "Have symbol strtod") + set(LIBC_HAS_STRTOK_R "1" CACHE INTERNAL "Have symbol strtok_r") + set(LIBC_HAS_STRTOL "1" CACHE INTERNAL "Have symbol strtol") + set(LIBC_HAS_STRTOLL "1" CACHE INTERNAL "Have symbol strtoll") + set(LIBC_HAS_STRTOUL "1" CACHE INTERNAL "Have symbol strtoul") + set(LIBC_HAS_STRTOULL "1" CACHE INTERNAL "Have symbol strtoull") + set(LIBC_HAS_SYS_TYPES_H "1" CACHE INTERNAL "Have include sys/types.h") + set(LIBC_HAS_TAN "1" CACHE INTERNAL "Have symbol tan") + set(LIBC_HAS_TANF "1" CACHE INTERNAL "Have symbol tanf") + set(LIBC_HAS_TIME_H "1" CACHE INTERNAL "Have include time.h") + set(LIBC_HAS_TRUNC "1" CACHE INTERNAL "Have symbol trunc") + set(LIBC_HAS_TRUNCF "1" CACHE INTERNAL "Have symbol truncf") + set(LIBC_HAS_UNSETENV "1" CACHE INTERNAL "Have symbol unsetenv") + set(LIBC_HAS_VSNPRINTF "1" CACHE INTERNAL "Have symbol vsnprintf") + set(LIBC_HAS_VSSCANF "1" CACHE INTERNAL "Have symbol vsscanf") + set(LIBC_HAS_WCHAR_H "1" CACHE INTERNAL "Have include wchar.h") + set(LIBC_HAS_WCSCMP "1" CACHE INTERNAL "Have symbol wcscmp") + set(LIBC_HAS_WCSDUP "1" CACHE INTERNAL "Have symbol wcsdup") + set(LIBC_HAS_WCSLCAT "" CACHE INTERNAL "Have symbol wcslcat") + set(LIBC_HAS_WCSLCPY "" CACHE INTERNAL "Have symbol wcslcpy") + set(LIBC_HAS_WCSLEN "1" CACHE INTERNAL "Have symbol wcslen") + set(LIBC_HAS_WCSNCMP "1" CACHE INTERNAL "Have symbol wcsncmp") + set(LIBC_HAS_WCSNLEN "1" CACHE INTERNAL "Have symbol wcsnlen") + set(LIBC_HAS_WCSSTR "1" CACHE INTERNAL "Have symbol wcsstr") + set(LIBC_HAS_WCSTOL "1" CACHE INTERNAL "Have symbol wcstol") + set(LIBC_HAS__EXIT "1" CACHE INTERNAL "Have symbol _Exit") + set(LIBC_HAS__I64TOA "" CACHE INTERNAL "Have symbol _i64toa") + set(LIBC_HAS__LTOA "" CACHE INTERNAL "Have symbol _ltoa") + set(LIBC_HAS__STRREV "" CACHE INTERNAL "Have symbol _strrev") + set(LIBC_HAS__UI64TOA "" CACHE INTERNAL "Have symbol _ui64toa") + set(LIBC_HAS__UITOA "" CACHE INTERNAL "Have symbol _uitoa") + set(LIBC_HAS__ULTOA "" CACHE INTERNAL "Have symbol _ultoa") + set(LIBC_HAS__WCSDUP "" CACHE INTERNAL "Have symbol _wcsdup") + set(LIBC_IS_GLIBC "" CACHE INTERNAL "Have symbol __GLIBC__") + set(_ALLOCA_IN_MALLOC_H "" CACHE INTERNAL "Have symbol _alloca") + set(SDL_CPU_EMSCRIPTEN "1" CACHE INTERNAL "Test SDL_CPU_EMSCRIPTEN") + set(HAVE_GCC_WALL "1" CACHE INTERNAL "Test HAVE_GCC_WALL") + set(HAVE_GCC_WUNDEF "1" CACHE INTERNAL "Test HAVE_GCC_WUNDEF") + set(HAVE_GCC_WFLOAT_CONVERSION "1" CACHE INTERNAL "Test HAVE_GCC_WFLOAT_CONVERSION") + set(HAVE_GCC_NO_STRICT_ALIASING "1" CACHE INTERNAL "Test HAVE_GCC_NO_STRICT_ALIASING") + set(HAVE_GCC_WDOCUMENTATION "1" CACHE INTERNAL "Test HAVE_GCC_WDOCUMENTATION") + set(HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND "1" CACHE INTERNAL "Test HAVE_GCC_WDOCUMENTATION_UNKNOWN_COMMAND") + set(HAVE_GCC_COMMENT_BLOCK_COMMANDS "1" CACHE INTERNAL "Test HAVE_GCC_COMMENT_BLOCK_COMMANDS") + set(HAVE_GCC_WSHADOW "1" CACHE INTERNAL "Test HAVE_GCC_WSHADOW") + set(HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS "1" CACHE INTERNAL "Test HAVE_GCC_WUNUSED_LOCAL_TYPEDEFS") + set(HAVE_GCC_WIMPLICIT_FALLTHROUGH "1" CACHE INTERNAL "Test HAVE_GCC_WIMPLICIT_FALLTHROUGH") + set(HAVE_GCC_FVISIBILITY "1" CACHE INTERNAL "Test HAVE_GCC_FVISIBILITY") + set(HAVE_ST_MTIM "1" CACHE INTERNAL "Test HAVE_ST_MTIM") + set(HAVE_O_CLOEXEC "1" CACHE INTERNAL "Test HAVE_O_CLOEXEC") + set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR") + set(COMPILER_SUPPORTS_GCC_ATOMICS "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_GCC_ATOMICS") + set(LINKER_SUPPORTS_VERSION_SCRIPT "" CACHE INTERNAL "Test LINKER_SUPPORTS_VERSION_SCRIPT") + set(LINKER_SUPPORTS_WL_NO_UNDEFINED "" CACHE INTERNAL "Test LINKER_SUPPORTS_WL_NO_UNDEFINED") + set(ICONV_IN_LIBC "1" CACHE INTERNAL "Test ICONV_IN_LIBC") + set(ICONV_IN_LIBICONV "" CACHE INTERNAL "Test ICONV_IN_LIBICONV") + set(LIBC_HAS_WORKING_LIBUNWIND "" CACHE INTERNAL "Test LIBC_HAS_WORKING_LIBUNWIND") + set(LIBUNWIND_HAS_WORKINGLIBUNWIND "" CACHE INTERNAL "Test LIBUNWIND_HAS_WORKINGLIBUNWIND") + set(HAVE_GETPAGESIZE "1" CACHE INTERNAL "Have symbol getpagesize") + set(HAVE_SIGACTION "1" CACHE INTERNAL "Have symbol sigaction") + set(HAVE_SA_SIGACTION "1" CACHE INTERNAL "Have symbol sa_sigaction") + set(HAVE_SETJMP "1" CACHE INTERNAL "Have symbol setjmp") + set(HAVE_NANOSLEEP "1" CACHE INTERNAL "Have symbol nanosleep") + set(HAVE_GMTIME_R "1" CACHE INTERNAL "Have symbol gmtime_r") + set(HAVE_LOCALTIME_R "1" CACHE INTERNAL "Have symbol localtime_r") + set(HAVE_NL_LANGINFO "1" CACHE INTERNAL "Have symbol nl_langinfo") + set(HAVE_SYSCONF "1" CACHE INTERNAL "Have symbol sysconf") + set(HAVE_SYSCTLBYNAME "" CACHE INTERNAL "Have symbol sysctlbyname") + set(HAVE_GETAUXVAL "" CACHE INTERNAL "Have symbol getauxval") + set(HAVE_ELF_AUX_INFO "" CACHE INTERNAL "Have symbol elf_aux_info") + set(HAVE_POLL "1" CACHE INTERNAL "Have symbol poll") + set(HAVE_MEMFD_CREATE "" CACHE INTERNAL "Have symbol memfd_create") + set(HAVE_POSIX_FALLOCATE "1" CACHE INTERNAL "Have symbol posix_fallocate") + set(HAVE_DLOPEN_IN_LIBC "1" CACHE INTERNAL "Have symbol dlopen") + endfunction() +endif() diff --git a/libs/SDL3/cmake/PreseedMSVCCache.cmake b/libs/SDL3/cmake/PreseedMSVCCache.cmake new file mode 100644 index 000000000..17495aa48 --- /dev/null +++ b/libs/SDL3/cmake/PreseedMSVCCache.cmake @@ -0,0 +1,183 @@ +if(MSVC) + function(SDL_Preseed_CMakeCache) + set(COMPILER_SUPPORTS_W3 "1" CACHE INTERNAL "Test /W3") + set(COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS "" CACHE INTERNAL "Test COMPILER_SUPPORTS_FDIAGNOSTICS_COLOR_ALWAYS") + set(HAVE_ALLOCA_H "" CACHE INTERNAL "Have include alloca.h") + set(HAVE_AUDIOCLIENT_H "1" CACHE INTERNAL "Have include audioclient.h") + set(HAVE_D3D11_H "1" CACHE INTERNAL "Have include d3d11_1.h") + set(HAVE_D3D9_H "1" CACHE INTERNAL "Have include d3d9.h") + set(HAVE_DDRAW_H "1" CACHE INTERNAL "Have include ddraw.h") + set(HAVE_DINPUT_H "1" CACHE INTERNAL "Have include dinput.h") + set(HAVE_DSOUND_H "1" CACHE INTERNAL "Have include dsound.h") + set(HAVE_DXGI_H "1" CACHE INTERNAL "Have include dxgi.h") + set(HAVE_LIBM "" CACHE INTERNAL "Have library m") + set(HAVE_MALLOC "1" CACHE INTERNAL "Have include malloc.h") + set(HAVE_MMDEVICEAPI_H "1" CACHE INTERNAL "Have include mmdeviceapi.h") + set(HAVE_SENSORSAPI_H "1" CACHE INTERNAL "Have include sensorsapi.h") + set(HAVE_SHELLSCALINGAPI_H "1" CACHE INTERNAL "Have include shellscalingapi.h") + set(HAVE_TPCSHRD_H "1" CACHE INTERNAL "Have include tpcshrd.h") + set(HAVE_WIN32_CC "1" CACHE INTERNAL "Test HAVE_WIN32_CC") + set(HAVE_XINPUT_H "1" CACHE INTERNAL "Test HAVE_XINPUT_H") + set(LIBC_HAS_ABS "1" CACHE INTERNAL "Have symbol abs") + set(LIBC_HAS_ACOS "1" CACHE INTERNAL "Have symbol acos") + set(LIBC_HAS_ACOSF "1" CACHE INTERNAL "Have symbol acosf") + set(LIBC_HAS_ASIN "1" CACHE INTERNAL "Have symbol asin") + set(LIBC_HAS_ASINF "1" CACHE INTERNAL "Have symbol asinf") + set(LIBC_HAS_ATAN "1" CACHE INTERNAL "Have symbol atan") + set(LIBC_HAS_ATAN2 "1" CACHE INTERNAL "Have symbol atan2") + set(LIBC_HAS_ATAN2F "1" CACHE INTERNAL "Have symbol atan2f") + set(LIBC_HAS_ATANF "1" CACHE INTERNAL "Have symbol atanf") + set(LIBC_HAS_ATOF "1" CACHE INTERNAL "Have symbol atof") + set(LIBC_HAS_ATOI "1" CACHE INTERNAL "Have symbol atoi") + set(LIBC_HAS_BCOPY "" CACHE INTERNAL "Have symbol bcopy") + set(LIBC_HAS_CALLOC "1" CACHE INTERNAL "Have symbol calloc") + set(LIBC_HAS_CEIL "1" CACHE INTERNAL "Have symbol ceil") + set(LIBC_HAS_CEILF "1" CACHE INTERNAL "Have symbol ceilf") + set(LIBC_HAS_COPYSIGN "1" CACHE INTERNAL "Have symbol copysign") + set(LIBC_HAS_COPYSIGNF "1" CACHE INTERNAL "Have symbol copysignf") + set(LIBC_HAS_COS "1" CACHE INTERNAL "Have symbol cos") + set(LIBC_HAS_COSF "1" CACHE INTERNAL "Have symbol cosf") + set(LIBC_HAS_EXP "1" CACHE INTERNAL "Have symbol exp") + set(LIBC_HAS_EXPF "1" CACHE INTERNAL "Have symbol expf") + set(LIBC_HAS_FABS "1" CACHE INTERNAL "Have symbol fabs") + set(LIBC_HAS_FABSF "1" CACHE INTERNAL "Have symbol fabsf") + set(LIBC_HAS_FLOAT_H "1" CACHE INTERNAL "Have include float.h") + set(LIBC_HAS_FLOOR "1" CACHE INTERNAL "Have symbol floor") + set(LIBC_HAS_FLOORF "1" CACHE INTERNAL "Have symbol floorf") + set(LIBC_HAS_FMOD "1" CACHE INTERNAL "Have symbol fmod") + set(LIBC_HAS_FMODF "1" CACHE INTERNAL "Have symbol fmodf") + set(LIBC_HAS_FOPEN64 "" CACHE INTERNAL "Have symbol fopen64") + set(LIBC_HAS_FREE "1" CACHE INTERNAL "Have symbol free") + set(LIBC_HAS_FSEEKO "" CACHE INTERNAL "Have symbol fseeko") + set(LIBC_HAS_FSEEKO64 "" CACHE INTERNAL "Have symbol fseeko64") + set(LIBC_HAS_GETENV "1" CACHE INTERNAL "Have symbol getenv") + set(LIBC_HAS_ICONV_H "" CACHE INTERNAL "Have include iconv.h") + set(LIBC_HAS_INDEX "" CACHE INTERNAL "Have symbol index") + set(LIBC_HAS_INTTYPES_H "1" CACHE INTERNAL "Have include inttypes.h") + set(LIBC_HAS_ISINF "1" CACHE INTERNAL "Have include isinf(double)") + set(LIBC_ISINF_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isinf(float)") + set(LIBC_HAS_ISINFF "" CACHE INTERNAL "Have include isinff(float)") + set(LIBC_HAS_ISNAN "1" CACHE INTERNAL "Have include isnan(double)") + set(LIBC_ISNAN_HANDLES_FLOAT "1" CACHE INTERNAL "Have include isnan(float)") + set(LIBC_HAS_ISNANF "" CACHE INTERNAL "Have include isnanf(float)") + set(LIBC_HAS_ITOA "1" CACHE INTERNAL "Have symbol itoa") + set(LIBC_HAS_LIMITS_H "1" CACHE INTERNAL "Have include limits.h") + set(LIBC_HAS_LOG "1" CACHE INTERNAL "Have symbol log") + set(LIBC_HAS_LOG10 "1" CACHE INTERNAL "Have symbol log10") + set(LIBC_HAS_LOG10F "1" CACHE INTERNAL "Have symbol log10f") + set(LIBC_HAS_LOGF "1" CACHE INTERNAL "Have symbol logf") + set(LIBC_HAS_LROUND "1" CACHE INTERNAL "Have symbol lround") + set(LIBC_HAS_LROUNDF "1" CACHE INTERNAL "Have symbol lroundf") + set(LIBC_HAS_MALLOC "1" CACHE INTERNAL "Have symbol malloc") + set(LIBC_HAS_MALLOC_H "1" CACHE INTERNAL "Have include malloc.h") + set(LIBC_HAS_MATH_H "1" CACHE INTERNAL "Have include math.h") + set(LIBC_HAS_MEMCMP "1" CACHE INTERNAL "Have symbol memcmp") + set(LIBC_HAS_MEMCPY "1" CACHE INTERNAL "Have symbol memcpy") + set(LIBC_HAS_MEMMOVE "1" CACHE INTERNAL "Have symbol memmove") + set(LIBC_HAS_MEMORY_H "1" CACHE INTERNAL "Have include memory.h") + set(LIBC_HAS_MEMSET "1" CACHE INTERNAL "Have symbol memset") + set(LIBC_HAS_MODF "1" CACHE INTERNAL "Have symbol modf") + set(LIBC_HAS_MODFF "1" CACHE INTERNAL "Have symbol modff") + set(LIBC_HAS_POW "1" CACHE INTERNAL "Have symbol pow") + set(LIBC_HAS_POWF "1" CACHE INTERNAL "Have symbol powf") + set(LIBC_HAS_PUTENV "1" CACHE INTERNAL "Have symbol putenv") + set(LIBC_HAS_REALLOC "1" CACHE INTERNAL "Have symbol realloc") + set(LIBC_HAS_RINDEX "" CACHE INTERNAL "Have symbol rindex") + set(LIBC_HAS_ROUND "1" CACHE INTERNAL "Have symbol round") + set(LIBC_HAS_ROUNDF "1" CACHE INTERNAL "Have symbol roundf") + set(LIBC_HAS_SCALBN "1" CACHE INTERNAL "Have symbol scalbn") + set(LIBC_HAS_SCALBNF "1" CACHE INTERNAL "Have symbol scalbnf") + set(LIBC_HAS_SETENV "" CACHE INTERNAL "Have symbol setenv") + set(LIBC_HAS_SIGNAL_H "1" CACHE INTERNAL "Have include signal.h") + set(LIBC_HAS_SIN "1" CACHE INTERNAL "Have symbol sin") + set(LIBC_HAS_SINF "1" CACHE INTERNAL "Have symbol sinf") + set(LIBC_HAS_SQR "" CACHE INTERNAL "Have symbol sqr") + set(LIBC_HAS_SQRT "1" CACHE INTERNAL "Have symbol sqrt") + set(LIBC_HAS_SQRTF "1" CACHE INTERNAL "Have symbol sqrtf") + set(LIBC_HAS_SSCANF "1" CACHE INTERNAL "Have symbol sscanf") + set(LIBC_HAS_STDARG_H "1" CACHE INTERNAL "Have include stdarg.h") + set(LIBC_HAS_STDBOOL_H "1" CACHE INTERNAL "Have include stdbool.h") + set(LIBC_HAS_STDDEF_H "1" CACHE INTERNAL "Have include stddef.h") + set(LIBC_HAS_STDINT_H "1" CACHE INTERNAL "Have include stdint.h") + set(LIBC_HAS_STDIO_H "1" CACHE INTERNAL "Have include stdio.h") + set(LIBC_HAS_STDLIB_H "1" CACHE INTERNAL "Have include stdlib.h") + set(LIBC_HAS_STRCHR "1" CACHE INTERNAL "Have symbol strchr") + set(LIBC_HAS_STRCMP "1" CACHE INTERNAL "Have symbol strcmp") + set(LIBC_HAS_STRINGS_H "" CACHE INTERNAL "Have include strings.h") + set(LIBC_HAS_STRING_H "1" CACHE INTERNAL "Have include string.h") + set(LIBC_HAS_STRLCAT "" CACHE INTERNAL "Have symbol strlcat") + set(LIBC_HAS_STRLCPY "" CACHE INTERNAL "Have symbol strlcpy") + set(LIBC_HAS_STRLEN "1" CACHE INTERNAL "Have symbol strlen") + set(LIBC_HAS_STRNCMP "1" CACHE INTERNAL "Have symbol strncmp") + set(LIBC_HAS_STRNLEN "1" CACHE INTERNAL "Have symbol strnlen") + set(LIBC_HAS_STRNSTR "" CACHE INTERNAL "Have symbol strnstr") + set(LIBC_HAS_STRPBRK "1" CACHE INTERNAL "Have symbol strpbrk") + set(LIBC_HAS_STRRCHR "1" CACHE INTERNAL "Have symbol strrchr") + set(LIBC_HAS_STRSTR "1" CACHE INTERNAL "Have symbol strstr") + set(LIBC_HAS_STRTOD "1" CACHE INTERNAL "Have symbol strtod") + set(LIBC_HAS_STRTOK_R "" CACHE INTERNAL "Have symbol strtok_r") + set(LIBC_HAS_STRTOL "1" CACHE INTERNAL "Have symbol strtol") + set(LIBC_HAS_STRTOLL "1" CACHE INTERNAL "Have symbol strtoll") + set(LIBC_HAS_STRTOUL "1" CACHE INTERNAL "Have symbol strtoul") + set(LIBC_HAS_STRTOULL "1" CACHE INTERNAL "Have symbol strtoull") + set(LIBC_HAS_SYS_TYPES_H "1" CACHE INTERNAL "Have include sys/types.h") + set(LIBC_HAS_TAN "1" CACHE INTERNAL "Have symbol tan") + set(LIBC_HAS_TANF "1" CACHE INTERNAL "Have symbol tanf") + set(LIBC_HAS_TIME_H "1" CACHE INTERNAL "Have include time.h") + set(LIBC_HAS_TRUNC "1" CACHE INTERNAL "Have symbol trunc") + set(LIBC_HAS_TRUNCF "1" CACHE INTERNAL "Have symbol truncf") + set(LIBC_HAS_UNSETENV "" CACHE INTERNAL "Have symbol unsetenv") + set(LIBC_HAS_VSNPRINTF "1" CACHE INTERNAL "Have symbol vsnprintf") + set(LIBC_HAS_VSSCANF "1" CACHE INTERNAL "Have symbol vsscanf") + set(LIBC_HAS_WCHAR_H "1" CACHE INTERNAL "Have include wchar.h") + set(LIBC_HAS_WCSCMP "1" CACHE INTERNAL "Have symbol wcscmp") + set(LIBC_HAS_WCSDUP "1" CACHE INTERNAL "Have symbol wcsdup") + set(LIBC_HAS_WCSLCAT "" CACHE INTERNAL "Have symbol wcslcat") + set(LIBC_HAS_WCSLCPY "" CACHE INTERNAL "Have symbol wcslcpy") + set(LIBC_HAS_WCSLEN "1" CACHE INTERNAL "Have symbol wcslen") + set(LIBC_HAS_WCSNCMP "1" CACHE INTERNAL "Have symbol wcsncmp") + set(LIBC_HAS_WCSNLEN "1" CACHE INTERNAL "Have symbol wcsnlen") + set(LIBC_HAS_WCSSTR "1" CACHE INTERNAL "Have symbol wcsstr") + set(LIBC_HAS_WCSTOL "1" CACHE INTERNAL "Have symbol wcstol") + set(LIBC_HAS__EXIT "1" CACHE INTERNAL "Have symbol _Exit") + set(LIBC_HAS__I64TOA "1" CACHE INTERNAL "Have symbol _i64toa") + set(LIBC_HAS__LTOA "1" CACHE INTERNAL "Have symbol _ltoa") + set(LIBC_HAS__STRREV "1" CACHE INTERNAL "Have symbol _strrev") + set(LIBC_HAS__UI64TOA "1" CACHE INTERNAL "Have symbol _ui64toa") + set(LIBC_HAS__UITOA "" CACHE INTERNAL "Have symbol _uitoa") + set(LIBC_HAS__ULTOA "1" CACHE INTERNAL "Have symbol _ultoa") + set(LIBC_HAS__WCSDUP "1" CACHE INTERNAL "Have symbol _wcsdup") + set(LIBC_IS_GLIBC "" CACHE INTERNAL "Have symbol __GLIBC__") + set(_ALLOCA_IN_MALLOC_H "" CACHE INTERNAL "Have symbol _alloca") + + if(CHECK_CPU_ARCHITECTURE_X86) + set(COMPILER_SUPPORTS_AVX "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_AVX") + set(COMPILER_SUPPORTS_AVX2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_AVX2") + set(COMPILER_SUPPORTS_MMX "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_MMX") + set(COMPILER_SUPPORTS_SSE "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE") + set(COMPILER_SUPPORTS_SSE2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE2") + set(COMPILER_SUPPORTS_SSE3 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE3") + set(COMPILER_SUPPORTS_SSE4_1 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE4_1") + set(COMPILER_SUPPORTS_SSE4_2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE4_2") + endif() + + if(CHECK_CPU_ARCHITECTURE_X64) + set(COMPILER_SUPPORTS_AVX "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_AVX") + set(COMPILER_SUPPORTS_AVX2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_AVX2") + set(COMPILER_SUPPORTS_MMX "" CACHE INTERNAL "Test COMPILER_SUPPORTS_MMX") + set(COMPILER_SUPPORTS_SSE "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE") + set(COMPILER_SUPPORTS_SSE2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE2") + set(COMPILER_SUPPORTS_SSE3 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE3") + set(COMPILER_SUPPORTS_SSE4_1 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE4_1") + set(COMPILER_SUPPORTS_SSE4_2 "1" CACHE INTERNAL "Test COMPILER_SUPPORTS_SSE4_2") + endif() + + if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "19.1") + set(HAVE_ROAPI_H "1" CACHE INTERNAL "Have include roapi.h") + set(HAVE_WINDOWS_GAMING_INPUT_H "1" CACHE INTERNAL "Test HAVE_WINDOWS_GAMING_INPUT_H") + else() + set(HAVE_ROAPI_H "" CACHE INTERNAL "Have include roapi.h") + set(HAVE_WINDOWS_GAMING_INPUT_H "" CACHE INTERNAL "Test HAVE_WINDOWS_GAMING_INPUT_H") + endif() + endfunction() +endif() diff --git a/libs/SDL3/cmake/macros.cmake b/libs/SDL3/cmake/macros.cmake index 656f4e090..0392a4338 100644 --- a/libs/SDL3/cmake/macros.cmake +++ b/libs/SDL3/cmake/macros.cmake @@ -209,8 +209,8 @@ function(target_get_dynamic_library DEST TARGET) endforeach() else() # 1. find the target library a file might be symbolic linking to - # 2. find all other files in the same folder that symolic link to it - # 3. sort all these files, and select the 1st item on Linux, and last on Macos + # 2. find all other files in the same folder that symbolic link to it + # 3. sort all these files, and select the 1st item on Linux, and last on macOS set(location_properties IMPORTED_LOCATION) if(CMAKE_BUILD_TYPE) list(APPEND location_properties IMPORTED_LOCATION_${CMAKE_BUILD_TYPE}) @@ -226,7 +226,7 @@ function(target_get_dynamic_library DEST TARGET) foreach(location_property ${location_properties}) if(NOT result) get_target_property(library_path "${TARGET}" ${location_property}) - message(DEBUG "get_target_property(${TARGET} ${location_propert}) -> ${library_path}") + message(DEBUG "get_target_property(${TARGET} ${location_property}) -> ${library_path}") if(EXISTS "${library_path}") get_filename_component(library_path "${library_path}" ABSOLUTE) while (IS_SYMLINK "${library_path}") @@ -393,6 +393,14 @@ function(SDL_PrintSummary) message(STATUS " -DSDL_ARMNEON=OFF") message(STATUS "") endif() + + if(UNIX AND NOT (ANDROID OR APPLE OR EMSCRIPTEN)) + if(NOT (HAVE_X11 OR HAVE_WAYLAND)) + message(STATUS "SDL is being built without a X11 or wayland video driver.") + message(STATUS "The library will not be able to create windows on most unix environments.") + message(STATUS "") + endif() + endif() endfunction() function(SDL_install_pdb TARGET DIRECTORY) diff --git a/libs/SDL3/cmake/sdl3.pc.in b/libs/SDL3/cmake/sdl3.pc.in index bfc2afffe..38566f57f 100644 --- a/libs/SDL3/cmake/sdl3.pc.in +++ b/libs/SDL3/cmake/sdl3.pc.in @@ -1,7 +1,7 @@ prefix=@SDL_PKGCONFIG_PREFIX@ exec_prefix=${prefix} -libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ -includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +libdir=@LIBDIR_FOR_PKG_CONFIG@ +includedir=@INCLUDEDIR_FOR_PKG_CONFIG@ Name: sdl3 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. diff --git a/libs/SDL3/cmake/sdlchecks.cmake b/libs/SDL3/cmake/sdlchecks.cmake index 6a12b3049..aecb98fe5 100644 --- a/libs/SDL3/cmake/sdlchecks.cmake +++ b/libs/SDL3/cmake/sdlchecks.cmake @@ -119,10 +119,11 @@ macro(CheckALSA) sdl_link_dependency(alsa LIBS ALSA::ALSA CMAKE_MODULE ALSA PKG_CONFIG_SPECS "${ALSA_PKG_CONFIG_SPEC}") endif() set(HAVE_SDL_AUDIO TRUE) + else() + message(WARNING "Unable to find the alsa development library") endif() else() set(HAVE_ALSA FALSE) - message(WARNING "Unable to find the alsa development library") endif() endmacro() @@ -133,18 +134,21 @@ endmacro() # - HAVE_SDL_LOADSO opt macro(CheckPipewire) if(SDL_PIPEWIRE) - set(PipeWire_PKG_CONFIG_SPEC libpipewire-0.3>=0.3.20) + set(PipeWire_PKG_CONFIG_SPEC libpipewire-0.3>=0.3.44) pkg_check_modules(PC_PIPEWIRE IMPORTED_TARGET ${PipeWire_PKG_CONFIG_SPEC}) if(PC_PIPEWIRE_FOUND) set(HAVE_PIPEWIRE TRUE) sdl_glob_sources("${SDL3_SOURCE_DIR}/src/audio/pipewire/*.c") + sdl_glob_sources("${SDL3_SOURCE_DIR}/src/camera/pipewire/*.c") set(SDL_AUDIO_DRIVER_PIPEWIRE 1) + set(SDL_CAMERA_DRIVER_PIPEWIRE 1) if(SDL_PIPEWIRE_SHARED AND NOT HAVE_SDL_LOADSO) message(WARNING "You must have SDL_LoadObject() support for dynamic PipeWire loading") endif() FindLibraryAndSONAME("pipewire-0.3" LIBDIRS ${PC_PIPEWIRE_LIBRARY_DIRS}) if(SDL_PIPEWIRE_SHARED AND PIPEWIRE_0.3_LIB AND HAVE_SDL_LOADSO) set(SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC "\"${PIPEWIRE_0.3_LIB_SONAME}\"") + set(SDL_CAMERA_DRIVER_PIPEWIRE_DYNAMIC "\"${PIPEWIRE_0.3_LIB_SONAME}\"") set(HAVE_PIPEWIRE_SHARED TRUE) sdl_link_dependency(pipewire INCLUDES $) else() @@ -367,7 +371,7 @@ macro(CheckX11) set(SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1) endif() - check_symbol_exists(XkbKeycodeToKeysym "X11/Xlib.h;X11/XKBlib.h" SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM) + check_symbol_exists(XkbLookupKeySym "X11/Xlib.h;X11/XKBlib.h" SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM) if(SDL_X11_XCURSOR AND HAVE_XCURSOR_H AND XCURSOR_LIB) set(HAVE_X11_XCURSOR TRUE) diff --git a/libs/SDL3/cmake/sdlcompilers.cmake b/libs/SDL3/cmake/sdlcompilers.cmake index 5138fdd0b..fc352e19c 100644 --- a/libs/SDL3/cmake/sdlcompilers.cmake +++ b/libs/SDL3/cmake/sdlcompilers.cmake @@ -29,6 +29,16 @@ endfunction() function(SDL_AddCommonCompilerFlags TARGET) option(SDL_WERROR "Enable -Werror" OFF) + get_property(TARGET_TYPE TARGET "${TARGET}" PROPERTY TYPE) + if(MSVC) + cmake_push_check_state() + check_c_compiler_flag("/W3" COMPILER_SUPPORTS_W3) + if(COMPILER_SUPPORTS_W3) + target_compile_options(${TARGET} PRIVATE "/W3") + endif() + cmake_pop_check_state() + endif() + if(USE_GCC OR USE_CLANG OR USE_INTELCC OR USE_QCC) if(MINGW) # See if GCC's -gdwarf-4 is supported @@ -59,6 +69,11 @@ function(SDL_AddCommonCompilerFlags TARGET) sdl_target_compile_option_all_languages(${TARGET} "-Wundef") endif() + check_c_compiler_flag(-Wfloat-conversion HAVE_GCC_WFLOAT_CONVERSION) + if(HAVE_GCC_WFLOAT_CONVERSION) + sdl_target_compile_option_all_languages(${TARGET} "-Wfloat-conversion") + endif() + check_c_compiler_flag(-fno-strict-aliasing HAVE_GCC_NO_STRICT_ALIASING) if(HAVE_GCC_NO_STRICT_ALIASING) sdl_target_compile_option_all_languages(${TARGET} "-fno-strict-aliasing") @@ -123,6 +138,13 @@ function(SDL_AddCommonCompilerFlags TARGET) if(HAVE_WERROR) sdl_target_compile_option_all_languages(${TARGET} "-Werror") endif() + + if(TARGET_TYPE STREQUAL "SHARED_LIBRARY") + check_linker_flag(C "-Wl,--no-undefined-version" LINKER_SUPPORTS_NO_UNDEFINED_VERSION) + if(LINKER_SUPPORTS_NO_UNDEFINED_VERSION) + target_link_options(${TARGET} PRIVATE "-Wl,--no-undefined-version") + endif() + endif() endif() endif() diff --git a/libs/SDL3/cmake/sdlcpu.cmake b/libs/SDL3/cmake/sdlcpu.cmake new file mode 100644 index 000000000..0df1bb104 --- /dev/null +++ b/libs/SDL3/cmake/sdlcpu.cmake @@ -0,0 +1,148 @@ +function(SDL_DetectTargetCPUArchitectures DETECTED_ARCHS) + + set(known_archs EMSCRIPTEN ARM32 ARM64 ARM64EC LOONGARCH64 POWERPC32 POWERPC64 X86 X64) + + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + foreach(known_arch IN LISTS known_archs) + set(SDL_CPU_${known_arch} "0") + endforeach() + set(detected_archs) + foreach(osx_arch IN LISTS CMAKE_OSX_ARCHITECTURES) + if(osx_arch STREQUAL "x86_64") + set(SDL_CPU_X64 "1") + list(APPEND detected_archs "X64") + elseif(osx_arch STREQUAL "arm64") + set(SDL_CPU_ARM64 "1") + list(APPEND detected_archs "ARM64") + endif() + endforeach() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(detected_archs) + foreach(known_arch IN LISTS known_archs) + if(SDL_CPU_${known_arch}) + list(APPEND detected_archs "${known_arch}") + endif() + endforeach() + + if(detected_archs) + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) + return() + endif() + + set(arch_check_ARM32 "defined(__arm__) || defined(_M_ARM)") + set(arch_check_ARM64 "defined(__aarch64__) || defined(_M_ARM64)") + set(arch_check_ARM64EC "defined(_M_ARM64EC)") + set(arch_check_EMSCRIPTEN "defined(__EMSCRIPTEN__)") + set(arch_check_LOONGARCH64 "defined(__loongarch64)") + set(arch_check_POWERPC32 "(defined(__PPC__) || defined(__powerpc__)) && !defined(__powerpc64__)") + set(arch_check_POWERPC64 "defined(__PPC64__) || defined(__powerpc64__)") + set(arch_check_X86 "defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)") + set(arch_check_X64 "(defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)") + + set(src_vars "") + set(src_main "") + foreach(known_arch IN LISTS known_archs) + set(detected_${known_arch} "0") + + string(APPEND src_vars " +#if ${arch_check_${known_arch}} +#define ARCH_${known_arch} \"1\" +#else +#define ARCH_${known_arch} \"0\" +#endif +const char *arch_${known_arch} = \"INFO<${known_arch}=\" ARCH_${known_arch} \">\"; +") + string(APPEND src_main " + result += arch_${known_arch}[argc];") + endforeach() + + set(src_arch_detect "${src_vars} +int main(int argc, char *argv[]) { + (void)argv; + int result = 0; +${src_main} + return result; +}") + + set(path_src_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch.c") + file(WRITE "${path_src_arch_detect}" "${src_arch_detect}") + set(path_dir_arch_detect "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch") + set(path_bin_arch_detect "${path_dir_arch_detect}/bin") + + set(detected_archs) + + set(msg "Detecting Target CPU Architecture") + message(STATUS "${msg}") + + include(CMakePushCheckState) + + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + + cmake_push_check_state(RESET) + try_compile(SDL_CPU_CHECK_ALL + "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/SDL_detect_arch" + SOURCES "${path_src_arch_detect}" + COPY_FILE "${path_bin_arch_detect}" + ) + cmake_pop_check_state() + if(NOT SDL_CPU_CHECK_ALL) + message(STATUS "${msg} - ") + message(WARNING "Failed to compile source detecting the target CPU architecture") + else() + set(re "INFO<([A-Z0-9]+)=([01])>") + file(STRINGS "${path_bin_arch_detect}" infos REGEX "${re}") + + foreach(info_arch_01 IN LISTS infos) + string(REGEX MATCH "${re}" A "${info_arch_01}") + if(NOT "${CMAKE_MATCH_1}" IN_LIST known_archs) + message(WARNING "Unknown architecture: \"${CMAKE_MATCH_1}\"") + continue() + endif() + set(arch "${CMAKE_MATCH_1}") + set(arch_01 "${CMAKE_MATCH_2}") + set(detected_${arch} "${arch_01}") + endforeach() + + foreach(known_arch IN LISTS known_archs) + if(detected_${known_arch}) + list(APPEND detected_archs ${known_arch}) + endif() + endforeach() + endif() + + if(detected_archs) + foreach(known_arch IN LISTS known_archs) + set("SDL_CPU_${known_arch}" "${detected_${known_arch}}" CACHE BOOL "Detected architecture ${known_arch}") + endforeach() + message(STATUS "${msg} - ${detected_archs}") + else() + include(CheckCSourceCompiles) + cmake_push_check_state(RESET) + foreach(known_arch IN LISTS known_archs) + if(NOT detected_archs) + set(cache_variable "SDL_CPU_${known_arch}") + set(test_src " + int main(int argc, char *argv[]) { + #if ${arch_check_${known_arch}} + return 0; + #else + choke + #endif + } + ") + check_c_source_compiles("${test_src}" "${cache_variable}") + if(${cache_variable}) + set(SDL_CPU_${known_arch} "1" CACHE BOOL "Detected architecture ${known_arch}") + set(detected_archs ${known_arch}) + else() + set(SDL_CPU_${known_arch} "0" CACHE BOOL "Detected architecture ${known_arch}") + endif() + endif() + endforeach() + cmake_pop_check_state() + endif() + set("${DETECTED_ARCHS}" "${detected_archs}" PARENT_SCOPE) +endfunction() diff --git a/libs/SDL3/cmake/sdlplatform.cmake b/libs/SDL3/cmake/sdlplatform.cmake index b402cc038..677b18707 100644 --- a/libs/SDL3/cmake/sdlplatform.cmake +++ b/libs/SDL3/cmake/sdlplatform.cmake @@ -1,109 +1,70 @@ -macro(SDL_DetectCMakePlatform) - set(SDL_CMAKE_PLATFORM ) - # Get the platform +function(SDL_DetectCMakePlatform) + set(sdl_cmake_platform ) if(WIN32) - set(SDL_CMAKE_PLATFORM Windows) + set(sdl_cmake_platform Windows) elseif(PSP) - set(SDL_CMAKE_PLATFORM psp) + set(sdl_cmake_platform psp) elseif(APPLE) - if(CMAKE_SYSTEM_NAME MATCHES ".*Darwin.*") - set(SDL_CMAKE_PLATFORM Darwin) - elseif(CMAKE_SYSTEM_NAME MATCHES ".*MacOS.*") - set(SDL_CMAKE_PLATFORM MacosX) + if(CMAKE_SYSTEM_NAME MATCHES ".*(Darwin|MacOS).*") + set(sdl_cmake_platform macOS) elseif(CMAKE_SYSTEM_NAME MATCHES ".*tvOS.*") - set(SDL_CMAKE_PLATFORM tvOS) + set(sdl_cmake_platform tvOS) elseif(CMAKE_SYSTEM_NAME MATCHES ".*iOS.*") - set(SDL_CMAKE_PLATFORM iOS) + set(sdl_cmake_platform iOS) + elseif(CMAKE_SYSTEM_NAME MATCHES ".*watchOS.*") + set(sdl_cmake_platform watchOS) elseif (CMAKE_SYSTEM_NAME MATCHES "visionOS") - set(SDL_CMAKE_PLATFORM visionOS) - set(VISIONOS ON) # CMAKE does not set this automatically yet + set(sdl_cmake_platform visionOS) + else() + message(WARNING "Unknown Apple platform: \"${CMAKE_SYSTEM_NAME}\"") endif() elseif(CMAKE_SYSTEM_NAME MATCHES "Haiku.*") - set(SDL_CMAKE_PLATFORM Haiku) + set(sdl_cmake_platform Haiku) elseif(NINTENDO_3DS) - set(SDL_CMAKE_PLATFORM n3ds) + set(sdl_cmake_platform n3ds) elseif(PS2) - set(SDL_CMAKE_PLATFORM ps2) + set(sdl_cmake_platform ps2) elseif(VITA) - set(SDL_CMAKE_PLATFORM Vita) + set(sdl_cmake_platform Vita) elseif(CMAKE_SYSTEM_NAME MATCHES ".*Linux") - set(SDL_CMAKE_PLATFORM Linux) + set(sdl_cmake_platform Linux) elseif(CMAKE_SYSTEM_NAME MATCHES "kFreeBSD.*") - set(SDL_CMAKE_PLATFORM FreeBSD) + set(sdl_cmake_platform FreeBSD) elseif(CMAKE_SYSTEM_NAME MATCHES "kNetBSD.*|NetBSD.*") - set(SDL_CMAKE_PLATFORM NetBSD) + set(sdl_cmake_platform NetBSD) elseif(CMAKE_SYSTEM_NAME MATCHES "kOpenBSD.*|OpenBSD.*") - set(SDL_CMAKE_PLATFORM OpenBSD) + set(sdl_cmake_platform OpenBSD) elseif(CMAKE_SYSTEM_NAME MATCHES ".*GNU.*") - set(SDL_CMAKE_PLATFORM GNU) + set(sdl_cmake_platform GNU) elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*") - set(SDL_CMAKE_PLATFORM BSDi) + set(sdl_cmake_platform BSDi) elseif(CMAKE_SYSTEM_NAME MATCHES "DragonFly.*|FreeBSD") - set(SDL_CMAKE_PLATFORM FreeBSD) + set(sdl_cmake_platform FreeBSD) elseif(CMAKE_SYSTEM_NAME MATCHES "SYSV5.*") - set(SDL_CMAKE_PLATFORM SYSV5) + set(sdl_cmake_platform SYSV5) elseif(CMAKE_SYSTEM_NAME MATCHES "Solaris.*|SunOS.*") - set(SDL_CMAKE_PLATFORM Solaris) + set(sdl_cmake_platform Solaris) elseif(CMAKE_SYSTEM_NAME MATCHES "HP-UX.*") - set(SDL_CMAKE_PLATFORM HPUX) + set(sdl_cmake_platform HPUX) elseif(CMAKE_SYSTEM_NAME MATCHES "AIX.*") - set(SDL_CMAKE_PLATFORM AIX) + set(sdl_cmake_platform AIX) elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*") - set(SDL_CMAKE_PLATFORM Minix) + set(sdl_cmake_platform Minix) elseif(CMAKE_SYSTEM_NAME MATCHES "Android.*") - set(SDL_CMAKE_PLATFORM Android) + set(sdl_cmake_platform Android) elseif(CMAKE_SYSTEM_NAME MATCHES "Emscripten.*") - set(SDL_CMAKE_PLATFORM Emscripten) + set(sdl_cmake_platform Emscripten) elseif(CMAKE_SYSTEM_NAME MATCHES "QNX.*") - set(SDL_CMAKE_PLATFORM QNX) + set(sdl_cmake_platform QNX) elseif(CMAKE_SYSTEM_NAME MATCHES "BeOS.*") message(FATAL_ERROR "BeOS support has been removed as of SDL 2.0.2.") endif() - if(SDL_CMAKE_PLATFORM) - string(TOUPPER "${SDL_CMAKE_PLATFORM}" _upper_platform) - set(${_upper_platform} TRUE) + if(sdl_cmake_platform) + string(TOUPPER "${sdl_cmake_platform}" _upper_platform) + set("${_upper_platform}" TRUE PARENT_SCOPE) else() - set(SDL_CMAKE_PLATFORM} "unknown") - endif() -endmacro() - -function(SDL_DetectCPUArchitecture) - set(sdl_cpu_names) - if(APPLE AND CMAKE_OSX_ARCHITECTURES) - foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) - if(osx_arch STREQUAL "x86_64") - list(APPEND sdl_cpu_names "x64") - elseif(osx_arch STREQUAL "arm64") - list(APPEND sdl_cpu_names "arm64") - endif() - endforeach() - endif() - - set(sdl_known_archs x64 x86 arm64 arm32 emscripten powerpc64 powerpc32 loongarch64) - if(NOT sdl_cpu_names) - set(found FALSE) - foreach(sdl_known_arch ${sdl_known_archs}) - if(NOT found) - string(TOUPPER "${sdl_known_arch}" sdl_known_arch_upper) - set(var_name "SDL_CPU_${sdl_known_arch_upper}") - check_cpu_architecture(${sdl_known_arch} ${var_name}) - if(${var_name}) - list(APPEND sdl_cpu_names ${sdl_known_arch}) - set(found TRUE) - endif() - endif() - endforeach() + set(sdl_cmake_platform "unknown") endif() - - foreach(sdl_known_arch ${sdl_known_archs}) - string(TOUPPER "${sdl_known_arch}" sdl_known_arch_upper) - set(var_name "SDL_CPU_${sdl_known_arch_upper}") - if(sdl_cpu_names MATCHES "(^|;)${sdl_known_arch}($|;)") # FIXME: use if(IN_LIST) - set(${var_name} 1 PARENT_SCOPE) - else() - set(${var_name} 0 PARENT_SCOPE) - endif() - endforeach() - set(SDL_CPU_NAMES ${sdl_cpu_names} PARENT_SCOPE) + set(SDL_CMAKE_PLATFORM "${sdl_cmake_platform}" PARENT_SCOPE) endfunction() diff --git a/libs/SDL3/cmake/sdltargets.cmake b/libs/SDL3/cmake/sdltargets.cmake index d4fe91375..781ca01c8 100644 --- a/libs/SDL3/cmake/sdltargets.cmake +++ b/libs/SDL3/cmake/sdltargets.cmake @@ -28,7 +28,7 @@ function(sdl_sources) set_property(TARGET SDL3-collector APPEND PROPERTY INTERFACE_SOURCES ${ARGS_SHARED} ${ARGS_STATIC} ${ARGS_UNPARSED_ARGUMENTS}) endfunction() -# Use sdl_generic_link_dependency to describe a private depency of SDL3. All options are optional. +# Use sdl_generic_link_dependency to describe a private dependency. All options are optional. # Users should use sdl_link_dependency and sdl_test_link_dependency instead # - SHARED_TARGETS: shared targets to add this dependency to # - STATIC_TARGETS: static targets to add this dependency to @@ -36,12 +36,13 @@ endfunction() # - INCLUDES: the include directories of the dependency # - PKG_CONFIG_PREFIX: name of the prefix, when using the functions of FindPkgConfig # - PKG_CONFIG_SPECS: pkg-config spec, used as argument for the functions of FindPkgConfig -# - PKG_CONFIG_LIBS: libs that will only end up in the Libs.private of sdl3.pc +# - PKG_CONFIG_LIBS: libs that will only end up in the Libs.private of the .pc file +# - PKG_CONFIG_LINK_OPTIONS: ldflags that will only end up in the Libs.private of sdl3.pc # - CMAKE_MODULE: CMake module name of the dependency, used as argument of find_package -# - LIBS: list of libraries to link to -# - LINK_OPTIONS: list of link options +# - LIBS: list of libraries to link to (cmake and pkg-config) +# - LINK_OPTIONS: list of link options (also used in pc file, unless PKG_CONFIG_LINK_OPTION is used) function(sdl_generic_link_dependency ID) - cmake_parse_arguments(ARGS "" "COLLECTOR" "SHARED_TARGETS;STATIC_TARGETS;INCLUDES;PKG_CONFIG_LIBS;PKG_CONFIG_PREFIX;PKG_CONFIG_SPECS;CMAKE_MODULE;LIBS;LINK_OPTIONS" ${ARGN}) + cmake_parse_arguments(ARGS "" "COLLECTOR" "SHARED_TARGETS;STATIC_TARGETS;INCLUDES;PKG_CONFIG_LINK_OPTIONS;PKG_CONFIG_LIBS;PKG_CONFIG_PREFIX;PKG_CONFIG_SPECS;CMAKE_MODULE;LIBS;LINK_OPTIONS" ${ARGN}) foreach(target IN LISTS ARGS_SHARED_TARGETS) if(TARGET ${target}) target_include_directories(${target} SYSTEM PRIVATE ${ARGS_INCLUDES}) @@ -63,6 +64,7 @@ function(sdl_generic_link_dependency ID) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_PREFIX ${ARGS_PKG_CONFIG_PREFIX}) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS ${ARGS_PKG_CONFIG_SPECS}) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LIBS ${ARGS_PKG_CONFIG_LIBS}) + set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LINK_OPTIONS ${ARGS_PKG_CONFIG_LINK_OPTIONS}) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_LIBS ${ARGS_LIBS}) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_LINK_OPTIONS ${ARGS_LINK_OPTIONS}) set_property(TARGET ${ARGS_COLLECTOR} APPEND PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE ${ARGS_CMAKE_MODULE}) @@ -133,7 +135,7 @@ function(sdl_compile_options) endif() endfunction() -# Use sdl_link_dependency to add incude directories to the SDL3 libraries. +# Use sdl_link_dependency to add include directories to the SDL3 libraries. function(sdl_include_directories) cmake_parse_arguments(ARGS "SYSTEM;BEFORE;AFTER;PRIVATE;PUBLIC;INTERFACE;NO_EXPORT" "" "" ${ARGN}) set(system "") @@ -294,14 +296,19 @@ function(configure_sdl3_pc) get_property(CMAKE_MODULE TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_CMAKE_MODULE) get_property(PKG_CONFIG_SPECS TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_SPECS) get_property(PKG_CONFIG_LIBS TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LIBS) + get_property(PKG_CONFIG_LDFLAGS TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_PKG_CONFIG_LINK_OPTIONS) get_property(LIBS TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LIBS) get_property(LINK_OPTIONS TARGET SDL3-collector PROPERTY INTERFACE_SDL_DEP_${ID}_LINK_OPTIONS) list(APPEND private_requires ${PKG_CONFIG_SPECS}) list(APPEND private_libs ${PKG_CONFIG_LIBS}) - if(NOT PKG_CONFIG_SPECS AND NOT CMAKE_MODULE) - list(APPEND private_libs ${LIBS}) + if(PKG_CONFIG_SPECS OR PKG_CONFIG_LIBS OR PKG_CONFIG_LDFLAGS) + list(APPEND private_ldflags ${PKG_CONFIG_LDFLAGS}) + else() list(APPEND private_ldflags ${LINK_OPTIONS}) + if(NOT CMAKE_MODULE) + list(APPEND private_libs ${LIBS}) + endif() endif() endforeach() @@ -339,6 +346,17 @@ function(configure_sdl3_pc) string(REGEX REPLACE "[/]+$" "" SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG "${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") set(SDL_PKGCONFIG_PREFIX "\${pcfiledir}/${SDL_PATH_PREFIX_RELATIVE_TO_PKGCONFIG}") + if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}") + set(INCLUDEDIR_FOR_PKG_CONFIG "${CMAKE_INSTALL_INCLUDEDIR}") + else() + set(INCLUDEDIR_FOR_PKG_CONFIG "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") + endif() + if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(LIBDIR_FOR_PKG_CONFIG "${CMAKE_INSTALL_LIBDIR}") + else() + set(LIBDIR_FOR_PKG_CONFIG "\${prefix}/${CMAKE_INSTALL_LIBDIR}") + endif() + configure_file("${SDL3_SOURCE_DIR}/cmake/sdl3.pc.in" "${SDL3_BINARY_DIR}/sdl3.pc" @ONLY) endfunction() diff --git a/libs/SDL3/cmake/test/CMakeLists.txt b/libs/SDL3/cmake/test/CMakeLists.txt index d3fd8a09a..e3766f0e1 100644 --- a/libs/SDL3/cmake/test/CMakeLists.txt +++ b/libs/SDL3/cmake/test/CMakeLists.txt @@ -1,13 +1,26 @@ # This cmake build script is meant for verifying the various CMake configuration scripts. cmake_minimum_required(VERSION 3.12) -project(sdl_test LANGUAGES C) -if(WINDOWS_STORE) - enable_language(CXX) - add_compile_options(/ZW) - set_source_files_properties(ain_cli.c main_gui.c PROPERTIES LANGUAGE CXX) +project(SDL_cmake_selftest LANGUAGES C) + +include(CheckLanguage) + +# FIXME: how to target ios/tvos with Swift? +# https://gitlab.kitware.com/cmake/cmake/-/issues/20104 +if(APPLE AND CMAKE_SYSTEM_NAME MATCHES ".*(Darwin|MacOS).*") + # multiple values for CMAKE_OSX_ARCHITECTURES not supported with Swift + list(LENGTH CMAKE_OSX_ARCHITECTURES count_osx_archs) + if(count_osx_archs LESS_EQUAL 1) + check_language(Swift) + if(CMAKE_Swift_COMPILER) + enable_language(Swift) + endif() + endif() endif() +message(STATUS "CMAKE_SYSTEM_NAME= ${CMAKE_SYSTEM_NAME}") +message(STATUS "CMAKE_SYSTEM_PROCESSOR= ${CMAKE_SYSTEM_PROCESSOR}") + include(GenerateExportHeader) if(ANDROID) @@ -41,8 +54,6 @@ add_feature_info("TEST_FULL" TEST_FULL "Build full SDL testsuite") find_package(SDL3 REQUIRED CONFIG COMPONENTS Headers) add_library(headers_test_slash OBJECT inc_sdl_slash.c) target_link_libraries(headers_test_slash PRIVATE SDL3::Headers) -add_library(headers_test_noslash OBJECT inc_sdl_noslash.c) -target_link_libraries(headers_test_noslash PRIVATE SDL3::Headers) if(TEST_SHARED) find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3-shared) @@ -72,6 +83,12 @@ if(TEST_SHARED) add_executable(sdltest-shared sdltest.c) target_link_libraries(sdltest-shared PRIVATE SDL3::SDL3_test SDL3::SDL3-shared) endif() + + if(CMAKE_Swift_COMPILER) + add_executable(swift-shared main.swift) + target_include_directories(swift-shared PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/swift") + target_link_libraries(swift-shared PRIVATE SDL3::SDL3-shared) + endif() endif() if(TEST_STATIC) @@ -79,19 +96,23 @@ if(TEST_STATIC) add_executable(gui-static WIN32 main_gui.c) target_link_libraries(gui-static PRIVATE SDL3::SDL3-static) - option(SDL_STATIC_PIC "SDL static library has been built with PIC") - if(SDL_STATIC_PIC OR WIN32) - add_library(sharedlib-static SHARED main_lib.c) - target_link_libraries(sharedlib-static PRIVATE SDL3::SDL3-static) - generate_export_header(sharedlib-static EXPORT_MACRO_NAME MYLIBRARY_EXPORT) - target_compile_definitions(sharedlib-static PRIVATE "EXPORT_HEADER=\"${CMAKE_CURRENT_BINARY_DIR}/sharedlib-static_export.h\"") - set_target_properties(sharedlib-static PROPERTIES C_VISIBILITY_PRESET "hidden") - endif() + # Assume SDL library has been built with `set(CMAKE_POSITION_INDEPENDENT_CODE ON)` + add_library(sharedlib-static SHARED main_lib.c) + target_link_libraries(sharedlib-static PRIVATE SDL3::SDL3-static) + generate_export_header(sharedlib-static EXPORT_MACRO_NAME MYLIBRARY_EXPORT) + target_compile_definitions(sharedlib-static PRIVATE "EXPORT_HEADER=\"${CMAKE_CURRENT_BINARY_DIR}/sharedlib-static_export.h\"") + set_target_properties(sharedlib-static PROPERTIES C_VISIBILITY_PRESET "hidden") if(TEST_TEST) add_executable(sdltest-static sdltest.c) target_link_libraries(sdltest-static PRIVATE SDL3::SDL3_test SDL3::SDL3-static) endif() + + if(CMAKE_Swift_COMPILER) + add_executable(swift-static main.swift) + target_include_directories(swift-static PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/swift") + target_link_libraries(swift-static PRIVATE SDL3::SDL3-static) + endif() endif() find_package(SDL3 REQUIRED CONFIG COMPONENTS SDL3) diff --git a/libs/SDL3/cmake/test/inc_sdl_noslash.c b/libs/SDL3/cmake/test/inc_sdl_noslash.c deleted file mode 100644 index 600329cab..000000000 --- a/libs/SDL3/cmake/test/inc_sdl_noslash.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "SDL.h" -#include "SDL_main.h" - -void inc_sdl_noslash(void) { - SDL_SetMainReady(); - SDL_Init(0); - SDL_Quit(); -} diff --git a/libs/SDL3/cmake/test/main.swift b/libs/SDL3/cmake/test/main.swift new file mode 100644 index 000000000..1943f7c42 --- /dev/null +++ b/libs/SDL3/cmake/test/main.swift @@ -0,0 +1,13 @@ +/* Contributed by Piotr Usewicz (https://github.com/pusewicz) */ + +import SDL3 + +guard SDL_Init(SDL_INIT_VIDEO) else { + fatalError("SDL_Init error: \(String(cString: SDL_GetError()))") +} + +var sdlVersion = SDL_GetVersion() + +print("SDL version: \(sdlVersion)") + +SDL_Quit() diff --git a/libs/SDL3/cmake/test/main_cli.c b/libs/SDL3/cmake/test/main_cli.c index 25bb28aed..5a1c0c625 100644 --- a/libs/SDL3/cmake/test/main_cli.c +++ b/libs/SDL3/cmake/test/main_cli.c @@ -5,7 +5,7 @@ int main(int argc, char *argv[]) { SDL_SetMainReady(); - if (SDL_Init(0) < 0) { + if (!SDL_Init(0)) { SDL_Log("Could not initialize SDL: %s\n", SDL_GetError()); return 1; } diff --git a/libs/SDL3/cmake/test/main_gui.c b/libs/SDL3/cmake/test/main_gui.c index c8cc03c12..3df64e5fd 100644 --- a/libs/SDL3/cmake/test/main_gui.c +++ b/libs/SDL3/cmake/test/main_gui.c @@ -5,7 +5,7 @@ int main(int argc, char *argv[]) { SDL_Window *window = NULL; SDL_Surface *screenSurface = NULL; - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (!SDL_Init(SDL_INIT_VIDEO)) { SDL_Log("Could not initialize SDL: %s\n", SDL_GetError()); return 1; } @@ -15,7 +15,7 @@ int main(int argc, char *argv[]) return 1; } screenSurface = SDL_GetWindowSurface(window); - SDL_FillSurfaceRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0xff, 0xff, 0xff)); + SDL_FillSurfaceRect(screenSurface, NULL, SDL_MapSurfaceRGB(screenSurface, 0xff, 0xff, 0xff)); SDL_UpdateWindowSurface(window); SDL_Delay(100); SDL_DestroyWindow(window); diff --git a/libs/SDL3/cmake/test/main_lib.c b/libs/SDL3/cmake/test/main_lib.c index f33c4ef8b..a59150b4a 100644 --- a/libs/SDL3/cmake/test/main_lib.c +++ b/libs/SDL3/cmake/test/main_lib.c @@ -17,7 +17,7 @@ int MYLIBRARY_EXPORT mylibrary_work(void); int mylibrary_init(void) { SDL_SetMainReady(); - if (SDL_Init(0) < 0) { + if (!SDL_Init(0)) { SDL_Log("Could not initialize SDL: %s\n", SDL_GetError()); return 1; } diff --git a/libs/SDL3/cmake/test/swift/module.modulemap b/libs/SDL3/cmake/test/swift/module.modulemap new file mode 100644 index 000000000..bbc26a995 --- /dev/null +++ b/libs/SDL3/cmake/test/swift/module.modulemap @@ -0,0 +1,4 @@ +module SDL3 [extern_c] { + header "shim.h" + export * +} diff --git a/libs/SDL3/cmake/test/swift/shim.h b/libs/SDL3/cmake/test/swift/shim.h new file mode 100644 index 000000000..dba8c6fd4 --- /dev/null +++ b/libs/SDL3/cmake/test/swift/shim.h @@ -0,0 +1,3 @@ +/* Contributed by Piotr Usewicz (https://github.com/pusewicz) */ + +#include diff --git a/libs/SDL3/docs/README-android.md b/libs/SDL3/docs/README-android.md index 94260dab1..e6065715b 100644 --- a/libs/SDL3/docs/README-android.md +++ b/libs/SDL3/docs/README-android.md @@ -16,7 +16,7 @@ https://developer.android.com/sdk/index.html Android NDK r15c or later https://developer.android.com/tools/sdk/ndk/index.html -Minimum API level supported by SDL: 19 (Android 4.4) +Minimum API level supported by SDL: 21 (Android 5.0) How the port works @@ -40,30 +40,31 @@ src/core/android/SDL_android.c Building an app ================================================================================ -For simple projects you can use the script located at build-scripts/androidbuild.sh +For simple projects you can use the script located at build-scripts/create-android-project.py There's two ways of using it: - androidbuild.sh com.yourcompany.yourapp < sources.list - androidbuild.sh com.yourcompany.yourapp source1.c source2.c ...sourceN.c + ./create-android-project.py com.yourcompany.yourapp < sources.list + ./create-android-project.py com.yourcompany.yourapp source1.c source2.c ...sourceN.c sources.list should be a text file with a source file name in each line Filenames should be specified relative to the current directory, for example if you are in the build-scripts directory and want to create the testgles.c test, you'll run: - ./androidbuild.sh org.libsdl.testgles ../test/testgles.c + ./create-android-project.py org.libsdl.testgles ../test/testgles.c One limitation of this script is that all sources provided will be aggregated into a single directory, thus all your source files should have a unique name. -Once the project is complete the script will tell you where the debug APK is located. +Once the project is complete the script will tell you how to build the project. If you want to create a signed release APK, you can use the project created by this utility to generate it. -Finally, a word of caution: re running androidbuild.sh wipes any changes you may have -done in the build directory for the app! +Running the script with `--help` will list all available options, and their purposes. +Finally, a word of caution: re running create-android-project.py wipes any changes you may have +done in the build directory for the app! For more complex projects, follow these instructions: @@ -122,6 +123,48 @@ Here's an explanation of the files in the Android project, so you can customize src/main/java/org/libsdl/app/SDLActivity.java - the Java class handling the initialization and binding to SDL. Be very careful changing this, as the SDL library relies on this implementation. You should instead subclass this for your application. +Using the SDL3 Android Archive (.aar) +================================================================================ + +The `create-android-project.py` script can +./create-android-project.py com.yourcompany.yourapp < sources.list + +The Android archive allows use of SDL3 in your Android project, without needing to copy any SDL c or java source. +For integration with CMake/ndk-build, it uses [prefab](https://google.github.io/prefab/). + +Copy the archive to a `app/libs` directory of your project and add the following to `app/gradle.build`: +``` +android { + /* ... */ + buildFeatures { + prefab true + } +} +dependencies { + implementation files('libs/@PROJECT_NAME@-@PROJECT_VERSION@.aar') + /* ... */ +} +``` + +If you're using CMake, add the following to your CMakeLists.txt: +``` +find_package(@PROJECT_NAME@ REQUIRED CONFIG) +target_link_libraries(yourgame PRIVATE @PROJECT_NAME@::@PROJECT_NAME@) +``` + +If you're using ndk-build, add the following somewhere after `LOCAL_MODULE := yourgame` to your `Android.mk` or `Application.mk`: +``` +# https://google.github.io/prefab/build-systems.html + +# Add the prefab modules to the import path. +$(call import-add-path,/out) + +# Import @PROJECT_NAME@ so we can depend on it. +$(call import-module,prefab/@PROJECT_NAME@) +``` + +If you want to avoid adding the complete SDL source base as a subproject, or adding the Java sources of the bindings to your Android project + Customizing your application name ================================================================================ @@ -169,9 +212,10 @@ them using the standard functions in SDL_iostream.h. There are also a few Android specific functions that allow you to get other useful paths for saving and loading data: -* SDL_AndroidGetInternalStoragePath() -* SDL_AndroidGetExternalStorageState() -* SDL_AndroidGetExternalStoragePath() +* SDL_GetAndroidInternalStoragePath() +* SDL_GetAndroidExternalStorageState() +* SDL_GetAndroidExternalStoragePath() +* SDL_GetAndroidCachePath() See SDL_system.h for more details on these functions. @@ -188,42 +232,87 @@ disable this behaviour, see for example: http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-apps/ -Pause / Resume behaviour +Activity lifecycle ================================================================================ +On Android the application goes through a fixed life cycle and you will get +notifications of state changes via application events. When these events +are delivered you must handle them in an event callback because the OS may +not give you any processing time after the events are delivered. + +e.g. + + int HandleAppEvents(void *userdata, SDL_Event *event) + { + switch (event->type) + { + case SDL_EVENT_TERMINATING: + /* Terminate the app. + Shut everything down before returning from this function. + */ + return 0; + case SDL_EVENT_LOW_MEMORY: + /* You will get this when your app is paused and iOS wants more memory. + Release as much memory as possible. + */ + return 0; + case SDL_EVENT_WILL_ENTER_BACKGROUND: + /* Prepare your app to go into the background. Stop loops, etc. + This gets called when the user hits the home button, or gets a call. + + You should not make any OpenGL graphics calls or use the rendering API, + in addition, you should set the render target to NULL, if you're using + it, e.g. call SDL_SetRenderTarget(renderer, NULL). + */ + return 0; + case SDL_EVENT_DID_ENTER_BACKGROUND: + /* Your app is NOT active at this point. */ + return 0; + case SDL_EVENT_WILL_ENTER_FOREGROUND: + /* This call happens when your app is coming back to the foreground. + Restore all your state here. + */ + return 0; + case SDL_EVENT_DID_ENTER_FOREGROUND: + /* Restart your loops here. + Your app is interactive and getting CPU again. + + You have access to the OpenGL context or rendering API at this point. + However, there's a chance (on older hardware, or on systems under heavy load), + where the graphics context can not be restored. You should listen for the + event SDL_EVENT_RENDER_DEVICE_RESET and recreate your OpenGL context and + restore your textures when you get it, or quit the app. + */ + return 0; + default: + /* No special processing, add it to the event queue */ + return 1; + } + } + + int main(int argc, char *argv[]) + { + SDL_SetEventFilter(HandleAppEvents, NULL); + + ... run your main loop + + return 0; + } + + +Note that if you are using main callbacks instead of a standard C main() function, +your SDL_AppEvent() callback will run as these events arrive and you do not need to +use SDL_SetEventFilter. + If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default), the event loop will block itself when the app is paused (ie, when the user returns to the main Android dashboard). Blocking is better in terms of battery use, and it allows your app to spring back to life instantaneously after resume (versus polling for a resume message). -Upon resume, SDL will attempt to restore the GL context automatically. -In modern devices (Android 3.0 and up) this will most likely succeed and your -app can continue to operate as it was. - -However, there's a chance (on older hardware, or on systems under heavy load), -where the GL context can not be restored. In that case you have to listen for -a specific message (SDL_EVENT_RENDER_DEVICE_RESET) and restore your textures -manually or quit the app. - -You should not use the SDL renderer API while the app going in background: -- SDL_EVENT_WILL_ENTER_BACKGROUND: - after you read this message, GL context gets backed-up and you should not - use the SDL renderer API. - - When this event is received, you have to set the render target to NULL, if you're using it. - (eg call SDL_SetRenderTarget(renderer, NULL)) - -- SDL_EVENT_DID_ENTER_FOREGROUND: - GL context is restored, and the SDL renderer API is available (unless you - receive SDL_EVENT_RENDER_DEVICE_RESET). - -Activity lifecycle -================================================================================ - -You can control activity re-creation (eg. onCreate()) behaviour. This allows to keep -or re-initialize java and native static datas, see SDL_hints.h: -- SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY +You can control activity re-creation (eg. onCreate()) behaviour. This allows you +to choose whether to keep or re-initialize java and native static datas, see +SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY in SDL_hints.h. Mouse / Touch events ================================================================================ @@ -377,9 +466,9 @@ Memory debugging The best (and slowest) way to debug memory issues on Android is valgrind. Valgrind has support for Android out of the box, just grab code using: - svn co svn://svn.valgrind.org/valgrind/trunk valgrind + git clone https://sourceware.org/git/valgrind.git -... and follow the instructions in the file README.android to build it. +... and follow the instructions in the file `README.android` to build it. One thing I needed to do on macOS was change the path to the toolchain, and add ranlib to the environment variables: diff --git a/libs/SDL3/docs/README-cmake.md b/libs/SDL3/docs/README-cmake.md index 73f80f21c..b1491b148 100644 --- a/libs/SDL3/docs/README-cmake.md +++ b/libs/SDL3/docs/README-cmake.md @@ -44,6 +44,14 @@ cmake -S ~/sdl -B ~/build -DSDL_TEST_LIBRARY=ON -DSDL_TESTS=ON ``` and then building normally. In this example, the test programs will be built and can be run from `~/build/tests/`. +### Building SDL examples + +You can build the SDL example programs by adding `-DSDL_EXAMPLES=ON` to the first cmake command above: +```sh +cmake -S ~/sdl -B ~/build -DSDL_EXAMPLES=ON +``` +and then building normally. In this example, the example programs will be built and can be run from `~/build/examples/`. + ## Including SDL in your project SDL can be included in your project in 2 major ways: @@ -90,6 +98,8 @@ The following components are available, to be used as an argument of `find_packa | SDL3 | The SDL3 library, available through the `SDL3::SDL3` target. This is an alias of `SDL3::SDL3-shared` or `SDL3::SDL3-static`. This component is always available. | | Headers | The SDL3 headers, available through the `SDL3::Headers` target. This component is always available. | +SDL's CMake support guarantees a `SDL3::SDL3` target. +Neither `SDL3::SDL3-shared` nor `SDL3::SDL3-static` are guaranteed to exist. ### Using a vendored SDL @@ -114,9 +124,13 @@ cmake --build . --config Release ### Shared or static -By default, only a shared SDL library is built and installed. +By default, only a dynamic (=shared) SDL library is built and installed. The options `-DSDL_SHARED=` and `-DSDL_STATIC=` accept boolean values to change this. +Exceptions exist: +- some platforms don't support dynamic libraries, so only `-DSDL_STATIC=ON` makes sense. +- a static Apple framework is not supported + ### Pass custom compile options to the compiler - Use [`CMAKE__FLAGS`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_FLAGS.html) to pass extra @@ -283,6 +297,32 @@ At the end of SDL CMake configuration, a table shows all CMake options along wit | `-DSDL_DISABLE_INSTALL_DOCS=` | `ON`/`OFF` | Don't install the SDL documentation | | `-DSDL_INSTALL_TESTS=` | `ON`/`OFF` | Install the SDL test programs | +## CMake FAQ + +### How do I copy a SDL3 dynamic library to another location? + +Use [CMake generator expressions](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#target-dependent-expressions). +Generator expressions support multiple configurations, and are evaluated during build system generation time. + +On Windows, the following example this copies `SDL3.dll` to the directory where `mygame.exe` is built. +On Unix systems, `$` will refer to the dynamic library (or framework). +```cmake +if(WIN32) + add_custom_command( + TARGET mygame POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy $ $ + VERBATIM + ) +endif() +``` + +### Linking against a static SDL library fails due to relocation errors + +On unix platforms, all code that ends up in shared libraries needs to be built as relocatable (=position independent) code. +However, by default CMake builds static libraries as non-relocatable. +Configuring SDL with `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` will result in a static `libSDL3.a` library +which you can link against to create a shared library. + ## Help, it doesn't work! Below, a SDL3 CMake project can be found that builds 99.9% of time (assuming you have internet connectivity). @@ -307,7 +347,7 @@ endif() # 2. Try using a vendored SDL library if(NOT SDL3_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/SDL/CMakeLists.txt") - add_subdirectory(SDL) + add_subdirectory(SDL EXCLUDE_FROM_ALL) message(STATUS "Using SDL3 via add_subdirectory") set(SDL3_FOUND TRUE) endif() @@ -345,7 +385,7 @@ int main(int argc, char *argv[]) { (void)argc; (void)argv; - if (SDL_Init(SDL_INIT_VIDEO) < 0) { + if (!SDL_Init(SDL_INIT_VIDEO)) { SDL_Log("SDL_Init failed (%s)", SDL_GetError()); return 1; } @@ -353,12 +393,11 @@ int main(int argc, char *argv[]) { SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; - if (SDL_CreateWindowAndRenderer(640, 480, 0, &window, &renderer) < 0) { + if (!SDL_CreateWindowAndRenderer("SDL issue", 640, 480, 0, &window, &renderer)) { SDL_Log("SDL_CreateWindowAndRenderer failed (%s)", SDL_GetError()); SDL_Quit(); return 1; } - SDL_SetWindowTitle(window, "SDL issue"); while (1) { int finished = 0; diff --git a/libs/SDL3/docs/README-contributing.md b/libs/SDL3/docs/README-contributing.md index 347f0f825..e6435f787 100644 --- a/libs/SDL3/docs/README-contributing.md +++ b/libs/SDL3/docs/README-contributing.md @@ -12,6 +12,7 @@ We appreciate your interest in contributing to SDL, this document will describe - [Following the style guide](#following-the-style-guide) - [Running the tests](#running-the-tests) - [Opening a pull request](#opening-a-pull-request) + - [Continuous integration](#continuous-integration) - [Contributing to the documentation](#contributing-to-the-documentation) - [Editing a function documentation](#editing-a-function-documentation) - [Editing the wiki](#editing-the-wiki) @@ -86,6 +87,15 @@ Tests allow you to verify if your changes did not break any behaviour, here are - Fill out the pull request template. - If any changes are requested, you can add new commits to your fork and they will be automatically added to the pull request. +### Continuous integration + +For each push and/or pull request, GitHub Actions will try to build SDL and the test suite on most supported platforms. + +Its behaviour can be influenced slightly by including SDL-specific tags in your commit message: +- `[sdl-ci-filter GLOB]` limits the platforms for which to run ci. +- `[sdl-ci-artifacts]` forces SDL artifacts, which can then be downloaded from the summary page. +- `[sdl-ci-trackmem-symbol-names]` makes sure the final report generated by `--trackmem` contains symbol names. + ## Contributing to the documentation ### Editing a function documentation diff --git a/libs/SDL3/docs/README-documentation-rules.md b/libs/SDL3/docs/README-documentation-rules.md new file mode 100644 index 000000000..ae705378f --- /dev/null +++ b/libs/SDL3/docs/README-documentation-rules.md @@ -0,0 +1,401 @@ +# Rules for documentation + +These are the rules for the care and feeding of wikiheaders.pl. + + +## No style guide + +When adding or editing documentation, we don't (currently) have a style guide +for what it should read like, so try to make it consistent with the rest of +the existing text. It generally should read more like technical reference +manuals and not sound conversational in tone. + +Most of these rules are about how to make sure the documentation works on +a _technical_ level, as scripts need to parse it, and there are a few simple +rules we need to obey to cooperate with those scripts. + +## The wiki and headers share the same text. + +There is a massive Perl script (`build-scripts/wikiheaders.pl`, hereafter +referred to as "wikiheaders") that can read both the wiki and the public +headers, and move changes in one across to the other. + +If you prefer to use the wiki, go ahead and edit there. If you prefer to use +your own text editor, or command line tools to batch-process text, etc, you +can [clone the wiki as a git repo](https://github.com/libsdl-org/sdlwiki) and +work locally. + + +## Don't taunt wikiheaders. + +The script isn't magic; it's a massive pile of Regular Expressions and not +a full C or markdown parser. While it isn't _fragile_, if you try to do clever +things, you might confuse it. This is to the benefit of documentation, though, +where we would rather you not do surprising things. + + +## We _sort of_ write in Doxygen format. + +To document a symbol, we use something that looks like Doxygen (and Javadoc) +standard comment format: + +```c +/** + * This is a function that does something. + * + * It can be used for frozzling bobbles. Be aware that the Frozulator module + * _must_ be initialized before calling this. + * + * \param frozzlevel The amount of frozzling to perform. + * \param color What color bobble to frozzle. 0 is red, 1 is green. + * \returns the number of bobbles that were actually frozzled, -1 on error. + * + * \threadsafety Do not call this from two threads at once, or the bobbles + * won't all frozzle correctly! + * + * \since This function is available since SDL 7.3.1. + * + * \sa SDL_DoSomethingElse + */ +extern SDL_DECLSPEC int SDLCALL SDL_DoSomething(int frozzlevel, int color); +``` + +Note the `/**` at the start of the comment. That's a "Doxygen-style" comment, +and wikiheaders will treat this differently than a comment with one `*`, as +this signifies that this is not just a comment, but _documentation_. + +These comments _must_ start in the first column of the line, or wikiheaders +will ignore them, even with the "/**" start (we should improve the script +someday to handle this, but currently this is a requirement). + +We do _not_ parse every magic Doxygen tag, and we don't parse them in `@param` +format. The goal here was to mostly coexist with people that might want +to run Doxygen on the SDL headers, not to build Doxygen from scratch. That +being said, compatibility with Doxygen is not a hard requirement here. + +wikiheaders uses these specific tags to turn this comment into a (hopefully) +well-formatted wiki page, and also can generate manpages and books in LaTeX +format from it! + +Text markup in the headers is _always_ done in Markdown format! But less is +more: try not to markup text more than necessary. + + +## Doxygen tags we support: + +- `\brief one-line description` (Not required, and wikiheaders will remove tag). +- `\param varname description` (One for each function/macro parameter) +- `\returns description` (One for each function, don't use on `void` returns). +- `\sa` (each of these get tucked into a "See Also" section on the wiki) +- `\since This function is available since SDL 3.0.0.` (one per Doxygen comment) +- `\threadsafety description` (one per function/macro). +- `\deprecated description` (one per symbol, if symbol is deprecated!) + +Other Doxygen things might exist in the headers, but they aren't understood +by wikiheaders. + + +## Use Markdown. + +The wiki also supports MediaWiki format, but we are transitioning away from it. +The headers always use Markdown. If you're editing the wiki from a git clone, +just make .md files and the wiki will know what to do with them. + + +## Most things in the headers can be documented. + +wikiheaders understands functions, typedefs, structs/unions/enums, `#defines` +... basically most of what makes up a C header. Just slap a Doxygen-style +comment in front of most things and it'll work. + + +## Defines right below typedefs and functions bind. + +Any `#define` directly below a function or non-struct/union/enum typedef is +considered part of that declaration. This happens to work well with how our +headers work, as these defines tend to be bitflags and such that are related +to that symbol. + +wikiheaders will include those defines in the syntax section of the wiki +page, and generate stub pages for each define that simply says "please refer +to (The Actual Symbol You Care About)" with a link. It will also pull in +any blank lines and most preprocessor directives for the syntax text, too. + +Sometimes an unrelated define, by itself, just happens to be right below one +of these symbols in the header. The easiest way to deal with this is either +to document that define with a Doxygen-style comment, if it makes sense to do +so, or just add a normal C comment right above it if not, so wikiheaders +doesn't bind it to the previous symbol. + + +## Don't document the `SDL_test*.h` headers. + +These are in the public headers but they aren't really considered public APIs. +They live in a separate library that doesn't, or at least probably shouldn't, +ship to end users. As such, we don't want it documented on the wiki. + +For now, we do this by not having any Doxygen-style comments in these files. +Please keep it that way! If you want to document these headers, just don't +use the magic two-`*` comment. + + +## The first line is the summary. + +The first line of a piece of documentation is meant to be a succinct +description. This is what Doxygen would call the `\brief` tag. wikiheaders +will split this text out until the first period (end of sentence!), and when +word wrapping, shuffle the overflow into a new paragraph below it. + + +## Split paragraphs with a blank line. + +And don't indent them at all (indenting in Markdown is treated as preformatted +text). + +wikiheaders will wordwrap header comments so they fit in 80 columns, so if you +don't leave a blank line between paragraphs, they will smush into a single +block of text when wordwrapping. + + +## Don't worry about word wrapping. + +If you don't word-wrap your header edits perfectly (and you won't, I promise), +wikiheaders will send your change to the wiki, and then to make things match, +send it right back to the headers with correct word wrapping. Since this +happens right after you push your changes, you might as well just write +however you like and assume the system will clean it up for you. + + +## Things that start with `SDL_` will automatically become wiki links. + +wikiheaders knows to turn these into links to other pages, so if you reference +an SDL symbol in the header documentation, you don't need to link to it. +You can optionally wrap the symbol in backticks, and wikiheaders will know to +link the backticked thing. It will not generate links in three-backtick +code/preformatted blocks. + + +## URLs will automatically become links. + +You can use Markdown's `[link markup format](https://example.com/)`, but +sometimes it's clearer to list bare URLs; the URL will be visible on the +wiki page, but also clickable to follow the link. This is up to your judgment +on a case-by-case basis. + + +## Hide stuff from wikiheaders. + +If all else fails, you can block off pieces of the header with this +magic line (whitespace is ignored): + +```c +#ifndef SDL_WIKI_DOCUMENTATION_SECTION +``` + +Everything between this line and the next `#endif` will just be skipped by +wikiheaders. Note that wikiheaders is not a C preprocessor! Don't try to +nest conditionals or use `!defined`. + +Just block off sections if you need to. And: you almost never need to. + + +## Hide stuff from the compiler. + +If you need to put something that's only of interest to wikiheaders, the +convention is to put it in a block like this: + +```c +#ifdef SDL_WIKI_DOCUMENTATION_SECTION +``` + +Generally this is used when there's a collection of preprocessor conditionals +to define the same symbol differently in different circumstances. You put +that symbol in this block with some reasonable generic version _and the +Doxygen-style comment_. Because wikiheaders doesn't care about this +preprocessor magic, and the C compiler can be as fancy as it wants, this is +strictly a useful convention. + + +## Struct/union/enum typedefs must have the name on the first line. + +This is because wikiheaders is not a full C parser. Don't write this: + +```c +typedef struct +{ + int a; + int b; +} SDL_MyStruct; +``` + +...make sure the name is at the start, too: + +```c +typedef struct SDL_MyStruct +{ + int a; + int b; +} SDL_MyStruct; +``` + +wikiheaders will complain loudly if you don't do this, and exit with an +error message. + + +## Code examples go in the wiki. + +We don't want the headers cluttered up with code examples. These live on the +wiki pages, and wikiheaders knows to not bridge them back to the headers. + +Put them in a `## Code Examples` section, and make sure to wrap them in a +three-backtick-c section for formatting purposes. Only write code in C, +please. + + +## Do you _need_ a code example? + +Most code examples aren't actually useful. If your code example is just +`SDL_CreateWindow("Hello SDL", 640, 480, 0);` then just delete it; if all +you're showing is how to call a function in C, it's not a useful code example. +Not all functions need an example. One with complex setup or usage details +might, though! + + +## Code examples are compiled by GitHub Actions. + +On each change to the wiki, there is a script that pulls out all the code +examples into discrete C files and attempts to compile them, and complains +if they don't work. + + +## Unrecognized sections are left alone in the wiki. + +A wiki section that starts with `## Section Name` (or `== Section Name ==` in +MediaWiki format) that isn't one of the recognized names will be left alone +by wikiheaders. Recognized sections might get overwritten with new content +from the headers, but the wiki file will not have other sections cleaned out +(this is how Code Examples remain wiki only, for example). You can use this +to add Wiki-specific text, or stuff that doesn't make sense in a header, or +would merely clutter it up. + +A possibly-incomplete list of sections that will be overwritten by changes +to the headers: + +- The page title line, and the "brief" one-sentence description section. +- "Deprecated" +- "Header File" +- "Syntax" +- "Function Parameters" +- "Macro Parameters" +- "Fields" +- "Values" +- "Return Value" +- "Remarks" +- "Thread Safety" +- "Version" +- "See Also" + + +## It's okay to repeat yourself. + +Each individual piece of documentation becomes a separate page on the wiki, so +small repeated details can just exist in different pieces of documentation. If +it's complicated, it's not unreasonable to say "Please refer to +SDL_SomeOtherFunction for more details" ... wiki users can click right +through, header users can search for the function name. + + +## The docs directory is bridged to the wiki, too. + +You might be reading this document on the wiki! Any `README-*.md` files in +the docs directory are bridged to the wiki, so `docs/README-linux.md` lands +at https://wiki.libsdl.org/SDL3/README/linux ...these are just copied directly +without any further processing by wikiheaders, and changes go in both +directions. + + +## The wiki can have its own pages, too. + +If a page name isn't a symbol that wikiheaders sees in the headers, or a +README in the source's `docs` directory, or a few other exceptions, it'll +assume it's an unrelated wiki page and leave it alone. So feel free to +write any wiki-only pages that make sense and not worry about it junking +up the headers! + + +## Wiki categories are (mostly) managed automatically. + +The wiki will see this pattern as the last thing on a page and treat it as a +list of categories that page belongs to: + +``` +---- +[CategoryStuff](CategoryStuff), [CategoryWhatever](CategoryWhatever) +``` + +You can use this to simply tag a page as part of a category, and the user can +click directly to see other pages in that category. The wiki will +automatically manage a `Category*` pages that list any tagged pages. + +You _should not_ add tags to the public headers. They don't mean anything +there. wikiheaders will add a few tags that make sense when generating wiki +content from the header files, and it will preserve other tags already present +on the page, so if you want to add extra categories to something, tag it on +the wiki itself. + +The wiki uses some magic HTML comment tags to decide how to list items on +Category pages and let other content live on the page as well. You can +see an example of this in action at: + +https://raw.githubusercontent.com/libsdl-org/sdlwiki/main/SDL3/CategoryEvents.md + + +## Categorizing the headers. + +To put a symbol in a specific category, we use three approaches in SDL: + +- Things in the `SDL_test*.h` headers aren't categorized at all (and you + shouldn't document them!) +- Most files are categorized by header name: we strip off the leading `SDL_` + and capitalize the first letter of what's left. So everything in SDL_audio.h + is in the "Audio" category, everything in SDL_video.h is in the "Video" + category, etc. +- If wikiheaders sees a comment like this on a line by itself... + ```c + /* WIKI CATEGORY: Blah */ + ``` + ...then all symbols below that will land in the "Blah" category. We use this + at the top of a few headers where the simple + chop-off-SDL_-and-captialize-the-first-letter trick doesn't work well, but + one could theoretically use this for headers that have some overlap in + category. + + +## Category documentation lives in headers. + +To document a category (text that lives before the item lists on a wiki +category page), you have to follow a simple rule: + +The _first_ Doxygen-style comment in a header must start with: + +``` +/** + * # CategoryABC +``` + +If these conditions aren't met, wikiheaders will assume that documentation +belongs to whatever is below it instead of the Category. + +The text of this comment will be added to the appropriate wiki Category page, +at the top, replacing everything in the file until it sees a line that starts +with an HTML comment (` East (1,0) - | - | - v - South (0,1) - - - [ USER ] - \|||/ - (o o) - ---ooO-(_)-Ooo--- - \endverbatim - * - * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a - * degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses - * the first \c dir parameter. The cardinal directions would be: - * - North: 0 (0 degrees) - * - East: 9000 (90 degrees) - * - South: 18000 (180 degrees) - * - West: 27000 (270 degrees) - * - * If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions - * (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses - * the first three \c dir parameters. The cardinal directions would be: - * - North: 0,-1, 0 - * - East: 1, 0, 0 - * - South: 0, 1, 0 - * - West: -1, 0, 0 - * - * The Z axis represents the height of the effect if supported, otherwise - * it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you - * can use any multiple you want, only the direction matters. - * - * If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations. - * The first two \c dir parameters are used. The \c dir parameters are as - * follows (all values are in hundredths of degrees): - * - Degrees from (1, 0) rotated towards (0, 1). - * - Degrees towards (0, 0, 1) (device needs at least 3 axes). - * - * - * Example of force coming from the south with all encodings (force coming - * from the south means the user will have to pull the stick to counteract): - * \code + * Structure that represents a haptic direction. + * + * This is the direction where the force comes from, instead of the direction + * in which the force is exerted. + * + * Directions can be specified by: + * + * - SDL_HAPTIC_POLAR : Specified by polar coordinates. + * - SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates. + * - SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates. + * + * Cardinal directions of the haptic device are relative to the positioning of + * the device. North is considered to be away from the user. + * + * The following diagram represents the cardinal directions: + * + * ``` + * .--. + * |__| .-------. + * |=.| |.-----.| + * |--| || || + * | | |'-----'| + * |__|~')_____(' + * [ COMPUTER ] + * + * + * North (0,-1) + * ^ + * | + * | + * (-1,0) West <----[ HAPTIC ]----> East (1,0) + * | + * | + * v + * South (0,1) + * + * + * [ USER ] + * \|||/ + * (o o) + * ---ooO-(_)-Ooo--- + * ``` + * + * If type is SDL_HAPTIC_POLAR, direction is encoded by hundredths of a degree + * starting north and turning clockwise. SDL_HAPTIC_POLAR only uses the first + * `dir` parameter. The cardinal directions would be: + * + * - North: 0 (0 degrees) + * - East: 9000 (90 degrees) + * - South: 18000 (180 degrees) + * - West: 27000 (270 degrees) + * + * If type is SDL_HAPTIC_CARTESIAN, direction is encoded by three positions (X + * axis, Y axis and Z axis (with 3 axes)). SDL_HAPTIC_CARTESIAN uses the first + * three `dir` parameters. The cardinal directions would be: + * + * - North: 0,-1, 0 + * - East: 1, 0, 0 + * - South: 0, 1, 0 + * - West: -1, 0, 0 + * + * The Z axis represents the height of the effect if supported, otherwise it's + * unused. In cartesian encoding (1, 2) would be the same as (2, 4), you can + * use any multiple you want, only the direction matters. + * + * If type is SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations. The + * first two `dir` parameters are used. The `dir` parameters are as follows + * (all values are in hundredths of degrees): + * + * - Degrees from (1, 0) rotated towards (0, 1). + * - Degrees towards (0, 0, 1) (device needs at least 3 axes). + * + * Example of force coming from the south with all encodings (force coming + * from the south means the user will have to pull the stick to counteract): + * + * ```c * SDL_HapticDirection direction; * * // Cartesian directions @@ -466,14 +520,16 @@ typedef struct SDL_Haptic SDL_Haptic; * // Spherical coordinates * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters. - * \endcode + * ``` + * + * \since This struct is available since SDL 3.0.0. * - * \sa SDL_HAPTIC_POLAR - * \sa SDL_HAPTIC_CARTESIAN - * \sa SDL_HAPTIC_SPHERICAL - * \sa SDL_HAPTIC_STEERING_AXIS - * \sa SDL_HapticEffect - * \sa SDL_GetNumHapticAxes + * \sa SDL_HAPTIC_POLAR + * \sa SDL_HAPTIC_CARTESIAN + * \sa SDL_HAPTIC_SPHERICAL + * \sa SDL_HAPTIC_STEERING_AXIS + * \sa SDL_HapticEffect + * \sa SDL_GetNumHapticAxes */ typedef struct SDL_HapticDirection { @@ -483,20 +539,22 @@ typedef struct SDL_HapticDirection /** - * A structure containing a template for a Constant effect. + * A structure containing a template for a Constant effect. + * + * This struct is exclusively for the SDL_HAPTIC_CONSTANT effect. * - * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect. + * A constant effect applies a constant force in the specified direction to + * the joystick. * - * A constant effect applies a constant force in the specified direction - * to the joystick. + * \since This struct is available since SDL 3.0.0. * - * \sa SDL_HAPTIC_CONSTANT - * \sa SDL_HapticEffect + * \sa SDL_HAPTIC_CONSTANT + * \sa SDL_HapticEffect */ typedef struct SDL_HapticConstant { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_CONSTANT */ + Uint16 type; /**< SDL_HAPTIC_CONSTANT */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -518,68 +576,73 @@ typedef struct SDL_HapticConstant } SDL_HapticConstant; /** - * A structure containing a template for a Periodic effect. - * - * The struct handles the following effects: - * - ::SDL_HAPTIC_SINE - * - ::SDL_HAPTIC_SQUARE - * - ::SDL_HAPTIC_TRIANGLE - * - ::SDL_HAPTIC_SAWTOOTHUP - * - ::SDL_HAPTIC_SAWTOOTHDOWN - * - * A periodic effect consists in a wave-shaped effect that repeats itself - * over time. The type determines the shape of the wave and the parameters - * determine the dimensions of the wave. - * - * Phase is given by hundredth of a degree meaning that giving the phase a value - * of 9000 will displace it 25% of its period. Here are sample values: - * - 0: No phase displacement. - * - 9000: Displaced 25% of its period. - * - 18000: Displaced 50% of its period. - * - 27000: Displaced 75% of its period. - * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred. - * - * Examples: - * \verbatim - SDL_HAPTIC_SINE - __ __ __ __ - / \ / \ / \ / - / \__/ \__/ \__/ - - SDL_HAPTIC_SQUARE - __ __ __ __ __ - | | | | | | | | | | - | |__| |__| |__| |__| | - - SDL_HAPTIC_TRIANGLE - /\ /\ /\ /\ /\ - / \ / \ / \ / \ / - / \/ \/ \/ \/ - - SDL_HAPTIC_SAWTOOTHUP - /| /| /| /| /| /| /| - / | / | / | / | / | / | / | - / |/ |/ |/ |/ |/ |/ | - - SDL_HAPTIC_SAWTOOTHDOWN - \ |\ |\ |\ |\ |\ |\ | - \ | \ | \ | \ | \ | \ | \ | - \| \| \| \| \| \| \| - \endverbatim - * - * \sa SDL_HAPTIC_SINE - * \sa SDL_HAPTIC_SQUARE - * \sa SDL_HAPTIC_TRIANGLE - * \sa SDL_HAPTIC_SAWTOOTHUP - * \sa SDL_HAPTIC_SAWTOOTHDOWN - * \sa SDL_HapticEffect + * A structure containing a template for a Periodic effect. + * + * The struct handles the following effects: + * + * - SDL_HAPTIC_SINE + * - SDL_HAPTIC_SQUARE + * - SDL_HAPTIC_TRIANGLE + * - SDL_HAPTIC_SAWTOOTHUP + * - SDL_HAPTIC_SAWTOOTHDOWN + * + * A periodic effect consists in a wave-shaped effect that repeats itself over + * time. The type determines the shape of the wave and the parameters + * determine the dimensions of the wave. + * + * Phase is given by hundredth of a degree meaning that giving the phase a + * value of 9000 will displace it 25% of its period. Here are sample values: + * + * - 0: No phase displacement. + * - 9000: Displaced 25% of its period. + * - 18000: Displaced 50% of its period. + * - 27000: Displaced 75% of its period. + * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred. + * + * Examples: + * + * ``` + * SDL_HAPTIC_SINE + * __ __ __ __ + * / \ / \ / \ / + * / \__/ \__/ \__/ + * + * SDL_HAPTIC_SQUARE + * __ __ __ __ __ + * | | | | | | | | | | + * | |__| |__| |__| |__| | + * + * SDL_HAPTIC_TRIANGLE + * /\ /\ /\ /\ /\ + * / \ / \ / \ / \ / + * / \/ \/ \/ \/ + * + * SDL_HAPTIC_SAWTOOTHUP + * /| /| /| /| /| /| /| + * / | / | / | / | / | / | / | + * / |/ |/ |/ |/ |/ |/ | + * + * SDL_HAPTIC_SAWTOOTHDOWN + * \ |\ |\ |\ |\ |\ |\ | + * \ | \ | \ | \ | \ | \ | \ | + * \| \| \| \| \| \| \| + * ``` + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_HAPTIC_SINE + * \sa SDL_HAPTIC_SQUARE + * \sa SDL_HAPTIC_TRIANGLE + * \sa SDL_HAPTIC_SAWTOOTHUP + * \sa SDL_HAPTIC_SAWTOOTHDOWN + * \sa SDL_HapticEffect */ typedef struct SDL_HapticPeriodic { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_SQUARE - ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or - ::SDL_HAPTIC_SAWTOOTHDOWN */ + Uint16 type; /**< SDL_HAPTIC_SINE, SDL_HAPTIC_SQUARE + SDL_HAPTIC_TRIANGLE, SDL_HAPTIC_SAWTOOTHUP or + SDL_HAPTIC_SAWTOOTHDOWN */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -604,34 +667,37 @@ typedef struct SDL_HapticPeriodic } SDL_HapticPeriodic; /** - * A structure containing a template for a Condition effect. + * A structure containing a template for a Condition effect. + * + * The struct handles the following effects: + * + * - SDL_HAPTIC_SPRING: Effect based on axes position. + * - SDL_HAPTIC_DAMPER: Effect based on axes velocity. + * - SDL_HAPTIC_INERTIA: Effect based on axes acceleration. + * - SDL_HAPTIC_FRICTION: Effect based on axes movement. * - * The struct handles the following effects: - * - ::SDL_HAPTIC_SPRING: Effect based on axes position. - * - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity. - * - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration. - * - ::SDL_HAPTIC_FRICTION: Effect based on axes movement. + * Direction is handled by condition internals instead of a direction member. + * The condition effect specific members have three parameters. The first + * refers to the X axis, the second refers to the Y axis and the third refers + * to the Z axis. The right terms refer to the positive side of the axis and + * the left terms refer to the negative side of the axis. Please refer to the + * SDL_HapticDirection diagram for which side is positive and which is + * negative. * - * Direction is handled by condition internals instead of a direction member. - * The condition effect specific members have three parameters. The first - * refers to the X axis, the second refers to the Y axis and the third - * refers to the Z axis. The right terms refer to the positive side of the - * axis and the left terms refer to the negative side of the axis. Please - * refer to the ::SDL_HapticDirection diagram for which side is positive and - * which is negative. + * \since This struct is available since SDL 3.0.0. * - * \sa SDL_HapticDirection - * \sa SDL_HAPTIC_SPRING - * \sa SDL_HAPTIC_DAMPER - * \sa SDL_HAPTIC_INERTIA - * \sa SDL_HAPTIC_FRICTION - * \sa SDL_HapticEffect + * \sa SDL_HapticDirection + * \sa SDL_HAPTIC_SPRING + * \sa SDL_HAPTIC_DAMPER + * \sa SDL_HAPTIC_INERTIA + * \sa SDL_HAPTIC_FRICTION + * \sa SDL_HapticEffect */ typedef struct SDL_HapticCondition { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER, - ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION */ + Uint16 type; /**< SDL_HAPTIC_SPRING, SDL_HAPTIC_DAMPER, + SDL_HAPTIC_INERTIA or SDL_HAPTIC_FRICTION */ SDL_HapticDirection direction; /**< Direction of the effect - Not used ATM. */ /* Replay */ @@ -652,22 +718,24 @@ typedef struct SDL_HapticCondition } SDL_HapticCondition; /** - * A structure containing a template for a Ramp effect. + * A structure containing a template for a Ramp effect. * - * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect. + * This struct is exclusively for the SDL_HAPTIC_RAMP effect. * - * The ramp effect starts at start strength and ends at end strength. - * It augments in linear fashion. If you use attack and fade with a ramp - * the effects get added to the ramp effect making the effect become - * quadratic instead of linear. + * The ramp effect starts at start strength and ends at end strength. It + * augments in linear fashion. If you use attack and fade with a ramp the + * effects get added to the ramp effect making the effect become quadratic + * instead of linear. * - * \sa SDL_HAPTIC_RAMP - * \sa SDL_HapticEffect + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_HAPTIC_RAMP + * \sa SDL_HapticEffect */ typedef struct SDL_HapticRamp { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_RAMP */ + Uint16 type; /**< SDL_HAPTIC_RAMP */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -692,19 +760,21 @@ typedef struct SDL_HapticRamp /** * A structure containing a template for a Left/Right effect. * - * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect. + * This struct is exclusively for the SDL_HAPTIC_LEFTRIGHT effect. * * The Left/Right effect is used to explicitly control the large and small * motors, commonly found in modern game controllers. The small (right) motor * is high frequency, and the large (left) motor is low frequency. * + * \since This struct is available since SDL 3.0.0. + * * \sa SDL_HAPTIC_LEFTRIGHT * \sa SDL_HapticEffect */ typedef struct SDL_HapticLeftRight { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */ + Uint16 type; /**< SDL_HAPTIC_LEFTRIGHT */ /* Replay */ Uint32 length; /**< Duration of the effect in milliseconds. */ @@ -715,24 +785,26 @@ typedef struct SDL_HapticLeftRight } SDL_HapticLeftRight; /** - * A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect. + * A structure containing a template for the SDL_HAPTIC_CUSTOM effect. + * + * This struct is exclusively for the SDL_HAPTIC_CUSTOM effect. * - * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect. + * A custom force feedback effect is much like a periodic effect, where the + * application can define its exact shape. You will have to allocate the data + * yourself. Data should consist of channels * samples Uint16 samples. * - * A custom force feedback effect is much like a periodic effect, where the - * application can define its exact shape. You will have to allocate the - * data yourself. Data should consist of channels * samples Uint16 samples. + * If channels is one, the effect is rotated using the defined direction. + * Otherwise it uses the samples in data for the different axes. * - * If channels is one, the effect is rotated using the defined direction. - * Otherwise it uses the samples in data for the different axes. + * \since This struct is available since SDL 3.0.0. * - * \sa SDL_HAPTIC_CUSTOM - * \sa SDL_HapticEffect + * \sa SDL_HAPTIC_CUSTOM + * \sa SDL_HapticEffect */ typedef struct SDL_HapticCustom { /* Header */ - Uint16 type; /**< ::SDL_HAPTIC_CUSTOM */ + Uint16 type; /**< SDL_HAPTIC_CUSTOM */ SDL_HapticDirection direction; /**< Direction of the effect. */ /* Replay */ @@ -757,27 +829,28 @@ typedef struct SDL_HapticCustom } SDL_HapticCustom; /** - * The generic template for any haptic effect. + * The generic template for any haptic effect. + * + * All values max at 32767 (0x7FFF). Signed values also can be negative. Time + * values unless specified otherwise are in milliseconds. * - * All values max at 32767 (0x7FFF). Signed values also can be negative. - * Time values unless specified otherwise are in milliseconds. + * You can also pass SDL_HAPTIC_INFINITY to length instead of a 0-32767 value. + * Neither delay, interval, attack_length nor fade_length support + * SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends. * - * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767 - * value. Neither delay, interval, attack_length nor fade_length support - * ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends. + * Additionally, the SDL_HAPTIC_RAMP effect does not support a duration of + * SDL_HAPTIC_INFINITY. * - * Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of - * ::SDL_HAPTIC_INFINITY. + * Button triggers may not be supported on all devices, it is advised to not + * use them if possible. Buttons start at index 1 instead of index 0 like the + * joystick. * - * Button triggers may not be supported on all devices, it is advised to not - * use them if possible. Buttons start at index 1 instead of index 0 like - * the joystick. + * If both attack_length and fade_level are 0, the envelope is not used, + * otherwise both values are used. * - * If both attack_length and fade_level are 0, the envelope is not used, - * otherwise both values are used. + * Common parts: * - * Common parts: - * \code + * ```c * // Replay - All effects have this * Uint32 length; // Duration of effect (ms). * Uint16 delay; // Delay before starting effect. @@ -791,39 +864,41 @@ typedef struct SDL_HapticCustom * Uint16 attack_level; // Level at the start of the attack. * Uint16 fade_length; // Duration of the fade out (ms). * Uint16 fade_level; // Level at the end of the fade. - * \endcode - * - * - * Here we have an example of a constant effect evolution in time: - * \verbatim - Strength - ^ - | - | effect level --> _________________ - | / \ - | / \ - | / \ - | / \ - | attack_level --> | \ - | | | <--- fade_level - | - +--------------------------------------------------> Time - [--] [---] - attack_length fade_length - - [------------------][-----------------------] - delay length - \endverbatim - * - * Note either the attack_level or the fade_level may be above the actual - * effect level. - * - * \sa SDL_HapticConstant - * \sa SDL_HapticPeriodic - * \sa SDL_HapticCondition - * \sa SDL_HapticRamp - * \sa SDL_HapticLeftRight - * \sa SDL_HapticCustom + * ``` + * + * Here we have an example of a constant effect evolution in time: + * + * ``` + * Strength + * ^ + * | + * | effect level --> _________________ + * | / \ + * | / \ + * | / \ + * | / \ + * | attack_level --> | \ + * | | | <--- fade_level + * | + * +--------------------------------------------------> Time + * [--] [---] + * attack_length fade_length + * + * [------------------][-----------------------] + * delay length + * ``` + * + * Note either the attack_level or the fade_level may be above the actual + * effect level. + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_HapticConstant + * \sa SDL_HapticPeriodic + * \sa SDL_HapticCondition + * \sa SDL_HapticRamp + * \sa SDL_HapticLeftRight + * \sa SDL_HapticCustom */ typedef union SDL_HapticEffect { @@ -838,9 +913,14 @@ typedef union SDL_HapticEffect } SDL_HapticEffect; /** - * This is a unique ID for a haptic device for the time it is connected to the system, and is never reused for the lifetime of the application. If the haptic device is disconnected and reconnected, it will get a new ID. + * This is a unique ID for a haptic device for the time it is connected to the + * system, and is never reused for the lifetime of the application. * - * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + * If the haptic device is disconnected and reconnected, it will get a new ID. + * + * The value 0 is an invalid ID. + * + * \since This datatype is available since SDL 3.0.0. */ typedef Uint32 SDL_HapticID; @@ -850,23 +930,24 @@ typedef Uint32 SDL_HapticID; /** * Get a list of currently connected haptic devices. * - * \param count a pointer filled in with the number of haptic devices returned - * \returns a 0 terminated array of haptic device instance IDs which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. + * \param count a pointer filled in with the number of haptic devices + * returned, may be NULL. + * \returns a 0 terminated array of haptic device instance IDs or NULL on + * failure; call SDL_GetError() for more information. This should be + * freed with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenHaptic */ -extern DECLSPEC SDL_HapticID *SDLCALL SDL_GetHaptics(int *count); +extern SDL_DECLSPEC SDL_HapticID * SDLCALL SDL_GetHaptics(int *count); /** * Get the implementation dependent name of a haptic device. * * This can be called before any haptic devices are opened. * - * \param instance_id the haptic device instance ID + * \param instance_id the haptic device instance ID. * \returns the name of the selected haptic device. If no name can be found, * this function returns NULL; call SDL_GetError() for more * information. @@ -876,7 +957,7 @@ extern DECLSPEC SDL_HapticID *SDLCALL SDL_GetHaptics(int *count); * \sa SDL_GetHapticName * \sa SDL_OpenHaptic */ -extern DECLSPEC const char *SDLCALL SDL_GetHapticInstanceName(SDL_HapticID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetHapticNameForID(SDL_HapticID instance_id); /** * Open a haptic device for use. @@ -888,7 +969,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetHapticInstanceName(SDL_HapticID insta * autocenter will be disabled. To modify these values use SDL_SetHapticGain() * and SDL_SetHapticAutocenter(). * - * \param instance_id the haptic device instance ID + * \param instance_id the haptic device instance ID. * \returns the device identifier or NULL on failure; call SDL_GetError() for * more information. * @@ -901,55 +982,55 @@ extern DECLSPEC const char *SDLCALL SDL_GetHapticInstanceName(SDL_HapticID insta * \sa SDL_SetHapticAutocenter * \sa SDL_SetHapticGain */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_OpenHaptic(SDL_HapticID instance_id); +extern SDL_DECLSPEC SDL_Haptic * SDLCALL SDL_OpenHaptic(SDL_HapticID instance_id); /** * Get the SDL_Haptic associated with an instance ID, if it has been opened. * - * \param instance_id the instance ID to get the SDL_Haptic for + * \param instance_id the instance ID to get the SDL_Haptic for. * \returns an SDL_Haptic on success or NULL on failure or if it hasn't been * opened yet; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_GetHapticFromInstanceID(SDL_HapticID instance_id); +extern SDL_DECLSPEC SDL_Haptic * SDLCALL SDL_GetHapticFromID(SDL_HapticID instance_id); /** * Get the instance ID of an opened haptic device. * - * \param haptic the SDL_Haptic device to query + * \param haptic the SDL_Haptic device to query. * \returns the instance ID of the specified haptic device on success or 0 on * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_HapticID SDLCALL SDL_GetHapticInstanceID(SDL_Haptic *haptic); +extern SDL_DECLSPEC SDL_HapticID SDLCALL SDL_GetHapticID(SDL_Haptic *haptic); /** * Get the implementation dependent name of a haptic device. * - * \param haptic the SDL_Haptic obtained from SDL_OpenJoystick() + * \param haptic the SDL_Haptic obtained from SDL_OpenJoystick(). * \returns the name of the selected haptic device. If no name can be found, * this function returns NULL; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetHapticInstanceName + * \sa SDL_GetHapticNameForID */ -extern DECLSPEC const char *SDLCALL SDL_GetHapticName(SDL_Haptic *haptic); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetHapticName(SDL_Haptic *haptic); /** * Query whether or not the current mouse has haptic capabilities. * - * \returns SDL_TRUE if the mouse is haptic or SDL_FALSE if it isn't. + * \returns true if the mouse is haptic or false if it isn't. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenHapticFromMouse */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsMouseHaptic(void); +extern SDL_DECLSPEC bool SDLCALL SDL_IsMouseHaptic(void); /** * Try to open a haptic device from the current mouse. @@ -962,19 +1043,19 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsMouseHaptic(void); * \sa SDL_CloseHaptic * \sa SDL_IsMouseHaptic */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_OpenHapticFromMouse(void); +extern SDL_DECLSPEC SDL_Haptic * SDLCALL SDL_OpenHapticFromMouse(void); /** * Query if a joystick has haptic features. * - * \param joystick the SDL_Joystick to test for haptic capabilities - * \returns SDL_TRUE if the joystick is haptic or SDL_FALSE if it isn't. + * \param joystick the SDL_Joystick to test for haptic capabilities. + * \returns true if the joystick is haptic or false if it isn't. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenHapticFromJoystick */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickHaptic(SDL_Joystick *joystick); +extern SDL_DECLSPEC bool SDLCALL SDL_IsJoystickHaptic(SDL_Joystick *joystick); /** * Open a haptic device for use from a joystick device. @@ -987,7 +1068,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickHaptic(SDL_Joystick *joystick); * device will also get unallocated and you'll be unable to use force feedback * on that device. * - * \param joystick the SDL_Joystick to create a haptic device from + * \param joystick the SDL_Joystick to create a haptic device from. * \returns a valid haptic device identifier on success or NULL on failure; * call SDL_GetError() for more information. * @@ -996,18 +1077,18 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickHaptic(SDL_Joystick *joystick); * \sa SDL_CloseHaptic * \sa SDL_IsJoystickHaptic */ -extern DECLSPEC SDL_Haptic *SDLCALL SDL_OpenHapticFromJoystick(SDL_Joystick *joystick); +extern SDL_DECLSPEC SDL_Haptic * SDLCALL SDL_OpenHapticFromJoystick(SDL_Joystick *joystick); /** * Close a haptic device previously opened with SDL_OpenHaptic(). * - * \param haptic the SDL_Haptic device to close + * \param haptic the SDL_Haptic device to close. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenHaptic */ -extern DECLSPEC void SDLCALL SDL_CloseHaptic(SDL_Haptic *haptic); +extern SDL_DECLSPEC void SDLCALL SDL_CloseHaptic(SDL_Haptic *haptic); /** * Get the number of effects a haptic device can store. @@ -1016,7 +1097,7 @@ extern DECLSPEC void SDLCALL SDL_CloseHaptic(SDL_Haptic *haptic); * approximation. Always check to see if your created effect was actually * created and do not rely solely on SDL_GetMaxHapticEffects(). * - * \param haptic the SDL_Haptic device to query + * \param haptic the SDL_Haptic device to query. * \returns the number of effects the haptic device can store or a negative * error code on failure; call SDL_GetError() for more information. * @@ -1025,29 +1106,28 @@ extern DECLSPEC void SDLCALL SDL_CloseHaptic(SDL_Haptic *haptic); * \sa SDL_GetMaxHapticEffectsPlaying * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_GetMaxHapticEffects(SDL_Haptic *haptic); +extern SDL_DECLSPEC int SDLCALL SDL_GetMaxHapticEffects(SDL_Haptic *haptic); /** * Get the number of effects a haptic device can play at the same time. * * This is not supported on all platforms, but will always return a value. * - * \param haptic the SDL_Haptic device to query maximum playing effects + * \param haptic the SDL_Haptic device to query maximum playing effects. * \returns the number of effects the haptic device can play at the same time - * or a negative error code on failure; call SDL_GetError() for more - * information. + * or -1 on failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetMaxHapticEffects * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic); +extern SDL_DECLSPEC int SDLCALL SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic); /** * Get the haptic device's supported features in bitwise manner. * - * \param haptic the SDL_Haptic device to query + * \param haptic the SDL_Haptic device to query. * \returns a list of supported haptic features in bitwise manner (OR'd), or 0 * on failure; call SDL_GetError() for more information. * @@ -1056,8 +1136,7 @@ extern DECLSPEC int SDLCALL SDL_GetMaxHapticEffectsPlaying(SDL_Haptic *haptic); * \sa SDL_HapticEffectSupported * \sa SDL_GetMaxHapticEffects */ -extern DECLSPEC Uint32 SDLCALL SDL_GetHapticFeatures(SDL_Haptic *haptic); - +extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetHapticFeatures(SDL_Haptic *haptic); /** * Get the number of haptic axes the device has. @@ -1065,36 +1144,36 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetHapticFeatures(SDL_Haptic *haptic); * The number of haptic axes might be useful if working with the * SDL_HapticDirection effect. * - * \param haptic the SDL_Haptic device to query - * \returns the number of axes on success or a negative error code on failure; - * call SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to query. + * \returns the number of axes on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetNumHapticAxes(SDL_Haptic *haptic); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumHapticAxes(SDL_Haptic *haptic); /** * Check to see if an effect is supported by a haptic device. * - * \param haptic the SDL_Haptic device to query - * \param effect the desired effect to query - * \returns SDL_TRUE if the effect is supported or SDL_FALSE if it isn't. + * \param haptic the SDL_Haptic device to query. + * \param effect the desired effect to query. + * \returns true if the effect is supported or false if it isn't. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateHapticEffect * \sa SDL_GetHapticFeatures */ -extern DECLSPEC SDL_bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, const SDL_HapticEffect *effect); +extern SDL_DECLSPEC bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, const SDL_HapticEffect *effect); /** * Create a new haptic effect on a specified device. * - * \param haptic an SDL_Haptic device to create the effect on + * \param haptic an SDL_Haptic device to create the effect on. * \param effect an SDL_HapticEffect structure containing the properties of - * the effect to create - * \returns the ID of the effect on success or a negative error code on - * failure; call SDL_GetError() for more information. + * the effect to create. + * \returns the ID of the effect on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -1102,7 +1181,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HapticEffectSupported(SDL_Haptic *haptic, c * \sa SDL_RunHapticEffect * \sa SDL_UpdateHapticEffect */ -extern DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect); +extern SDL_DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL_HapticEffect *effect); /** * Update the properties of an effect. @@ -1112,19 +1191,19 @@ extern DECLSPEC int SDLCALL SDL_CreateHapticEffect(SDL_Haptic *haptic, const SDL * start playing from the start. You also cannot change the type either when * running SDL_UpdateHapticEffect(). * - * \param haptic the SDL_Haptic device that has the effect - * \param effect the identifier of the effect to update + * \param haptic the SDL_Haptic device that has the effect. + * \param effect the identifier of the effect to update. * \param data an SDL_HapticEffect structure containing the new effect - * properties to use - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * properties to use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateHapticEffect * \sa SDL_RunHapticEffect */ -extern DECLSPEC int SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data); +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effect, const SDL_HapticEffect *data); /** * Run the haptic effect on its associated haptic device. @@ -1135,12 +1214,12 @@ extern DECLSPEC int SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effec * set the effect's `length` in its structure/union to `SDL_HAPTIC_INFINITY` * instead. * - * \param haptic the SDL_Haptic device to run the effect on - * \param effect the ID of the haptic effect to run + * \param haptic the SDL_Haptic device to run the effect on. + * \param effect the ID of the haptic effect to run. * \param iterations the number of iterations to run the effect; use - * `SDL_HAPTIC_INFINITY` to repeat forever - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * `SDL_HAPTIC_INFINITY` to repeat forever. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1148,24 +1227,22 @@ extern DECLSPEC int SDLCALL SDL_UpdateHapticEffect(SDL_Haptic *haptic, int effec * \sa SDL_StopHapticEffect * \sa SDL_StopHapticEffects */ -extern DECLSPEC int SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations); +extern SDL_DECLSPEC bool SDLCALL SDL_RunHapticEffect(SDL_Haptic *haptic, int effect, Uint32 iterations); /** * Stop the haptic effect on its associated haptic device. * - * * - * - * \param haptic the SDL_Haptic device to stop the effect on - * \param effect the ID of the haptic effect to stop - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to stop the effect on. + * \param effect the ID of the haptic effect to stop. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RunHapticEffect * \sa SDL_StopHapticEffects */ -extern DECLSPEC int SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect); /** * Destroy a haptic effect on the device. @@ -1173,28 +1250,30 @@ extern DECLSPEC int SDLCALL SDL_StopHapticEffect(SDL_Haptic *haptic, int effect) * This will stop the effect if it's running. Effects are automatically * destroyed when the device is closed. * - * \param haptic the SDL_Haptic device to destroy the effect on - * \param effect the ID of the haptic effect to destroy + * \param haptic the SDL_Haptic device to destroy the effect on. + * \param effect the ID of the haptic effect to destroy. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateHapticEffect */ -extern DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyHapticEffect(SDL_Haptic *haptic, int effect); /** * Get the status of the current effect on the specified haptic device. * * Device must support the SDL_HAPTIC_STATUS feature. * - * \param haptic the SDL_Haptic device to query for the effect status on - * \param effect the ID of the haptic effect to query its status - * \returns 0 if it isn't playing, 1 if it is playing, or a negative error - * code on failure; call SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to query for the effect status on. + * \param effect the ID of the haptic effect to query its status. + * \returns true if it is playing, false if it isn't playing or haptic status + * isn't supported. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int effect); /** * Set the global gain of the specified haptic device. @@ -1206,16 +1285,17 @@ extern DECLSPEC int SDLCALL SDL_GetHapticEffectStatus(SDL_Haptic *haptic, int ef * SDL_SetHapticGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the * maximum. * - * \param haptic the SDL_Haptic device to set the gain on - * \param gain value to set the gain to, should be between 0 and 100 (0 - 100) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to set the gain on. + * \param gain value to set the gain to, should be between 0 and 100 (0 - + * 100). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_SetHapticGain(SDL_Haptic *haptic, int gain); +extern SDL_DECLSPEC bool SDLCALL SDL_SetHapticGain(SDL_Haptic *haptic, int gain); /** * Set the global autocenter of the device. @@ -1225,16 +1305,16 @@ extern DECLSPEC int SDLCALL SDL_SetHapticGain(SDL_Haptic *haptic, int gain); * * Device must support the SDL_HAPTIC_AUTOCENTER feature. * - * \param haptic the SDL_Haptic device to set autocentering on - * \param autocenter value to set autocenter to (0-100) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to set autocentering on. + * \param autocenter value to set autocenter to (0-100). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetHapticFeatures */ -extern DECLSPEC int SDLCALL SDL_SetHapticAutocenter(SDL_Haptic *haptic, int autocenter); +extern SDL_DECLSPEC bool SDLCALL SDL_SetHapticAutocenter(SDL_Haptic *haptic, int autocenter); /** * Pause a haptic device. @@ -1245,63 +1325,63 @@ extern DECLSPEC int SDLCALL SDL_SetHapticAutocenter(SDL_Haptic *haptic, int auto * Do not modify the effects nor add new ones while the device is paused. That * can cause all sorts of weird errors. * - * \param haptic the SDL_Haptic device to pause - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to pause. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ResumeHaptic */ -extern DECLSPEC int SDLCALL SDL_PauseHaptic(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_PauseHaptic(SDL_Haptic *haptic); /** * Resume a haptic device. * * Call to unpause after SDL_PauseHaptic(). * - * \param haptic the SDL_Haptic device to unpause - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to unpause. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_PauseHaptic */ -extern DECLSPEC int SDLCALL SDL_ResumeHaptic(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_ResumeHaptic(SDL_Haptic *haptic); /** * Stop all the currently playing effects on a haptic device. * - * \param haptic the SDL_Haptic device to stop - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the SDL_Haptic device to stop. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RunHapticEffect * \sa SDL_StopHapticEffects */ -extern DECLSPEC int SDLCALL SDL_StopHapticEffects(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticEffects(SDL_Haptic *haptic); /** * Check whether rumble is supported on a haptic device. * - * \param haptic haptic device to check for rumble support - * \returns SDL_TRUE if the effect is supported or SDL_FALSE if it isn't. + * \param haptic haptic device to check for rumble support. + * \returns true if the effect is supported or false if it isn't. * * \since This function is available since SDL 3.0.0. * * \sa SDL_InitHapticRumble */ -extern DECLSPEC SDL_bool SDLCALL SDL_HapticRumbleSupported(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_HapticRumbleSupported(SDL_Haptic *haptic); /** * Initialize a haptic device for simple rumble playback. * - * \param haptic the haptic device to initialize for simple rumble playback - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the haptic device to initialize for simple rumble playback. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1309,36 +1389,36 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HapticRumbleSupported(SDL_Haptic *haptic); * \sa SDL_StopHapticRumble * \sa SDL_HapticRumbleSupported */ -extern DECLSPEC int SDLCALL SDL_InitHapticRumble(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_InitHapticRumble(SDL_Haptic *haptic); /** * Run a simple rumble effect on a haptic device. * - * \param haptic the haptic device to play the rumble effect on - * \param strength strength of the rumble to play as a 0-1 float value - * \param length length of the rumble to play in milliseconds - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the haptic device to play the rumble effect on. + * \param strength strength of the rumble to play as a 0-1 float value. + * \param length length of the rumble to play in milliseconds. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_InitHapticRumble * \sa SDL_StopHapticRumble */ -extern DECLSPEC int SDLCALL SDL_PlayHapticRumble(SDL_Haptic *haptic, float strength, Uint32 length); +extern SDL_DECLSPEC bool SDLCALL SDL_PlayHapticRumble(SDL_Haptic *haptic, float strength, Uint32 length); /** * Stop the simple rumble on a haptic device. * - * \param haptic the haptic device to stop the rumble effect on - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param haptic the haptic device to stop the rumble effect on. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_PlayHapticRumble */ -extern DECLSPEC int SDLCALL SDL_StopHapticRumble(SDL_Haptic *haptic); +extern SDL_DECLSPEC bool SDLCALL SDL_StopHapticRumble(SDL_Haptic *haptic); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_hidapi.h b/libs/SDL3/include/SDL3/SDL_hidapi.h index 422c329ac..730fdee42 100644 --- a/libs/SDL3/include/SDL3/SDL_hidapi.h +++ b/libs/SDL3/include/SDL3/SDL_hidapi.h @@ -19,50 +19,42 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* WIKI CATEGORY: HIDAPI */ + /** - * \file SDL_hidapi.h - * - * Header file for SDL HIDAPI functions. - * - * This is an adaptation of the original HIDAPI interface by Alan Ott, - * and includes source code licensed under the following BSD license: - * - Copyright (c) 2010, Alan Ott, Signal 11 Software - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Signal 11 Software nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + * # CategoryHIDAPI + * + * Header file for SDL HIDAPI functions. + * + * This is an adaptation of the original HIDAPI interface by Alan Ott, and + * includes source code licensed under the following license: + * + * ``` + * HIDAPI - Multi-Platform library for + * communication with HID devices. + * + * Copyright 2009, Alan Ott, Signal 11 Software. + * All Rights Reserved. + * + * This software may be used by anyone for any reason so + * long as the copyright notice in the source files + * remains intact. + * ``` + * + * (Note that this license is the same as item three of SDL's zlib license, so + * it adds no new requirements on the user.) * * If you would like a version of SDL without this code, you can build SDL - * with SDL_HIDAPI_DISABLED defined to 1. You might want to do this for example - * on iOS or tvOS to avoid a dependency on the CoreBluetooth framework. + * with SDL_HIDAPI_DISABLED defined to 1. You might want to do this for + * example on iOS or tvOS to avoid a dependency on the CoreBluetooth + * framework. */ #ifndef SDL_hidapi_h_ #define SDL_hidapi_h_ #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -71,15 +63,18 @@ extern "C" { #endif /** - * A handle representing an open HID device + * An opaque handle representing an open HID device. + * + * \since This struct is available since SDL 3.0.0. */ -struct SDL_hid_device_; -typedef struct SDL_hid_device_ SDL_hid_device; /**< opaque hidapi structure */ +typedef struct SDL_hid_device SDL_hid_device; /** - * HID underlying bus types. + * HID underlying bus types. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum { +typedef enum SDL_hid_bus_type { /** Unknown bus type */ SDL_HID_API_BUS_UNKNOWN = 0x00, @@ -108,8 +103,11 @@ typedef enum { } SDL_hid_bus_type; /** hidapi info structure */ + /** - * Information about a connected HID device + * Information about a connected HID device + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_hid_device_info { @@ -175,7 +173,7 @@ typedef struct SDL_hid_device_info * * \sa SDL_hid_exit */ -extern DECLSPEC int SDLCALL SDL_hid_init(void); +extern SDL_DECLSPEC int SDLCALL SDL_hid_init(void); /** * Finalize the HIDAPI library. @@ -190,7 +188,7 @@ extern DECLSPEC int SDLCALL SDL_hid_init(void); * * \sa SDL_hid_init */ -extern DECLSPEC int SDLCALL SDL_hid_exit(void); +extern SDL_DECLSPEC int SDLCALL SDL_hid_exit(void); /** * Check to see if devices may have been added or removed. @@ -211,7 +209,7 @@ extern DECLSPEC int SDLCALL SDL_hid_exit(void); * * \sa SDL_hid_enumerate */ -extern DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void); /** * Enumerate the HID Devices. @@ -226,9 +224,9 @@ extern DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void); * or crashing on bad drivers, but SDL_HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS * can be set to "0" to enumerate all HID devices. * - * \param vendor_id The Vendor ID (VID) of the types of device to open, or 0 + * \param vendor_id the Vendor ID (VID) of the types of device to open, or 0 * to match any vendor. - * \param product_id The Product ID (PID) of the types of device to open, or 0 + * \param product_id the Product ID (PID) of the types of device to open, or 0 * to match any product. * \returns a pointer to a linked list of type SDL_hid_device_info, containing * information about the HID devices attached to the system, or NULL @@ -239,19 +237,19 @@ extern DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void); * * \sa SDL_hid_device_change_count */ -extern DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id); +extern SDL_DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id); /** - * Free an enumeration Linked List + * Free an enumeration linked list. * * This function frees a linked list created by SDL_hid_enumerate(). * - * \param devs Pointer to a list of struct_device returned from + * \param devs pointer to a list of struct_device returned from * SDL_hid_enumerate(). * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_hid_free_enumeration(SDL_hid_device_info *devs); +extern SDL_DECLSPEC void SDLCALL SDL_hid_free_enumeration(SDL_hid_device_info *devs); /** * Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally @@ -260,16 +258,16 @@ extern DECLSPEC void SDLCALL SDL_hid_free_enumeration(SDL_hid_device_info *devs) * If `serial_number` is NULL, the first device with the specified VID and PID * is opened. * - * \param vendor_id The Vendor ID (VID) of the device to open. - * \param product_id The Product ID (PID) of the device to open. - * \param serial_number The Serial Number of the device to open (Optionally + * \param vendor_id the Vendor ID (VID) of the device to open. + * \param product_id the Product ID (PID) of the device to open. + * \param serial_number the Serial Number of the device to open (Optionally * NULL). * \returns a pointer to a SDL_hid_device object on success or NULL on - * failure. + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); +extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); /** * Open a HID device by its path name. @@ -277,13 +275,13 @@ extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_id, * The path name be determined by calling SDL_hid_enumerate(), or a * platform-specific path name can be used (eg: /dev/hidraw0 on Linux). * - * \param path The path name of the device to open + * \param path the path name of the device to open. * \returns a pointer to a SDL_hid_device object on success or NULL on - * failure. + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path); +extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path); /** * Write an Output report to a HID device. @@ -301,15 +299,16 @@ extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path); * exists. If it does not, it will send the data through the Control Endpoint * (Endpoint 0). * - * \param dev A device handle returned from SDL_hid_open(). - * \param data The data to send, including the report number as the first + * \param dev a device handle returned from SDL_hid_open(). + * \param data the data to send, including the report number as the first * byte. - * \param length The length in bytes of the data to send. - * \returns the actual number of bytes written and -1 on error. + * \param length the length in bytes of the data to send. + * \returns the actual number of bytes written and -1 on on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_write(SDL_hid_device *dev, const unsigned char *data, size_t length); +extern SDL_DECLSPEC int SDLCALL SDL_hid_write(SDL_hid_device *dev, const unsigned char *data, size_t length); /** * Read an Input report from a HID device with timeout. @@ -318,19 +317,19 @@ extern DECLSPEC int SDLCALL SDL_hid_write(SDL_hid_device *dev, const unsigned ch * The first byte will contain the Report number if the device uses numbered * reports. * - * \param dev A device handle returned from SDL_hid_open(). - * \param data A buffer to put the read data into. - * \param length The number of bytes to read. For devices with multiple + * \param dev a device handle returned from SDL_hid_open(). + * \param data a buffer to put the read data into. + * \param length the number of bytes to read. For devices with multiple * reports, make sure to read an extra byte for the report * number. * \param milliseconds timeout in milliseconds or -1 for blocking wait. - * \returns the actual number of bytes read and -1 on error. If no packet was - * available to be read within the timeout period, this function - * returns 0. + * \returns the actual number of bytes read and -1 on on failure; call + * SDL_GetError() for more information. If no packet was available to + * be read within the timeout period, this function returns 0. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_read_timeout(SDL_hid_device *dev, unsigned char *data, size_t length, int milliseconds); +extern SDL_DECLSPEC int SDLCALL SDL_hid_read_timeout(SDL_hid_device *dev, unsigned char *data, size_t length, int milliseconds); /** * Read an Input report from a HID device. @@ -339,18 +338,19 @@ extern DECLSPEC int SDLCALL SDL_hid_read_timeout(SDL_hid_device *dev, unsigned c * The first byte will contain the Report number if the device uses numbered * reports. * - * \param dev A device handle returned from SDL_hid_open(). - * \param data A buffer to put the read data into. - * \param length The number of bytes to read. For devices with multiple + * \param dev a device handle returned from SDL_hid_open(). + * \param data a buffer to put the read data into. + * \param length the number of bytes to read. For devices with multiple * reports, make sure to read an extra byte for the report * number. - * \returns the actual number of bytes read and -1 on error. If no packet was - * available to be read and the handle is in non-blocking mode, this - * function returns 0. + * \returns the actual number of bytes read and -1 on failure; call + * SDL_GetError() for more information. If no packet was available to + * be read and the handle is in non-blocking mode, this function + * returns 0. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *data, size_t length); +extern SDL_DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *data, size_t length); /** * Set the device handle to be non-blocking. @@ -361,7 +361,7 @@ extern DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *dat * * Nonblocking can be turned on and off at any time. * - * \param dev A device handle returned from SDL_hid_open(). + * \param dev a device handle returned from SDL_hid_open(). * \param nonblock enable or not the nonblocking reads - 1 to enable * nonblocking - 0 to disable nonblocking. * \returns 0 on success or a negative error code on failure; call @@ -369,7 +369,7 @@ extern DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *dat * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_set_nonblocking(SDL_hid_device *dev, int nonblock); +extern SDL_DECLSPEC int SDLCALL SDL_hid_set_nonblocking(SDL_hid_device *dev, int nonblock); /** * Send a Feature report to the device. @@ -384,16 +384,17 @@ extern DECLSPEC int SDLCALL SDL_hid_set_nonblocking(SDL_hid_device *dev, int non * devices which do not use numbered reports), followed by the report data (16 * bytes). In this example, the length passed in would be 17. * - * \param dev A device handle returned from SDL_hid_open(). - * \param data The data to send, including the report number as the first + * \param dev a device handle returned from SDL_hid_open(). + * \param data the data to send, including the report number as the first * byte. - * \param length The length in bytes of the data to send, including the report + * \param length the length in bytes of the data to send, including the report * number. - * \returns the actual number of bytes written and -1 on error. + * \returns the actual number of bytes written and -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_send_feature_report(SDL_hid_device *dev, const unsigned char *data, size_t length); +extern SDL_DECLSPEC int SDLCALL SDL_hid_send_feature_report(SDL_hid_device *dev, const unsigned char *data, size_t length); /** * Get a feature report from a HID device. @@ -403,19 +404,20 @@ extern DECLSPEC int SDLCALL SDL_hid_send_feature_report(SDL_hid_device *dev, con * first byte will still contain the Report ID, and the report data will start * in data[1]. * - * \param dev A device handle returned from SDL_hid_open(). - * \param data A buffer to put the read data into, including the Report ID. + * \param dev a device handle returned from SDL_hid_open(). + * \param data a buffer to put the read data into, including the Report ID. * Set the first byte of `data` to the Report ID of the report to * be read, or set it to zero if your device does not use numbered * reports. - * \param length The number of bytes to read, including an extra byte for the + * \param length the number of bytes to read, including an extra byte for the * report ID. The buffer can be longer than the actual report. * \returns the number of bytes read plus one for the report ID (which is - * still in the first byte), or -1 on error. + * still in the first byte), or -1 on on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_feature_report(SDL_hid_device *dev, unsigned char *data, size_t length); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_feature_report(SDL_hid_device *dev, unsigned char *data, size_t length); /** * Get an input report from a HID device. @@ -425,96 +427,96 @@ extern DECLSPEC int SDLCALL SDL_hid_get_feature_report(SDL_hid_device *dev, unsi * first byte will still contain the Report ID, and the report data will start * in data[1]. * - * \param dev A device handle returned from SDL_hid_open(). - * \param data A buffer to put the read data into, including the Report ID. + * \param dev a device handle returned from SDL_hid_open(). + * \param data a buffer to put the read data into, including the Report ID. * Set the first byte of `data` to the Report ID of the report to * be read, or set it to zero if your device does not use numbered * reports. - * \param length The number of bytes to read, including an extra byte for the + * \param length the number of bytes to read, including an extra byte for the * report ID. The buffer can be longer than the actual report. * \returns the number of bytes read plus one for the report ID (which is - * still in the first byte), or -1 on error. + * still in the first byte), or -1 on on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_input_report(SDL_hid_device *dev, unsigned char *data, size_t length); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_input_report(SDL_hid_device *dev, unsigned char *data, size_t length); /** * Close a HID device. * - * \param dev A device handle returned from SDL_hid_open(). + * \param dev a device handle returned from SDL_hid_open(). * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_close(SDL_hid_device *dev); +extern SDL_DECLSPEC int SDLCALL SDL_hid_close(SDL_hid_device *dev); /** * Get The Manufacturer String from a HID device. * - * \param dev A device handle returned from SDL_hid_open(). - * \param string A wide string buffer to put the data into. - * \param maxlen The length of the buffer in multiples of wchar_t. + * \param dev a device handle returned from SDL_hid_open(). + * \param string a wide string buffer to put the data into. + * \param maxlen the length of the buffer in multiples of wchar_t. * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_manufacturer_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_manufacturer_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); /** * Get The Product String from a HID device. * - * \param dev A device handle returned from SDL_hid_open(). - * \param string A wide string buffer to put the data into. - * \param maxlen The length of the buffer in multiples of wchar_t. + * \param dev a device handle returned from SDL_hid_open(). + * \param string a wide string buffer to put the data into. + * \param maxlen the length of the buffer in multiples of wchar_t. * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_product_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_product_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); /** * Get The Serial Number String from a HID device. * - * \param dev A device handle returned from SDL_hid_open(). - * \param string A wide string buffer to put the data into. - * \param maxlen The length of the buffer in multiples of wchar_t. + * \param dev a device handle returned from SDL_hid_open(). + * \param string a wide string buffer to put the data into. + * \param maxlen the length of the buffer in multiples of wchar_t. * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_serial_number_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_serial_number_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen); /** * Get a string from a HID device, based on its string index. * - * \param dev A device handle returned from SDL_hid_open(). - * \param string_index The index of the string to get. - * \param string A wide string buffer to put the data into. - * \param maxlen The length of the buffer in multiples of wchar_t. + * \param dev a device handle returned from SDL_hid_open(). + * \param string_index the index of the string to get. + * \param string a wide string buffer to put the data into. + * \param maxlen the length of the buffer in multiples of wchar_t. * \returns 0 on success or a negative error code on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_indexed_string(SDL_hid_device *dev, int string_index, wchar_t *string, size_t maxlen); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_indexed_string(SDL_hid_device *dev, int string_index, wchar_t *string, size_t maxlen); /** * Get the device info from a HID device. * - * \param dev A device handle returned from SDL_hid_open(). - * \returns a pointer to the SDL_hid_device_info for this hid_device, or NULL - * in the case of failure; call SDL_GetError() for more information. - * This struct is valid until the device is closed with - * SDL_hid_close(). + * \param dev a device handle returned from SDL_hid_open(). + * \returns a pointer to the SDL_hid_device_info for this hid_device or NULL + * on failure; call SDL_GetError() for more information. This struct + * is valid until the device is closed with SDL_hid_close(). * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_get_device_info(SDL_hid_device *dev); +extern SDL_DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_get_device_info(SDL_hid_device *dev); /** * Get a report descriptor from a HID device. @@ -522,24 +524,24 @@ extern DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_get_device_info(SDL_hid_de * User has to provide a preallocated buffer where descriptor will be copied * to. The recommended size for a preallocated buffer is 4096 bytes. * - * \param dev A device handle returned from SDL_hid_open(). - * \param buf The buffer to copy descriptor into. - * \param buf_size The size of the buffer in bytes. - * \returns the number of bytes actually copied, or -1 on error; call + * \param dev a device handle returned from SDL_hid_open(). + * \param buf the buffer to copy descriptor into. + * \param buf_size the size of the buffer in bytes. + * \returns the number of bytes actually copied or -1 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_hid_get_report_descriptor(SDL_hid_device *dev, unsigned char *buf, size_t buf_size); +extern SDL_DECLSPEC int SDLCALL SDL_hid_get_report_descriptor(SDL_hid_device *dev, unsigned char *buf, size_t buf_size); /** - * Start or stop a BLE scan on iOS and tvOS to pair Steam Controllers + * Start or stop a BLE scan on iOS and tvOS to pair Steam Controllers. * - * \param active SDL_TRUE to start the scan, SDL_FALSE to stop the scan + * \param active true to start the scan, false to stop the scan. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_hid_ble_scan(SDL_bool active); +extern SDL_DECLSPEC void SDLCALL SDL_hid_ble_scan(bool active); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_hints.h b/libs/SDL3/include/SDL3/SDL_hints.h index 065b1b319..142130de5 100644 --- a/libs/SDL3/include/SDL3/SDL_hints.h +++ b/libs/SDL3/include/SDL3/SDL_hints.h @@ -20,25 +20,24 @@ */ /** - * \file SDL_hints.h + * # CategoryHints * - * Official documentation for SDL configuration variables + * This file contains functions to set and get configuration hints, as well as + * listing each of them alphabetically. * - * This file contains functions to set and get configuration hints, - * as well as listing each of them alphabetically. + * The convention for naming hints is SDL_HINT_X, where "SDL_X" is the + * environment variable that can be used to override the default. * - * The convention for naming hints is SDL_HINT_X, where "SDL_X" is - * the environment variable that can be used to override the default. - * - * In general these hints are just that - they may or may not be - * supported or applicable on any given platform, but they provide - * a way for an application or user to give the library a hint as - * to how they would like the library to work. + * In general these hints are just that - they may or may not be supported or + * applicable on any given platform, but they provide a way for an application + * or user to give the library a hint as to how they would like the library to + * work. */ #ifndef SDL_hints_h_ #define SDL_hints_h_ +#include #include #include @@ -50,202 +49,239 @@ extern "C" { /** * Specify the behavior of Alt+Tab while the keyboard is grabbed. * - * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed - * and your window is full-screen. This prevents the user from getting stuck in - * your application if you've enabled keyboard grab. + * By default, SDL emulates Alt+Tab functionality while the keyboard is + * grabbed and your window is full-screen. This prevents the user from getting + * stuck in your application if you've enabled keyboard grab. * * The variable can be set to the following values: - * "0" - SDL will not handle Alt+Tab. Your application is responsible for handling Alt+Tab while the keyboard is grabbed. - * "1" - SDL will minimize your window when Alt+Tab is pressed (default) + * + * - "0": SDL will not handle Alt+Tab. Your application is responsible for + * handling Alt+Tab while the keyboard is grabbed. + * - "1": SDL will minimize your window when Alt+Tab is pressed (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED" /** * A variable to control whether the SDL activity is allowed to be re-created. * - * If this hint is true, the activity can be recreated on demand by the OS, and Java static data and C++ static data remain with their current values. If this hint is false, then SDL will call exit() when you return from your main function and the application will be terminated and then started fresh each time. + * If this hint is true, the activity can be recreated on demand by the OS, + * and Java static data and C++ static data remain with their current values. + * If this hint is false, then SDL will call exit() when you return from your + * main function and the application will be terminated and then started fresh + * each time. * * The variable can be set to the following values: - * "0" - The application starts fresh at each launch. (default) - * "1" - The application activity can be recreated by the OS. + * + * - "0": The application starts fresh at each launch. (default) + * - "1": The application activity can be recreated by the OS. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY "SDL_ANDROID_ALLOW_RECREATE_ACTIVITY" /** - * A variable to control whether the event loop will block itself when the app is paused. + * A variable to control whether the event loop will block itself when the app + * is paused. * * The variable can be set to the following values: - * "0" - Non blocking. - * "1" - Blocking. (default) - * - * This hint should be set before SDL is initialized. - */ -#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" - -/** - * A variable to control whether SDL will pause audio in background. * - * The variable can be set to the following values: - * "0" - Not paused, requires that SDL_HINT_ANDROID_BLOCK_ON_PAUSE be set to "0" - * "1" - Paused. (default) + * - "0": Non blocking. + * - "1": Blocking. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO" +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" /** - * A variable to control whether we trap the Android back button to handle it manually. + * A variable to control whether we trap the Android back button to handle it + * manually. * - * This is necessary for the right mouse button to work on some Android devices, or to be able to trap the back button for use in your code reliably. If this hint is true, the back button will show up as an SDL_EVENT_KEY_DOWN / SDL_EVENT_KEY_UP pair with a keycode of SDL_SCANCODE_AC_BACK. + * This is necessary for the right mouse button to work on some Android + * devices, or to be able to trap the back button for use in your code + * reliably. If this hint is true, the back button will show up as an + * SDL_EVENT_KEY_DOWN / SDL_EVENT_KEY_UP pair with a keycode of + * SDL_SCANCODE_AC_BACK. * * The variable can be set to the following values: - * "0" - Back button will be handled as usual for system. (default) - * "1" - Back button will be trapped, allowing you to handle the key press - * manually. (This will also let right mouse click work on systems - * where the right mouse button functions as back.) + * + * - "0": Back button will be handled as usual for system. (default) + * - "1": Back button will be trapped, allowing you to handle the key press + * manually. (This will also let right mouse click work on systems where the + * right mouse button functions as back.) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" /** * A variable setting the app ID string. * - * This string is used by desktop compositors to identify and group windows together, as well as match applications with associated desktop settings and icons. + * This string is used by desktop compositors to identify and group windows + * together, as well as match applications with associated desktop settings + * and icons. * - * On Wayland this corresponds to the "app ID" window property and on X11 this corresponds to the WM_CLASS property. Windows inherit the value of this hint at creation time. Changing this hint after a window has been created will not change the app ID or class of existing windows. - * - * For *nix platforms, this string should be formatted in reverse-DNS notation and follow some basic rules to be valid: - * - * - The application ID must be composed of two or more elements separated by a period (.) character. - * - * - Each element must contain one or more of the alphanumeric characters (A-Z, a-z, 0-9) plus underscore (_) and hyphen (-) and must not start with a digit. Note that hyphens, while technically allowed, should not be used if possible, as they are not supported by all components that use the ID, such as D-Bus. For maximum compatibility, replace hyphens with an underscore. - * - * - The empty string is not a valid element (ie: your application ID may not start or end with a period and it is not valid to have two periods in a row). - * - * - The entire ID must be less than 255 characters in length. - * - * Examples of valid app ID strings: - * - * - org.MyOrg.MyApp - * - com.your_company.your_app - * - * Desktops such as GNOME and KDE require that the app ID string matches your application's .desktop file name (e.g. if the app ID string is 'org.MyOrg.MyApp', your application's .desktop file should be named 'org.MyOrg.MyApp.desktop'). - * - * If you plan to package your application in a container such as Flatpak, the app ID should match the name of your Flatpak container as well. - * - * If not set, SDL will attempt to use the application executable name. - * If the executable name cannot be retrieved, the generic string "SDL_App" will be used. + * This will override SDL_PROP_APP_METADATA_IDENTIFIER_STRING, if set by the + * application. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_APP_ID "SDL_APP_ID" +#define SDL_HINT_APP_ID "SDL_APP_ID" /** - * Specify an application name. + * A variable setting the application name. * * This hint lets you specify the application name sent to the OS when * required. For example, this will often appear in volume control applets for * audio streams, and in lists of applications which are inhibiting the - * screensaver. You should use a string that describes your program ("My Game 2: The Revenge") - * - * Setting this to "" or leaving it unset will have SDL use a reasonable - * default: probably the application's name or "SDL Application" if SDL - * doesn't have any better information. + * screensaver. You should use a string that describes your program ("My Game + * 2: The Revenge") * - * Note that, for audio streams, this can be overridden with - * SDL_HINT_AUDIO_DEVICE_APP_NAME. + * This will override SDL_PROP_APP_METADATA_NAME_STRING, if set by the + * application. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_APP_NAME "SDL_APP_NAME" /** - * A variable controlling whether controllers used with the Apple TV generate UI events. + * A variable controlling whether controllers used with the Apple TV generate + * UI events. * * When UI events are generated by controller input, the app will be - * backgrounded when the Apple TV remote's menu button is pressed, and when the - * pause or B buttons on gamepads are pressed. + * backgrounded when the Apple TV remote's menu button is pressed, and when + * the pause or B buttons on gamepads are pressed. * * More information about properly making use of controllers for the Apple TV * can be found here: * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ * * The variable can be set to the following values: - * "0" - Controller input does not generate UI events. (default) - * "1" - Controller input generates UI events. + * + * - "0": Controller input does not generate UI events. (default) + * - "1": Controller input generates UI events. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS" /** - * A variable controlling whether the Apple TV remote's joystick axes will automatically match the rotation of the remote. + * A variable controlling whether the Apple TV remote's joystick axes will + * automatically match the rotation of the remote. * * The variable can be set to the following values: - * "0" - Remote orientation does not affect joystick axes. (default) - * "1" - Joystick axes are based on the orientation of the remote. + * + * - "0": Remote orientation does not affect joystick axes. (default) + * - "1": Joystick axes are based on the orientation of the remote. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" +/** + * Specify the default ALSA audio device name. + * + * This variable is a specific audio device to open when the "default" audio + * device is used. By default if 4 channel audio is requested, the + * "plug:surround40" device will be opened and if 6 channel audio is requested + * the "plug:surround51" device will be opened. + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_ALSA_DEFAULT_DEVICE "SDL_AUDIO_ALSA_DEFAULT_DEVICE" + /** * A variable controlling the audio category on iOS and macOS. * * The variable can be set to the following values: - * "ambient" - Use the AVAudioSessionCategoryAmbient audio category, will be muted by the phone mute switch (default) - * "playback" - Use the AVAudioSessionCategoryPlayback category. * - * For more information, see Apple's documentation: - * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html + * - "ambient": Use the AVAudioSessionCategoryAmbient audio category, will be + * muted by the phone mute switch (default) + * - "playback": Use the AVAudioSessionCategoryPlayback category. + * + * For more information, see Apple's documentation: + * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html * * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" +#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" /** - * Specify an application name for an audio device. + * A variable controlling the default audio channel count. * - * Some audio backends (such as PulseAudio) allow you to describe your audio - * stream. Among other things, this description might show up in a system - * control panel that lets the user adjust the volume on specific audio - * streams instead of using one giant master volume slider. + * If the application doesn't specify the audio channel count when opening the + * device, this hint can be used to specify a default channel count that will + * be used. This defaults to "1" for recording and "2" for playback devices. * - * This hints lets you transmit that information to the OS. The contents of - * this hint are used while opening an audio device. You should use a string - * that describes your program ("My Game 2: The Revenge") + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_CHANNELS "SDL_AUDIO_CHANNELS" + +/** + * Specify an application icon name for an audio device. + * + * Some audio backends (such as Pulseaudio and Pipewire) allow you to set an + * XDG icon name for your application. Among other things, this icon might + * show up in a system control panel that lets the user adjust the volume on + * specific audio streams instead of using one giant master volume slider. + * Note that this is unrelated to the icon used by the windowing system, which + * may be set with SDL_SetWindowIcon (or via desktop file on Wayland). * * Setting this to "" or leaving it unset will have SDL use a reasonable - * default: this will be the name set with SDL_HINT_APP_NAME, if that hint is - * set. Otherwise, it'll probably the application's name or "SDL Application" - * if SDL doesn't have any better information. + * default, "applications-games", which is likely to be installed. See + * https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html + * and + * https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html + * for the relevant XDG icon specs. * * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME" +#define SDL_HINT_AUDIO_DEVICE_APP_ICON_NAME "SDL_AUDIO_DEVICE_APP_ICON_NAME" /** * A variable controlling device buffer size. * * This hint is an integer > 0, that represents the size of the device's - * buffer in sample frames (stereo audio data in 16-bit format is 4 bytes - * per sample frame, for example). + * buffer in sample frames (stereo audio data in 16-bit format is 4 bytes per + * sample frame, for example). * * SDL3 generally decides this value on behalf of the app, but if for some * reason the app needs to dictate this (because they want either lower - * latency or higher throughput AND ARE WILLING TO DEAL WITH what that - * might require of the app), they can specify it. + * latency or higher throughput AND ARE WILLING TO DEAL WITH what that might + * require of the app), they can specify it. * - * SDL will try to accomodate this value, but there is no promise you'll - * get the buffer size requested. Many platforms won't honor this request - * at all, or might adjust it. + * SDL will try to accommodate this value, but there is no promise you'll get + * the buffer size requested. Many platforms won't honor this request at all, + * or might adjust it. * * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES "SDL_AUDIO_DEVICE_SAMPLE_FRAMES" @@ -266,7 +302,13 @@ extern "C" { * Setting this to "" or leaving it unset will have SDL use a reasonable * default: "audio stream" or something similar. * + * Note that while this talks about audio streams, this is an OS-level + * concept, so it applies to a physical audio device in this case, and not an + * SDL_AudioStream, nor an SDL logical audio device. + * * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME" @@ -274,9 +316,9 @@ extern "C" { * Specify an application role for an audio device. * * Some audio backends (such as Pipewire) allow you to describe the role of - * your audio stream. Among other things, this description might show up in - * a system control panel or software for displaying and manipulating media - * playback/capture graphs. + * your audio stream. Among other things, this description might show up in a + * system control panel or software for displaying and manipulating media + * playback/recording graphs. * * This hints lets you transmit that information to the OS. The contents of * this hint are used while opening an audio device. You should use a string @@ -286,158 +328,319 @@ extern "C" { * Setting this to "" or leaving it unset will have SDL use a reasonable * default: "Game" or something similar. * + * Note that while this talks about audio streams, this is an OS-level + * concept, so it applies to a physical audio device in this case, and not an + * SDL_AudioStream, nor an SDL logical audio device. + * * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE" +/** + * Specify the input file when recording audio using the disk audio driver. + * + * This defaults to "sdlaudio-in.raw" + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_DISK_INPUT_FILE "SDL_AUDIO_DISK_INPUT_FILE" + +/** + * Specify the output file when playing audio using the disk audio driver. + * + * This defaults to "sdlaudio.raw" + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_DISK_OUTPUT_FILE "SDL_AUDIO_DISK_OUTPUT_FILE" + +/** + * A variable controlling the audio rate when using the disk audio driver. + * + * The disk audio driver normally simulates real-time for the audio rate that + * was specified, but you can use this variable to adjust this rate higher or + * lower down to 0. The default value is "1.0". + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_DISK_TIMESCALE "SDL_AUDIO_DISK_TIMESCALE" + /** * A variable that specifies an audio backend to use. * - * By default, SDL will try all available audio backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific driver, such as "pipewire" if, say, you are on PulseAudio but want to try talking to the lower level instead. + * By default, SDL will try all available audio backends in a reasonable order + * until it finds one that can work, but this hint allows the app or user to + * force a specific driver, such as "pipewire" if, say, you are on PulseAudio + * but want to try talking to the lower level instead. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_AUDIO_DRIVER "SDL_AUDIO_DRIVER" /** - * A variable that causes SDL to not ignore audio "monitors" + * A variable controlling the audio rate when using the dummy audio driver. + * + * The dummy audio driver normally simulates real-time for the audio rate that + * was specified, but you can use this variable to adjust this rate higher or + * lower down to 0. The default value is "1.0". + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_DUMMY_TIMESCALE "SDL_AUDIO_DUMMY_TIMESCALE" + +/** + * A variable controlling the default audio format. + * + * If the application doesn't specify the audio format when opening the + * device, this hint can be used to specify a default format that will be + * used. + * + * The variable can be set to the following values: - "U8": Unsigned 8-bit + * audio - "S8": Signed 8-bit audio - "S16LE": Signed 16-bit little-endian + * audio - "S16BE": Signed 16-bit big-endian audio - "S16": Signed 16-bit + * native-endian audio (default) - "S32LE": Signed 32-bit little-endian audio + * - "S32BE": Signed 32-bit big-endian audio - "S32": Signed 32-bit + * native-endian audio - "F32LE": Floating point little-endian audio - + * "F32BE": Floating point big-endian audio - "F32": Floating point + * native-endian audio + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_FORMAT "SDL_AUDIO_FORMAT" + +/** + * A variable controlling the default audio frequency. + * + * If the application doesn't specify the audio frequency when opening the + * device, this hint can be used to specify a default frequency that will be + * used. This defaults to "44100". + * + * This hint should be set before an audio device is opened. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_AUDIO_FREQUENCY "SDL_AUDIO_FREQUENCY" + +/** + * A variable that causes SDL to not ignore audio "monitors". * * This is currently only used by the PulseAudio driver. * - * By default, SDL ignores audio devices that aren't associated with physical hardware. Changing this hint to "1" will expose anything SDL sees that appears to be an audio source or sink. This will add "devices" to the list that the user probably doesn't want or need, but it can be useful in scenarios where you want to hook up SDL to some sort of virtual device, etc. + * By default, SDL ignores audio devices that aren't associated with physical + * hardware. Changing this hint to "1" will expose anything SDL sees that + * appears to be an audio source or sink. This will add "devices" to the list + * that the user probably doesn't want or need, but it can be useful in + * scenarios where you want to hook up SDL to some sort of virtual device, + * etc. * * The variable can be set to the following values: - * "0" - Audio monitor devices will be ignored. (default) - * "1" - Audio monitor devices will show up in the device list. + * + * - "0": Audio monitor devices will be ignored. (default) + * - "1": Audio monitor devices will show up in the device list. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS" /** - * A variable controlling whether SDL updates joystick state when getting input events. + * A variable controlling whether SDL updates joystick state when getting + * input events. * * The variable can be set to the following values: - * "0" - You'll call SDL_UpdateJoysticks() manually. - * "1" - SDL will automatically call SDL_UpdateJoysticks(). (default) + * + * - "0": You'll call SDL_UpdateJoysticks() manually. + * - "1": SDL will automatically call SDL_UpdateJoysticks(). (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS" +#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS" /** - * A variable controlling whether SDL updates sensor state when getting input events + * A variable controlling whether SDL updates sensor state when getting input + * events. * * The variable can be set to the following values: - * "0" - You'll call SDL_UpdateSensors() manually. - * "1" - SDL will automatically call SDL_UpdateSensors(). (default) + * + * - "0": You'll call SDL_UpdateSensors() manually. + * - "1": SDL will automatically call SDL_UpdateSensors(). (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS" +#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS" /** * Prevent SDL from using version 4 of the bitmap header when saving BMPs. * - * The bitmap header version 4 is required for proper alpha channel support and - * SDL will use it when required. Should this not be desired, this hint can - * force the use of the 40 byte header version which is supported everywhere. + * The bitmap header version 4 is required for proper alpha channel support + * and SDL will use it when required. Should this not be desired, this hint + * can force the use of the 40 byte header version which is supported + * everywhere. * * The variable can be set to the following values: - * "0" - Surfaces with a colorkey or an alpha channel are saved to a - * 32-bit BMP file with an alpha mask. SDL will use the bitmap - * header version 4 and set the alpha mask accordingly. (default) - * "1" - Surfaces with a colorkey or an alpha channel are saved to a - * 32-bit BMP file without an alpha mask. The alpha channel data - * will be in the file, but applications are going to ignore it. + * + * - "0": Surfaces with a colorkey or an alpha channel are saved to a 32-bit + * BMP file with an alpha mask. SDL will use the bitmap header version 4 and + * set the alpha mask accordingly. (default) + * - "1": Surfaces with a colorkey or an alpha channel are saved to a 32-bit + * BMP file without an alpha mask. The alpha channel data will be in the + * file, but applications are going to ignore it. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT" /** - * A variable that decides what camera backend to use. + * A variable that decides what camera backend to use. * - * By default, SDL will try all available camera backends in a reasonable - * order until it finds one that can work, but this hint allows the app - * or user to force a specific target, such as "directshow" if, say, you are - * on Windows Media Foundations but want to try DirectShow instead. + * By default, SDL will try all available camera backends in a reasonable + * order until it finds one that can work, but this hint allows the app or + * user to force a specific target, such as "directshow" if, say, you are on + * Windows Media Foundations but want to try DirectShow instead. * - * The default value is unset, in which case SDL will try to figure out - * the best camera backend on your behalf. This hint needs to be set - * before SDL_Init() is called to be useful. + * The default value is unset, in which case SDL will try to figure out the + * best camera backend on your behalf. This hint needs to be set before + * SDL_Init() is called to be useful. * - * This hint is available since SDL 3.0.0. + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_CAMERA_DRIVER "SDL_CAMERA_DRIVER" /** - * A variable that limits what CPU features are available. + * A variable that limits what CPU features are available. + * + * By default, SDL marks all features the current CPU supports as available. + * This hint allows to limit these to a subset. * - * By default, SDL marks all features the current CPU supports as available. - * This hint allows to limit these to a subset. + * When the hint is unset, or empty, SDL will enable all detected CPU + * features. * - * When the hint is unset, or empty, SDL will enable all detected CPU - * features. + * The variable can be set to a comma separated list containing the following + * items: * - * The variable can be set to a comma separated list containing the following items: - * "all" - * "altivec" - * "sse" - * "sse2" - * "sse3" - * "sse41" - * "sse42" - * "avx" - * "avx2" - * "avx512f" - * "arm-simd" - * "neon" - * "lsx" - * "lasx" + * - "all" + * - "altivec" + * - "sse" + * - "sse2" + * - "sse3" + * - "sse41" + * - "sse42" + * - "avx" + * - "avx2" + * - "avx512f" + * - "arm-simd" + * - "neon" + * - "lsx" + * - "lasx" * - * The items can be prefixed by '+'/'-' to add/remove features. + * The items can be prefixed by '+'/'-' to add/remove features. * - * This hint is available since SDL 3.0.0. + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_CPU_FEATURE_MASK "SDL_CPU_FEATURE_MASK" /** - * A variable controlling whether DirectInput should be used for controllers + * A variable controlling whether DirectInput should be used for controllers. * * The variable can be set to the following values: - * "0" - Disable DirectInput detection. - * "1" - Enable DirectInput detection. (default) + * + * - "0": Disable DirectInput detection. + * - "1": Enable DirectInput detection. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_DIRECTINPUT "SDL_JOYSTICK_DIRECTINPUT" /** - * Override for SDL_GetDisplayUsableBounds() + * A variable that specifies a dialog backend to use. + * + * By default, SDL will try all available dialog backends in a reasonable + * order until it finds one that can work, but this hint allows the app or + * user to force a specific target. + * + * If the specified target does not exist or is not available, the + * dialog-related function calls will fail. + * + * This hint currently only applies to platforms using the generic "Unix" + * dialog implementation, but may be extended to more platforms in the future. + * Note that some Unix and Unix-like platforms have their own implementation, + * such as macOS and Haiku. + * + * The variable can be set to the following values: + * + * - NULL: Select automatically (default, all platforms) + * - "portal": Use XDG Portals through DBus (Unix only) + * - "zenity": Use the Zenity program (Unix only) + * + * More options may be added in the future. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_FILE_DIALOG_DRIVER "SDL_FILE_DIALOG_DRIVER" + +/** + * Override for SDL_GetDisplayUsableBounds(). * - * If set, this hint will override the expected results for SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want to do this, but this allows an embedded system to request that some of the screen be reserved for other uses when paired with a well-behaved application. + * If set, this hint will override the expected results for + * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want + * to do this, but this allows an embedded system to request that some of the + * screen be reserved for other uses when paired with a well-behaved + * application. * - * The contents of this hint must be 4 comma-separated integers, the first is the bounds x, then y, width and height, in that order. + * The contents of this hint must be 4 comma-separated integers, the first is + * the bounds x, then y, width and height, in that order. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS" /** - * Disable giving back control to the browser automatically when running with asyncify. + * Disable giving back control to the browser automatically when running with + * asyncify. * - * With -s ASYNCIFY, SDL calls emscripten_sleep during operations such as refreshing the screen or polling events. + * With -s ASYNCIFY, SDL calls emscripten_sleep during operations such as + * refreshing the screen or polling events. * * This hint only applies to the emscripten platform. * * The variable can be set to the following values: - * "0" - Disable emscripten_sleep calls (if you give back browser control manually or use asyncify for other purposes). - * "1" - Enable emscripten_sleep calls. (default) + * + * - "0": Disable emscripten_sleep calls (if you give back browser control + * manually or use asyncify for other purposes). + * - "1": Enable emscripten_sleep calls. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY" +#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY" /** * Specify the CSS selector used for the "default" window/canvas. @@ -447,6 +650,8 @@ extern "C" { * The default value is "#canvas" * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_EMSCRIPTEN_CANVAS_SELECTOR "SDL_EMSCRIPTEN_CANVAS_SELECTOR" @@ -455,94 +660,153 @@ extern "C" { * * This hint only applies to the emscripten platform. * - * The variable can be one of - * "#window" - The javascript window object (default) - * "#document" - The javascript document object - * "#screen" - the javascript window.screen object - * "#canvas" - the WebGL canvas element - * any other string without a leading # sign applies to the element on the page with that ID. + * The variable can be one of: + * + * - "#window": the javascript window object (default) + * - "#document": the javascript document object + * - "#screen": the javascript window.screen object + * - "#canvas": the WebGL canvas element + * - any other string without a leading # sign applies to the element on the + * page with that ID. * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" +#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT" /** - * A variable that controls whether the on-screen keyboard should be shown when text input is active + * A variable that controls whether the on-screen keyboard should be shown + * when text input is active. * * The variable can be set to the following values: - * "auto" - The on-screen keyboard will be shown if there is no physical keyboard attached. (default) - * "0" - Do not show the on-screen keyboard. - * "1" - Show the on-screen keyboard, if available. + * + * - "auto": The on-screen keyboard will be shown if there is no physical + * keyboard attached. (default) + * - "0": Do not show the on-screen keyboard. + * - "1": Show the on-screen keyboard, if available. * * This hint must be set before SDL_StartTextInput() is called + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_ENABLE_SCREEN_KEYBOARD "SDL_ENABLE_SCREEN_KEYBOARD" /** - * A variable controlling verbosity of the logging of SDL events pushed onto the internal queue. + * A variable containing a list of evdev devices to use if udev is not + * available. + * + * The list of devices is in the form: + * + * deviceclass:path[,deviceclass:path[,...]] + * + * where device class is an integer representing the SDL_UDEV_deviceclass and + * path is the full path to the event device. + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_EVDEV_DEVICES "SDL_EVDEV_DEVICES" + +/** + * A variable controlling verbosity of the logging of SDL events pushed onto + * the internal queue. * - * The variable can be set to the following values, from least to most verbose: - * "0" - Don't log any events. (default) - * "1" - Log most events (other than the really spammy ones). - * "2" - Include mouse and finger motion events. + * The variable can be set to the following values, from least to most + * verbose: * - * This is generally meant to be used to debug SDL itself, but can be useful for application developers that need better visibility into what is going on in the event queue. Logged events are sent through SDL_Log(), which means by default they appear on stdout on most platforms or maybe OutputDebugString() on Windows, and can be funneled by the app with SDL_SetLogOutputFunction(), etc. + * - "0": Don't log any events. (default) + * - "1": Log most events (other than the really spammy ones). + * - "2": Include mouse and finger motion events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_SetLogOutputFunction(), etc. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" /** - * A variable controlling whether raising the window should be done more forcefully. + * A variable controlling whether raising the window should be done more + * forcefully. * * The variable can be set to the following values: - * "0" - Honor the OS policy for raising windows. (default) - * "1" - Force the window to be raised, overriding any OS policy. * - * At present, this is only an issue under MS Windows, which makes it nearly impossible to programmatically move a window to the foreground, for "security" reasons. See http://stackoverflow.com/a/34414846 for a discussion. + * - "0": Honor the OS policy for raising windows. (default) + * - "1": Force the window to be raised, overriding any OS policy. + * + * At present, this is only an issue under MS Windows, which makes it nearly + * impossible to programmatically move a window to the foreground, for + * "security" reasons. See http://stackoverflow.com/a/34414846 for a + * discussion. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_FORCE_RAISEWINDOW "SDL_HINT_FORCE_RAISEWINDOW" +#define SDL_HINT_FORCE_RAISEWINDOW "SDL_FORCE_RAISEWINDOW" /** - * A variable controlling how 3D acceleration is used to accelerate the SDL screen surface. + * A variable controlling how 3D acceleration is used to accelerate the SDL + * screen surface. * - * SDL can try to accelerate the SDL screen surface by using streaming textures with a 3D rendering engine. This variable controls whether and how this is done. + * SDL can try to accelerate the SDL screen surface by using streaming + * textures with a 3D rendering engine. This variable controls whether and how + * this is done. * * The variable can be set to the following values: - * "0" - Disable 3D acceleration - * "1" - Enable 3D acceleration, using the default renderer. (default) - * "X" - Enable 3D acceleration, using X where X is one of the valid rendering drivers. (e.g. "direct3d", "opengl", etc.) + * + * - "0": Disable 3D acceleration + * - "1": Enable 3D acceleration, using the default renderer. (default) + * - "X": Enable 3D acceleration, using X where X is one of the valid + * rendering drivers. (e.g. "direct3d", "opengl", etc.) * * This hint should be set before calling SDL_GetWindowSurface() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION" +#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION" /** * A variable that lets you manually hint extra gamecontroller db entries. * - * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamepad.h + * The variable should be newline delimited rows of gamecontroller config + * data, see SDL_gamepad.h * - * You can update mappings after SDL is initialized with SDL_GetGamepadMappingForGUID() and SDL_AddGamepadMapping() + * You can update mappings after SDL is initialized with + * SDL_GetGamepadMappingForGUID() and SDL_AddGamepadMapping() * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" /** - * A variable that lets you provide a file with extra gamecontroller db entries. + * A variable that lets you provide a file with extra gamecontroller db + * entries. * - * The file should contain lines of gamecontroller config data, see SDL_gamepad.h + * The file should contain lines of gamecontroller config data, see + * SDL_gamepad.h * - * You can update mappings after SDL is initialized with SDL_GetGamepadMappingForGUID() and SDL_AddGamepadMapping() + * You can update mappings after SDL is initialized with + * SDL_GetGamepadMappingForGUID() and SDL_AddGamepadMapping() * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" /** - * A variable that overrides the automatic controller type detection + * A variable that overrides the automatic controller type detection. * * The variable should be comma separated entries, in the form: VID/PID=type * @@ -551,97 +815,131 @@ extern "C" { * This hint affects what low level protocol is used with the HIDAPI driver. * * The variable can be set to the following values: - * "Xbox360" - * "XboxOne" - * "PS3" - * "PS4" - * "PS5" - * "SwitchPro" + * + * - "Xbox360" + * - "XboxOne" + * - "PS3" + * - "PS4" + * - "PS5" + * - "SwitchPro" * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE" /** - * A variable containing a list of devices to skip when scanning for game controllers. + * A variable containing a list of devices to skip when scanning for game + * controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES" /** - * If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable. + * If set, all devices will be skipped when scanning for game controllers + * except for the ones listed in this variable. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT" /** - * A variable that controls whether the device's built-in accelerometer and gyro should be used as sensors for gamepads. + * A variable that controls whether the device's built-in accelerometer and + * gyro should be used as sensors for gamepads. * * The variable can be set to the following values: - * "0" - Sensor fusion is disabled - * "1" - Sensor fusion is enabled for all controllers that lack sensors * - * Or the variable can be a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * - "0": Sensor fusion is disabled + * - "1": Sensor fusion is enabled for all controllers that lack sensors * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * Or the variable can be a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint should be set before a gamepad is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GAMECONTROLLER_SENSOR_FUSION "SDL_GAMECONTROLLER_SENSOR_FUSION" /** - * This variable sets the default text of the TextInput window on GDK platforms. + * This variable sets the default text of the TextInput window on GDK + * platforms. * * This hint is available only if SDL_GDK_TEXTINPUT defined. * * This hint should be set before calling SDL_StartTextInput() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT "SDL_GDK_TEXTINPUT_DEFAULT_TEXT" +#define SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT "SDL_GDK_TEXTINPUT_DEFAULT_TEXT" /** - * This variable sets the description of the TextInput window on GDK platforms. + * This variable sets the description of the TextInput window on GDK + * platforms. * * This hint is available only if SDL_GDK_TEXTINPUT defined. * * This hint should be set before calling SDL_StartTextInput() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GDK_TEXTINPUT_DESCRIPTION "SDL_GDK_TEXTINPUT_DESCRIPTION" /** - * This variable sets the maximum input length of the TextInput window on GDK platforms. + * This variable sets the maximum input length of the TextInput window on GDK + * platforms. * - * The value must be a stringified integer, for example "10" to allow for up to 10 characters of text input. + * The value must be a stringified integer, for example "10" to allow for up + * to 10 characters of text input. * * This hint is available only if SDL_GDK_TEXTINPUT defined. * * This hint should be set before calling SDL_StartTextInput() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GDK_TEXTINPUT_MAX_LENGTH "SDL_GDK_TEXTINPUT_MAX_LENGTH" /** - * This variable sets the input scope of the TextInput window on GDK platforms. + * This variable sets the input scope of the TextInput window on GDK + * platforms. * - * Set this hint to change the XGameUiTextEntryInputScope value that will be passed to the window creation function. The value must be a stringified integer, for example "0" for XGameUiTextEntryInputScope::Default. + * Set this hint to change the XGameUiTextEntryInputScope value that will be + * passed to the window creation function. The value must be a stringified + * integer, for example "0" for XGameUiTextEntryInputScope::Default. * * This hint is available only if SDL_GDK_TEXTINPUT defined. * * This hint should be set before calling SDL_StartTextInput() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GDK_TEXTINPUT_SCOPE "SDL_GDK_TEXTINPUT_SCOPE" @@ -651,191 +949,346 @@ extern "C" { * This hint is available only if SDL_GDK_TEXTINPUT defined. * * This hint should be set before calling SDL_StartTextInput() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_GDK_TEXTINPUT_TITLE "SDL_GDK_TEXTINPUT_TITLE" /** - * A variable to control whether SDL_hid_enumerate() enumerates all HID devices or only controllers. + * A variable to control whether HIDAPI uses libusb for device access. + * + * By default libusb will only be used for a few devices that require direct + * USB access, and this can be controlled with + * SDL_HINT_HIDAPI_LIBUSB_WHITELIST. * * The variable can be set to the following values: - * "0" - SDL_hid_enumerate() will enumerate all HID devices. - * "1" - SDL_hid_enumerate() will only enumerate controllers. (default) * - * By default SDL will only enumerate controllers, to reduce risk of hanging or crashing on devices with bad drivers and avoiding macOS keyboard capture permission prompts. + * - "0": HIDAPI will not use libusb for device access. + * - "1": HIDAPI will use libusb for device access if available. (default) * - * This hint can be set anytime. + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS "SDL_HIDAPI_ENUMERATE_ONLY_CONTROLLERS" +#define SDL_HINT_HIDAPI_LIBUSB "SDL_HIDAPI_LIBUSB" /** - * A variable containing a list of devices to ignore in SDL_hid_enumerate() + * A variable to control whether HIDAPI uses libusb only for whitelisted + * devices. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * By default libusb will only be used for a few devices that require direct + * USB access. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * The variable can be set to the following values: * - * For example, to ignore the Shanwan DS3 controller and any Valve controller, you might use the string "0x2563/0x0523,0x28de/0x0000" + * - "0": HIDAPI will use libusb for all device access. + * - "1": HIDAPI will use libusb only for whitelisted devices. (default) * - * This hint can be set anytime. + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES" +#define SDL_HINT_HIDAPI_LIBUSB_WHITELIST "SDL_HIDAPI_LIBUSB_WHITELIST" /** - * A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_EVENT_TEXT_EDITING events. + * A variable to control whether HIDAPI uses udev for device detection. * * The variable can be set to the following values: - * "0" - SDL_EVENT_TEXT_EDITING events are sent, and it is the application's - * responsibility to render the text from these events and - * differentiate it somehow from committed text. (default) - * "1" - If supported by the IME then SDL_EVENT_TEXT_EDITING events are not sent, - * and text that is being composed will be rendered in its own UI. * - * This hint can be set anytime. + * - "0": HIDAPI will poll for device changes. + * - "1": HIDAPI will use udev for device detection. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_HIDAPI_UDEV "SDL_HIDAPI_UDEV" + +/** + * A variable that specifies a GPU backend to use. + * + * By default, SDL will try all available GPU backends in a reasonable order + * until it finds one that can work, but this hint allows the app or user to + * force a specific target, such as "direct3d11" if, say, your hardware + * supports D3D12 but want to try using D3D11 instead. + * + * This hint should be set before SDL_GPUSelectBackend() is called. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" +#define SDL_HINT_GPU_DRIVER "SDL_GPU_DRIVER" /** - * A variable to control whether certain IMEs should show native UI components (such as the Candidate List) instead of suppressing them. + * A variable to control whether SDL_hid_enumerate() enumerates all HID + * devices or only controllers. * * The variable can be set to the following values: - * "0" - Native UI components are not display. (default) - * "1" - Native UI components are displayed. + * + * - "0": SDL_hid_enumerate() will enumerate all HID devices. + * - "1": SDL_hid_enumerate() will only enumerate controllers. (default) + * + * By default SDL will only enumerate controllers, to reduce risk of hanging + * or crashing on devices with bad drivers and avoiding macOS keyboard capture + * permission prompts. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS "SDL_HIDAPI_ENUMERATE_ONLY_CONTROLLERS" + +/** + * A variable containing a list of devices to ignore in SDL_hid_enumerate(). + * + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. + * + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` + * + * For example, to ignore the Shanwan DS3 controller and any Valve controller, + * you might use the string "0x2563/0x0523,0x28de/0x0000" + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES" + +/** + * A variable describing what IME UI elements the application can display. + * + * By default IME UI is handled using native components by the OS where + * possible, however this can interfere with or not be visible when exclusive + * fullscreen mode is used. + * + * The variable can be set to a comma separated list containing the following + * items: + * + * - "none" or "0": The application can't render any IME elements, and native + * UI should be used. (default) + * - "composition": The application handles SDL_EVENT_TEXT_EDITING events and + * can render the composition text. + * - "candidates": The application handles SDL_EVENT_TEXT_EDITING_CANDIDATES + * and can render the candidate list. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI" +#define SDL_HINT_IME_IMPLEMENTED_UI "SDL_IME_IMPLEMENTED_UI" /** - * A variable controlling whether the home indicator bar on iPhone X should be hidden. + * A variable controlling whether the home indicator bar on iPhone X should be + * hidden. * - * The variable can be set to the following values: - * "0" - The indicator bar is not hidden. (default for windowed applications) - * "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications). - * "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action. (default for fullscreen applications) + * The variable can be set to the following values: + * + * - "0": The indicator bar is not hidden. (default for windowed applications) + * - "1": The indicator bar is hidden and is shown when the screen is touched + * (useful for movie playback applications). + * - "2": The indicator bar is dim and the first swipe makes it visible and + * the second swipe performs the "home" action. (default for fullscreen + * applications) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR" /** - * A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background. + * A variable that lets you enable joystick (and gamecontroller) events even + * when your app is in the background. * * The variable can be set to the following values: - * "0" - Disable joystick & gamecontroller input events when the application is in the background. (default) - * "1" - Enable joystick & gamecontroller input events when the application is in the background. + * + * - "0": Disable joystick & gamecontroller input events when the application + * is in the background. (default) + * - "1": Enable joystick & gamecontroller input events when the application + * is in the background. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS" /** * A variable containing a list of arcade stick style controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES "SDL_JOYSTICK_ARCADESTICK_DEVICES" /** - * A variable containing a list of devices that are not arcade stick style controllers. This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in device list. + * A variable containing a list of devices that are not arcade stick style + * controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * This will override SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES and the built in + * device list. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` + * + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED" /** - * A variable containing a list of devices that should not be considerd joysticks. + * A variable containing a list of devices that should not be considered + * joysticks. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES "SDL_JOYSTICK_BLACKLIST_DEVICES" /** - * A variable containing a list of devices that should be considered joysticks. This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in device list. + * A variable containing a list of devices that should be considered + * joysticks. + * + * This will override SDL_HINT_JOYSTICK_BLACKLIST_DEVICES and the built in + * device list. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED" /** - * A variable containing a comma separated list of devices to open as joysticks. - * - * This variable is currently only used by the Linux joystick driver. - */ + * A variable containing a comma separated list of devices to open as + * joysticks. + * + * This variable is currently only used by the Linux joystick driver. + * + * \since This hint is available since SDL 3.0.0. + */ #define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE" /** * A variable containing a list of flightstick style controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of @file, in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of @file, in which case the named file + * will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES "SDL_JOYSTICK_FLIGHTSTICK_DEVICES" /** - * A variable containing a list of devices that are not flightstick style controllers. This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in device list. + * A variable containing a list of devices that are not flightstick style + * controllers. + * + * This will override SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES and the built in + * device list. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED" /** - * A variable containing a list of devices known to have a GameCube form factor. + * A variable controlling whether GameInput should be used for controller + * handling on Windows. + * + * The variable can be set to the following values: + * + * - "0": GameInput is not used. (default) + * - "1": GameInput is used. + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_JOYSTICK_GAMEINPUT "SDL_JOYSTICK_GAMEINPUT" + +/** + * A variable containing a list of devices known to have a GameCube form + * factor. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES "SDL_JOYSTICK_GAMECUBE_DEVICES" /** - * A variable containing a list of devices known not to have a GameCube form factor. This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in device list. + * A variable containing a list of devices known not to have a GameCube form + * factor. + * + * This will override SDL_HINT_JOYSTICK_GAMECUBE_DEVICES and the built in + * device list. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED" @@ -843,671 +1296,1013 @@ extern "C" { * A variable controlling whether the HIDAPI joystick drivers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI drivers are not used. - * "1" - HIDAPI drivers are used. (default) * - * This variable is the default for all drivers, but can be overridden by the hints for specific drivers below. + * - "0": HIDAPI drivers are not used. + * - "1": HIDAPI drivers are used. (default) + * + * This variable is the default for all drivers, but can be overridden by the + * hints for specific drivers below. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI" /** - * A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver. + * A variable controlling whether Nintendo Switch Joy-Con controllers will be + * combined into a single Pro-like controller when using the HIDAPI driver. * * The variable can be set to the following values: - * "0" - Left and right Joy-Con controllers will not be combined and each will be a mini-gamepad. - * "1" - Left and right Joy-Con controllers will be combined into a single controller. (default) + * + * - "0": Left and right Joy-Con controllers will not be combined and each + * will be a mini-gamepad. + * - "1": Left and right Joy-Con controllers will be combined into a single + * controller. (default) * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS" /** - * A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo GameCube + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE" /** - * A variable controlling whether rumble is used to implement the GameCube controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2) + * A variable controlling whether rumble is used to implement the GameCube + * controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2). * - * This is useful for applications that need full compatibility for things like ADSR envelopes. - * - Stop is implemented by setting low_frequency_rumble to 0 and high_frequency_rumble >0 - * - Rumble is both at any arbitrary value - * - StopHard is implemented by setting both low_frequency_rumble and high_frequency_rumble to 0 + * This is useful for applications that need full compatibility for things + * like ADSR envelopes. - Stop is implemented by setting low_frequency_rumble + * to 0 and high_frequency_rumble >0 - Rumble is both at any arbitrary value - + * StopHard is implemented by setting both low_frequency_rumble and + * high_frequency_rumble to 0 * * The variable can be set to the following values: - * "0" - Normal rumble behavior is behavior is used. (default) - * "1" - Proper GameCube controller rumble behavior is used. + * + * - "0": Normal rumble behavior is behavior is used. (default) + * - "1": Proper GameCube controller rumble behavior is used. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE" /** - * A variable controlling whether the HIDAPI driver for Nintendo Switch Joy-Cons should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Switch + * Joy-Cons should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS" /** - * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened + * A variable controlling whether the Home button LED should be turned on when + * a Nintendo Switch Joy-Con controller is opened. * * The variable can be set to the following values: - * "0" - home button LED is turned off - * "1" - home button LED is turned on * - * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED. + * - "0": home button LED is turned off + * - "1": home button LED is turned on + * + * By default the Home button LED state is not changed. This hint can also be + * set to a floating point value between 0.0 and 1.0 which controls the + * brightness of the Home button LED. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED "SDL_JOYSTICK_HIDAPI_JOYCON_HOME_LED" /** - * A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used. + * A variable controlling whether the HIDAPI driver for Amazon Luna + * controllers connected via Bluetooth should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA" /** - * A variable controlling whether the HIDAPI driver for Nintendo Online classic controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Online + * classic controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC "SDL_JOYSTICK_HIDAPI_NINTENDO_CLASSIC" /** - * A variable controlling whether the HIDAPI driver for PS3 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS3 controllers should + * be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI on macOS, and "0" on other platforms. + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI on macOS, and "0" on + * other platforms. * - * For official Sony driver (sixaxis.sys) use SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER. - * See https://github.com/ViGEm/DsHidMini for an alternative driver on Windows. + * For official Sony driver (sixaxis.sys) use + * SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER. See + * https://github.com/ViGEm/DsHidMini for an alternative driver on Windows. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS3 "SDL_JOYSTICK_HIDAPI_PS3" /** - * A variable controlling whether the Sony driver (sixaxis.sys) for PS3 controllers (Sixaxis/DualShock 3) should be used. + * A variable controlling whether the Sony driver (sixaxis.sys) for PS3 + * controllers (Sixaxis/DualShock 3) should be used. * * The variable can be set to the following values: - * "0" - Sony driver (sixaxis.sys) is not used. - * "1" - Sony driver (sixaxis.sys) is used. + * + * - "0": Sony driver (sixaxis.sys) is not used. + * - "1": Sony driver (sixaxis.sys) is used. * * The default value is 0. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER "SDL_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER" /** - * A variable controlling whether the HIDAPI driver for PS4 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS4 controllers should + * be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4" /** - * A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver. + * A variable controlling the update rate of the PS4 controller over Bluetooth + * when using the HIDAPI driver. + * + * This defaults to 4 ms, to match the behavior over USB, and to be more + * friendly to other Bluetooth devices and older Bluetooth hardware on the + * computer. It can be set to "1" (1000Hz), "2" (500Hz) and "4" (250Hz) + * + * This hint can be set anytime, but only takes effect when extended input + * reports are enabled. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL "SDL_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL" + +/** + * A variable controlling whether extended input reports should be used for + * PS4 controllers when using the HIDAPI driver. * * The variable can be set to the following values: - * "0" - extended reports are not enabled. (default) - * "1" - extended reports are enabled. * - * Extended input reports allow rumble on Bluetooth PS4 controllers, but break DirectInput handling for applications that don't use SDL. + * - "0": extended reports are not enabled. (default) + * - "1": extended reports are enabled. + * + * Extended input reports allow rumble on Bluetooth PS4 controllers, but break + * DirectInput handling for applications that don't use SDL. * - * Once extended reports are enabled, they can not be disabled without power cycling the controller. + * Once extended reports are enabled, they can not be disabled without power + * cycling the controller. * - * For compatibility with applications written for versions of SDL prior to the introduction of PS5 controller support, this value will also control the state of extended reports on PS5 controllers when the SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set. + * For compatibility with applications written for versions of SDL prior to + * the introduction of PS5 controller support, this value will also control + * the state of extended reports on PS5 controllers when the + * SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set. * * This hint can be enabled anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE" /** - * A variable controlling whether the HIDAPI driver for PS5 controllers should be used. + * A variable controlling whether the HIDAPI driver for PS5 controllers should + * be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5" /** - * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller. + * A variable controlling whether the player LEDs should be lit to indicate + * which player is associated with a PS5 controller. * * The variable can be set to the following values: - * "0" - player LEDs are not enabled. - * "1" - player LEDs are enabled. (default) + * + * - "0": player LEDs are not enabled. + * - "1": player LEDs are enabled. (default) + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED" /** - * A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver. + * A variable controlling whether extended input reports should be used for + * PS5 controllers when using the HIDAPI driver. * * The variable can be set to the following values: - * "0" - extended reports are not enabled. (default) - * "1" - extended reports. * - * Extended input reports allow rumble on Bluetooth PS5 controllers, but break DirectInput handling for applications that don't use SDL. + * - "0": extended reports are not enabled. (default) + * - "1": extended reports. * - * Once extended reports are enabled, they can not be disabled without power cycling the controller. + * Extended input reports allow rumble on Bluetooth PS5 controllers, but break + * DirectInput handling for applications that don't use SDL. * - * For compatibility with applications written for versions of SDL prior to the introduction of PS5 controller support, this value defaults to the value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE. + * Once extended reports are enabled, they can not be disabled without power + * cycling the controller. + * + * For compatibility with applications written for versions of SDL prior to + * the introduction of PS5 controller support, this value defaults to the + * value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE. * * This hint can be enabled anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE" /** - * A variable controlling whether the HIDAPI driver for NVIDIA SHIELD controllers should be used. + * A variable controlling whether the HIDAPI driver for NVIDIA SHIELD + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_SHIELD "SDL_JOYSTICK_HIDAPI_SHIELD" /** - * A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used. + * A variable controlling whether the HIDAPI driver for Google Stadia + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA" /** - * A variable controlling whether the HIDAPI driver for Bluetooth Steam Controllers should be used. + * A variable controlling whether the HIDAPI driver for Bluetooth Steam + * Controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. (default) - * "1" - HIDAPI driver is used for Steam Controllers, which requires Bluetooth access and may prompt the user for permission on iOS and Android. + * + * - "0": HIDAPI driver is not used. (default) + * - "1": HIDAPI driver is used for Steam Controllers, which requires + * Bluetooth access and may prompt the user for permission on iOS and + * Android. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM" /** - * A variable controlling whether the HIDAPI driver for the Steam Deck builtin controller should be used. + * A variable controlling whether the HIDAPI driver for the Steam Deck builtin + * controller should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_STEAMDECK "SDL_JOYSTICK_HIDAPI_STEAMDECK" /** - * A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used. + * A variable controlling whether the HIDAPI driver for HORI licensed Steam + * controllers should be used. + * + * This variable can be set to the following values: "0" - HIDAPI driver is + * not used "1" - HIDAPI driver is used + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI + */ +#define SDL_HINT_JOYSTICK_HIDAPI_STEAM_HORI "SDL_JOYSTICK_HIDAPI_STEAM_HORI" + +/** + * A variable controlling whether the HIDAPI driver for Nintendo Switch + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH" /** - * A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Pro controller is opened + * A variable controlling whether the Home button LED should be turned on when + * a Nintendo Switch Pro controller is opened. * * The variable can be set to the following values: - * "0" - Home button LED is turned off. - * "1" - Home button LED is turned on. * - * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED. + * - "0": Home button LED is turned off. + * - "1": Home button LED is turned on. + * + * By default the Home button LED state is not changed. This hint can also be + * set to a floating point value between 0.0 and 1.0 which controls the + * brightness of the Home button LED. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED" /** - * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Nintendo Switch controller. + * A variable controlling whether the player LEDs should be lit to indicate + * which player is associated with a Nintendo Switch controller. * * The variable can be set to the following values: - * "0" - Player LEDs are not enabled. - * "1" - Player LEDs are enabled. (default) + * + * - "0": Player LEDs are not enabled. + * - "1": Player LEDs are enabled. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED" /** - * A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver. + * A variable controlling whether Nintendo Switch Joy-Con controllers will be + * in vertical mode when using the HIDAPI driver. * * The variable can be set to the following values: - * "0" - Left and right Joy-Con controllers will not be in vertical mode. (default) - * "1" - Left and right Joy-Con controllers will be in vertical mode. + * + * - "0": Left and right Joy-Con controllers will not be in vertical mode. + * (default) + * - "1": Left and right Joy-Con controllers will be in vertical mode. * * This hint should be set before opening a Joy-Con controller. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS" /** - * A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U controllers should be used. + * A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. * - * This driver doesn't work with the dolphinbar, so the default is SDL_FALSE for now. + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * This driver doesn't work with the dolphinbar, so the default is false for + * now. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_WII "SDL_JOYSTICK_HIDAPI_WII" /** - * A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Wii controller. + * A variable controlling whether the player LEDs should be lit to indicate + * which player is associated with a Wii controller. * * The variable can be set to the following values: - * "0" - Player LEDs are not enabled. - * "1" - Player LEDs are enabled. (default) + * + * - "0": Player LEDs are not enabled. + * - "1": Player LEDs are enabled. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED" /** - * A variable controlling whether the HIDAPI driver for XBox controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox controllers + * should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. * - * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is "0" on Windows, otherwise the value of + * SDL_HINT_JOYSTICK_HIDAPI * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX" +#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX" /** - * A variable controlling whether the HIDAPI driver for XBox 360 controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox 360 controllers + * should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360" +#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360" /** - * A variable controlling whether the player LEDs should be lit to indicate which player is associated with an Xbox 360 controller. + * A variable controlling whether the player LEDs should be lit to indicate + * which player is associated with an Xbox 360 controller. * * The variable can be set to the following values: - * "0" - Player LEDs are not enabled. - * "1" - Player LEDs are enabled. (default) + * + * - "0": Player LEDs are not enabled. + * - "1": Player LEDs are enabled. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED "SDL_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED" /** - * A variable controlling whether the HIDAPI driver for XBox 360 wireless controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox 360 wireless + * controllers should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. + * + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. * * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS" +#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS" /** - * A variable controlling whether the HIDAPI driver for XBox One controllers should be used. + * A variable controlling whether the HIDAPI driver for XBox One controllers + * should be used. * * The variable can be set to the following values: - * "0" - HIDAPI driver is not used. - * "1" - HIDAPI driver is used. * - * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX. + * - "0": HIDAPI driver is not used. + * - "1": HIDAPI driver is used. + * + * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX. * * This hint should be set before enumerating controllers. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE "SDL_JOYSTICK_HIDAPI_XBOX_ONE" +#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE "SDL_JOYSTICK_HIDAPI_XBOX_ONE" /** - * A variable controlling whether the Home button LED should be turned on when an Xbox One controller is opened. + * A variable controlling whether the Home button LED should be turned on when + * an Xbox One controller is opened. * * The variable can be set to the following values: - * "0" - Home button LED is turned off. - * "1" - Home button LED is turned on. * - * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED. The default brightness is 0.4. + * - "0": Home button LED is turned off. + * - "1": Home button LED is turned on. + * + * By default the Home button LED state is not changed. This hint can also be + * set to a floating point value between 0.0 and 1.0 which controls the + * brightness of the Home button LED. The default brightness is 0.4. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED" /** - * A variable controlling whether IOKit should be used for controller handling. + * A variable controlling whether IOKit should be used for controller + * handling. * * The variable can be set to the following values: - * "0" - IOKit is not used. - * "1" - IOKit is used. (default) + * + * - "0": IOKit is not used. + * - "1": IOKit is used. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_IOKIT "SDL_JOYSTICK_IOKIT" /** - * A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux + * A variable controlling whether to use the classic /dev/input/js* joystick + * interface or the newer /dev/input/event* joystick interface on Linux. * * The variable can be set to the following values: - * "0" - Use /dev/input/event* (default) - * "1" - Use /dev/input/js* + * + * - "0": Use /dev/input/event* (default) + * - "1": Use /dev/input/js* * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_LINUX_CLASSIC "SDL_JOYSTICK_LINUX_CLASSIC" /** - * A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values. + * A variable controlling whether joysticks on Linux adhere to their + * HID-defined deadzones or return unfiltered values. * * The variable can be set to the following values: - * "0" - Return unfiltered joystick axis values. (default) - * "1" - Return axis values with deadzones taken into account. + * + * - "0": Return unfiltered joystick axis values. (default) + * - "1": Return axis values with deadzones taken into account. * * This hint should be set before a controller is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_LINUX_DEADZONES "SDL_JOYSTICK_LINUX_DEADZONES" /** - * A variable controlling whether joysticks on Linux will always treat 'hat' axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking whether they may be analog. + * A variable controlling whether joysticks on Linux will always treat 'hat' + * axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking + * whether they may be analog. * * The variable can be set to the following values: - * "0" - Only map hat axis inputs to digital hat outputs if the input axes appear to actually be digital. (default) - * "1" - Always handle the input axes numbered ABS_HAT0X to ABS_HAT3Y as digital hats. + * + * - "0": Only map hat axis inputs to digital hat outputs if the input axes + * appear to actually be digital. (default) + * - "1": Always handle the input axes numbered ABS_HAT0X to ABS_HAT3Y as + * digital hats. * * This hint should be set before a controller is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_LINUX_DIGITAL_HATS "SDL_JOYSTICK_LINUX_DIGITAL_HATS" /** - * A variable controlling whether digital hats on Linux will apply deadzones to their underlying input axes or use unfiltered values. + * A variable controlling whether digital hats on Linux will apply deadzones + * to their underlying input axes or use unfiltered values. * * The variable can be set to the following values: - * "0" - Return digital hat values based on unfiltered input axis values. - * "1" - Return digital hat values with deadzones on the input axes taken into account. (default) + * + * - "0": Return digital hat values based on unfiltered input axis values. + * - "1": Return digital hat values with deadzones on the input axes taken + * into account. (default) * * This hint should be set before a controller is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES "SDL_JOYSTICK_LINUX_HAT_DEADZONES" /** - * A variable controlling whether GCController should be used for controller handling. + * A variable controlling whether GCController should be used for controller + * handling. * * The variable can be set to the following values: - * "0" - GCController is not used. - * "1" - GCController is used. (default) + * + * - "0": GCController is not used. + * - "1": GCController is used. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_MFI "SDL_JOYSTICK_MFI" /** - * A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices. + * A variable controlling whether the RAWINPUT joystick drivers should be used + * for better handling XInput-capable devices. * * The variable can be set to the following values: - * "0" - RAWINPUT drivers are not used. - * "1" - RAWINPUT drivers are used. (default) + * + * - "0": RAWINPUT drivers are not used. + * - "1": RAWINPUT drivers are used. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT" /** - * A variable controlling whether the RAWINPUT driver should pull correlated data from XInput. + * A variable controlling whether the RAWINPUT driver should pull correlated + * data from XInput. * * The variable can be set to the following values: - * "0" - RAWINPUT driver will only use data from raw input APIs. - * "1" - RAWINPUT driver will also pull data from XInput and Windows.Gaming.Input, providing better trigger axes, guide button presses, and rumble support for Xbox controllers. (default) + * + * - "0": RAWINPUT driver will only use data from raw input APIs. + * - "1": RAWINPUT driver will also pull data from XInput and + * Windows.Gaming.Input, providing better trigger axes, guide button + * presses, and rumble support for Xbox controllers. (default) * * This hint should be set before a gamepad is opened. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT" +#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT" /** - * A variable controlling whether the ROG Chakram mice should show up as joysticks. + * A variable controlling whether the ROG Chakram mice should show up as + * joysticks. * * The variable can be set to the following values: - * "0" - ROG Chakram mice do not show up as joysticks. (default) - * "1" - ROG Chakram mice show up as joysticks. + * + * - "0": ROG Chakram mice do not show up as joysticks. (default) + * - "1": ROG Chakram mice show up as joysticks. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_ROG_CHAKRAM "SDL_JOYSTICK_ROG_CHAKRAM" /** - * A variable controlling whether a separate thread should be used for handling joystick detection and raw input messages on Windows. + * A variable controlling whether a separate thread should be used for + * handling joystick detection and raw input messages on Windows. + * + * The variable can be set to the following values: * - * The variable can be set to the following values: - * "0" - A separate thread is not used. (default) - * "1" - A separate thread is used for handling raw input messages. + * - "0": A separate thread is not used. (default) + * - "1": A separate thread is used for handling raw input messages. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD" /** * A variable containing a list of throttle style controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_THROTTLE_DEVICES "SDL_JOYSTICK_THROTTLE_DEVICES" /** - * A variable containing a list of devices that are not throttle style controllers. This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in device list. + * A variable containing a list of devices that are not throttle style + * controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * This will override SDL_HINT_JOYSTICK_THROTTLE_DEVICES and the built in + * device list. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` + * + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED" /** - * A variable controlling whether Windows.Gaming.Input should be used for controller handling. + * A variable controlling whether Windows.Gaming.Input should be used for + * controller handling. * * The variable can be set to the following values: - * "0" - WGI is not used. - * "1" - WGI is used. (default) + * + * - "0": WGI is not used. + * - "1": WGI is used. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI" /** * A variable containing a list of wheel style controllers. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_WHEEL_DEVICES "SDL_JOYSTICK_WHEEL_DEVICES" /** - * A variable containing a list of devices that are not wheel style controllers. This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device list. + * A variable containing a list of devices that are not wheel style + * controllers. + * + * This will override SDL_HINT_JOYSTICK_WHEEL_DEVICES and the built in device + * list. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED" /** - * A variable containing a list of devices known to have all axes centered at zero. + * A variable containing a list of devices known to have all axes centered at + * zero. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint should be set before a controller is opened. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_JOYSTICK_ZERO_CENTERED_DEVICES "SDL_JOYSTICK_ZERO_CENTERED_DEVICES" +/** + * A variable that controls keycode representation in keyboard events. + * + * This variable is a comma separated set of options for translating keycodes + * in events: + * + * - "none": Keycode options are cleared, this overrides other options. + * - "hide_numpad": The numpad keysyms will be translated into their + * non-numpad versions based on the current NumLock state. For example, + * SDLK_KP_4 would become SDLK_4 if SDL_KMOD_NUM is set in the event + * modifiers, and SDLK_LEFT if it is unset. + * - "french_numbers": The number row on French keyboards is inverted, so + * pressing the 1 key would yield the keycode SDLK_1, or '1', instead of + * SDLK_AMPERSAND, or '&' + * - "latin_letters": For keyboards using non-Latin letters, such as Russian + * or Thai, the letter keys generate keycodes as though it had an en_US + * layout. e.g. pressing the key associated with SDL_SCANCODE_A on a Russian + * keyboard would yield 'a' instead of a Cyrillic letter. + * + * The default value for this hint is "french_numbers,latin_letters" + * + * Some platforms like Emscripten only provide modified keycodes and the + * options are not used. + * + * These options do not affect the return value of SDL_GetKeyFromScancode() or + * SDL_GetScancodeFromKey(), they just apply to the keycode included in key + * events. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_KEYCODE_OPTIONS "SDL_KEYCODE_OPTIONS" + /** * A variable that controls what KMSDRM device to use. * - * SDL might open something like "/dev/dri/cardNN" to access KMSDRM functionality, where "NN" is a device index number. SDL makes a guess at the best index to use (usually zero), but the app or user can set this hint to a number between 0 and 99 to force selection. + * SDL might open something like "/dev/dri/cardNN" to access KMSDRM + * functionality, where "NN" is a device index number. SDL makes a guess at + * the best index to use (usually zero), but the app or user can set this hint + * to a number between 0 and 99 to force selection. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_KMSDRM_DEVICE_INDEX "SDL_KMSDRM_DEVICE_INDEX" /** - * A variable that controls whether SDL requires DRM master access in order to initialize the KMSDRM video backend. + * A variable that controls whether SDL requires DRM master access in order to + * initialize the KMSDRM video backend. * - * The DRM subsystem has a concept of a "DRM master" which is a DRM client that - * has the ability to set planes, set cursor, etc. When SDL is DRM master, it - * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL - * is still able to process input and query attributes of attached displays, - * but it cannot change display state or draw to the screen directly. + * The DRM subsystem has a concept of a "DRM master" which is a DRM client + * that has the ability to set planes, set cursor, etc. When SDL is DRM + * master, it can draw to the screen using the SDL rendering APIs. Without DRM + * master, SDL is still able to process input and query attributes of attached + * displays, but it cannot change display state or draw to the screen + * directly. * - * In some cases, it can be useful to have the KMSDRM backend even if it cannot - * be used for rendering. An app may want to use SDL for input processing while - * using another rendering API (such as an MMAL overlay on Raspberry Pi) or - * using its own code to render to DRM overlays that SDL doesn't support. + * In some cases, it can be useful to have the KMSDRM backend even if it + * cannot be used for rendering. An app may want to use SDL for input + * processing while using another rendering API (such as an MMAL overlay on + * Raspberry Pi) or using its own code to render to DRM overlays that SDL + * doesn't support. * * The variable can be set to the following values: - * "0" - SDL will allow usage of the KMSDRM backend without DRM master. - * "1" - SDL Will require DRM master to use the KMSDRM backend. (default) + * + * - "0": SDL will allow usage of the KMSDRM backend without DRM master. + * - "1": SDL Will require DRM master to use the KMSDRM backend. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" +#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER" /** * A variable controlling the default SDL log levels. * - * This variable is a comma separated set of category=level tokens that define the default logging levels for SDL applications. + * This variable is a comma separated set of category=level tokens that define + * the default logging levels for SDL applications. * - * The category can be a numeric category, one of "app", "error", "assert", "system", "audio", "video", "render", "input", "test", or `*` for any unspecified category. + * The category can be a numeric category, one of "app", "error", "assert", + * "system", "audio", "video", "render", "input", "test", or `*` for any + * unspecified category. * - * The level can be a numeric level, one of "verbose", "debug", "info", "warn", "error", "critical", or "quiet" to disable that category. + * The level can be a numeric level, one of "verbose", "debug", "info", + * "warn", "error", "critical", or "quiet" to disable that category. * - * You can omit the category if you want to set the logging level for all categories. + * You can omit the category if you want to set the logging level for all + * categories. * * If this hint isn't set, the default log levels are equivalent to: - * "app=info,assert=warn,test=verbose,*=error" + * + * `app=info,assert=warn,test=verbose,*=error` * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_LOGGING "SDL_LOGGING" +#define SDL_HINT_LOGGING "SDL_LOGGING" /** - * A variable controlling whether to force the application to become the foreground process when launched on macOS. + * A variable controlling whether to force the application to become the + * foreground process when launched on macOS. * * The variable can be set to the following values: - * "0" - The application is brought to the foreground when launched. (default) - * "1" - The application may remain in the background when launched. * - * This hint should be set before applicationDidFinishLaunching() is called. + * - "0": The application is brought to the foreground when launched. + * (default) + * - "1": The application may remain in the background when launched. + * + * This hint needs to be set before SDL_Init(). + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP" +#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP" /** - * A variable that determines whether Ctrl+Click should generate a right-click event on macOS. + * A variable that determines whether Ctrl+Click should generate a right-click + * event on macOS. * * The variable can be set to the following values: - * "0" - Ctrl+Click does not generate a right mouse button click event. (default) - * "1" - Ctrl+Click generated a right mouse button click event. + * + * - "0": Ctrl+Click does not generate a right mouse button click event. + * (default) + * - "1": Ctrl+Click generated a right mouse button click event. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK" /** - * A variable controlling whether dispatching OpenGL context updates should block the dispatching thread until the main thread finishes processing on macOS. + * A variable controlling whether dispatching OpenGL context updates should + * block the dispatching thread until the main thread finishes processing on + * macOS. * * The variable can be set to the following values: - * "0" - Dispatching OpenGL context updates will block the dispatching thread until the main thread finishes processing. (default) - * "1" - Dispatching OpenGL context updates will allow the dispatching thread to continue execution. * - * Generally you want the default, but if you have OpenGL code in a background thread on a Mac, and the main thread hangs because it's waiting for that background thread, but that background thread is also hanging because it's waiting for the main thread to do an update, this might fix your issue. + * - "0": Dispatching OpenGL context updates will block the dispatching thread + * until the main thread finishes processing. (default) + * - "1": Dispatching OpenGL context updates will allow the dispatching thread + * to continue execution. + * + * Generally you want the default, but if you have OpenGL code in a background + * thread on a Mac, and the main thread hangs because it's waiting for that + * background thread, but that background thread is also hanging because it's + * waiting for the main thread to do an update, this might fix your issue. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH "SDL_MAC_OPENGL_ASYNC_DISPATCH" +/** + * A variable controlling whether SDL_EVENT_MOUSE_WHEEL event values will have + * momentum on macOS. + * + * The variable can be set to the following values: + * + * - "0": The mouse wheel events will have no momentum. (default) + * - "1": The mouse wheel events will have momentum. + * + * This hint needs to be set before SDL_Init(). + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_MAC_SCROLL_MOMENTUM "SDL_HINT_MAC_SCROLL_MOMENTUM" + /** * Request SDL_AppIterate() be called at a specific rate. * @@ -1521,237 +2316,405 @@ extern "C" { * the default. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_MAIN_CALLBACK_RATE "SDL_MAIN_CALLBACK_RATE" /** - * A variable controlling whether the mouse is captured while mouse buttons are pressed. + * A variable controlling whether the mouse is captured while mouse buttons + * are pressed. * * The variable can be set to the following values: - * "0" - The mouse is not captured while mouse buttons are pressed. - * "1" - The mouse is captured while mouse buttons are pressed. * - * By default the mouse is captured while mouse buttons are pressed so if the mouse is dragged outside the window, the application continues to receive mouse events until the button is released. + * - "0": The mouse is not captured while mouse buttons are pressed. + * - "1": The mouse is captured while mouse buttons are pressed. + * + * By default the mouse is captured while mouse buttons are pressed so if the + * mouse is dragged outside the window, the application continues to receive + * mouse events until the button is released. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE" +#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE" /** * A variable setting the double click radius, in pixels. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS" +#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS" /** * A variable setting the double click time, in milliseconds. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" +#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME" + +/** + * A variable controlling whether warping a hidden mouse cursor will activate + * relative mouse mode. + * + * When this hint is set, the mouse cursor is hidden, and multiple warps to + * the window center occur within a short time period, SDL will emulate mouse + * warps using relative mouse mode. This can provide smoother and more + * reliable mouse motion for some older games, which continuously calculate + * the distance travelled by the mouse pointer and warp it back to the center + * of the window, rather than using relative mouse motion. + * + * Note that relative mouse mode may have different mouse acceleration + * behavior than pointer warps. + * + * If your application needs to repeatedly warp the hidden mouse cursor at a + * high-frequency for other purposes, it should disable this hint. + * + * The variable can be set to the following values: + * + * - "0": Attempts to warp the mouse will always be made. + * - "1": Some mouse warps will be emulated by forcing relative mouse mode. + * (default) + * + * If not set, this is automatically enabled unless an application uses + * relative mouse mode directly. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE "SDL_MOUSE_EMULATE_WARP_WITH_RELATIVE" /** * Allow mouse click events when clicking to focus an SDL window. * * The variable can be set to the following values: - * "0" - Ignore mouse clicks that activate a window. (default) - * "1" - Generate events for mouse clicks that activate a window. + * + * - "0": Ignore mouse clicks that activate a window. (default) + * - "1": Generate events for mouse clicks that activate a window. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH" /** - * A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode. + * A variable setting the speed scale for mouse motion, in floating point, + * when the mouse is not in relative mode. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE" +#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE" /** - * A variable controlling whether relative mouse mode constrains the mouse to the center of the window. + * A variable controlling whether relative mouse mode constrains the mouse to + * the center of the window. * - * Constraining to the center of the window works better for FPS games and when the application is running over RDP. Constraining to the whole window works better for 2D games and increases the chance that the mouse will be in the correct position when using high DPI mice. + * Constraining to the center of the window works better for FPS games and + * when the application is running over RDP. Constraining to the whole window + * works better for 2D games and increases the chance that the mouse will be + * in the correct position when using high DPI mice. * * The variable can be set to the following values: - * "0" - Relative mouse mode constrains the mouse to the window. - * "1" - Relative mouse mode constrains the mouse to the center of the window. (default) + * + * - "0": Relative mouse mode constrains the mouse to the window. + * - "1": Relative mouse mode constrains the mouse to the center of the + * window. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER" +#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER" /** - * A variable controlling whether relative mouse mode is implemented using mouse warping. + * A variable controlling whether relative mouse mode is implemented using + * mouse warping. * * The variable can be set to the following values: - * "0" - Relative mouse mode uses raw input. (default) - * "1" - Relative mouse mode uses mouse warping. + * + * - "0": Relative mouse mode uses raw input. (default) + * - "1": Relative mouse mode uses mouse warping. * * This hint can be set anytime relative mode is not currently enabled. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP" +#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP" /** - * A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode. + * A variable setting the scale for mouse motion, in floating point, when the + * mouse is in relative mode. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" +#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" /** - * A variable controlling whether the system mouse acceleration curve is used for relative mouse motion. + * A variable controlling whether the system mouse acceleration curve is used + * for relative mouse motion. * * The variable can be set to the following values: - * "0" - Relative mouse motion will be unscaled. (default) - * "1" - Relative mouse motion will be scaled using the system mouse acceleration curve. * - * If SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE is set, that will override the system speed scale. + * - "0": Relative mouse motion will be unscaled. (default) + * - "1": Relative mouse motion will be scaled using the system mouse + * acceleration curve. + * + * If SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE is set, that will override the + * system speed scale. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE" +#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE" /** - * A variable controlling whether a motion event should be generated for mouse warping in relative mode. + * A variable controlling whether a motion event should be generated for mouse + * warping in relative mode. * * The variable can be set to the following values: - * "0" - Warping the mouse will not generate a motion event in relative mode - * "1" - Warping the mouse will generate a motion event in relative mode * - * By default warping the mouse will not generate motion events in relative mode. This avoids the application having to filter out large relative motion due to warping. + * - "0": Warping the mouse will not generate a motion event in relative mode + * - "1": Warping the mouse will generate a motion event in relative mode + * + * By default warping the mouse will not generate motion events in relative + * mode. This avoids the application having to filter out large relative + * motion due to warping. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION" +#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION" /** - * A variable controlling whether mouse events should generate synthetic touch events + * A variable controlling whether the hardware cursor stays visible when + * relative mode is active. * - * The variable can be set to the following values: - * "0" - Mouse events will not generate touch events. (default for desktop platforms) - * "1" - Mouse events will generate touch events. (default for mobile platforms, such as Android and iOS) + * This variable can be set to the following values: "0" - The cursor will be + * hidden while relative mode is active (default) "1" - The cursor will remain + * visible while relative mode is active + * + * Note that for systems without raw hardware inputs, relative mode is + * implemented using warping, so the hardware cursor will visibly warp between + * frames if this is enabled on those systems. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" +#define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE" /** - * Tell SDL not to catch the SIGINT or SIGTERM signals on POSIX platforms. + * Controls how often SDL issues cursor confinement commands to the operating + * system while relative mode is active, in case the desired confinement state + * became out-of-sync due to interference from other running programs. * - * The variable can be set to the following values: - * "0" - SDL will install a SIGINT and SIGTERM handler, and when it catches a signal, convert it into an SDL_EVENT_QUIT event. (default) - * "1" - SDL will not install a signal handler at all. + * The variable can be integers representing milliseconds between each + * refresh. A value of zero means SDL will not automatically refresh the + * confinement. The default value varies depending on the operating system, + * this variable might not have any effects on inapplicable platforms such as + * those without a cursor. * - * This hint should be set before SDL is initialized. + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" +#define SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL "SDL_MOUSE_RELATIVE_CLIP_INTERVAL" /** - * A variable controlling what driver to use for OpenGL ES contexts. + * A variable controlling whether mouse events should generate synthetic touch + * events. * - * On some platforms, currently Windows and X11, OpenGL drivers may support creating contexts with an OpenGL ES profile. By default SDL uses these profiles, when available, otherwise it attempts to load an OpenGL ES library, e.g. that provided by the ANGLE project. This variable controls whether SDL follows this default behaviour or will always load an OpenGL ES library. + * The variable can be set to the following values: * - * Circumstances where this is useful include - * - Testing an app with a particular OpenGL ES implementation, e.g ANGLE, or emulator, e.g. those from ARM, Imagination or Qualcomm. - * - Resolving OpenGL ES function addresses at link time by linking with the OpenGL ES library instead of querying them at run time with SDL_GL_GetProcAddress(). + * - "0": Mouse events will not generate touch events. (default for desktop + * platforms) + * - "1": Mouse events will generate touch events. (default for mobile + * platforms, such as Android and iOS) * - * Caution: for an application to work with the default behaviour across different OpenGL drivers it must query the OpenGL ES function addresses at run time using SDL_GL_GetProcAddress(). + * This hint can be set anytime. * - * This variable is ignored on most platforms because OpenGL ES is native or not supported. + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + +/** + * A variable controlling whether the keyboard should be muted on the console. + * + * Normally the keyboard is muted while SDL applications are running so that + * keyboard input doesn't show up as key strokes on the console. This hint + * allows you to turn that off for debugging purposes. * * The variable can be set to the following values: - * "0" - Use ES profile of OpenGL, if available. (default) - * "1" - Load OpenGL ES library using the default library names. + * + * - "0": Allow keystrokes to go through to the console. + * - "1": Mute keyboard input so it doesn't show up on the console. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" +#define SDL_HINT_MUTE_CONSOLE_KEYBOARD "SDL_MUTE_CONSOLE_KEYBOARD" /** - * A variable controlling which orientations are allowed on iOS/Android. + * Tell SDL not to catch the SIGINT or SIGTERM signals on POSIX platforms. * - * In some circumstances it is necessary to be able to explicitly control which UI orientations are allowed. + * The variable can be set to the following values: * - * This variable is a space delimited list of the following values: - * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown" + * - "0": SDL will install a SIGINT and SIGTERM handler, and when it catches a + * signal, convert it into an SDL_EVENT_QUIT event. (default) + * - "1": SDL will not install a signal handler at all. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS" + +/** + * Specify the OpenGL library to load. + * + * This hint should be set before creating an OpenGL window or creating an + * OpenGL context. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS" +#define SDL_HINT_OPENGL_LIBRARY "SDL_OPENGL_LIBRARY" /** - * A variable controlling whether pen mouse button emulation triggers only when the pen touches the tablet surface. + * A variable controlling what driver to use for OpenGL ES contexts. + * + * On some platforms, currently Windows and X11, OpenGL drivers may support + * creating contexts with an OpenGL ES profile. By default SDL uses these + * profiles, when available, otherwise it attempts to load an OpenGL ES + * library, e.g. that provided by the ANGLE project. This variable controls + * whether SDL follows this default behaviour or will always load an OpenGL ES + * library. + * + * Circumstances where this is useful include - Testing an app with a + * particular OpenGL ES implementation, e.g ANGLE, or emulator, e.g. those + * from ARM, Imagination or Qualcomm. - Resolving OpenGL ES function addresses + * at link time by linking with the OpenGL ES library instead of querying them + * at run time with SDL_GL_GetProcAddress(). + * + * Caution: for an application to work with the default behaviour across + * different OpenGL drivers it must query the OpenGL ES function addresses at + * run time using SDL_GL_GetProcAddress(). + * + * This variable is ignored on most platforms because OpenGL ES is native or + * not supported. * * The variable can be set to the following values: - * "0" - The pen reports mouse button press/release immediately when the pen button is pressed/released, and the pen tip touching the surface counts as left mouse button press. - * "1" - Mouse button presses are sent when the pen first touches the tablet (analogously for releases). Not pressing a pen button simulates mouse button 1, pressing the first pen button simulates mouse button 2 etc.; it is not possible to report multiple buttons as pressed at the same time. (default) * - * This hint can be set anytime. + * - "0": Use ES profile of OpenGL, if available. (default) + * - "1": Load OpenGL ES library using the default library names. + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_PEN_DELAY_MOUSE_BUTTON "SDL_HINT_PEN_DELAY_MOUSE_BUTTON" +#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER" /** - * A variable controlling whether to treat pen movement as separate from mouse movement + * A variable controlling which orientations are allowed on iOS/Android. * - * By default, pens report both ::SDL_MouseMotionEvent and ::SDL_PenMotionEvent updates (analogously for button presses). This hint allows decoupling mouse and pen updates. + * In some circumstances it is necessary to be able to explicitly control + * which UI orientations are allowed. * - * This variable toggles between the following behaviour: - * "0" - Pen acts as a mouse with mouse ID ::SDL_PEN_MOUSEID. (default) - * Use case: client application is not pen aware, user wants to use pen instead of mouse to interact. - * "1" - Pen reports mouse clicks and movement events but does not update SDL-internal mouse state (buttons pressed, current mouse location). - * Use case: client application is not pen aware, user frequently alternates between pen and "real" mouse. - * "2" - Pen reports no mouse events. - * Use case: pen-aware client application uses this hint to allow user to toggle between pen+mouse mode ("2") and pen-only mode ("1" or "0"). + * This variable is a space delimited list of the following values: * - * This hint can be set anytime. + * - "LandscapeLeft" + * - "LandscapeRight" + * - "Portrait" + * - "PortraitUpsideDown" + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_PEN_NOT_MOUSE "SDL_HINT_PEN_NOT_MOUSE" +#define SDL_HINT_ORIENTATIONS "SDL_ORIENTATIONS" /** - * A variable controlling the use of a sentinel event when polling the event queue + * A variable controlling the use of a sentinel event when polling the event + * queue. * - * When polling for events, SDL_PumpEvents is used to gather new events from devices. If a device keeps producing new events between calls to SDL_PumpEvents, a poll loop will become stuck until the new events stop. This is most noticeable when moving a high frequency mouse. + * When polling for events, SDL_PumpEvents is used to gather new events from + * devices. If a device keeps producing new events between calls to + * SDL_PumpEvents, a poll loop will become stuck until the new events stop. + * This is most noticeable when moving a high frequency mouse. * * The variable can be set to the following values: - * "0" - Disable poll sentinels. - * "1" - Enable poll sentinels. (default) + * + * - "0": Disable poll sentinels. + * - "1": Enable poll sentinels. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL" /** - * Override for SDL_GetPreferredLocales() + * Override for SDL_GetPreferredLocales(). * - * If set, this will be favored over anything the OS might report for the user's preferred locales. Changing this hint at runtime will not generate a SDL_EVENT_LOCALE_CHANGED event (but if you can change the hint, you can push your own event, if you want). + * If set, this will be favored over anything the OS might report for the + * user's preferred locales. Changing this hint at runtime will not generate a + * SDL_EVENT_LOCALE_CHANGED event (but if you can change the hint, you can + * push your own event, if you want). * - * The format of this hint is a comma-separated list of language and locale, combined with an underscore, as is a common format: "en_GB". Locale is optional: "en". So you might have a list like this: "en_GB,jp,es_PT" + * The format of this hint is a comma-separated list of language and locale, + * combined with an underscore, as is a common format: "en_GB". Locale is + * optional: "en". So you might have a list like this: "en_GB,jp,es_PT" * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" /** - * A variable that decides whether to send SDL_EVENT_QUIT when closing the last window. + * A variable that decides whether to send SDL_EVENT_QUIT when closing the + * last window. * * The variable can be set to the following values: - * "0" - SDL will not send an SDL_EVENT_QUIT event when the last window is requesting to close. Note that in this case, there are still other legitimate reasons one might get an SDL_EVENT_QUIT event: choosing "Quit" from the macOS menu bar, sending a SIGINT (ctrl-c) on Unix, etc. - * "1" - SDL will send a quit event when the last window is requesting to close. (default) + * + * - "0": SDL will not send an SDL_EVENT_QUIT event when the last window is + * requesting to close. Note that in this case, there are still other + * legitimate reasons one might get an SDL_EVENT_QUIT event: choosing "Quit" + * from the macOS menu bar, sending a SIGINT (ctrl-c) on Unix, etc. + * - "1": SDL will send a quit event when the last window is requesting to + * close. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE "SDL_QUIT_ON_LAST_WINDOW_CLOSE" /** - * A variable controlling whether the Direct3D device is initialized for thread-safe operations. + * A variable controlling whether the Direct3D device is initialized for + * thread-safe operations. * * The variable can be set to the following values: - * "0" - Thread-safety is not enabled. (default) - * "1" - Thread-safety is enabled. + * + * - "0": Thread-safety is not enabled. (default) + * - "1": Thread-safety is enabled. * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE" @@ -1761,129 +2724,190 @@ extern "C" { * This variable does not have any effect on the Direct3D 9 based renderer. * * The variable can be set to the following values: - * "0" - Disable Debug Layer use. (default) - * "1" - Enable Debug Layer use. + * + * - "0": Disable Debug Layer use. (default) + * - "1": Enable Debug Layer use. * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" +#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG" /** - * A variable controlling whether to enable Vulkan Validation Layers + * A variable controlling whether to enable Vulkan Validation Layers. + * + * This variable can be set to the following values: * + * - "0": Disable Validation Layer use + * - "1": Enable Validation Layer use * - * This variable can be set to the following values: - * "0" - Disable Validation Layer use - * "1" - Enable Validation Layer use + * By default, SDL does not use Vulkan Validation Layers. * - * By default, SDL does not use Vulkan Validation Layers. + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_VULKAN_DEBUG "SDL_RENDER_VULKAN_DEBUG" +#define SDL_HINT_RENDER_VULKAN_DEBUG "SDL_RENDER_VULKAN_DEBUG" /** - * A variable specifying which render driver to use. + * A variable controlling whether to create the GPU device in debug mode. * - * If the application doesn't pick a specific renderer to use, this variable specifies the name of the preferred renderer. If the preferred renderer can't be initialized, the normal default renderer is used. + * This variable can be set to the following values: * - * This variable is case insensitive and can be set to the following values: - * "direct3d" - * "direct3d11" - * "direct3d12" - * "opengl" - * "opengles2" - * "opengles" - * "metal" - * "vulkan" - * "software" - * - * The default varies by platform, but it's the first one in the list that is available on the current platform. + * - "0": Disable debug mode use (default) + * - "1": Enable debug mode use * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER" +#define SDL_HINT_RENDER_GPU_DEBUG "SDL_RENDER_GPU_DEBUG" /** - * A variable controlling how the 2D render API renders lines. + * A variable controlling whether to prefer a low-power GPU on multi-GPU + * systems. * - * The variable can be set to the following values: - * "0" - Use the default line drawing method (Bresenham's line algorithm) - * "1" - Use the driver point API using Bresenham's line algorithm (correct, draws many points) - * "2" - Use the driver line API (occasionally misses line endpoints based on hardware driver quirks - * "3" - Use the driver geometry API (correct, draws thicker diagonal lines) + * This variable can be set to the following values: + * + * - "0": Prefer high-performance GPU (default) + * - "1": Prefer low-power GPU * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" +#define SDL_HINT_RENDER_GPU_LOW_POWER "SDL_RENDER_GPU_LOW_POWER" /** - * A variable controlling whether the Metal render driver select low power device over default one. + * A variable specifying which render driver to use. + * + * If the application doesn't pick a specific renderer to use, this variable + * specifies the name of the preferred renderer. If the preferred renderer + * can't be initialized, creating a renderer will fail. + * + * This variable is case insensitive and can be set to the following values: + * + * - "direct3d" + * - "direct3d11" + * - "direct3d12" + * - "opengl" + * - "opengles2" + * - "opengles" + * - "metal" + * - "vulkan" + * - "software" + * + * The default varies by platform, but it's the first one in the list that is + * available on the current platform. + * + * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER" + +/** + * A variable controlling how the 2D render API renders lines. * * The variable can be set to the following values: - * "0" - Use the prefered OS device. (default) - * "1" - Select a low power device. + * + * - "0": Use the default line drawing method (Bresenham's line algorithm) + * - "1": Use the driver point API using Bresenham's line algorithm (correct, + * draws many points) + * - "2": Use the driver line API (occasionally misses line endpoints based on + * hardware driver quirks + * - "3": Use the driver geometry API (correct, draws thicker diagonal lines) * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" +#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD" /** - * A variable controlling whether vsync is automatically disabled if doesn't reach enough FPS. + * A variable controlling whether the Metal render driver select low power + * device over default one. * * The variable can be set to the following values: - * "0" - It will be using VSYNC as defined in the main flag. (default) - * "1" - If VSYNC was previously enabled, then it will disable VSYNC if doesn't reach enough speed + * + * - "0": Use the preferred OS device. (default) + * - "1": Select a low power device. * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC "SDL_RENDER_PS2_DYNAMIC_VSYNC" +#define SDL_HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE" /** - * A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing. + * A variable controlling whether updates to the SDL screen surface should be + * synchronized with the vertical refresh, to avoid tearing. * * This hint overrides the application preference when creating a renderer. * * The variable can be set to the following values: - * "0" - Disable vsync. (default) - * "1" - Enable vsync. + * + * - "0": Disable vsync. (default) + * - "1": Enable vsync. * * This hint should be set before creating a renderer. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" +#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" /** - * A variable to control whether the return key on the soft keyboard should hide the soft keyboard on Android and iOS. + * A variable to control whether the return key on the soft keyboard should + * hide the soft keyboard on Android and iOS. + * + * This hint sets the default value of SDL_PROP_TEXTINPUT_MULTILINE_BOOLEAN. * * The variable can be set to the following values: - * "0" - The return key will be handled as a key event. (default) - * "1" - The return key will hide the keyboard. + * + * - "0": The return key will be handled as a key event. (default) + * - "1": The return key will hide the keyboard. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME" /** * A variable containing a list of ROG gamepad capable mice. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + * + * \sa SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED */ #define SDL_HINT_ROG_GAMEPAD_MICE "SDL_ROG_GAMEPAD_MICE" /** - * A variable containing a list of devices that are not ROG gamepad capable mice. This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. + * A variable containing a list of devices that are not ROG gamepad capable + * mice. * - * The format of the string is a comma separated list of USB VID/PID pairs in hexadecimal form, e.g. + * This will override SDL_HINT_ROG_GAMEPAD_MICE and the built in device list. * - * 0xAAAA/0xBBBB,0xCCCC/0xDDDD + * The format of the string is a comma separated list of USB VID/PID pairs in + * hexadecimal form, e.g. * - * The variable can also take the form of "@file", in which case the named file will be loaded and interpreted as the value of the variable. + * `0xAAAA/0xBBBB,0xCCCC/0xDDDD` + * + * The variable can also take the form of "@file", in which case the named + * file will be loaded and interpreted as the value of the variable. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_ROG_GAMEPAD_MICE_EXCLUDED "SDL_ROG_GAMEPAD_MICE_EXCLUDED" @@ -1894,89 +2918,138 @@ extern "C" { * The default is 10000. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER" +#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER" /** * Specify an "activity name" for screensaver inhibition. * - * Some platforms, notably Linux desktops, list the applications which are inhibiting the screensaver or other power-saving features. + * Some platforms, notably Linux desktops, list the applications which are + * inhibiting the screensaver or other power-saving features. * - * This hint lets you specify the "activity name" sent to the OS when SDL_DisableScreenSaver() is used (or the screensaver is automatically disabled). The contents of this hint are used when the screensaver is disabled. You should use a string that describes what your program is doing (and, therefore, why the screensaver is disabled). For example, "Playing a game" or "Watching a video". + * This hint lets you specify the "activity name" sent to the OS when + * SDL_DisableScreenSaver() is used (or the screensaver is automatically + * disabled). The contents of this hint are used when the screensaver is + * disabled. You should use a string that describes what your program is doing + * (and, therefore, why the screensaver is disabled). For example, "Playing a + * game" or "Watching a video". * - * Setting this to "" or leaving it unset will have SDL use a reasonable default: "Playing a game" or something similar. + * Setting this to "" or leaving it unset will have SDL use a reasonable + * default: "Playing a game" or something similar. * * This hint should be set before calling SDL_DisableScreenSaver() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME" /** * A variable controlling whether SDL calls dbus_shutdown() on quit. * - * This is useful as a debug tool to validate memory leaks, but shouldn't ever be set in production applications, as other libraries used by the application might use dbus under the hood and this cause cause crashes if they continue after SDL_Quit(). + * This is useful as a debug tool to validate memory leaks, but shouldn't ever + * be set in production applications, as other libraries used by the + * application might use dbus under the hood and this can cause crashes if + * they continue after SDL_Quit(). * * The variable can be set to the following values: - * "0" - SDL will not call dbus_shutdown() on quit. (default) - * "1" - SDL will call dbus_shutdown() on quit. + * + * - "0": SDL will not call dbus_shutdown() on quit. (default) + * - "1": SDL will call dbus_shutdown() on quit. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_SHUTDOWN_DBUS_ON_QUIT "SDL_SHUTDOWN_DBUS_ON_QUIT" /** * A variable that specifies a backend to use for title storage. * - * By default, SDL will try all available storage backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific target, such as "pc" if, say, you are on Steam but want to avoid SteamRemoteStorage for title data. + * By default, SDL will try all available storage backends in a reasonable + * order until it finds one that can work, but this hint allows the app or + * user to force a specific target, such as "pc" if, say, you are on Steam but + * want to avoid SteamRemoteStorage for title data. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_STORAGE_TITLE_DRIVER "SDL_STORAGE_TITLE_DRIVER" /** * A variable that specifies a backend to use for user storage. * - * By default, SDL will try all available storage backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific target, such as "pc" if, say, you are on Steam but want to avoid SteamRemoteStorage for user data. + * By default, SDL will try all available storage backends in a reasonable + * order until it finds one that can work, but this hint allows the app or + * user to force a specific target, such as "pc" if, say, you are on Steam but + * want to avoid SteamRemoteStorage for user data. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_STORAGE_USER_DRIVER "SDL_STORAGE_USER_DRIVER" /** - * Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime. + * Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as + * realtime. * - * On some platforms, like Linux, a realtime priority thread may be subject to restrictions that require special handling by the application. This hint exists to let SDL know that the app is prepared to handle said restrictions. + * On some platforms, like Linux, a realtime priority thread may be subject to + * restrictions that require special handling by the application. This hint + * exists to let SDL know that the app is prepared to handle said + * restrictions. * - * On Linux, SDL will apply the following configuration to any thread that becomes realtime: - * - The SCHED_RESET_ON_FORK bit will be set on the scheduling policy, - * - An RLIMIT_RTTIME budget will be configured to the rtkit specified limit. - * - Exceeding this limit will result in the kernel sending SIGKILL to the app, refer to the man pages for more information. + * On Linux, SDL will apply the following configuration to any thread that + * becomes realtime: + * + * - The SCHED_RESET_ON_FORK bit will be set on the scheduling policy, + * - An RLIMIT_RTTIME budget will be configured to the rtkit specified limit. + * - Exceeding this limit will result in the kernel sending SIGKILL to the + * app, refer to the man pages for more information. * * The variable can be set to the following values: - * "0" - default platform specific behaviour - * "1" - Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling policy * - * This hint should be set before calling SDL_SetThreadPriority() + * - "0": default platform specific behaviour + * - "1": Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling + * policy + * + * This hint should be set before calling SDL_SetCurrentThreadPriority() + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL" /** - * A string specifying additional information to use with SDL_SetThreadPriority. + * A string specifying additional information to use with + * SDL_SetCurrentThreadPriority. + * + * By default SDL_SetCurrentThreadPriority will make appropriate system + * changes in order to apply a thread priority. For example on systems using + * pthreads the scheduler policy is changed automatically to a policy that + * works well with a given priority. Code which has specific requirements can + * override SDL's default behavior with this hint. * - * By default SDL_SetThreadPriority will make appropriate system changes in order to apply a thread priority. For example on systems using pthreads the scheduler policy is changed automatically to a policy that works well with a given priority. Code which has specific requirements can override SDL's default behavior with this hint. + * pthread hint values are "current", "other", "fifo" and "rr". Currently no + * other platform hint values are defined but may be in the future. * - * pthread hint values are "current", "other", "fifo" and "rr". - * Currently no other platform hint values are defined but may be in the future. + * On Linux, the kernel may send SIGKILL to realtime tasks which exceed the + * distro configured execution budget for rtkit. This budget can be queried + * through RLIMIT_RTTIME after calling SDL_SetCurrentThreadPriority(). * - * On Linux, the kernel may send SIGKILL to realtime tasks which exceed the distro configured execution budget for rtkit. This budget can be queried through RLIMIT_RTTIME after calling SDL_SetThreadPriority(). + * This hint should be set before calling SDL_SetCurrentThreadPriority() * - * This hint should be set before calling SDL_SetThreadPriority() + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY" +#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY" /** * A variable that controls the timer resolution, in milliseconds. * - * The higher resolution the timer, the more frequently the CPU services timer interrupts, and the more precise delays are, but this takes up power and CPU time. This hint is only used on Windows. + * The higher resolution the timer, the more frequently the CPU services timer + * interrupts, and the more precise delays are, but this takes up power and + * CPU time. This hint is only used on Windows. * * See this blog post for more information: * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/ @@ -1986,41 +3059,59 @@ extern "C" { * If this variable is set to "0", the system timer resolution is not set. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION" /** - * A variable controlling whether touch events should generate synthetic mouse events + * A variable controlling whether touch events should generate synthetic mouse + * events. * * The variable can be set to the following values: - * "0" - Touch events will not generate mouse events. - * "1" - Touch events will generate mouse events. (default) + * + * - "0": Touch events will not generate mouse events. + * - "1": Touch events will generate mouse events. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" +#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" /** - * A variable controlling whether trackpads should be treated as touch devices. + * A variable controlling whether trackpads should be treated as touch + * devices. * - * On macOS (and possibly other platforms in the future), SDL will report touches on a trackpad as mouse input, which is generally what users expect from this device; however, these are often actually full multitouch-capable touch devices, so it might be preferable to some apps to treat them as such. + * On macOS (and possibly other platforms in the future), SDL will report + * touches on a trackpad as mouse input, which is generally what users expect + * from this device; however, these are often actually full multitouch-capable + * touch devices, so it might be preferable to some apps to treat them as + * such. * * The variable can be set to the following values: - * "0" - Trackpad will send mouse events. (default) - * "1" - Trackpad will send touch events. + * + * - "0": Trackpad will send mouse events. (default) + * - "1": Trackpad will send touch events. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY" /** - * A variable controlling whether the Android / tvOS remotes should be listed as joystick devices, instead of sending keyboard events. + * A variable controlling whether the Android / tvOS remotes should be listed + * as joystick devices, instead of sending keyboard events. * * The variable can be set to the following values: - * "0" - Remotes send enter/escape/arrow key events. - * "1" - Remotes are available as 2 axis, 2 button joysticks. (default) + * + * - "0": Remotes send enter/escape/arrow key events. + * - "1": Remotes are available as 2 axis, 2 button joysticks. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" @@ -2028,55 +3119,93 @@ extern "C" { * A variable controlling whether the screensaver is enabled. * * The variable can be set to the following values: - * "0" - Disable screensaver. (default) - * "1" - Enable screensaver. + * + * - "0": Disable screensaver. (default) + * - "1": Enable screensaver. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" +#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" /** * Tell the video driver that we only want a double buffer. * - * By default, most lowlevel 2D APIs will use a triple buffer scheme that wastes no CPU time on waiting for vsync after issuing a flip, but introduces a frame of latency. On the other hand, using a double buffer scheme instead is recommended for cases where low latency is an important factor because we save a whole frame of latency. + * By default, most lowlevel 2D APIs will use a triple buffer scheme that + * wastes no CPU time on waiting for vsync after issuing a flip, but + * introduces a frame of latency. On the other hand, using a double buffer + * scheme instead is recommended for cases where low latency is an important + * factor because we save a whole frame of latency. * - * We do so by waiting for vsync immediately after issuing a flip, usually just after eglSwapBuffers call in the backend's *_SwapWindow function. + * We do so by waiting for vsync immediately after issuing a flip, usually + * just after eglSwapBuffers call in the backend's *_SwapWindow function. * * This hint is currently supported on the following drivers: + * * - Raspberry Pi (raspberrypi) + * - Wayland (wayland) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER" +#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER" /** * A variable that specifies a video backend to use. * - * By default, SDL will try all available video backends in a reasonable order until it finds one that can work, but this hint allows the app or user to force a specific target, such as "x11" if, say, you are on Wayland but want to try talking to the X server instead. + * By default, SDL will try all available video backends in a reasonable order + * until it finds one that can work, but this hint allows the app or user to + * force a specific target, such as "x11" if, say, you are on Wayland but want + * to try talking to the X server instead. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_DRIVER "SDL_VIDEO_DRIVER" +/** + * A variable controlling whether the dummy video driver saves output frames. + * + * - "0": Video frames are not saved to disk. (default) + * - "1": Video frames are saved to files in the format "SDL_windowX-Y.bmp", + * where X is the window ID, and Y is the frame number. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VIDEO_DUMMY_SAVE_FRAMES "SDL_VIDEO_DUMMY_SAVE_FRAMES" + /** * If eglGetPlatformDisplay fails, fall back to calling eglGetDisplay. * * The variable can be set to one of the following values: - * "0" - Do not fall back to eglGetDisplay. - * "1" - Fall back to eglGetDisplay if eglGetPlatformDisplay fails. (default) + * + * - "0": Do not fall back to eglGetDisplay. + * - "1": Fall back to eglGetDisplay if eglGetPlatformDisplay fails. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_GETDISPLAY_FALLBACK" +#define SDL_HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK "SDL_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK" /** - * A variable controlling whether the OpenGL context should be created with EGL. + * A variable controlling whether the OpenGL context should be created with + * EGL. * * The variable can be set to the following values: - * "0" - Use platform-specific GL context creation API (GLX, WGL, CGL, etc). (default) - * "1" - Use EGL + * + * - "0": Use platform-specific GL context creation API (GLX, WGL, CGL, etc). + * (default) + * - "1": Use EGL * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_FORCE_EGL "SDL_VIDEO_FORCE_EGL" @@ -2084,167 +3213,265 @@ extern "C" { * A variable that specifies the policy for fullscreen Spaces on macOS. * * The variable can be set to the following values: - * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen" button on their titlebars). - * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and SDL_WINDOW_RESIZABLE windows will offer the "fullscreen" button on their titlebars). (default) + * + * - "0": Disable Spaces support (FULLSCREEN_DESKTOP won't use them and + * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen" button on their + * titlebars). + * - "1": Enable Spaces support (FULLSCREEN_DESKTOP will use them and + * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen" button on their + * titlebars). (default) * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" +#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" /** - * A variable controlling whether fullscreen windows are minimized when they lose focus. + * A variable controlling whether fullscreen windows are minimized when they + * lose focus. * * The variable can be set to the following values: - * "0" - Fullscreen windows will not be minimized when they lose focus. (default) - * "1" - Fullscreen windows are minimized when they lose focus. + * + * - "0": Fullscreen windows will not be minimized when they lose focus. + * (default) + * - "1": Fullscreen windows are minimized when they lose focus. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" +#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" /** - * A variable controlling whether all window operations will block until complete. - * - * Window systems that run asynchronously may not have the results of window operations that resize or move the window applied immediately upon the return of the requesting function. Setting this hint will cause such operations to block after every call until the pending operation has completed. Setting this to '1' is the equivalent of calling SDL_SyncWindow() after every function call. + * A variable controlling whether the offscreen video driver saves output + * frames. * - * Be aware that amount of time spent blocking while waiting for window operations to complete can be quite lengthy, as animations may have to complete, which can take upwards of multiple seconds in some cases. + * This only saves frames that are generated using software rendering, not + * accelerated OpenGL rendering. * - * The variable can be set to the following values: - * "0" - Window operations are non-blocking. (default) - * "1" - Window operations will block until completed. + * - "0": Video frames are not saved to disk. (default) + * - "1": Video frames are saved to files in the format "SDL_windowX-Y.bmp", + * where X is the window ID, and Y is the frame number. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" +#define SDL_HINT_VIDEO_OFFSCREEN_SAVE_FRAMES "SDL_VIDEO_OFFSCREEN_SAVE_FRAMES" /** - * A variable controlling whether the libdecor Wayland backend is allowed to be used. + * A variable controlling whether all window operations will block until + * complete. + * + * Window systems that run asynchronously may not have the results of window + * operations that resize or move the window applied immediately upon the + * return of the requesting function. Setting this hint will cause such + * operations to block after every call until the pending operation has + * completed. Setting this to '1' is the equivalent of calling + * SDL_SyncWindow() after every function call. * - * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable. + * Be aware that amount of time spent blocking while waiting for window + * operations to complete can be quite lengthy, as animations may have to + * complete, which can take upwards of multiple seconds in some cases. * * The variable can be set to the following values: - * "0" - libdecor use is disabled. - * "1" - libdecor use is enabled. (default) * - * This hint should be set before SDL is initialized. + * - "0": Window operations are non-blocking. (default) + * - "1": Window operations will block until completed. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" +#define SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS "SDL_VIDEO_SYNC_WINDOW_OPERATIONS" /** - * Enable or disable mouse pointer warp emulation, needed by some older games. + * A variable controlling whether the libdecor Wayland backend is allowed to + * be used. * - * Wayland does not directly support warping the mouse. When this hint is set, any SDL will emulate mouse warps using relative mouse mode. This is required for some older games (such as Source engine games), which warp the mouse to the centre of the screen rather than using relative mouse motion. Note that relative mouse mode may have different mouse acceleration behaviour than pointer warps. + * libdecor is used over xdg-shell when xdg-decoration protocol is + * unavailable. * * The variable can be set to the following values: - * "0" - All mouse warps fail, as mouse warping is not available under wayland. - * "1" - Some mouse warps will be emulated by forcing relative mouse mode. * - * If not set, this is automatically enabled unless an application uses relative mouse mode directly. + * - "0": libdecor use is disabled. + * - "1": libdecor use is enabled. (default) * - * This hint can be set anytime. + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP" +#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR" /** - * A variable controlling whether video mode emulation is enabled under Wayland. + * A variable controlling whether video mode emulation is enabled under + * Wayland. * - * When this hint is set, a standard set of emulated CVT video modes will be exposed for use by the application. If it is disabled, the only modes exposed will be the logical desktop size and, in the case of a scaled desktop, the native display resolution. + * When this hint is set, a standard set of emulated CVT video modes will be + * exposed for use by the application. If it is disabled, the only modes + * exposed will be the logical desktop size and, in the case of a scaled + * desktop, the native display resolution. * * The variable can be set to the following values: - * "0" - Video mode emulation is disabled. - * "1" - Video mode emulation is enabled. (default) + * + * - "0": Video mode emulation is disabled. + * - "1": Video mode emulation is enabled. (default) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_WAYLAND_MODE_EMULATION "SDL_VIDEO_WAYLAND_MODE_EMULATION" /** - * A variable controlling how modes with a non-native aspect ratio are displayed under Wayland. + * A variable controlling how modes with a non-native aspect ratio are + * displayed under Wayland. * - * When this hint is set, the requested scaling will be used when displaying fullscreen video modes that don't match the display's native aspect ratio. This is contingent on compositor viewport support. + * When this hint is set, the requested scaling will be used when displaying + * fullscreen video modes that don't match the display's native aspect ratio. + * This is contingent on compositor viewport support. * * The variable can be set to the following values: - * "aspect" - Video modes will be displayed scaled, in their proper aspect ratio, with black bars. - * "stretch" - Video modes will be scaled to fill the entire display. (default) - * "none" - Video modes will be displayed as 1:1 with no scaling. + * + * - "aspect" - Video modes will be displayed scaled, in their proper aspect + * ratio, with black bars. + * - "stretch" - Video modes will be scaled to fill the entire display. + * (default) + * - "none" - Video modes will be displayed as 1:1 with no scaling. * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_WAYLAND_MODE_SCALING "SDL_VIDEO_WAYLAND_MODE_SCALING" /** - * A variable controlling whether the libdecor Wayland backend is preferred over native decrations. + * A variable controlling whether the libdecor Wayland backend is preferred + * over native decorations. * - * When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is available. (Note that, by default, libdecor will use xdg-decoration itself if available). + * When this hint is set, libdecor will be used to provide window decorations, + * even if xdg-decoration is available. (Note that, by default, libdecor will + * use xdg-decoration itself if available). * * The variable can be set to the following values: - * "0" - libdecor is enabled only if server-side decorations are unavailable. (default) - * "1" - libdecor is always enabled if available. + * + * - "0": libdecor is enabled only if server-side decorations are unavailable. + * (default) + * - "1": libdecor is always enabled if available. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR" /** * A variable forcing non-DPI-aware Wayland windows to output at 1:1 scaling. * - * When this hint is set, Wayland windows that are not flagged as being DPI-aware will be output with scaling designed to force 1:1 pixel mapping. + * This must be set before initializing the video subsystem. + * + * When this hint is set, Wayland windows that are not flagged as being + * DPI-aware will be output with scaling designed to force 1:1 pixel mapping. * - * This is intended to allow legacy applications to be displayed without desktop scaling being applied, and has issues with certain display configurations, as this forces the window to behave in a way that Wayland desktops were not designed to accommodate: + * This is intended to allow legacy applications to be displayed without + * desktop scaling being applied, and has issues with certain display + * configurations, as this forces the window to behave in a way that Wayland + * desktops were not designed to accommodate: * - * - Rounding errors can result with odd window sizes and/or desktop scales. - * - The window may be unusably small. - * - The window may jump in size at times. - * - The window may appear to be larger than the desktop size to the application. - * - Possible loss of cursor precision. + * - Rounding errors can result with odd window sizes and/or desktop scales, + * which can cause the window contents to appear slightly blurry. + * - The window may be unusably small on scaled desktops. + * - The window may jump in size when moving between displays of different + * scale factors. + * - Displays may appear to overlap when using a multi-monitor setup with + * scaling enabled. + * - Possible loss of cursor precision due to the logical size of the window + * being reduced. * - * New applications should be designed with proper DPI awareness handling instead of enabling this. + * New applications should be designed with proper DPI awareness handling + * instead of enabling this. * * The variable can be set to the following values: - * "0" - Windows will be scaled normally. - * "1" - Windows will be forced to scale to achieve 1:1 output. + * + * - "0": Windows will be scaled normally. + * - "1": Windows will be forced to scale to achieve 1:1 output. * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY "SDL_VIDEO_WAYLAND_SCALE_TO_DISPLAY" /** - * A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries. + * A variable specifying which shader compiler to preload when using the + * Chrome ANGLE binaries. * - * SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It can use two different sets of binaries, those compiled by the user from source or those provided by the Chrome browser. In the later case, these binaries require that SDL loads a DLL providing the shader compiler. + * SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It can + * use two different sets of binaries, those compiled by the user from source + * or those provided by the Chrome browser. In the later case, these binaries + * require that SDL loads a DLL providing the shader compiler. * * The variable can be set to the following values: - * "d3dcompiler_46.dll" - best for Vista or later. (default) - * "d3dcompiler_43.dll" - for XP support. - * "none" - do not load any library, useful if you compiled ANGLE from source and included the compiler in your binaries. + * + * - "d3dcompiler_46.dll" - best for Vista or later. (default) + * - "d3dcompiler_43.dll" - for XP support. + * - "none" - do not load any library, useful if you compiled ANGLE from + * source and included the compiler in your binaries. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" +#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER" /** - * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used. + * A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint + * should be used. * * The variable can be set to the following values: - * "0" - Disable _NET_WM_BYPASS_COMPOSITOR. - * "1" - Enable _NET_WM_BYPASS_COMPOSITOR. (default) + * + * - "0": Disable _NET_WM_BYPASS_COMPOSITOR. + * - "1": Enable _NET_WM_BYPASS_COMPOSITOR. (default) * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR" /** - * A variable controlling whether the X11 _NET_WM_PING protocol should be supported. + * A variable controlling whether the X11 _NET_WM_PING protocol should be + * supported. * - * By default SDL will use _NET_WM_PING, but for applications that know they will not always be able to respond to ping requests in a timely manner they can turn it off to avoid the window manager thinking the app is hung. + * By default SDL will use _NET_WM_PING, but for applications that know they + * will not always be able to respond to ping requests in a timely manner they + * can turn it off to avoid the window manager thinking the app is hung. * * The variable can be set to the following values: - * "0" - Disable _NET_WM_PING. - * "1" - Enable _NET_WM_PING. (default) + * + * - "0": Disable _NET_WM_PING. + * - "1": Enable _NET_WM_PING. (default) * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" +#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING" + +/** + * A variable controlling whether SDL uses DirectColor visuals. + * + * The variable can be set to the following values: + * + * - "0": Disable DirectColor visuals. + * - "1": Enable DirectColor visuals. (default) + * + * This hint should be set before initializing the video subsystem. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VIDEO_X11_NODIRECTCOLOR "SDL_VIDEO_X11_NODIRECTCOLOR" /** * A variable forcing the content scaling factor for X11 displays. @@ -2252,333 +3479,590 @@ extern "C" { * The variable can be set to a floating point value in the range 1.0-10.0f * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR" + +/** + * A variable forcing the visual ID used for X11 display modes. + * + * This hint should be set before initializing the video subsystem. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_X11_SCALING_FACTOR "SDL_VIDEO_X11_SCALING_FACTOR" +#define SDL_HINT_VIDEO_X11_VISUALID "SDL_VIDEO_X11_VISUALID" /** - * A variable forcing the visual ID chosen for new X11 windows + * A variable forcing the visual ID chosen for new X11 windows. * * This hint should be set before creating a window. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID" +#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID" /** * A variable controlling whether the X11 XRandR extension should be used. * * The variable can be set to the following values: - * "0" - Disable XRandR. - * "1" - Enable XRandR. (default) + * + * - "0": Disable XRandR. + * - "1": Enable XRandR. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" + +/** + * A variable controlling whether touch should be enabled on the back panel of + * the PlayStation Vita. + * + * The variable can be set to the following values: + * + * - "0": Disable touch on the back panel. + * - "1": Enable touch on the back panel. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_ENABLE_BACK_TOUCH "SDL_VITA_ENABLE_BACK_TOUCH" + +/** + * A variable controlling whether touch should be enabled on the front panel + * of the PlayStation Vita. + * + * The variable can be set to the following values: + * + * - "0": Disable touch on the front panel. + * - "1": Enable touch on the front panel. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_ENABLE_FRONT_TOUCH "SDL_VITA_ENABLE_FRONT_TOUCH" + +/** + * A variable controlling the module path on the PlayStation Vita. + * + * This hint defaults to "app0:module" + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_MODULE_PATH "SDL_VITA_MODULE_PATH" + +/** + * A variable controlling whether to perform PVR initialization on the + * PlayStation Vita. + * + * - "0": Skip PVR initialization. + * - "1": Perform the normal PVR initialization. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_PVR_INIT "SDL_VITA_PVR_INIT" + +/** + * A variable overriding the resolution reported on the PlayStation Vita. + * + * The variable can be set to the following values: + * + * - "544": 544p (default) + * - "720": 725p for PSTV + * - "1080": 1088i for PSTV * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR" +#define SDL_HINT_VITA_RESOLUTION "SDL_VITA_RESOLUTION" /** - * A variable controlling which touchpad should generate synthetic mouse events + * A variable controlling whether OpenGL should be used instead of OpenGL ES + * on the PlayStation Vita. * * The variable can be set to the following values: - * "0" - Only front touchpad should generate mouse events. (default) - * "1" - Only back touchpad should generate mouse events. - * "2" - Both touchpads should generate mouse events. + * + * - "0": Use OpenGL ES. (default) + * - "1": Use OpenGL. + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_PVR_OPENGL "SDL_VITA_PVR_OPENGL" + +/** + * A variable controlling which touchpad should generate synthetic mouse + * events. + * + * The variable can be set to the following values: + * + * - "0": Only front touchpad should generate mouse events. (default) + * - "1": Only back touchpad should generate mouse events. + * - "2": Both touchpads should generate mouse events. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_VITA_TOUCH_MOUSE_DEVICE" + +/** + * A variable overriding the display index used in SDL_Vulkan_CreateSurface() + * + * The display index starts at 0, which is the default. + * + * This hint should be set before calling SDL_Vulkan_CreateSurface() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE" +#define SDL_HINT_VULKAN_DISPLAY "SDL_VULKAN_DISPLAY" /** - * A variable controlling how the fact chunk affects the loading of a WAVE file. + * Specify the Vulkan library to load. * - * The fact chunk stores information about the number of samples of a WAVE file. The Standards Update from Microsoft notes that this value can be used to 'determine the length of the data in seconds'. This is especially useful for compressed formats (for which this is a mandatory chunk) if they produce multiple sample frames per block and truncating the block is not allowed. The fact chunk can exactly specify how many sample frames there should be in this case. + * This hint should be set before creating a Vulkan window or calling + * SDL_Vulkan_LoadLibrary(). + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_VULKAN_LIBRARY "SDL_VULKAN_LIBRARY" + +/** + * A variable controlling how the fact chunk affects the loading of a WAVE + * file. * - * Unfortunately, most application seem to ignore the fact chunk and so SDL ignores it by default as well. + * The fact chunk stores information about the number of samples of a WAVE + * file. The Standards Update from Microsoft notes that this value can be used + * to 'determine the length of the data in seconds'. This is especially useful + * for compressed formats (for which this is a mandatory chunk) if they + * produce multiple sample frames per block and truncating the block is not + * allowed. The fact chunk can exactly specify how many sample frames there + * should be in this case. + * + * Unfortunately, most application seem to ignore the fact chunk and so SDL + * ignores it by default as well. * * The variable can be set to the following values: - * "truncate" - Use the number of samples to truncate the wave data if the fact chunk is present and valid. - * "strict" - Like "truncate", but raise an error if the fact chunk is invalid, not present for non-PCM formats, or if the data chunk doesn't have that many samples. - * "ignorezero" - Like "truncate", but ignore fact chunk if the number of samples is zero. - * "ignore" - Ignore fact chunk entirely. (default) + * + * - "truncate" - Use the number of samples to truncate the wave data if the + * fact chunk is present and valid. + * - "strict" - Like "truncate", but raise an error if the fact chunk is + * invalid, not present for non-PCM formats, or if the data chunk doesn't + * have that many samples. + * - "ignorezero" - Like "truncate", but ignore fact chunk if the number of + * samples is zero. + * - "ignore" - Ignore fact chunk entirely. (default) + * + * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + * + * \since This hint is available since SDL 3.0.0. + */ +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" + +/** + * A variable controlling the maximum number of chunks in a WAVE file. + * + * This sets an upper bound on the number of chunks in a WAVE file to avoid + * wasting time on malformed or corrupt WAVE files. This defaults to "10000". * * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" +#define SDL_HINT_WAVE_CHUNK_LIMIT "SDL_WAVE_CHUNK_LIMIT" /** - * A variable controlling how the size of the RIFF chunk affects the loading of a WAVE file. + * A variable controlling how the size of the RIFF chunk affects the loading + * of a WAVE file. * - * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE file) is not always reliable. In case the size is wrong, it's possible to just ignore it and step through the chunks until a fixed limit is reached. + * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE + * file) is not always reliable. In case the size is wrong, it's possible to + * just ignore it and step through the chunks until a fixed limit is reached. * - * Note that files that have trailing data unrelated to the WAVE file or corrupt files may slow down the loading process without a reliable boundary. By default, SDL stops after 10000 chunks to prevent wasting time. Use the environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value. + * Note that files that have trailing data unrelated to the WAVE file or + * corrupt files may slow down the loading process without a reliable + * boundary. By default, SDL stops after 10000 chunks to prevent wasting time. + * Use SDL_HINT_WAVE_CHUNK_LIMIT to adjust this value. * * The variable can be set to the following values: - * "force" - Always use the RIFF chunk size as a boundary for the chunk search. - * "ignorezero" - Like "force", but a zero size searches up to 4 GiB. (default) - * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB. - * "maximum" - Search for chunks until the end of file. (not recommended) + * + * - "force" - Always use the RIFF chunk size as a boundary for the chunk + * search. + * - "ignorezero" - Like "force", but a zero size searches up to 4 GiB. + * (default) + * - "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB. + * - "maximum" - Search for chunks until the end of file. (not recommended) * * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" +#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" /** * A variable controlling how a truncated WAVE file is handled. * - * A WAVE file is considered truncated if any of the chunks are incomplete or the data chunk size is not a multiple of the block size. By default, SDL decodes until the first incomplete block, as most applications seem to do. + * A WAVE file is considered truncated if any of the chunks are incomplete or + * the data chunk size is not a multiple of the block size. By default, SDL + * decodes until the first incomplete block, as most applications seem to do. * * The variable can be set to the following values: - * "verystrict" - Raise an error if the file is truncated. - * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored. - * "dropframe" - Decode until the first incomplete sample frame. - * "dropblock" - Decode until the first incomplete block. (default) + * + * - "verystrict" - Raise an error if the file is truncated. + * - "strict" - Like "verystrict", but the size of the RIFF chunk is ignored. + * - "dropframe" - Decode until the first incomplete sample frame. + * - "dropblock" - Decode until the first incomplete block. (default) * * This hint should be set before calling SDL_LoadWAV() or SDL_LoadWAV_IO() + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" /** - * A variable controlling whether the window is activated when the SDL_RaiseWindow function is called. + * A variable controlling whether the window is activated when the + * SDL_RaiseWindow function is called. * * The variable can be set to the following values: - * "0" - The window is not activated when the SDL_RaiseWindow function is called. - * "1" - The window is activated when the SDL_RaiseWindow function is called. (default) + * + * - "0": The window is not activated when the SDL_RaiseWindow function is + * called. + * - "1": The window is activated when the SDL_RaiseWindow function is called. + * (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED "SDL_WINDOW_ACTIVATE_WHEN_RAISED" +#define SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED "SDL_WINDOW_ACTIVATE_WHEN_RAISED" /** - * A variable controlling whether the window is activated when the SDL_ShowWindow function is called. + * A variable controlling whether the window is activated when the + * SDL_ShowWindow function is called. * * The variable can be set to the following values: - * "0" - The window is not activated when the SDL_ShowWindow function is called. - * "1" - The window is activated when the SDL_ShowWindow function is called. (default) + * + * - "0": The window is not activated when the SDL_ShowWindow function is + * called. + * - "1": The window is activated when the SDL_ShowWindow function is called. + * (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN "SDL_WINDOW_ACTIVATE_WHEN_SHOWN" +#define SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN "SDL_WINDOW_ACTIVATE_WHEN_SHOWN" /** - * If set to "0" then never set the top-most flag on an SDL Window even if the application requests it. + * If set to "0" then never set the top-most flag on an SDL Window even if the + * application requests it. * - * This is a debugging aid for developers and not expected to be used by end users. + * This is a debugging aid for developers and not expected to be used by end + * users. * * The variable can be set to the following values: - * "0" - don't allow topmost - * "1" - allow topmost (default) + * + * - "0": don't allow topmost + * - "1": allow topmost (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOW_ALLOW_TOPMOST "SDL_WINDOW_ALLOW_TOPMOST" /** - * A variable controlling whether the window frame and title bar are interactive when the cursor is hidden + * A variable controlling whether the window frame and title bar are + * interactive when the cursor is hidden. * * The variable can be set to the following values: - * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc). - * "1" - The window frame is interactive when the cursor is hidden. (default) + * + * - "0": The window frame is not interactive when the cursor is hidden (no + * move, resize, etc). + * - "1": The window frame is interactive when the cursor is hidden. (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN" +#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN" /** - * A variable controlling whether SDL generates window-close events for Alt+F4 on Windows. + * A variable controlling whether SDL generates window-close events for Alt+F4 + * on Windows. * * The variable can be set to the following values: - * "0" - SDL will only do normal key handling for Alt+F4. - * "1" - SDL will generate a window-close event when it sees Alt+F4. (default) + * + * - "0": SDL will only do normal key handling for Alt+F4. + * - "1": SDL will generate a window-close event when it sees Alt+F4. + * (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_CLOSE_ON_ALT_F4 "SDL_WINDOWS_CLOSE_ON_ALT_F4" /** - * A variable controlling whether menus can be opened with their keyboard shortcut (Alt+mnemonic). + * A variable controlling whether menus can be opened with their keyboard + * shortcut (Alt+mnemonic). * - * If the mnemonics are enabled, then menus can be opened by pressing the Alt key and the corresponding mnemonic (for example, Alt+F opens the File menu). However, in case an invalid mnemonic is pressed, Windows makes an audible beep to convey that nothing happened. This is true even if the window has no menu at all! + * If the mnemonics are enabled, then menus can be opened by pressing the Alt + * key and the corresponding mnemonic (for example, Alt+F opens the File + * menu). However, in case an invalid mnemonic is pressed, Windows makes an + * audible beep to convey that nothing happened. This is true even if the + * window has no menu at all! * - * Because most SDL applications don't have menus, and some want to use the Alt key for other purposes, SDL disables mnemonics (and the beeping) by default. + * Because most SDL applications don't have menus, and some want to use the + * Alt key for other purposes, SDL disables mnemonics (and the beeping) by + * default. * - * Note: This also affects keyboard events: with mnemonics enabled, when a menu is opened from the keyboard, you will not receive a KEYUP event for the mnemonic key, and *might* not receive one for Alt. + * Note: This also affects keyboard events: with mnemonics enabled, when a + * menu is opened from the keyboard, you will not receive a KEYUP event for + * the mnemonic key, and *might* not receive one for Alt. * * The variable can be set to the following values: - * "0" - Alt+mnemonic does nothing, no beeping. (default) - * "1" - Alt+mnemonic opens menus, invalid mnemonics produce a beep. + * + * - "0": Alt+mnemonic does nothing, no beeping. (default) + * - "1": Alt+mnemonic opens menus, invalid mnemonics produce a beep. * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS "SDL_WINDOWS_ENABLE_MENU_MNEMONICS" /** - * A variable controlling whether the windows message loop is processed by SDL. + * A variable controlling whether the windows message loop is processed by + * SDL. * * The variable can be set to the following values: - * "0" - The window message loop is not run. - * "1" - The window message loop is processed in SDL_PumpEvents(). (default) + * + * - "0": The window message loop is not run. + * - "1": The window message loop is processed in SDL_PumpEvents(). (default) * * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP" /** - * A variable controlling whether raw keyboard events are used on Windows + * A variable controlling whether GameInput is used for raw keyboard and mouse + * on Windows. * * The variable can be set to the following values: - * "0" - The Windows message loop is used for keyboard events. - * "1" - Low latency raw keyboard events are used. (default) * - * This hint can be set anytime. + * - "0": GameInput is not used for raw keyboard and mouse events. + * - "1": GameInput is used for raw keyboard and mouse events, if available. + * (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD" +#define SDL_HINT_WINDOWS_GAMEINPUT "SDL_WINDOWS_GAMEINPUT" /** - * A variable controlling whether SDL uses Critical Sections for mutexes on Windows. - * - * On Windows 7 and newer, Slim Reader/Writer Locks are available. They offer better performance, allocate no kernel resources and use less memory. SDL will fall back to Critical Sections on older OS versions or if forced to by this hint. + * A variable controlling whether raw keyboard events are used on Windows. * * The variable can be set to the following values: - * "0" - Use SRW Locks when available, otherwise fall back to Critical Sections. (default) - * "1" - Force the use of Critical Sections in all cases. * - * This hint should be set before SDL is initialized. + * - "0": The Windows message loop is used for keyboard events. (default) + * - "1": Low latency raw keyboard events are used. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS" +#define SDL_HINT_WINDOWS_RAW_KEYBOARD "SDL_WINDOWS_RAW_KEYBOARD" /** * A variable controlling whether SDL uses Kernel Semaphores on Windows. * - * Kernel Semaphores are inter-process and require a context switch on every interaction. On Windows 8 and newer, the WaitOnAddress API is available. Using that and atomics to implement semaphores increases performance. SDL will fall back to Kernel Objects on older OS versions or if forced to by this hint. + * Kernel Semaphores are inter-process and require a context switch on every + * interaction. On Windows 8 and newer, the WaitOnAddress API is available. + * Using that and atomics to implement semaphores increases performance. SDL + * will fall back to Kernel Objects on older OS versions or if forced to by + * this hint. * * The variable can be set to the following values: - * "0" - Use Atomics and WaitOnAddress API when available, otherwise fall back to Kernel Objects. (default) - * "1" - Force the use of Kernel Objects in all cases. + * + * - "0": Use Atomics and WaitOnAddress API when available, otherwise fall + * back to Kernel Objects. (default) + * - "1": Force the use of Kernel Objects in all cases. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL" /** - * A variable to specify custom icon resource id from RC file on Windows platform + * A variable to specify custom icon resource id from RC file on Windows + * platform. * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON" #define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL" /** - * A variable controlling whether SDL uses the D3D9Ex API introduced in Windows Vista, instead of normal D3D9. + * A variable controlling whether SDL uses the D3D9Ex API introduced in + * Windows Vista, instead of normal D3D9. * - * Direct3D 9Ex contains changes to state management that can eliminate device loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require some changes to your application to cope with the new behavior, so this is disabled by default. + * Direct3D 9Ex contains changes to state management that can eliminate device + * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may + * require some changes to your application to cope with the new behavior, so + * this is disabled by default. * * For more information on Direct3D 9Ex, see: - * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex - * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements + * + * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex + * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements * * The variable can be set to the following values: - * "0" - Use the original Direct3D 9 API. (default) - * "1" - Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex is unavailable) + * + * - "0": Use the original Direct3D 9 API. (default) + * - "1": Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex + * is unavailable) * * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ #define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX" /** - * A variable controlling whether back-button-press events on Windows Phone to be marked as handled. - * - * Windows Phone devices typically feature a Back button. When pressed, the OS will emit back-button-press events, which apps are expected to handle in an appropriate manner. If apps do not explicitly mark these events as 'Handled', then the OS will invoke its default behavior for unhandled back-button-press events, which on Windows Phone 8 and 8.1 is to terminate the app (and attempt to switch to the previous app, or to the device's home screen). - * - * Setting the SDL_HINT_WINRT_HANDLE_BACK_BUTTON hint to "1" will cause SDL to mark back-button-press events as Handled, if and when one is sent to the app. + * A variable controlling whether SDL will clear the window contents when the + * WM_ERASEBKGND message is received. * - * Internally, Windows Phone sends back button events as parameters to special back-button-press callback functions. Apps that need to respond to back-button-press events are expected to register one or more callback functions for such, shortly after being launched (during the app's initialization phase). After the back button is pressed, the OS will invoke these callbacks. If the app's callback(s) do not explicitly mark the event as handled by the time they return, or if the app never registers one of these callback, the OS will consider the event un-handled, and it will apply its default back button behavior (terminate the app). - * - * SDL registers its own back-button-press callback with the Windows Phone OS. This callback will emit a pair of SDL key-press events (SDL_EVENT_KEY_DOWN and SDL_EVENT_KEY_UP), each with a scancode of SDL_SCANCODE_AC_BACK, after which it will check the contents of the hint, SDL_HINT_WINRT_HANDLE_BACK_BUTTON. If the hint's value is set to "1", the back button event's Handled property will get set to 'true'. If the hint's value is set to something else, or if it is unset, SDL will leave the event's Handled property alone. (By default, the OS sets this property to 'false', to note.) + * The variable can be set to the following values: * - * SDL apps can either set SDL_HINT_WINRT_HANDLE_BACK_BUTTON well before a back button is pressed, or can set it in direct-response to a back button being pressed. + * - "0"/"never": Never clear the window. + * - "1"/"initial": Clear the window when the first WM_ERASEBKGND event fires. + * (default) + * - "2"/"always": Clear the window on every WM_ERASEBKGND event. * - * In order to get notified when a back button is pressed, SDL apps should register a callback function with SDL_AddEventWatch(), and have it listen for SDL_EVENT_KEY_DOWN events that have a scancode of SDL_SCANCODE_AC_BACK. (Alternatively, SDL_EVENT_KEY_UP events can be listened-for. Listening for either event type is suitable.) Any value of SDL_HINT_WINRT_HANDLE_BACK_BUTTON set by such a callback, will be applied to the OS' current back-button-press event. + * This hint should be set before creating a window. * - * More details on back button behavior in Windows Phone apps can be found at the following page, on Microsoft's developer site: - * http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj247550(v=vs.105).aspx + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON" +#define SDL_HINT_WINDOWS_ERASE_BACKGROUND_MODE "SDL_WINDOWS_ERASE_BACKGROUND_MODE" /** - * A variable specifying the label text for a WinRT app's privacy policy link + * A variable controlling whether X11 windows are marked as override-redirect. * - * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be available via the Windows Settings charm. SDL provides code to add a link there, with its label text being set via the optional hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. + * If set, this _might_ increase framerate at the expense of the desktop not + * working as expected. Override-redirect windows aren't noticed by the window + * manager at all. * - * Please note that a privacy policy's contents are not set via this hint. A separate hint, SDL_HINT_WINRT_PRIVACY_POLICY_URL, is used to link to the actual text of the policy. + * You should probably only use this for fullscreen windows, and you probably + * shouldn't even use it for that. But it's here if you want to try! * - * The contents of this hint should be encoded as a UTF8 string. + * The variable can be set to the following values: * - * The default value is "Privacy Policy". + * - "0": Do not mark the window as override-redirect. (default) + * - "1": Mark the window as override-redirect. * - * For additional information on linking to a privacy policy, see the documentation for SDL_HINT_WINRT_PRIVACY_POLICY_URL. + * This hint should be set before creating a window. * - * This hint should be set before SDL is initialized. + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL" +#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" /** - * A variable specifying the URL to a WinRT app's privacy policy - * - * All network-enabled WinRT apps must make a privacy policy available to its users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be be available in the Windows Settings charm, as accessed from within the app. SDL provides code to add a URL-based link there, which can point to the app's privacy policy. - * - * To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL before calling any SDL_Init() functions. The contents of the hint should be a valid URL. For example, "http://www.example.com". + * A variable specifying the type of an X11 window. * - * The default value is "", which will prevent SDL from adding a privacy policy link to the Settings charm. This hint should only be set during app init. + * During SDL_CreateWindow, SDL uses the _NET_WM_WINDOW_TYPE X11 property to + * report to the window manager the type of window it wants to create. This + * might be set to various things if SDL_WINDOW_TOOLTIP or + * SDL_WINDOW_POPUP_MENU, etc, were specified. For "normal" windows that + * haven't set a specific type, this hint can be used to specify a custom + * type. For example, a dock window might set this to + * "_NET_WM_WINDOW_TYPE_DOCK". * - * The label text of an app's "Privacy Policy" link may be customized via another hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL. + * This hint should be set before creating a window. * - * Please note that on Windows Phone, Microsoft does not provide standard UI for displaying a privacy policy link, and as such, SDL_HINT_WINRT_PRIVACY_POLICY_URL will not get used on that platform. Network-enabled phone apps should display their privacy policy through some other, in-app means. + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL" +#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE" /** - * A variable controlling whether X11 windows are marked as override-redirect. + * Specify the XCB library to load for the X11 driver. * - * If set, this _might_ increase framerate at the expense of the desktop not working as expected. Override-redirect windows aren't noticed by the window manager at all. + * The default is platform-specific, often "libX11-xcb.so.1". * - * You should probably only use this for fullscreen windows, and you probably shouldn't even use it for that. But it's here if you want to try! + * This hint should be set before initializing the video subsystem. * - * The variable can be set to the following values: - * "0" - Do not mark the window as override-redirect. (default) - * "1" - Mark the window as override-redirect. - * - * This hint should be set before creating a window. + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" +#define SDL_HINT_X11_XCB_LIBRARY "SDL_X11_XCB_LIBRARY" /** - * A variable specifying the type of an X11 window. + * A variable controlling whether XInput should be used for controller + * handling. * - * During SDL_CreateWindow, SDL uses the _NET_WM_WINDOW_TYPE X11 property to report to the window manager the type of window it wants to create. This might be set to various things if SDL_WINDOW_TOOLTIP or SDL_WINDOW_POPUP_MENU, etc, were specified. For "normal" windows that haven't set a specific type, this hint can be used to specify a custom type. For example, a dock window might set this to "_NET_WM_WINDOW_TYPE_DOCK". + * The variable can be set to the following values: * - * This hint should be set before creating a window. + * - "0": XInput is not enabled. + * - "1": XInput is enabled. (default) + * + * This hint should be set before SDL is initialized. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE" +#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" /** - * A variable controlling whether XInput should be used for controller handling. + * A variable controlling response to SDL_assert failures. * - * The variable can be set to the following values: - * "0" - XInput is not enabled. - * "1" - XInput is enabled. (default) + * The variable can be set to the following case-sensitive values: * - * This hint should be set before SDL is initialized. + * - "abort": Program terminates immediately. + * - "break": Program triggers a debugger breakpoint. + * - "retry": Program reruns the SDL_assert's test again. + * - "ignore": Program continues on, ignoring this assertion failure this + * time. + * - "always_ignore": Program continues on, ignoring this assertion failure + * for the rest of the run. + * + * Note that SDL_SetAssertionHandler offers a programmatic means to deal with + * assertion failures through a callback, and this hint is largely intended to + * be used via environment variables by end users and automated tools. + * + * This hint should be set before an assertion failure is triggered and can be + * changed at any time. + * + * \since This hint is available since SDL 3.0.0. */ -#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" +#define SDL_HINT_ASSERT "SDL_ASSERT" + /** - * An enumeration of hint priorities + * An enumeration of hint priorities. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_HintPriority { SDL_HINT_DEFAULT, SDL_HINT_NORMAL, SDL_HINT_OVERRIDE } SDL_HintPriority; - /** * Set a hint with a specific priority. * @@ -2586,10 +4070,13 @@ typedef enum * value. Hints will replace existing hints of their priority and lower. * Environment variables are considered to have override priority. * - * \param name the hint to set - * \param value the value of the hint variable - * \param priority the SDL_HintPriority level for the hint - * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * \param name the hint to set. + * \param value the value of the hint variable. + * \param priority the SDL_HintPriority level for the hint. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -2597,9 +4084,7 @@ typedef enum * \sa SDL_ResetHint * \sa SDL_SetHint */ -extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, - const char *value, - SDL_HintPriority priority); +extern SDL_DECLSPEC bool SDLCALL SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority); /** * Set a hint with normal priority. @@ -2608,9 +4093,12 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, * variable that takes precedence. You can use SDL_SetHintWithPriority() to * set the hint with override priority instead. * - * \param name the hint to set - * \param value the value of the hint variable - * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * \param name the hint to set. + * \param value the value of the hint variable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -2618,8 +4106,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name, * \sa SDL_ResetHint * \sa SDL_SetHintWithPriority */ -extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, - const char *value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetHint(const char *name, const char *value); /** * Reset a hint to the default value. @@ -2628,15 +4115,18 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name, * the environment isn't set. Callbacks will be called normally with this * change. * - * \param name the hint to set - * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise. + * \param name the hint to set. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetHint * \sa SDL_ResetHints */ -extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name); +extern SDL_DECLSPEC bool SDLCALL SDL_ResetHint(const char *name); /** * Reset all hints to the default values. @@ -2645,83 +4135,110 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name); * variable, or NULL if the environment isn't set. Callbacks will be called * normally with this change. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_ResetHint */ -extern DECLSPEC void SDLCALL SDL_ResetHints(void); +extern SDL_DECLSPEC void SDLCALL SDL_ResetHints(void); /** * Get the value of a hint. * - * \param name the hint to query + * \param name the hint to query. * \returns the string value of a hint or NULL if the hint isn't set. * + * \threadsafety It is safe to call this function from any thread, however the + * return value only remains valid until the hint is changed; if + * another thread might do so, the app should supply locks + * and/or make a copy of the string. Note that using a hint + * callback instead is always thread-safe, as SDL holds a lock + * on the thread subsystem during the callback. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetHint * \sa SDL_SetHintWithPriority */ -extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name); +extern SDL_DECLSPEC const char *SDLCALL SDL_GetHint(const char *name); /** * Get the boolean value of a hint variable. * - * \param name the name of the hint to get the boolean value from - * \param default_value the value to return if the hint does not exist + * \param name the name of the hint to get the boolean value from. + * \param default_value the value to return if the hint does not exist. * \returns the boolean value of a hint or the provided default value if the * hint does not exist. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetHint * \sa SDL_SetHint */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value); +extern SDL_DECLSPEC bool SDLCALL SDL_GetHintBoolean(const char *name, bool default_value); /** - * Type definition of the hint callback function. + * A callback used to send notifications of hint value changes. + * + * This is called an initial time during SDL_AddHintCallback with the hint's + * current value, and then again each time the hint's value changes. + * + * \param userdata what was passed as `userdata` to SDL_AddHintCallback(). + * \param name what was passed as `name` to SDL_AddHintCallback(). + * \param oldValue the previous hint value. + * \param newValue the new value hint is to be set to. * - * \param userdata what was passed as `userdata` to SDL_AddHintCallback() - * \param name what was passed as `name` to SDL_AddHintCallback() - * \param oldValue the previous hint value - * \param newValue the new value hint is to be set to + * \threadsafety This callback is fired from whatever thread is setting a new + * hint value. SDL holds a lock on the hint subsystem when + * calling this callback. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_AddHintCallback */ -typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue); +typedef void(SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue); /** * Add a function to watch a particular hint. * - * \param name the hint to watch + * The callback function is called _during_ this function, to provide it an + * initial value, and again each time the hint's value changes. + * + * \param name the hint to watch. * \param callback An SDL_HintCallback function that will be called when the - * hint value changes - * \param userdata a pointer to pass to the callback function - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * hint value changes. + * \param userdata a pointer to pass to the callback function. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_DelHintCallback + * \sa SDL_RemoveHintCallback */ -extern DECLSPEC int SDLCALL SDL_AddHintCallback(const char *name, - SDL_HintCallback callback, - void *userdata); +extern SDL_DECLSPEC bool SDLCALL SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata); /** * Remove a function watching a particular hint. * - * \param name the hint being watched - * \param callback An SDL_HintCallback function that will be called when the - * hint value changes - * \param userdata a pointer being passed to the callback function + * \param name the hint being watched. + * \param callback an SDL_HintCallback function that will be called when the + * hint value changes. + * \param userdata a pointer being passed to the callback function. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_AddHintCallback */ -extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name, - SDL_HintCallback callback, - void *userdata); +extern SDL_DECLSPEC void SDLCALL SDL_RemoveHintCallback(const char *name, + SDL_HintCallback callback, + void *userdata); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_init.h b/libs/SDL3/include/SDL3/SDL_init.h index cb2de9997..645dad51f 100644 --- a/libs/SDL3/include/SDL3/SDL_init.h +++ b/libs/SDL3/include/SDL3/SDL_init.h @@ -20,15 +20,38 @@ */ /** - * \file SDL_init.h + * # CategoryInit * - * Init and quit header for the SDL library + * All SDL programs need to initialize the library before starting to work + * with it. + * + * Almost everything can simply call SDL_Init() near startup, with a handful + * of flags to specify subsystems to touch. These are here to make sure SDL + * does not even attempt to touch low-level pieces of the operating system + * that you don't intend to use. For example, you might be using SDL for video + * and input but chose an external library for audio, and in this case you + * would just need to leave off the `SDL_INIT_AUDIO` flag to make sure that + * external library has complete control. + * + * Most apps, when terminating, should call SDL_Quit(). This will clean up + * (nearly) everything that SDL might have allocated, and crucially, it'll + * make sure that the display's resolution is back to what the user expects if + * you had previously changed it for your game. + * + * SDL3 apps are strongly encouraged to call SDL_SetAppMetadata() at startup + * to fill in details about the program. This is completely optional, but it + * helps in small ways (we can provide an About dialog box for the macOS menu, + * we can name the app in the system's audio mixer, etc). Those that want to + * provide a _lot_ of information should look at the more-detailed + * SDL_SetAppMetadataProperty(). */ #ifndef SDL_init_h_ #define SDL_init_h_ #include +#include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -39,10 +62,12 @@ extern "C" { /* As of version 0.5, SDL is loaded dynamically into the application */ /** - * Initialization flags for SDL_Init and/or SDL_InitSubSystem + * Initialization flags for SDL_Init and/or SDL_InitSubSystem + * + * These are the flags which may be passed to SDL_Init(). You should specify + * the subsystems which you will be using in your application. * - * These are the flags which may be passed to SDL_Init(). You should - * specify the subsystems which you will be using in your application. + * \since This datatype is available since SDL 3.0.0. * * \sa SDL_Init * \sa SDL_Quit @@ -50,18 +75,48 @@ extern "C" { * \sa SDL_QuitSubSystem * \sa SDL_WasInit */ -typedef enum +typedef Uint32 SDL_InitFlags; + +#define SDL_INIT_AUDIO 0x00000010u /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */ +#define SDL_INIT_VIDEO 0x00000020u /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS` */ +#define SDL_INIT_JOYSTICK 0x00000200u /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS`, should be initialized on the same thread as SDL_INIT_VIDEO on Windows if you don't set SDL_HINT_JOYSTICK_THREAD */ +#define SDL_INIT_HAPTIC 0x00001000u +#define SDL_INIT_GAMEPAD 0x00002000u /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ +#define SDL_INIT_EVENTS 0x00004000u +#define SDL_INIT_SENSOR 0x00008000u /**< `SDL_INIT_SENSOR` implies `SDL_INIT_EVENTS` */ +#define SDL_INIT_CAMERA 0x00010000u /**< `SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS` */ + +/** + * Return values for optional main callbacks. + * + * Returning SDL_APP_SUCCESS or SDL_APP_FAILURE from SDL_AppInit, + * SDL_AppEvent, or SDL_AppIterate will terminate the program and report + * success/failure to the operating system. What that means is + * platform-dependent. On Unix, for example, on success, the process error + * code will be zero, and on failure it will be 1. This interface doesn't + * allow you to return specific exit codes, just whether there was an error + * generally or not. + * + * Returning SDL_APP_CONTINUE from these functions will let the app continue + * to run. + * + * See + * [Main callbacks in SDL3](https://wiki.libsdl.org/SDL3/README/main-functions#main-callbacks-in-sdl3) + * for complete details. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_AppResult { - SDL_INIT_TIMER = 0x00000001, - SDL_INIT_AUDIO = 0x00000010, /**< `SDL_INIT_AUDIO` implies `SDL_INIT_EVENTS` */ - SDL_INIT_VIDEO = 0x00000020, /**< `SDL_INIT_VIDEO` implies `SDL_INIT_EVENTS` */ - SDL_INIT_JOYSTICK = 0x00000200, /**< `SDL_INIT_JOYSTICK` implies `SDL_INIT_EVENTS` */ - SDL_INIT_HAPTIC = 0x00001000, - SDL_INIT_GAMEPAD = 0x00002000, /**< `SDL_INIT_GAMEPAD` implies `SDL_INIT_JOYSTICK` */ - SDL_INIT_EVENTS = 0x00004000, - SDL_INIT_SENSOR = 0x00008000, /**< `SDL_INIT_SENSOR` implies `SDL_INIT_EVENTS` */ - SDL_INIT_CAMERA = 0x00010000 /**< `SDL_INIT_CAMERA` implies `SDL_INIT_EVENTS` */ -} SDL_InitFlags; + SDL_APP_CONTINUE, /**< Value that requests that the app continue from the main callbacks. */ + SDL_APP_SUCCESS, /**< Value that requests termination with success from the main callbacks. */ + SDL_APP_FAILURE /**< Value that requests termination with error from the main callbacks. */ +} SDL_AppResult; + +typedef SDL_AppResult (SDLCALL *SDL_AppInit_func)(void **appstate, int argc, char *argv[]); +typedef SDL_AppResult (SDLCALL *SDL_AppIterate_func)(void *appstate); +typedef SDL_AppResult (SDLCALL *SDL_AppEvent_func)(void *appstate, SDL_Event *event); +typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate, SDL_AppResult result); /** * Initialize the SDL library. @@ -81,8 +136,8 @@ typedef enum * * `flags` may be any of the following OR'd together: * - * - `SDL_INIT_TIMER`: timer subsystem - * - `SDL_INIT_AUDIO`: audio subsystem + * - `SDL_INIT_AUDIO`: audio subsystem; automatically initializes the events + * subsystem * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events * subsystem * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the @@ -91,25 +146,34 @@ typedef enum * - `SDL_INIT_GAMEPAD`: gamepad subsystem; automatically initializes the * joystick subsystem * - `SDL_INIT_EVENTS`: events subsystem - * - `SDL_INIT_SENSOR`: sensor subsystem + * - `SDL_INIT_SENSOR`: sensor subsystem; automatically initializes the events + * subsystem + * - `SDL_INIT_CAMERA`: camera subsystem; automatically initializes the events + * subsystem * * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem() * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or * call SDL_Quit() to force shutdown). If a subsystem is already loaded then * this call will increase the ref-count and return. * - * \param flags subsystem initialization flags - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * Consider reporting some basic metadata about your application before + * calling SDL_Init, using either SDL_SetAppMetadata() or + * SDL_SetAppMetadataProperty(). + * + * \param flags subsystem initialization flags. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_SetAppMetadata + * \sa SDL_SetAppMetadataProperty * \sa SDL_InitSubSystem * \sa SDL_Quit * \sa SDL_SetMainReady * \sa SDL_WasInit */ -extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags); +extern SDL_DECLSPEC bool SDLCALL SDL_Init(SDL_InitFlags flags); /** * Compatibility function to initialize the SDL library. @@ -117,8 +181,8 @@ extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags); * This function and SDL_Init() are interchangeable. * * \param flags any of the flags used by SDL_Init(); see SDL_Init for details. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -126,7 +190,7 @@ extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags); * \sa SDL_Quit * \sa SDL_QuitSubSystem */ -extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags); +extern SDL_DECLSPEC bool SDLCALL SDL_InitSubSystem(SDL_InitFlags flags); /** * Shut down specific SDL subsystems. @@ -141,7 +205,7 @@ extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags); * \sa SDL_InitSubSystem * \sa SDL_Quit */ -extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags); +extern SDL_DECLSPEC void SDLCALL SDL_QuitSubSystem(SDL_InitFlags flags); /** * Get a mask of the specified subsystems which are currently initialized. @@ -155,7 +219,7 @@ extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags); * \sa SDL_Init * \sa SDL_InitSubSystem */ -extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags); +extern SDL_DECLSPEC SDL_InitFlags SDLCALL SDL_WasInit(SDL_InitFlags flags); /** * Clean up all initialized subsystems. @@ -173,7 +237,139 @@ extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags); * \sa SDL_Init * \sa SDL_QuitSubSystem */ -extern DECLSPEC void SDLCALL SDL_Quit(void); +extern SDL_DECLSPEC void SDLCALL SDL_Quit(void); + +/** + * Specify basic metadata about your app. + * + * You can optionally provide metadata about your app to SDL. This is not + * required, but strongly encouraged. + * + * There are several locations where SDL can make use of metadata (an "About" + * box in the macOS menu bar, the name of the app can be shown on some audio + * mixers, etc). Any piece of metadata can be left as NULL, if a specific + * detail doesn't make sense for the app. + * + * This function should be called as early as possible, before SDL_Init. + * Multiple calls to this function are allowed, but various state might not + * change once it has been set up with a previous call to this function. + * + * Passing a NULL removes any previous metadata. + * + * This is a simplified interface for the most important information. You can + * supply significantly more detailed metadata with + * SDL_SetAppMetadataProperty(). + * + * \param appname The name of the application ("My Game 2: Bad Guy's + * Revenge!"). + * \param appversion The version of the application ("1.0.0beta5" or a git + * hash, or whatever makes sense). + * \param appidentifier A unique string in reverse-domain format that + * identifies this app ("com.example.mygame2"). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetAppMetadataProperty + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetAppMetadata(const char *appname, const char *appversion, const char *appidentifier); + +/** + * Specify metadata about your app through a set of properties. + * + * You can optionally provide metadata about your app to SDL. This is not + * required, but strongly encouraged. + * + * There are several locations where SDL can make use of metadata (an "About" + * box in the macOS menu bar, the name of the app can be shown on some audio + * mixers, etc). Any piece of metadata can be left out, if a specific detail + * doesn't make sense for the app. + * + * This function should be called as early as possible, before SDL_Init. + * Multiple calls to this function are allowed, but various state might not + * change once it has been set up with a previous call to this function. + * + * Once set, this metadata can be read using SDL_GetMetadataProperty(). + * + * These are the supported properties: + * + * - `SDL_PROP_APP_METADATA_NAME_STRING`: The human-readable name of the + * application, like "My Game 2: Bad Guy's Revenge!". This will show up + * anywhere the OS shows the name of the application separately from window + * titles, such as volume control applets, etc. This defaults to "SDL + * Application". + * - `SDL_PROP_APP_METADATA_VERSION_STRING`: The version of the app that is + * running; there are no rules on format, so "1.0.3beta2" and "April 22nd, + * 2024" and a git hash are all valid options. This has no default. + * - `SDL_PROP_APP_METADATA_IDENTIFIER_STRING`: A unique string that + * identifies this app. This must be in reverse-domain format, like + * "com.example.mygame2". This string is used by desktop compositors to + * identify and group windows together, as well as match applications with + * associated desktop settings and icons. If you plan to package your + * application in a container such as Flatpak, the app ID should match the + * name of your Flatpak container as well. This has no default. + * - `SDL_PROP_APP_METADATA_CREATOR_STRING`: The human-readable name of the + * creator/developer/maker of this app, like "MojoWorkshop, LLC" + * - `SDL_PROP_APP_METADATA_COPYRIGHT_STRING`: The human-readable copyright + * notice, like "Copyright (c) 2024 MojoWorkshop, LLC" or whatnot. Keep this + * to one line, don't paste a copy of a whole software license in here. This + * has no default. + * - `SDL_PROP_APP_METADATA_URL_STRING`: A URL to the app on the web. Maybe a + * product page, or a storefront, or even a GitHub repository, for user's + * further information This has no default. + * - `SDL_PROP_APP_METADATA_TYPE_STRING`: The type of application this is. + * Currently this string can be "game" for a video game, "mediaplayer" for a + * media player, or generically "application" if nothing else applies. + * Future versions of SDL might add new types. This defaults to + * "application". + * + * \param name the name of the metadata property to set. + * \param value the value of the property, or NULL to remove that property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetAppMetadataProperty + * \sa SDL_SetAppMetadata + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetAppMetadataProperty(const char *name, const char *value); + +#define SDL_PROP_APP_METADATA_NAME_STRING "SDL.app.metadata.name" +#define SDL_PROP_APP_METADATA_VERSION_STRING "SDL.app.metadata.version" +#define SDL_PROP_APP_METADATA_IDENTIFIER_STRING "SDL.app.metadata.identifier" +#define SDL_PROP_APP_METADATA_CREATOR_STRING "SDL.app.metadata.creator" +#define SDL_PROP_APP_METADATA_COPYRIGHT_STRING "SDL.app.metadata.copyright" +#define SDL_PROP_APP_METADATA_URL_STRING "SDL.app.metadata.url" +#define SDL_PROP_APP_METADATA_TYPE_STRING "SDL.app.metadata.type" + +/** + * Get metadata about your app. + * + * This returns metadata previously set using SDL_SetAppMetadata() or + * SDL_SetAppMetadataProperty(). See SDL_SetAppMetadataProperty() for the list + * of available properties and their meanings. + * + * \param name the name of the metadata property to get. + * \returns the current value of the metadata property, or the default if it + * is not set, NULL for properties with no default. + * + * \threadsafety It is safe to call this function from any thread, although + * the string returned is not protected and could potentially be + * freed if you call SDL_SetAppMetadataProperty() to set that + * property from another thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetAppMetadata + * \sa SDL_SetAppMetadataProperty + */ +extern SDL_DECLSPEC const char * SDLCALL SDL_GetAppMetadataProperty(const char *name); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_intrin.h b/libs/SDL3/include/SDL3/SDL_intrin.h index f907df9ce..efba11d53 100644 --- a/libs/SDL3/include/SDL3/SDL_intrin.h +++ b/libs/SDL3/include/SDL3/SDL_intrin.h @@ -19,9 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_intrin.h - * +/* * Header file for CPU intrinsics for SDL */ @@ -138,21 +136,21 @@ _m_prefetch(void *__P) # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX__) && !defined(SDL_DISABLE_AVX) # define SDL_DISABLE_AVX /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */ # endif -# if (defined(_MSC_VER) || defined(__AVX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_AVX) +# if (defined(_MSC_VER) || defined(__AVX__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX) # define SDL_AVX_INTRINSICS 1 # include # endif # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX2__) && !defined(SDL_DISABLE_AVX2) # define SDL_DISABLE_AVX2 /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */ # endif -# if (defined(_MSC_VER) || defined(__AVX2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_AVX2) +# if (defined(_MSC_VER) || defined(__AVX2__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX2) # define SDL_AVX2_INTRINSICS 1 # include # endif # if defined(__clang__) && (defined(_MSC_VER) || defined(__SCE__)) && !defined(__AVX512F__) && !defined(SDL_DISABLE_AVX512F) # define SDL_DISABLE_AVX512F /* see https://reviews.llvm.org/D20291 and https://reviews.llvm.org/D79194 */ # endif -# if (defined(_MSC_VER) || defined(__AVX512F__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(SDL_DISABLE_AVX512F) +# if (defined(_MSC_VER) || defined(__AVX512F__) || defined(SDL_HAS_TARGET_ATTRIBS)) && !defined(_M_ARM64EC) && !defined(SDL_DISABLE_AVX512F) # define SDL_AVX512F_INTRINSICS 1 # include # endif diff --git a/libs/SDL3/include/SDL3/SDL_iostream.h b/libs/SDL3/include/SDL3/SDL_iostream.h index 52e218e69..3c4ffd5b3 100644 --- a/libs/SDL3/include/SDL3/SDL_iostream.h +++ b/libs/SDL3/include/SDL3/SDL_iostream.h @@ -19,14 +19,17 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* WIKI CATEGORY: IOStream */ + /** - * \file SDL_iostream.h + * # CategoryIOStream * - * This file provides a general interface for SDL to read and write - * data streams. It can easily be extended to files, memory, etc. + * SDL provides an abstract interface for reading and writing data streams. It + * offers implementations for files, memory, etc, and the app can provideo + * their own implementations, too. * - * SDL_IOStream is not related to the standard C++ iostream class, other - * than both are abstract interfaces to read/write data. + * SDL_IOStream is not related to the standard C++ iostream class, other than + * both are abstract interfaces to read/write data. */ #ifndef SDL_iostream_h_ @@ -42,10 +45,14 @@ extern "C" { #endif -/* SDL_IOStream status, set by a read or write operation */ +/** + * SDL_IOStream status, set by a read or write operation. + * + * \since This enum is available since SDL 3.0.0. + */ typedef enum SDL_IOStatus { - SDL_IO_STATUS_READY, /**< Everything is ready */ + SDL_IO_STATUS_READY, /**< Everything is ready (no errors and not EOF). */ SDL_IO_STATUS_ERROR, /**< Read or write I/O error */ SDL_IO_STATUS_EOF, /**< End of file */ SDL_IO_STATUS_NOT_READY, /**< Non blocking I/O, not ready */ @@ -53,8 +60,40 @@ typedef enum SDL_IOStatus SDL_IO_STATUS_WRITEONLY /**< Tried to read a write-only buffer */ } SDL_IOStatus; +/** + * Possible `whence` values for SDL_IOStream seeking. + * + * These map to the same "whence" concept that `fseek` or `lseek` use in the + * standard C runtime. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_IOWhence +{ + SDL_IO_SEEK_SET, /**< Seek from the beginning of data */ + SDL_IO_SEEK_CUR, /**< Seek relative to current read point */ + SDL_IO_SEEK_END /**< Seek relative to the end of data */ +} SDL_IOWhence; + +/** + * The function pointers that drive an SDL_IOStream. + * + * Applications can provide this struct to SDL_OpenIO() to create their own + * implementation of SDL_IOStream. This is not necessarily required, as SDL + * already offers several common types of I/O streams, via functions like + * SDL_IOFromFile() and SDL_IOFromMem(). + * + * This structure should be initialized using SDL_INIT_INTERFACE() + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_INIT_INTERFACE + */ typedef struct SDL_IOStreamInterface { + /* The version of this interface */ + Uint32 version; + /** * Return the number of bytes in this SDL_IOStream * @@ -63,16 +102,16 @@ typedef struct SDL_IOStreamInterface Sint64 (SDLCALL *size)(void *userdata); /** - * Seek to \c offset relative to \c whence, one of stdio's whence values: + * Seek to `offset` relative to `whence`, one of stdio's whence values: * SDL_IO_SEEK_SET, SDL_IO_SEEK_CUR, SDL_IO_SEEK_END * * \return the final offset in the data stream, or -1 on error. */ - Sint64 (SDLCALL *seek)(void *userdata, Sint64 offset, int whence); + Sint64 (SDLCALL *seek)(void *userdata, Sint64 offset, SDL_IOWhence whence); /** - * Read up to \c size bytes from the data stream to the area pointed - * at by \c ptr. + * Read up to `size` bytes from the data stream to the area pointed + * at by `ptr`. * * On an incomplete read, you should set `*status` to a value from the * SDL_IOStatus enum. You do not have to explicitly set this on @@ -83,7 +122,7 @@ typedef struct SDL_IOStreamInterface size_t (SDLCALL *read)(void *userdata, void *ptr, size_t size, SDL_IOStatus *status); /** - * Write exactly \c size bytes from the area pointed at by \c ptr + * Write exactly `size` bytes from the area pointed at by `ptr` * to data stream. * * On an incomplete write, you should set `*status` to a value from the @@ -94,20 +133,51 @@ typedef struct SDL_IOStreamInterface */ size_t (SDLCALL *write)(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status); + /** + * If the stream is buffering, make sure the data is written out. + * + * On failure, you should set `*status` to a value from the + * SDL_IOStatus enum. You do not have to explicitly set this on + * a successful flush. + * + * \return true if successful or false on write error when flushing data. + */ + bool (SDLCALL *flush)(void *userdata, SDL_IOStatus *status); + /** * Close and free any allocated resources. * + * This does not guarantee file writes will sync to physical media; they + * can be in the system's file cache, waiting to go to disk. + * * The SDL_IOStream is still destroyed even if this fails, so clean up anything - * even if flushing to disk returns an error. + * even if flushing buffers, etc, returns an error. * - * \return 0 if successful or -1 on write error when flushing data. + * \return true if successful or false on write error when flushing data. */ - int (SDLCALL *close)(void *userdata); + bool (SDLCALL *close)(void *userdata); + } SDL_IOStreamInterface; +/* Check the size of SDL_IOStreamInterface + * + * If this assert fails, either the compiler is padding to an unexpected size, + * or the interface has been updated and this should be updated to match and + * the code using this interface should be updated to handle the old version. + */ +SDL_COMPILE_TIME_ASSERT(SDL_IOStreamInterface_SIZE, + (sizeof(void *) == 4 && sizeof(SDL_IOStreamInterface) == 28) || + (sizeof(void *) == 8 && sizeof(SDL_IOStreamInterface) == 56)); /** - * This is the read/write operation structure -- opaque, as of SDL3! + * The read/write operation structure. + * + * This operates as an opaque handle. There are several APIs to create various + * types of I/O streams, or an app can supply an SDL_IOStreamInterface to + * SDL_OpenIO() to provide their own stream implementation behind this + * struct's abstract interface. + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_IOStream SDL_IOStream; @@ -158,8 +228,9 @@ typedef struct SDL_IOStream SDL_IOStream; * This function supports Unicode filenames, but they must be encoded in UTF-8 * format, regardless of the underlying operating system. * - * As a fallback, SDL_IOFromFile() will transparently open a matching filename - * in an Android app's `assets`. + * In Android, SDL_IOFromFile() can be used to open content:// URIs. As a + * fallback, SDL_IOFromFile() will transparently open a matching filename in + * the app's `assets`. * * Closing the SDL_IOStream will close SDL's internal file handle. * @@ -176,29 +247,33 @@ typedef struct SDL_IOStream SDL_IOStream; * than your app, trying to use this pointer will almost certainly result in * a crash! This is mostly a problem on Windows; make sure you build SDL and * your app with the same compiler and settings to avoid it. + * - `SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER`: a file descriptor that this + * SDL_IOStream is using to access the filesystem. * - `SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER`: a pointer, that can be cast * to an Android NDK `AAsset *`, that this SDL_IOStream is using to access * the filesystem. If SDL used some other method to access the filesystem, * this property will not be set. * - * \param file a UTF-8 string representing the filename to open + * \param file a UTF-8 string representing the filename to open. * \param mode an ASCII string representing the mode to be used for opening * the file. - * \returns a pointer to the SDL_IOStream structure that is created, or NULL - * on failure; call SDL_GetError() for more information. + * \returns a pointer to the SDL_IOStream structure that is created or NULL on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CloseIO + * \sa SDL_FlushIO * \sa SDL_ReadIO * \sa SDL_SeekIO * \sa SDL_TellIO * \sa SDL_WriteIO */ -extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromFile(const char *file, const char *mode); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromFile(const char *file, const char *mode); #define SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER "SDL.iostream.windows.handle" #define SDL_PROP_IOSTREAM_STDIO_FILE_POINTER "SDL.iostream.stdio.file" +#define SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER "SDL.iostream.file_descriptor" #define SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER "SDL.iostream.android.aasset" /** @@ -216,21 +291,32 @@ extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromFile(const char *file, const cha * buffer, you should use SDL_IOFromConstMem() with a read-only buffer of * memory instead. * - * \param mem a pointer to a buffer to feed an SDL_IOStream stream - * \param size the buffer size, in bytes - * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; - * call SDL_GetError() for more information. + * The following properties will be set at creation time by SDL: + * + * - `SDL_PROP_IOSTREAM_MEMORY_POINTER`: this will be the `mem` parameter that + * was passed to this function. + * - `SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER`: this will be the `size` parameter + * that was passed to this function. + * + * \param mem a pointer to a buffer to feed an SDL_IOStream stream. + * \param size the buffer size, in bytes. + * \returns a pointer to a new SDL_IOStream structure or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_IOFromConstMem * \sa SDL_CloseIO + * \sa SDL_FlushIO * \sa SDL_ReadIO * \sa SDL_SeekIO * \sa SDL_TellIO * \sa SDL_WriteIO */ -extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromMem(void *mem, size_t size); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromMem(void *mem, size_t size); + +#define SDL_PROP_IOSTREAM_MEMORY_POINTER "SDL.iostream.memory.base" +#define SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER "SDL.iostream.memory.size" /** * Use this function to prepare a read-only memory buffer for use with @@ -249,10 +335,17 @@ extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromMem(void *mem, size_t size); * If you need to write to a memory buffer, you should use SDL_IOFromMem() * with a writable buffer of memory instead. * - * \param mem a pointer to a read-only buffer to feed an SDL_IOStream stream - * \param size the buffer size, in bytes - * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; - * call SDL_GetError() for more information. + * The following properties will be set at creation time by SDL: + * + * - `SDL_PROP_IOSTREAM_MEMORY_POINTER`: this will be the `mem` parameter that + * was passed to this function. + * - `SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER`: this will be the `size` parameter + * that was passed to this function. + * + * \param mem a pointer to a read-only buffer to feed an SDL_IOStream stream. + * \param size the buffer size, in bytes. + * \returns a pointer to a new SDL_IOStream structure or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -262,22 +355,25 @@ extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromMem(void *mem, size_t size); * \sa SDL_SeekIO * \sa SDL_TellIO */ -extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromConstMem(const void *mem, size_t size); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromConstMem(const void *mem, size_t size); /** * Use this function to create an SDL_IOStream that is backed by dynamically * allocated memory. * * This supports the following properties to provide access to the memory and - * control over allocations: - `SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER`: a - * pointer to the internal memory of the stream. This can be set to NULL to - * transfer ownership of the memory to the application, which should free the - * memory with SDL_free(). If this is done, the next operation on the stream - * must be SDL_CloseIO(). - `SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER`: - * memory will be allocated in multiples of this size, defaulting to 1024. - * - * \returns a pointer to a new SDL_IOStream structure, or NULL if it fails; - * call SDL_GetError() for more information. + * control over allocations: + * + * - `SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER`: a pointer to the internal + * memory of the stream. This can be set to NULL to transfer ownership of + * the memory to the application, which should free the memory with + * SDL_free(). If this is done, the next operation on the stream must be + * SDL_CloseIO(). + * - `SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER`: memory will be allocated in + * multiples of this size, defaulting to 1024. + * + * \returns a pointer to a new SDL_IOStream structure or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -287,7 +383,7 @@ extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromConstMem(const void *mem, size_t * \sa SDL_TellIO * \sa SDL_WriteIO */ -extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromDynamicMem(void); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_IOFromDynamicMem(void); #define SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER "SDL.iostream.dynamic.memory" #define SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER "SDL.iostream.dynamic.chunksize" @@ -303,61 +399,65 @@ extern DECLSPEC SDL_IOStream *SDLCALL SDL_IOFromDynamicMem(void); * read/write a common data source, you should use the built-in * implementations in SDL, like SDL_IOFromFile() or SDL_IOFromMem(), etc. * - * You must free the returned pointer with SDL_CloseIO(). + * This function makes a copy of `iface` and the caller does not need to keep + * it around after this call. * - * \param iface The function pointers that implement this SDL_IOStream. - * \param userdata The app-controlled pointer that is passed to iface's - * functions when called. - * \returns a pointer to the allocated memory on success, or NULL on failure; + * \param iface the interface that implements this SDL_IOStream, initialized + * using SDL_INIT_INTERFACE(). + * \param userdata the pointer that will be passed to the interface functions. + * \returns a pointer to the allocated memory on success or NULL on failure; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CloseIO + * \sa SDL_INIT_INTERFACE * \sa SDL_IOFromConstMem * \sa SDL_IOFromFile * \sa SDL_IOFromMem */ -extern DECLSPEC SDL_IOStream *SDLCALL SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata); +extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata); /** * Close and free an allocated SDL_IOStream structure. * * SDL_CloseIO() closes and cleans up the SDL_IOStream stream. It releases any * resources used by the stream and frees the SDL_IOStream itself. This - * returns 0 on success, or -1 if the stream failed to flush to its output - * (e.g. to disk). - * - * Note that if this fails to flush the stream to disk, this function reports - * an error, but the SDL_IOStream is still invalid once this function returns. - * - * \param context SDL_IOStream structure to close - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * returns true on success, or false if the stream failed to flush to its + * output (e.g. to disk). + * + * Note that if this fails to flush the stream for any reason, this function + * reports an error, but the SDL_IOStream is still invalid once this function + * returns. + * + * This call flushes any buffered writes to the operating system, but there + * are no guarantees that those writes have gone to physical media; they might + * be in the OS's file cache, waiting to go to disk later. If it's absolutely + * crucial that writes go to disk immediately, so they are definitely stored + * even if the power fails before the file cache would have caught up, one + * should call SDL_FlushIO() before closing. Note that flushing takes time and + * makes the system and your app operate less efficiently, so do so sparingly. + * + * \param context SDL_IOStream structure to close. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenIO */ -extern DECLSPEC int SDLCALL SDL_CloseIO(SDL_IOStream *context); +extern SDL_DECLSPEC bool SDLCALL SDL_CloseIO(SDL_IOStream *context); /** * Get the properties associated with an SDL_IOStream. * - * \param context a pointer to an SDL_IOStream structure + * \param context a pointer to an SDL_IOStream structure. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *context); - -#define SDL_IO_SEEK_SET 0 /**< Seek from the beginning of data */ -#define SDL_IO_SEEK_CUR 1 /**< Seek relative to current read point */ -#define SDL_IO_SEEK_END 2 /**< Seek relative to the end of data */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *context); /** * Query the stream status of an SDL_IOStream. @@ -378,19 +478,19 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetIOProperties(SDL_IOStream *conte * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_IOStatus SDLCALL SDL_GetIOStatus(SDL_IOStream *context); +extern SDL_DECLSPEC SDL_IOStatus SDLCALL SDL_GetIOStatus(SDL_IOStream *context); /** * Use this function to get the size of the data stream in an SDL_IOStream. * - * \param context the SDL_IOStream to get the size of the data stream from + * \param context the SDL_IOStream to get the size of the data stream from. * \returns the size of the data stream in the SDL_IOStream on success or a * negative error code on failure; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Sint64 SDLCALL SDL_GetIOSize(SDL_IOStream *context); +extern SDL_DECLSPEC Sint64 SDLCALL SDL_GetIOSize(SDL_IOStream *context); /** * Seek within an SDL_IOStream data stream. @@ -405,19 +505,19 @@ extern DECLSPEC Sint64 SDLCALL SDL_GetIOSize(SDL_IOStream *context); * * If this stream can not seek, it will return -1. * - * \param context a pointer to an SDL_IOStream structure - * \param offset an offset in bytes, relative to **whence** location; can be - * negative + * \param context a pointer to an SDL_IOStream structure. + * \param offset an offset in bytes, relative to `whence` location; can be + * negative. * \param whence any of `SDL_IO_SEEK_SET`, `SDL_IO_SEEK_CUR`, - * `SDL_IO_SEEK_END` - * \returns the final offset in the data stream after the seek or a negative - * error code on failure; call SDL_GetError() for more information. + * `SDL_IO_SEEK_END`. + * \returns the final offset in the data stream after the seek or -1 on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_TellIO */ -extern DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence); +extern SDL_DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, SDL_IOWhence whence); /** * Determine the current read/write offset in an SDL_IOStream data stream. @@ -427,7 +527,7 @@ extern DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, * simplify application development. * * \param context an SDL_IOStream data stream object from which to get the - * current offset + * current offset. * \returns the current offset in the stream, or -1 if the information can not * be determined. * @@ -435,73 +535,70 @@ extern DECLSPEC Sint64 SDLCALL SDL_SeekIO(SDL_IOStream *context, Sint64 offset, * * \sa SDL_SeekIO */ -extern DECLSPEC Sint64 SDLCALL SDL_TellIO(SDL_IOStream *context); +extern SDL_DECLSPEC Sint64 SDLCALL SDL_TellIO(SDL_IOStream *context); /** * Read from a data source. * * This function reads up `size` bytes from the data source to the area * pointed at by `ptr`. This function may read less bytes than requested. It - * will return zero when the data stream is completely read, or -1 on error. - * For streams that support non-blocking operation, if nothing was read - * because it would require blocking, this function returns -2 to distinguish - * that this is not an error or end-of-file, and the caller can try again - * later. - * - * \param context a pointer to an SDL_IOStream structure - * \param ptr a pointer to a buffer to read data into + * will return zero when the data stream is completely read, and + * SDL_GetIOStatus() will return SDL_IO_STATUS_EOF, or on error, and + * SDL_GetIOStatus() will return SDL_IO_STATUS_ERROR. + * + * \param context a pointer to an SDL_IOStream structure. + * \param ptr a pointer to a buffer to read data into. * \param size the number of bytes to read from the data source. - * \returns the number of bytes read, or 0 on end of file or other error. + * \returns the number of bytes read, or 0 on end of file or other failure; + * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_SeekIO * \sa SDL_WriteIO + * \sa SDL_GetIOStatus */ -extern DECLSPEC size_t SDLCALL SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size); +extern SDL_DECLSPEC size_t SDLCALL SDL_ReadIO(SDL_IOStream *context, void *ptr, size_t size); /** * Write to an SDL_IOStream data stream. * * This function writes exactly `size` bytes from the area pointed at by `ptr` * to the stream. If this fails for any reason, it'll return less than `size` - * to demonstrate how far the write progressed. On success, it returns `num`. + * to demonstrate how far the write progressed. On success, it returns `size`. * * On error, this function still attempts to write as much as possible, so it - * might return a positive value less than the requested write size. If the - * function failed to write anything and there was an actual error, it will - * return -1. For streams that support non-blocking operation, if nothing was - * written because it would require blocking, this function returns -2 to - * distinguish that this is not an error and the caller can try again later. + * might return a positive value less than the requested write size. * - * It is an error to specify a negative `size`, but this parameter is signed - * so you definitely cannot overflow the return value on a successful run with - * enormous amounts of data. + * The caller can use SDL_GetIOStatus() to determine if the problem is + * recoverable, such as a non-blocking write that can simply be retried later, + * or a fatal error. * - * \param context a pointer to an SDL_IOStream structure - * \param ptr a pointer to a buffer containing data to write - * \param size the number of bytes to write - * \returns the number of bytes written, which will be less than `num` on - * error; call SDL_GetError() for more information. + * \param context a pointer to an SDL_IOStream structure. + * \param ptr a pointer to a buffer containing data to write. + * \param size the number of bytes to write. + * \returns the number of bytes written, which will be less than `size` on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_IOprintf * \sa SDL_ReadIO * \sa SDL_SeekIO + * \sa SDL_FlushIO + * \sa SDL_GetIOStatus */ -extern DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size); +extern SDL_DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void *ptr, size_t size); /** * Print to an SDL_IOStream data stream. * * This function does formatted printing to the stream. * - * \param context a pointer to an SDL_IOStream structure - * \param fmt a printf() style format string + * \param context a pointer to an SDL_IOStream structure. + * \param fmt a printf() style format string. * \param ... additional parameters matching % tokens in the `fmt` string, if - * any - * \returns the number of bytes written, or 0 on error; call SDL_GetError() + * any. + * \returns the number of bytes written or 0 on failure; call SDL_GetError() * for more information. * * \since This function is available since SDL 3.0.0. @@ -509,17 +606,17 @@ extern DECLSPEC size_t SDLCALL SDL_WriteIO(SDL_IOStream *context, const void *pt * \sa SDL_IOvprintf * \sa SDL_WriteIO */ -extern DECLSPEC size_t SDLCALL SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC size_t SDLCALL SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Print to an SDL_IOStream data stream. * * This function does formatted printing to the stream. * - * \param context a pointer to an SDL_IOStream structure - * \param fmt a printf() style format string - * \param ap a variable argument list - * \returns the number of bytes written, or 0 on error; call SDL_GetError() + * \param context a pointer to an SDL_IOStream structure. + * \param fmt a printf() style format string. + * \param ap a variable argument list. + * \returns the number of bytes written or 0 on failure; call SDL_GetError() * for more information. * * \since This function is available since SDL 3.0.0. @@ -527,7 +624,25 @@ extern DECLSPEC size_t SDLCALL SDL_IOprintf(SDL_IOStream *context, SDL_PRINTF_FO * \sa SDL_IOprintf * \sa SDL_WriteIO */ -extern DECLSPEC size_t SDLCALL SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); +extern SDL_DECLSPEC size_t SDLCALL SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); + +/** + * Flush any buffered data in the stream. + * + * This function makes sure that any buffered data is written to the stream. + * Normally this isn't necessary but if the stream is a pipe or socket it + * guarantees that any pending data is sent. + * + * \param context SDL_IOStream structure to flush. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_OpenIO + * \sa SDL_WriteIO + */ +extern SDL_DECLSPEC bool SDLCALL SDL_FlushIO(SDL_IOStream *context); /** * Load all the data from an SDL data stream. @@ -538,17 +653,19 @@ extern DECLSPEC size_t SDLCALL SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_F * * The data should be freed with SDL_free(). * - * \param src the SDL_IOStream to read all available data from - * \param datasize if not NULL, will store the number of bytes read - * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `src` before returning, - * even in the case of an error - * \returns the data, or NULL if there was an error. + * \param src the SDL_IOStream to read all available data from. + * \param datasize a pointer filled in with the number of bytes read, may be + * NULL. + * \param closeio if true, calls SDL_CloseIO() on `src` before returning, even + * in the case of an error. + * \returns the data or NULL on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadFile */ -extern DECLSPEC void *SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio); +extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, bool closeio); /** * Load all the data from a file path. @@ -559,15 +676,16 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasiz * * The data should be freed with SDL_free(). * - * \param file the path to read all available data from - * \param datasize if not NULL, will store the number of bytes read - * \returns the data, or NULL if there was an error. + * \param file the path to read all available data from. + * \param datasize if not NULL, will store the number of bytes read. + * \returns the data or NULL on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadFile_IO */ -extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); +extern SDL_DECLSPEC void * SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /** * \name Read endian functions @@ -579,14 +697,26 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /** * Use this function to read a byte from an SDL_IOStream. * - * \param src the SDL_IOStream to read from - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() - * for more information. + * \param src the SDL_IOStream to read from. + * \param value a pointer filled in with the data read. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value); + +/** + * Use this function to read a signed byte from an SDL_IOStream. + * + * \param src the SDL_IOStream to read from. + * \param value a pointer filled in with the data read. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS8(SDL_IOStream *src, Sint8 *value); /** * Use this function to read 16 bits of little-endian data from an @@ -595,14 +725,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU8(SDL_IOStream *src, Uint8 *value); * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value); /** * Use this function to read 16 bits of little-endian data from an @@ -611,14 +741,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value); /** * Use this function to read 16 bits of big-endian data from an SDL_IOStream @@ -627,14 +757,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value); /** * Use this function to read 16 bits of big-endian data from an SDL_IOStream @@ -643,14 +773,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value); /** * Use this function to read 32 bits of little-endian data from an @@ -659,14 +789,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value); /** * Use this function to read 32 bits of little-endian data from an @@ -675,14 +805,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value); /** * Use this function to read 32 bits of big-endian data from an SDL_IOStream @@ -691,14 +821,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value); /** * Use this function to read 32 bits of big-endian data from an SDL_IOStream @@ -707,14 +837,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value); /** * Use this function to read 64 bits of little-endian data from an @@ -723,14 +853,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value); /** * Use this function to read 64 bits of little-endian data from an @@ -739,14 +869,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value); /** * Use this function to read 64 bits of big-endian data from an SDL_IOStream @@ -755,14 +885,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value); /** * Use this function to read 64 bits of big-endian data from an SDL_IOStream @@ -771,14 +901,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value) * SDL byteswaps the data only if necessary, so the data returned will be in * the native byte order. * - * \param src the stream from which to read data - * \param value a pointer filled in with the data read - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param src the stream from which to read data. + * \param value a pointer filled in with the data read. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value); /* @} *//* Read endian functions */ /** @@ -791,14 +921,26 @@ extern DECLSPEC SDL_bool SDLCALL SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value) /** * Use this function to write a byte to an SDL_IOStream. * - * \param dst the SDL_IOStream to write to - * \param value the byte value to write - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the SDL_IOStream to write to. + * \param value the byte value to write. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value); + +/** + * Use this function to write a signed byte to an SDL_IOStream. + * + * \param dst the SDL_IOStream to write to. + * \param value the byte value to write. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS8(SDL_IOStream *dst, Sint8 value); /** * Use this function to write 16 bits in native format to an SDL_IOStream as @@ -808,14 +950,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU8(SDL_IOStream *dst, Uint8 value); * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value); /** * Use this function to write 16 bits in native format to an SDL_IOStream as @@ -825,14 +967,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value) * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value); /** * Use this function to write 16 bits in native format to an SDL_IOStream as @@ -841,14 +983,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value); /** * Use this function to write 16 bits in native format to an SDL_IOStream as @@ -857,14 +999,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value); /** * Use this function to write 32 bits in native format to an SDL_IOStream as @@ -874,14 +1016,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value) * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value); /** * Use this function to write 32 bits in native format to an SDL_IOStream as @@ -891,14 +1033,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value) * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value); /** * Use this function to write 32 bits in native format to an SDL_IOStream as @@ -907,14 +1049,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value); /** * Use this function to write 32 bits in native format to an SDL_IOStream as @@ -923,14 +1065,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value); /** * Use this function to write 64 bits in native format to an SDL_IOStream as @@ -940,14 +1082,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value) * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value); /** * Use this function to write 64 bits in native format to an SDL_IOStream as @@ -957,14 +1099,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value) * specifies native format, and the data written will be in little-endian * format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value); /** * Use this function to write 64 bits in native format to an SDL_IOStream as @@ -973,14 +1115,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value); /** * Use this function to write 64 bits in native format to an SDL_IOStream as @@ -989,14 +1131,14 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value) * SDL byteswaps the data only if necessary, so the application always * specifies native format, and the data written will be in big-endian format. * - * \param dst the stream to which data will be written - * \param value the data to be written, in native format - * \returns SDL_TRUE on successful write, SDL_FALSE on failure; call - * SDL_GetError() for more information. + * \param dst the stream to which data will be written. + * \param value the data to be written, in native format. + * \returns true on successful write or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value); /* @} *//* Write endian functions */ diff --git a/libs/SDL3/include/SDL3/SDL_joystick.h b/libs/SDL3/include/SDL3/SDL_joystick.h index 3840c9afc..520e6eb07 100644 --- a/libs/SDL3/include/SDL3/SDL_joystick.h +++ b/libs/SDL3/include/SDL3/SDL_joystick.h @@ -20,19 +20,34 @@ */ /** - * \file SDL_joystick.h + * # CategoryJoystick * - * Include file for SDL joystick event handling + * SDL joystick support. * - * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted - * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in. + * This is the lower-level joystick handling. If you want the simpler option, + * where what buttons does what is well-defined, you should use the gamepad + * API instead. * - * The term "player_index" is the number assigned to a player on a specific - * controller. For XInput controllers this returns the XInput user index. - * Many joysticks will not be able to supply this information. + * The term "instance_id" is the current instantiation of a joystick device in + * the system, if the joystick is removed and then re-inserted then it will + * get a new instance_id, instance_id's are monotonically increasing + * identifiers of a joystick plugged in. * - * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of - * the device (a X360 wired controller for example). This identifier is platform dependent. + * The term "player_index" is the number assigned to a player on a specific + * controller. For XInput controllers this returns the XInput user index. Many + * joysticks will not be able to supply this information. + * + * SDL_GUID is used as a stable 128-bit identifier for a joystick device that + * does not change over time. It identifies class of the device (a X360 wired + * controller for example). This identifier is platform dependent. + * + * In order to use these functions, SDL_Init() must have been called with the + * SDL_INIT_JOYSTICK flag. This causes SDL to scan the system for joysticks, + * and load appropriate drivers. + * + * If you would like to receive joystick updates while the application is in + * the background, you should set the following hint before calling + * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS */ #ifndef SDL_joystick_h_ @@ -44,6 +59,7 @@ #include #include #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -51,40 +67,49 @@ extern "C" { #endif -/** - * \file SDL_joystick.h - * - * In order to use these functions, SDL_Init() must have been called - * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system - * for joysticks, and load appropriate drivers. - * - * If you would like to receive joystick updates while the application - * is in the background, you should set the following hint before calling - * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS +#ifdef SDL_THREAD_SAFETY_ANALYSIS +/* + * This is not an exported symbol from SDL, this is only in the headers to + * help Clang's thread safety analysis tools to function. Do not attempt + * to access this symbol from your app, it will not work! */ +extern SDL_Mutex *SDL_joystick_lock; +#endif /** - * The joystick structure used to identify an SDL joystick + * The joystick structure used to identify an SDL joystick. + * + * This is opaque data. + * + * \since This struct is available since SDL 3.0.0. */ -#ifdef SDL_THREAD_SAFETY_ANALYSIS -extern SDL_Mutex *SDL_joystick_lock; -#endif -struct SDL_Joystick; typedef struct SDL_Joystick SDL_Joystick; -/* A structure that encodes the stable unique id for a joystick device */ -typedef SDL_GUID SDL_JoystickGUID; - /** - * This is a unique ID for a joystick for the time it is connected to the system, - * and is never reused for the lifetime of the application. If the joystick is - * disconnected and reconnected, it will get a new ID. + * This is a unique ID for a joystick for the time it is connected to the + * system, and is never reused for the lifetime of the application. * - * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + * If the joystick is disconnected and reconnected, it will get a new ID. + * + * The value 0 is an invalid ID. + * + * \since This datatype is available since SDL 3.0.0. */ typedef Uint32 SDL_JoystickID; -typedef enum +/** + * An enum of some common joystick types. + * + * In some cases, SDL can identify a low-level joystick as being a certain + * type of device, and will report it through SDL_GetJoystickType (or + * SDL_GetJoystickTypeForID). + * + * This is by no means a complete list of everything that can be plugged into + * a computer. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_JoystickType { SDL_JOYSTICK_TYPE_UNKNOWN, SDL_JOYSTICK_TYPE_GAMEPAD, @@ -95,30 +120,51 @@ typedef enum SDL_JOYSTICK_TYPE_GUITAR, SDL_JOYSTICK_TYPE_DRUM_KIT, SDL_JOYSTICK_TYPE_ARCADE_PAD, - SDL_JOYSTICK_TYPE_THROTTLE + SDL_JOYSTICK_TYPE_THROTTLE, + SDL_JOYSTICK_TYPE_COUNT } SDL_JoystickType; -typedef enum +/** + * Possible connection states for a joystick device. + * + * This is used by SDL_GetJoystickConnectionState to report how a device is + * connected to the system. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_JoystickConnectionState { SDL_JOYSTICK_CONNECTION_INVALID = -1, SDL_JOYSTICK_CONNECTION_UNKNOWN, SDL_JOYSTICK_CONNECTION_WIRED, - SDL_JOYSTICK_CONNECTION_WIRELESS, + SDL_JOYSTICK_CONNECTION_WIRELESS } SDL_JoystickConnectionState; +/** + * The largest value an SDL_Joystick's axis can report. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_JOYSTICK_AXIS_MIN + */ #define SDL_JOYSTICK_AXIS_MAX 32767 -#define SDL_JOYSTICK_AXIS_MIN -32768 -/* Set max recognized G-force from accelerometer - See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed +/** + * The smallest value an SDL_Joystick's axis can report. + * + * This is a negative number! + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_JOYSTICK_AXIS_MAX */ -#define SDL_IPHONE_MAX_GFORCE 5.0 +#define SDL_JOYSTICK_AXIS_MIN -32768 /* Function prototypes */ /** - * Locking for atomic access to the joystick API + * Locking for atomic access to the joystick API. * * The SDL joystick functions are thread-safe, however you can lock the * joysticks while processing to guarantee that the joystick list won't change @@ -126,47 +172,48 @@ typedef enum * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock); +extern SDL_DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock); /** - * Unlocking for atomic access to the joystick API + * Unlocking for atomic access to the joystick API. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock); /** * Return whether a joystick is currently connected. * - * \returns SDL_TRUE if a joystick is connected, SDL_FALSE otherwise. + * \returns true if a joystick is connected, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoysticks */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasJoystick(void); +extern SDL_DECLSPEC bool SDLCALL SDL_HasJoystick(void); /** * Get a list of currently connected joysticks. * - * \param count a pointer filled in with the number of joysticks returned - * \returns a 0 terminated array of joystick instance IDs which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. + * \param count a pointer filled in with the number of joysticks returned, may + * be NULL. + * \returns a 0 terminated array of joystick instance IDs or NULL on failure; + * call SDL_GetError() for more information. This should be freed + * with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HasJoystick * \sa SDL_OpenJoystick */ -extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetJoysticks(int *count); +extern SDL_DECLSPEC SDL_JoystickID * SDLCALL SDL_GetJoysticks(int *count); /** * Get the implementation dependent name of a joystick. * * This can be called before any joysticks are opened. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the name of the selected joystick. If no name can be found, this * function returns NULL; call SDL_GetError() for more information. * @@ -175,14 +222,14 @@ extern DECLSPEC SDL_JoystickID *SDLCALL SDL_GetJoysticks(int *count); * \sa SDL_GetJoystickName * \sa SDL_GetJoysticks */ -extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_JoystickID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickNameForID(SDL_JoystickID instance_id); /** * Get the implementation dependent path of a joystick. * * This can be called before any joysticks are opened. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the path of the selected joystick. If no path can be found, this * function returns NULL; call SDL_GetError() for more information. * @@ -191,38 +238,38 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstanceName(SDL_JoystickID i * \sa SDL_GetJoystickPath * \sa SDL_GetJoysticks */ -extern DECLSPEC const char *SDLCALL SDL_GetJoystickInstancePath(SDL_JoystickID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickPathForID(SDL_JoystickID instance_id); /** * Get the player index of a joystick. * * This can be called before any joysticks are opened. * - * \param instance_id the joystick instance ID - * \returns the player index of a joystick, or -1 if it's not available + * \param instance_id the joystick instance ID. + * \returns the player index of a joystick, or -1 if it's not available. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickPlayerIndex * \sa SDL_GetJoysticks */ -extern DECLSPEC int SDLCALL SDL_GetJoystickInstancePlayerIndex(SDL_JoystickID instance_id); +extern SDL_DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndexForID(SDL_JoystickID instance_id); /** * Get the implementation-dependent GUID of a joystick. * * This can be called before any joysticks are opened. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the GUID of the selected joystick. If called with an invalid * instance_id, this function returns a zero GUID. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickGUID - * \sa SDL_GetJoystickGUIDString + * \sa SDL_GUIDToString */ -extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickInstanceGUID(SDL_JoystickID instance_id); +extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetJoystickGUIDForID(SDL_JoystickID instance_id); /** * Get the USB vendor ID of a joystick, if available. @@ -230,7 +277,7 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickInstanceGUID(SDL_Joystic * This can be called before any joysticks are opened. If the vendor ID isn't * available this function returns 0. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the USB vendor ID of the selected joystick. If called with an * invalid instance_id, this function returns 0. * @@ -239,7 +286,7 @@ extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickInstanceGUID(SDL_Joystic * \sa SDL_GetJoystickVendor * \sa SDL_GetJoysticks */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID instance_id); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendorForID(SDL_JoystickID instance_id); /** * Get the USB product ID of a joystick, if available. @@ -247,7 +294,7 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID inst * This can be called before any joysticks are opened. If the product ID isn't * available this function returns 0. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the USB product ID of the selected joystick. If called with an * invalid instance_id, this function returns 0. * @@ -256,7 +303,7 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceVendor(SDL_JoystickID inst * \sa SDL_GetJoystickProduct * \sa SDL_GetJoysticks */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID instance_id); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductForID(SDL_JoystickID instance_id); /** * Get the product version of a joystick, if available. @@ -264,7 +311,7 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID ins * This can be called before any joysticks are opened. If the product version * isn't available this function returns 0. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the product version of the selected joystick. If called with an * invalid instance_id, this function returns 0. * @@ -273,14 +320,14 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProduct(SDL_JoystickID ins * \sa SDL_GetJoystickProductVersion * \sa SDL_GetJoysticks */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProductVersion(SDL_JoystickID instance_id); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersionForID(SDL_JoystickID instance_id); /** * Get the type of a joystick, if available. * * This can be called before any joysticks are opened. * - * \param instance_id the joystick instance ID + * \param instance_id the joystick instance ID. * \returns the SDL_JoystickType of the selected joystick. If called with an * invalid instance_id, this function returns * `SDL_JOYSTICK_TYPE_UNKNOWN`. @@ -290,7 +337,7 @@ extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickInstanceProductVersion(SDL_Joystic * \sa SDL_GetJoystickType * \sa SDL_GetJoysticks */ -extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickInstanceType(SDL_JoystickID instance_id); +extern SDL_DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickTypeForID(SDL_JoystickID instance_id); /** * Open a joystick for use. @@ -298,31 +345,31 @@ extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickInstanceType(SDL_Joystic * The joystick subsystem must be initialized before a joystick can be opened * for use. * - * \param instance_id the joystick instance ID - * \returns a joystick identifier or NULL if an error occurred; call - * SDL_GetError() for more information. + * \param instance_id the joystick instance ID. + * \returns a joystick identifier or NULL on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CloseJoystick */ -extern DECLSPEC SDL_Joystick *SDLCALL SDL_OpenJoystick(SDL_JoystickID instance_id); +extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_OpenJoystick(SDL_JoystickID instance_id); /** * Get the SDL_Joystick associated with an instance ID, if it has been opened. * - * \param instance_id the instance ID to get the SDL_Joystick for + * \param instance_id the instance ID to get the SDL_Joystick for. * \returns an SDL_Joystick on success or NULL on failure or if it hasn't been * opened yet; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromInstanceID(SDL_JoystickID instance_id); +extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetJoystickFromID(SDL_JoystickID instance_id); /** * Get the SDL_Joystick associated with a player index. * - * \param player_index the player index to get the SDL_Joystick for + * \param player_index the player index to get the SDL_Joystick for. * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError() * for more information. * @@ -331,108 +378,129 @@ extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromInstanceID(SDL_Joystick * \sa SDL_GetJoystickPlayerIndex * \sa SDL_SetJoystickPlayerIndex */ -extern DECLSPEC SDL_Joystick *SDLCALL SDL_GetJoystickFromPlayerIndex(int player_index); +extern SDL_DECLSPEC SDL_Joystick * SDLCALL SDL_GetJoystickFromPlayerIndex(int player_index); /** - * Attach a new virtual joystick. + * The structure that describes a virtual joystick touchpad. * - * \param type type of joystick - * \param naxes number of axes - * \param nbuttons number of buttons - * \param nhats number of hats - * \returns the joystick instance ID, or 0 if an error occurred; call - * SDL_GetError() for more information. + * \since This struct is available since SDL 3.0.0. * - * \since This function is available since SDL 3.0.0. + * \sa SDL_VirtualJoystickDesc + */ +typedef struct SDL_VirtualJoystickTouchpadDesc +{ + Uint16 nfingers; /**< the number of simultaneous fingers on this touchpad */ + Uint16 padding[3]; +} SDL_VirtualJoystickTouchpadDesc; + +/** + * The structure that describes a virtual joystick sensor. * - * \sa SDL_AttachVirtualJoystickEx - * \sa SDL_DetachVirtualJoystick + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_VirtualJoystickDesc */ -extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(SDL_JoystickType type, - int naxes, - int nbuttons, - int nhats); +typedef struct SDL_VirtualJoystickSensorDesc +{ + SDL_SensorType type; /**< the type of this sensor */ + float rate; /**< the update frequency of this sensor, may be 0.0f */ +} SDL_VirtualJoystickSensorDesc; /** - * The structure that defines an extended virtual joystick description + * The structure that describes a virtual joystick. + * + * This structure should be initialized using SDL_INIT_INTERFACE(). All + * elements of this structure are optional. * - * The caller must zero the structure and then initialize the version with `SDL_VIRTUAL_JOYSTICK_DESC_VERSION` before passing it to SDL_AttachVirtualJoystickEx() - * All other elements of this structure are optional and can be left 0. + * \since This struct is available since SDL 3.0.0. * - * \sa SDL_AttachVirtualJoystickEx + * \sa SDL_AttachVirtualJoystick + * \sa SDL_INIT_INTERFACE + * \sa SDL_VirtualJoystickSensorDesc + * \sa SDL_VirtualJoystickTouchpadDesc */ typedef struct SDL_VirtualJoystickDesc { - Uint16 version; /**< `SDL_VIRTUAL_JOYSTICK_DESC_VERSION` */ + Uint32 version; /**< the version of this interface */ Uint16 type; /**< `SDL_JoystickType` */ + Uint16 padding; /**< unused */ + Uint16 vendor_id; /**< the USB vendor ID of this joystick */ + Uint16 product_id; /**< the USB product ID of this joystick */ Uint16 naxes; /**< the number of axes on this joystick */ Uint16 nbuttons; /**< the number of buttons on this joystick */ + Uint16 nballs; /**< the number of balls on this joystick */ Uint16 nhats; /**< the number of hats on this joystick */ - Uint16 vendor_id; /**< the USB vendor ID of this joystick */ - Uint16 product_id; /**< the USB product ID of this joystick */ - Uint16 padding; /**< unused */ + Uint16 ntouchpads; /**< the number of touchpads on this joystick, requires `touchpads` to point at valid descriptions */ + Uint16 nsensors; /**< the number of sensors on this joystick, requires `sensors` to point at valid descriptions */ + Uint16 padding2[2]; /**< unused */ Uint32 button_mask; /**< A mask of which buttons are valid for this controller e.g. (1 << SDL_GAMEPAD_BUTTON_SOUTH) */ Uint32 axis_mask; /**< A mask of which axes are valid for this controller e.g. (1 << SDL_GAMEPAD_AXIS_LEFTX) */ const char *name; /**< the name of the joystick */ + const SDL_VirtualJoystickTouchpadDesc *touchpads; /**< A pointer to an array of touchpad descriptions, required if `ntouchpads` is > 0 */ + const SDL_VirtualJoystickSensorDesc *sensors; /**< A pointer to an array of sensor descriptions, required if `nsensors` is > 0 */ void *userdata; /**< User data pointer passed to callbacks */ void (SDLCALL *Update)(void *userdata); /**< Called when the joystick state should be updated */ void (SDLCALL *SetPlayerIndex)(void *userdata, int player_index); /**< Called when the player index is set */ - int (SDLCALL *Rumble)(void *userdata, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); /**< Implements SDL_RumbleJoystick() */ - int (SDLCALL *RumbleTriggers)(void *userdata, Uint16 left_rumble, Uint16 right_rumble); /**< Implements SDL_RumbleJoystickTriggers() */ - int (SDLCALL *SetLED)(void *userdata, Uint8 red, Uint8 green, Uint8 blue); /**< Implements SDL_SetJoystickLED() */ - int (SDLCALL *SendEffect)(void *userdata, const void *data, int size); /**< Implements SDL_SendJoystickEffect() */ - + bool (SDLCALL *Rumble)(void *userdata, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); /**< Implements SDL_RumbleJoystick() */ + bool (SDLCALL *RumbleTriggers)(void *userdata, Uint16 left_rumble, Uint16 right_rumble); /**< Implements SDL_RumbleJoystickTriggers() */ + bool (SDLCALL *SetLED)(void *userdata, Uint8 red, Uint8 green, Uint8 blue); /**< Implements SDL_SetJoystickLED() */ + bool (SDLCALL *SendEffect)(void *userdata, const void *data, int size); /**< Implements SDL_SendJoystickEffect() */ + bool (SDLCALL *SetSensorsEnabled)(void *userdata, bool enabled); /**< Implements SDL_SetGamepadSensorEnabled() */ + void (SDLCALL *Cleanup)(void *userdata); /**< Cleans up the userdata when the joystick is detached */ } SDL_VirtualJoystickDesc; -/** - * The current version of the SDL_VirtualJoystickDesc structure +/* Check the size of SDL_VirtualJoystickDesc + * + * If this assert fails, either the compiler is padding to an unexpected size, + * or the interface has been updated and this should be updated to match and + * the code using this interface should be updated to handle the old version. */ -#define SDL_VIRTUAL_JOYSTICK_DESC_VERSION 1 +SDL_COMPILE_TIME_ASSERT(SDL_VirtualJoystickDesc_SIZE, + (sizeof(void *) == 4 && sizeof(SDL_VirtualJoystickDesc) == 84) || + (sizeof(void *) == 8 && sizeof(SDL_VirtualJoystickDesc) == 136)); /** - * Attach a new virtual joystick with extended properties. + * Attach a new virtual joystick. * - * \param desc Joystick description - * \returns the joystick instance ID, or 0 if an error occurred; call - * SDL_GetError() for more information. + * \param desc joystick description, initialized using SDL_INIT_INTERFACE(). + * \returns the joystick instance ID, or 0 on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AttachVirtualJoystick * \sa SDL_DetachVirtualJoystick */ -extern DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystickEx(const SDL_VirtualJoystickDesc *desc); +extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_AttachVirtualJoystick(const SDL_VirtualJoystickDesc *desc); /** * Detach a virtual joystick. * * \param instance_id the joystick instance ID, previously returned from - * SDL_AttachVirtualJoystick() - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * SDL_AttachVirtualJoystick(). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_AttachVirtualJoystick - * \sa SDL_AttachVirtualJoystickEx */ -extern DECLSPEC int SDLCALL SDL_DetachVirtualJoystick(SDL_JoystickID instance_id); +extern SDL_DECLSPEC bool SDLCALL SDL_DetachVirtualJoystick(SDL_JoystickID instance_id); /** * Query whether or not a joystick is virtual. * - * \param instance_id the joystick instance ID - * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise. + * \param instance_id the joystick instance ID. + * \returns true if the joystick is virtual, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_id); +extern SDL_DECLSPEC bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_id); /** - * Set values on an opened, virtual-joystick's axis. + * Set the state of an axis on an opened virtual joystick. * * Please note that values set here will not be applied until the next call to * SDL_UpdateJoysticks, which can either be called directly, or can be called @@ -445,17 +513,17 @@ extern DECLSPEC SDL_bool SDLCALL SDL_IsJoystickVirtual(SDL_JoystickID instance_i * `SDL_JOYSTICK_AXIS_MIN`. * * \param joystick the virtual joystick on which to set state. - * \param axis the specific axis on the virtual joystick to set. + * \param axis the index of the axis on the virtual joystick to update. * \param value the new value for the specified axis. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value); /** - * Set values on an opened, virtual-joystick's button. + * Generate ball motion on an opened virtual joystick. * * Please note that values set here will not be applied until the next call to * SDL_UpdateJoysticks, which can either be called directly, or can be called @@ -464,17 +532,37 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualAxis(SDL_Joystick *joystick, i * SDL_WaitEvent. * * \param joystick the virtual joystick on which to set state. - * \param button the specific button on the virtual joystick to set. - * \param value the new value for the specified button. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param ball the index of the ball on the virtual joystick to update. + * \param xrel the relative motion on the X axis. + * \param yrel the relative motion on the Y axis. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualBall(SDL_Joystick *joystick, int ball, Sint16 xrel, Sint16 yrel); + +/** + * Set the state of a button on an opened virtual joystick. + * + * Please note that values set here will not be applied until the next call to + * SDL_UpdateJoysticks, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param button the index of the button on the virtual joystick to update. + * \param down true if the button is pressed, false otherwise. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, Uint8 value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, int button, bool down); /** - * Set values on an opened, virtual-joystick's hat. + * Set the state of a hat on an opened virtual joystick. * * Please note that values set here will not be applied until the next call to * SDL_UpdateJoysticks, which can either be called directly, or can be called @@ -483,14 +571,62 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualButton(SDL_Joystick *joystick, * SDL_WaitEvent. * * \param joystick the virtual joystick on which to set state. - * \param hat the specific hat on the virtual joystick to set. + * \param hat the index of the hat on the virtual joystick to update. * \param value the new value for the specified hat. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value); + +/** + * Set touchpad finger state on an opened virtual joystick. + * + * Please note that values set here will not be applied until the next call to + * SDL_UpdateJoysticks, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param touchpad the index of the touchpad on the virtual joystick to + * update. + * \param finger the index of the finger on the touchpad to set. + * \param down true if the finger is pressed, false if the finger is released. + * \param x the x coordinate of the finger on the touchpad, normalized 0 to 1, + * with the origin in the upper left. + * \param y the y coordinate of the finger on the touchpad, normalized 0 to 1, + * with the origin in the upper left. + * \param pressure the pressure of the finger. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickVirtualTouchpad(SDL_Joystick *joystick, int touchpad, int finger, bool down, float x, float y, float pressure); + +/** + * Send a sensor update for an opened virtual joystick. + * + * Please note that values set here will not be applied until the next call to + * SDL_UpdateJoysticks, which can either be called directly, or can be called + * indirectly through various other SDL APIs, including, but not limited to + * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout, + * SDL_WaitEvent. + * + * \param joystick the virtual joystick on which to set state. + * \param type the type of the sensor on the virtual joystick to update. + * \param sensor_timestamp a 64-bit timestamp in nanoseconds associated with + * the sensor reading. + * \param data the data associated with the sensor reading. + * \param num_values the number of values pointed to by `data`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickVirtualSensorData(SDL_Joystick *joystick, SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values); /** * Get the properties associated with a joystick. @@ -508,16 +644,13 @@ extern DECLSPEC int SDLCALL SDL_SetJoystickVirtualHat(SDL_Joystick *joystick, in * - `SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN`: true if this joystick has * simple trigger rumble * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick *joystick); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick *joystick); #define SDL_PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN "SDL.joystick.cap.mono_led" #define SDL_PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN "SDL.joystick.cap.rgb_led" @@ -528,28 +661,28 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetJoystickProperties(SDL_Joystick /** * Get the implementation dependent name of a joystick. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the name of the selected joystick. If no name can be found, this * function returns NULL; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceName + * \sa SDL_GetJoystickNameForID */ -extern DECLSPEC const char *SDLCALL SDL_GetJoystickName(SDL_Joystick *joystick); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickName(SDL_Joystick *joystick); /** * Get the implementation dependent path of a joystick. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the path of the selected joystick. If no path can be found, this * function returns NULL; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstancePath + * \sa SDL_GetJoystickPathForID */ -extern DECLSPEC const char *SDLCALL SDL_GetJoystickPath(SDL_Joystick *joystick); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickPath(SDL_Joystick *joystick); /** * Get the player index of an opened joystick. @@ -557,202 +690,167 @@ extern DECLSPEC const char *SDLCALL SDL_GetJoystickPath(SDL_Joystick *joystick); * For XInput controllers this returns the XInput user index. Many joysticks * will not be able to supply this information. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the player index, or -1 if it's not available. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetJoystickPlayerIndex */ -extern DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndex(SDL_Joystick *joystick); +extern SDL_DECLSPEC int SDLCALL SDL_GetJoystickPlayerIndex(SDL_Joystick *joystick); /** * Set the player index of an opened joystick. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() - * \param player_index Player index to assign to this joystick, or -1 to clear + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). + * \param player_index player index to assign to this joystick, or -1 to clear * the player index and turn off player LEDs. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetJoystickPlayerIndex */ -extern DECLSPEC int SDLCALL SDL_SetJoystickPlayerIndex(SDL_Joystick *joystick, int player_index); +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickPlayerIndex(SDL_Joystick *joystick, int player_index); /** * Get the implementation-dependent GUID for the joystick. * * This function requires an open joystick. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the GUID of the given joystick. If called on an invalid index, * this function returns a zero GUID; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceGUID - * \sa SDL_GetJoystickGUIDString + * \sa SDL_GetJoystickGUIDForID + * \sa SDL_GUIDToString */ -extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickGUID(SDL_Joystick *joystick); +extern SDL_DECLSPEC SDL_GUID SDLCALL SDL_GetJoystickGUID(SDL_Joystick *joystick); /** * Get the USB vendor ID of an opened joystick, if available. * * If the vendor ID isn't available this function returns 0. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the USB vendor ID of the selected joystick, or 0 if unavailable. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceVendor + * \sa SDL_GetJoystickVendorForID */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendor(SDL_Joystick *joystick); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickVendor(SDL_Joystick *joystick); /** * Get the USB product ID of an opened joystick, if available. * * If the product ID isn't available this function returns 0. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the USB product ID of the selected joystick, or 0 if unavailable. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceProduct + * \sa SDL_GetJoystickProductForID */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickProduct(SDL_Joystick *joystick); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProduct(SDL_Joystick *joystick); /** * Get the product version of an opened joystick, if available. * * If the product version isn't available this function returns 0. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the product version of the selected joystick, or 0 if unavailable. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceProductVersion + * \sa SDL_GetJoystickProductVersionForID */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersion(SDL_Joystick *joystick); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickProductVersion(SDL_Joystick *joystick); /** * Get the firmware version of an opened joystick, if available. * * If the firmware version isn't available this function returns 0. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the firmware version of the selected joystick, or 0 if * unavailable. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Uint16 SDLCALL SDL_GetJoystickFirmwareVersion(SDL_Joystick *joystick); +extern SDL_DECLSPEC Uint16 SDLCALL SDL_GetJoystickFirmwareVersion(SDL_Joystick *joystick); /** * Get the serial number of an opened joystick, if available. * * Returns the serial number of the joystick, or NULL if it is not available. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the serial number of the selected joystick, or NULL if * unavailable. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char * SDLCALL SDL_GetJoystickSerial(SDL_Joystick *joystick); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetJoystickSerial(SDL_Joystick *joystick); /** * Get the type of an opened joystick. * - * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick() + * \param joystick the SDL_Joystick obtained from SDL_OpenJoystick(). * \returns the SDL_JoystickType of the selected joystick. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickInstanceType - */ -extern DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickType(SDL_Joystick *joystick); - -/** - * Get an ASCII string representation for a given SDL_JoystickGUID. - * - * You should supply at least 33 bytes for pszGUID. - * - * \param guid the SDL_JoystickGUID you wish to convert to string - * \param pszGUID buffer in which to write the ASCII string - * \param cbGUID the size of pszGUID - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetJoystickInstanceGUID - * \sa SDL_GetJoystickGUID - * \sa SDL_GetJoystickGUIDFromString + * \sa SDL_GetJoystickTypeForID */ -extern DECLSPEC int SDLCALL SDL_GetJoystickGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID); +extern SDL_DECLSPEC SDL_JoystickType SDLCALL SDL_GetJoystickType(SDL_Joystick *joystick); /** - * Convert a GUID string into a SDL_JoystickGUID structure. - * - * Performs no error checking. If this function is given a string containing - * an invalid GUID, the function will silently succeed, but the GUID generated - * will not be useful. + * Get the device information encoded in a SDL_GUID structure. * - * \param pchGUID string containing an ASCII representation of a GUID - * \returns a SDL_JoystickGUID structure. + * \param guid the SDL_GUID you wish to get info about. + * \param vendor a pointer filled in with the device VID, or 0 if not + * available. + * \param product a pointer filled in with the device PID, or 0 if not + * available. + * \param version a pointer filled in with the device version, or 0 if not + * available. + * \param crc16 a pointer filled in with a CRC used to distinguish different + * products with the same VID/PID, or 0 if not available. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetJoystickGUIDString + * \sa SDL_GetJoystickGUIDForID */ -extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_GetJoystickGUIDFromString(const char *pchGUID); - -/** - * Get the device information encoded in a SDL_JoystickGUID structure - * - * \param guid the SDL_JoystickGUID you wish to get info about - * \param vendor A pointer filled in with the device VID, or 0 if not - * available - * \param product A pointer filled in with the device PID, or 0 if not - * available - * \param version A pointer filled in with the device version, or 0 if not - * available - * \param crc16 A pointer filled in with a CRC used to distinguish different - * products with the same VID/PID, or 0 if not available - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetJoystickInstanceGUID - */ -extern DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16); +extern SDL_DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_GUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16); /** * Get the status of a specified joystick. * - * \param joystick the joystick to query - * \returns SDL_TRUE if the joystick has been opened, SDL_FALSE if it has not; - * call SDL_GetError() for more information. + * \param joystick the joystick to query. + * \returns true if the joystick has been opened, false if it has not; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); +extern SDL_DECLSPEC bool SDLCALL SDL_JoystickConnected(SDL_Joystick *joystick); /** * Get the instance ID of an opened joystick. * - * \param joystick an SDL_Joystick structure containing joystick information + * \param joystick an SDL_Joystick structure containing joystick information. * \returns the instance ID of the specified joystick on success or 0 on * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickInstanceID(SDL_Joystick *joystick); +extern SDL_DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickID(SDL_Joystick *joystick); /** * Get the number of general axis controls on a joystick. @@ -761,10 +859,9 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickInstanceID(SDL_Joystick *j * separate buttons or a POV hat, and not axes, but all of this is up to the * device and platform. * - * \param joystick an SDL_Joystick structure containing joystick information - * \returns the number of axis controls/number of axes on success or a - * negative error code on failure; call SDL_GetError() for more - * information. + * \param joystick an SDL_Joystick structure containing joystick information. + * \returns the number of axis controls/number of axes on success or -1 on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -773,7 +870,7 @@ extern DECLSPEC SDL_JoystickID SDLCALL SDL_GetJoystickInstanceID(SDL_Joystick *j * \sa SDL_GetNumJoystickButtons * \sa SDL_GetNumJoystickHats */ -extern DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); /** * Get the number of trackballs on a joystick. @@ -783,9 +880,9 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); * * Most joysticks do not have trackballs. * - * \param joystick an SDL_Joystick structure containing joystick information - * \returns the number of trackballs on success or a negative error code on - * failure; call SDL_GetError() for more information. + * \param joystick an SDL_Joystick structure containing joystick information. + * \returns the number of trackballs on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -794,14 +891,14 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickAxes(SDL_Joystick *joystick); * \sa SDL_GetNumJoystickButtons * \sa SDL_GetNumJoystickHats */ -extern DECLSPEC int SDLCALL SDL_GetNumJoystickBalls(SDL_Joystick *joystick); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickBalls(SDL_Joystick *joystick); /** * Get the number of POV hats on a joystick. * - * \param joystick an SDL_Joystick structure containing joystick information - * \returns the number of POV hats on success or a negative error code on - * failure; call SDL_GetError() for more information. + * \param joystick an SDL_Joystick structure containing joystick information. + * \returns the number of POV hats on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -810,14 +907,14 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickBalls(SDL_Joystick *joystick); * \sa SDL_GetNumJoystickBalls * \sa SDL_GetNumJoystickButtons */ -extern DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); /** * Get the number of buttons on a joystick. * - * \param joystick an SDL_Joystick structure containing joystick information - * \returns the number of buttons on success or a negative error code on - * failure; call SDL_GetError() for more information. + * \param joystick an SDL_Joystick structure containing joystick information. + * \returns the number of buttons on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -826,7 +923,7 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickHats(SDL_Joystick *joystick); * \sa SDL_GetNumJoystickBalls * \sa SDL_GetNumJoystickHats */ -extern DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick); /** * Set the state of joystick event processing. @@ -835,14 +932,14 @@ extern DECLSPEC int SDLCALL SDL_GetNumJoystickButtons(SDL_Joystick *joystick); * yourself and check the state of the joystick when you want joystick * information. * - * \param enabled whether to process joystick events or not + * \param enabled whether to process joystick events or not. * * \since This function is available since SDL 3.0.0. * * \sa SDL_JoystickEventsEnabled * \sa SDL_UpdateJoysticks */ -extern DECLSPEC void SDLCALL SDL_SetJoystickEventsEnabled(SDL_bool enabled); +extern SDL_DECLSPEC void SDLCALL SDL_SetJoystickEventsEnabled(bool enabled); /** * Query the state of joystick event processing. @@ -851,14 +948,13 @@ extern DECLSPEC void SDLCALL SDL_SetJoystickEventsEnabled(SDL_bool enabled); * yourself and check the state of the joystick when you want joystick * information. * - * \returns SDL_TRUE if joystick events are being processed, SDL_FALSE - * otherwise. + * \returns true if joystick events are being processed, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetJoystickEventsEnabled */ -extern DECLSPEC SDL_bool SDLCALL SDL_JoystickEventsEnabled(void); +extern SDL_DECLSPEC bool SDLCALL SDL_JoystickEventsEnabled(void); /** * Update the current state of the open joysticks. @@ -868,7 +964,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_JoystickEventsEnabled(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); +extern SDL_DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); /** * Get the current state of an axis control on a joystick. @@ -883,8 +979,8 @@ extern DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); * 32767) representing the current position of the axis. It may be necessary * to impose certain tolerances on these values to account for jitter. * - * \param joystick an SDL_Joystick structure containing joystick information - * \param axis the axis to query; the axis indices start at index 0 + * \param joystick an SDL_Joystick structure containing joystick information. + * \param axis the axis to query; the axis indices start at index 0. * \returns a 16-bit signed integer representing the current position of the * axis or 0 on failure; call SDL_GetError() for more information. * @@ -892,7 +988,7 @@ extern DECLSPEC void SDLCALL SDL_UpdateJoysticks(void); * * \sa SDL_GetNumJoystickAxes */ -extern DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, int axis); +extern SDL_DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, int axis); /** * Get the initial state of an axis control on a joystick. @@ -901,14 +997,14 @@ extern DECLSPEC Sint16 SDLCALL SDL_GetJoystickAxis(SDL_Joystick *joystick, int a * * The axis indices start at index 0. * - * \param joystick an SDL_Joystick structure containing joystick information - * \param axis the axis to query; the axis indices start at index 0 - * \param state Upon return, the initial value is supplied here. - * \returns SDL_TRUE if this axis has any initial value, or SDL_FALSE if not. + * \param joystick an SDL_Joystick structure containing joystick information. + * \param axis the axis to query; the axis indices start at index 0. + * \param state upon return, the initial value is supplied here. + * \returns true if this axis has any initial value, or false if not. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state); +extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *joystick, int axis, Sint16 *state); /** * Get the ball axis change since the last poll. @@ -918,72 +1014,57 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetJoystickAxisInitialState(SDL_Joystick *j * * Most joysticks do not have trackballs. * - * \param joystick the SDL_Joystick to query - * \param ball the ball index to query; ball indices start at index 0 - * \param dx stores the difference in the x axis position since the last poll - * \param dy stores the difference in the y axis position since the last poll - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param joystick the SDL_Joystick to query. + * \param ball the ball index to query; ball indices start at index 0. + * \param dx stores the difference in the x axis position since the last poll. + * \param dy stores the difference in the y axis position since the last poll. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetNumJoystickBalls */ -extern DECLSPEC int SDLCALL SDL_GetJoystickBall(SDL_Joystick *joystick, int ball, int *dx, int *dy); - -/** - * \name Hat positions - */ -/* @{ */ -#define SDL_HAT_CENTERED 0x00 -#define SDL_HAT_UP 0x01 -#define SDL_HAT_RIGHT 0x02 -#define SDL_HAT_DOWN 0x04 -#define SDL_HAT_LEFT 0x08 -#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) -#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) -#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) -#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) -/* @} */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickBall(SDL_Joystick *joystick, int ball, int *dx, int *dy); /** * Get the current state of a POV hat on a joystick. * - * The returned value will be one of the following positions: + * The returned value will be one of the `SDL_HAT_*` values. * - * - `SDL_HAT_CENTERED` - * - `SDL_HAT_UP` - * - `SDL_HAT_RIGHT` - * - `SDL_HAT_DOWN` - * - `SDL_HAT_LEFT` - * - `SDL_HAT_RIGHTUP` - * - `SDL_HAT_RIGHTDOWN` - * - `SDL_HAT_LEFTUP` - * - `SDL_HAT_LEFTDOWN` - * - * \param joystick an SDL_Joystick structure containing joystick information - * \param hat the hat index to get the state from; indices start at index 0 + * \param joystick an SDL_Joystick structure containing joystick information. + * \param hat the hat index to get the state from; indices start at index 0. * \returns the current hat position. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetNumJoystickHats */ -extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, int hat); +extern SDL_DECLSPEC Uint8 SDLCALL SDL_GetJoystickHat(SDL_Joystick *joystick, int hat); + +#define SDL_HAT_CENTERED 0x00u +#define SDL_HAT_UP 0x01u +#define SDL_HAT_RIGHT 0x02u +#define SDL_HAT_DOWN 0x04u +#define SDL_HAT_LEFT 0x08u +#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP) +#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN) +#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP) +#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN) /** * Get the current state of a button on a joystick. * - * \param joystick an SDL_Joystick structure containing joystick information + * \param joystick an SDL_Joystick structure containing joystick information. * \param button the button index to get the state from; indices start at - * index 0 - * \returns 1 if the specified button is pressed, 0 otherwise. + * index 0. + * \returns true if the button is pressed, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetNumJoystickButtons */ -extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int button); +extern SDL_DECLSPEC bool SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int button); /** * Start a rumble effect. @@ -994,20 +1075,20 @@ extern DECLSPEC Uint8 SDLCALL SDL_GetJoystickButton(SDL_Joystick *joystick, int * This function requires you to process SDL events or call * SDL_UpdateJoysticks() to update rumble state. * - * \param joystick The joystick to vibrate - * \param low_frequency_rumble The intensity of the low frequency (left) - * rumble motor, from 0 to 0xFFFF - * \param high_frequency_rumble The intensity of the high frequency (right) - * rumble motor, from 0 to 0xFFFF - * \param duration_ms The duration of the rumble effect, in milliseconds - * \returns 0, or -1 if rumble isn't supported on this joystick + * \param joystick the joystick to vibrate. + * \param low_frequency_rumble the intensity of the low frequency (left) + * rumble motor, from 0 to 0xFFFF. + * \param high_frequency_rumble the intensity of the high frequency (right) + * rumble motor, from 0 to 0xFFFF. + * \param duration_ms the duration of the rumble effect, in milliseconds. + * \returns true, or false if rumble isn't supported on this joystick. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); +extern SDL_DECLSPEC bool SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); /** - * Start a rumble effect in the joystick's triggers + * Start a rumble effect in the joystick's triggers. * * Each call to this function cancels any previous trigger rumble effect, and * calling it with 0 intensity stops any rumbling. @@ -1020,20 +1101,20 @@ extern DECLSPEC int SDLCALL SDL_RumbleJoystick(SDL_Joystick *joystick, Uint16 lo * This function requires you to process SDL events or call * SDL_UpdateJoysticks() to update rumble state. * - * \param joystick The joystick to vibrate - * \param left_rumble The intensity of the left trigger rumble motor, from 0 - * to 0xFFFF - * \param right_rumble The intensity of the right trigger rumble motor, from 0 - * to 0xFFFF - * \param duration_ms The duration of the rumble effect, in milliseconds - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param joystick the joystick to vibrate. + * \param left_rumble the intensity of the left trigger rumble motor, from 0 + * to 0xFFFF. + * \param right_rumble the intensity of the right trigger rumble motor, from 0 + * to 0xFFFF. + * \param duration_ms the duration of the rumble effect, in milliseconds. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RumbleJoystick */ -extern DECLSPEC int SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); +extern SDL_DECLSPEC bool SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms); /** * Update a joystick's LED color. @@ -1044,52 +1125,52 @@ extern DECLSPEC int SDLCALL SDL_RumbleJoystickTriggers(SDL_Joystick *joystick, U * For joysticks with a single color LED, the maximum of the RGB values will * be used as the LED brightness. * - * \param joystick The joystick to update - * \param red The intensity of the red LED - * \param green The intensity of the green LED - * \param blue The intensity of the blue LED - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param joystick the joystick to update. + * \param red the intensity of the red LED. + * \param green the intensity of the green LED. + * \param blue the intensity of the blue LED. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetJoystickLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); +extern SDL_DECLSPEC bool SDLCALL SDL_SetJoystickLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue); /** - * Send a joystick specific effect packet + * Send a joystick specific effect packet. * - * \param joystick The joystick to affect - * \param data The data to send to the joystick - * \param size The size of the data to send to the joystick - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param joystick the joystick to affect. + * \param data the data to send to the joystick. + * \param size the size of the data to send to the joystick. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SendJoystickEffect(SDL_Joystick *joystick, const void *data, int size); +extern SDL_DECLSPEC bool SDLCALL SDL_SendJoystickEffect(SDL_Joystick *joystick, const void *data, int size); /** * Close a joystick previously opened with SDL_OpenJoystick(). * - * \param joystick The joystick device to close + * \param joystick the joystick device to close. * * \since This function is available since SDL 3.0.0. * * \sa SDL_OpenJoystick */ -extern DECLSPEC void SDLCALL SDL_CloseJoystick(SDL_Joystick *joystick); +extern SDL_DECLSPEC void SDLCALL SDL_CloseJoystick(SDL_Joystick *joystick); /** * Get the connection state of a joystick. * - * \param joystick The joystick to query + * \param joystick the joystick to query. * \returns the connection state on success or * `SDL_JOYSTICK_CONNECTION_INVALID` on failure; call SDL_GetError() * for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectionState(SDL_Joystick *joystick); +extern SDL_DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectionState(SDL_Joystick *joystick); /** * Get the battery state of a joystick. @@ -1100,7 +1181,7 @@ extern DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectionSta * not uncommon for older batteries to lose stored power much faster than it * reports, or completely drain when reporting it has 20 percent left, etc. * - * \param joystick The joystick to query + * \param joystick the joystick to query. * \param percent a pointer filled in with the percentage of battery life * left, between 0 and 100, or NULL to ignore. This will be * filled in with -1 we can't determine a value or there is no @@ -1110,7 +1191,7 @@ extern DECLSPEC SDL_JoystickConnectionState SDLCALL SDL_GetJoystickConnectionSta * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_PowerState SDLCALL SDL_GetJoystickPowerInfo(SDL_Joystick *joystick, int *percent); +extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetJoystickPowerInfo(SDL_Joystick *joystick, int *percent); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_keyboard.h b/libs/SDL3/include/SDL3/SDL_keyboard.h index fe06957c6..f6ab13bb5 100644 --- a/libs/SDL3/include/SDL3/SDL_keyboard.h +++ b/libs/SDL3/include/SDL3/SDL_keyboard.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_keyboard.h + * # CategoryKeyboard * - * Include file for SDL keyboard event handling + * SDL keyboard management. */ #ifndef SDL_keyboard_h_ @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include @@ -39,33 +42,30 @@ extern "C" { #endif -typedef Uint32 SDL_KeyboardID; - /** - * The SDL keysym structure, used in key events. + * This is a unique ID for a keyboard for the time it is connected to the + * system, and is never reused for the lifetime of the application. + * + * If the keyboard is disconnected and reconnected, it will get a new ID. + * + * The value 0 is an invalid ID. * - * \note If you are looking for translated character input, see the ::SDL_EVENT_TEXT_INPUT event. + * \since This datatype is available since SDL 3.0.0. */ -typedef struct SDL_Keysym -{ - SDL_Scancode scancode; /**< SDL physical key code - see ::SDL_Scancode for details */ - SDL_Keycode sym; /**< SDL virtual key code - see ::SDL_Keycode for details */ - Uint16 mod; /**< current key modifiers */ - Uint32 unused; -} SDL_Keysym; +typedef Uint32 SDL_KeyboardID; /* Function prototypes */ /** * Return whether a keyboard is currently connected. * - * \returns SDL_TRUE if a keyboard is connected, SDL_FALSE otherwise. + * \returns true if a keyboard is connected, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetKeyboards */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasKeyboard(void); +extern SDL_DECLSPEC bool SDLCALL SDL_HasKeyboard(void); /** * Get a list of currently connected keyboards. @@ -75,32 +75,33 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasKeyboard(void); * power buttons, etc. You should wait for input from a device before you * consider it actively in use. * - * \param count a pointer filled in with the number of keyboards returned - * \returns a 0 terminated array of keyboards instance IDs which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. + * \param count a pointer filled in with the number of keyboards returned, may + * be NULL. + * \returns a 0 terminated array of keyboards instance IDs or NULL on failure; + * call SDL_GetError() for more information. This should be freed + * with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetKeyboardInstanceName + * \sa SDL_GetKeyboardNameForID * \sa SDL_HasKeyboard */ -extern DECLSPEC SDL_KeyboardID *SDLCALL SDL_GetKeyboards(int *count); +extern SDL_DECLSPEC SDL_KeyboardID * SDLCALL SDL_GetKeyboards(int *count); /** * Get the name of a keyboard. * * This function returns "" if the keyboard doesn't have a name. * - * \param instance_id the keyboard instance ID - * \returns the name of the selected keyboard, or NULL on failure; call + * \param instance_id the keyboard instance ID. + * \returns the name of the selected keyboard or NULL on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetKeyboards */ -extern DECLSPEC const char *SDLCALL SDL_GetKeyboardInstanceName(SDL_KeyboardID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id); /** * Query the window which currently has keyboard focus. @@ -109,7 +110,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetKeyboardInstanceName(SDL_KeyboardID i * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); /** * Get a snapshot of the current state of the keyboard. @@ -118,9 +119,9 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); * valid for the whole lifetime of the application and should not be freed by * the caller. * - * A array element with a value of 1 means that the key is pressed and a value - * of 0 means that it is not. Indexes into this array are obtained by using - * SDL_Scancode values. + * A array element with a value of true means that the key is pressed and a + * value of false means that it is not. Indexes into this array are obtained + * by using SDL_Scancode values. * * Use SDL_PumpEvents() to update the state array. * @@ -132,7 +133,7 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); * Note: This function doesn't take into account whether shift has been * pressed or not. * - * \param numkeys if non-NULL, receives the length of the returned array + * \param numkeys if non-NULL, receives the length of the returned array. * \returns a pointer to an array of key states. * * \since This function is available since SDL 3.0.0. @@ -140,10 +141,10 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void); * \sa SDL_PumpEvents * \sa SDL_ResetKeyboard */ -extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys); +extern SDL_DECLSPEC const bool * SDLCALL SDL_GetKeyboardState(int *numkeys); /** - * Clear the state of the keyboard + * Clear the state of the keyboard. * * This function will generate key up events for all pressed keys. * @@ -151,7 +152,7 @@ extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys); * * \sa SDL_GetKeyboardState */ -extern DECLSPEC void SDLCALL SDL_ResetKeyboard(void); +extern SDL_DECLSPEC void SDLCALL SDL_ResetKeyboard(void); /** * Get the current key modifier state for the keyboard. @@ -164,7 +165,7 @@ extern DECLSPEC void SDLCALL SDL_ResetKeyboard(void); * \sa SDL_GetKeyboardState * \sa SDL_SetModState */ -extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void); +extern SDL_DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void); /** * Set the current key modifier state for the keyboard. @@ -177,21 +178,27 @@ extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void); * This does not change the keyboard state, only the key modifier flags that * SDL reports. * - * \param modstate the desired SDL_Keymod for the keyboard + * \param modstate the desired SDL_Keymod for the keyboard. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetModState */ -extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate); +extern SDL_DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate); /** * Get the key code corresponding to the given scancode according to the * current keyboard layout. * - * See SDL_Keycode for details. + * If you want to get the keycode as it would be delivered in key events, + * including options specified in SDL_HINT_KEYCODE_OPTIONS, then you should + * pass `key_event` as true. Otherwise this function simply translates the + * scancode based on the given modifier state. * - * \param scancode the desired SDL_Scancode to query + * \param scancode the desired SDL_Scancode to query. + * \param modstate the modifier state to use when translating the scancode to + * a keycode. + * \param key_event true if the keycode will be used in key events. * \returns the SDL_Keycode that corresponds to the given SDL_Scancode. * * \since This function is available since SDL 3.0.0. @@ -199,15 +206,18 @@ extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate); * \sa SDL_GetKeyName * \sa SDL_GetScancodeFromKey */ -extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode); +extern SDL_DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate, bool key_event); /** * Get the scancode corresponding to the given key code according to the * current keyboard layout. * - * See SDL_Scancode for details. + * Note that there may be multiple scancode+modifier states that can generate + * this keycode, this will just return the first one found. * - * \param key the desired SDL_Keycode to query + * \param key the desired SDL_Keycode to query. + * \param modstate a pointer to the modifier state that would be used when the + * scancode generates this key, may be NULL. * \returns the SDL_Scancode that corresponds to the given SDL_Keycode. * * \since This function is available since SDL 3.0.0. @@ -215,12 +225,26 @@ extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode * \sa SDL_GetKeyFromScancode * \sa SDL_GetScancodeName */ -extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key); +extern SDL_DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate); /** - * Get a human-readable name for a scancode. + * Set a human-readable name for a scancode. + * + * \param scancode the desired SDL_Scancode. + * \param name the name to use for the scancode, encoded as UTF-8. The string + * is not copied, so the pointer given to this function must stay + * valid while SDL is being used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * - * See SDL_Scancode for details. + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetScancodeName + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetScancodeName(SDL_Scancode scancode, const char *name); + +/** + * Get a human-readable name for a scancode. * * **Warning**: The returned name is by design not stable across platforms, * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left @@ -231,7 +255,7 @@ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key); * unsuitable for creating a stable cross-platform two-way mapping between * strings and scancodes. * - * \param scancode the desired SDL_Scancode to query + * \param scancode the desired SDL_Scancode to query. * \returns a pointer to the name for the scancode. If the scancode doesn't * have a name this function returns an empty string (""). * @@ -239,13 +263,14 @@ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key); * * \sa SDL_GetScancodeFromKey * \sa SDL_GetScancodeFromName + * \sa SDL_SetScancodeName */ -extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetScancodeName(SDL_Scancode scancode); /** * Get a scancode from a human-readable name. * - * \param name the human-readable scancode name + * \param name the human-readable scancode name. * \returns the SDL_Scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't * recognized; call SDL_GetError() for more information. * @@ -255,18 +280,15 @@ extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode); * \sa SDL_GetScancodeFromKey * \sa SDL_GetScancodeName */ -extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name); +extern SDL_DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name); /** * Get a human-readable name for a key. * - * See SDL_Scancode and SDL_Keycode for details. + * If the key doesn't have a name, this function returns an empty string (""). * - * \param key the desired SDL_Keycode to query - * \returns a pointer to a UTF-8 string that stays valid at least until the - * next call to this function. If you need it around any longer, you - * must copy it. If the key doesn't have a name, this function - * returns an empty string (""). + * \param key the desired SDL_Keycode to query. + * \returns a UTF-8 encoded string of the key name. * * \since This function is available since SDL 3.0.0. * @@ -274,12 +296,12 @@ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name); * \sa SDL_GetKeyFromScancode * \sa SDL_GetScancodeFromKey */ -extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetKeyName(SDL_Keycode key); /** * Get a key code from a human-readable name. * - * \param name the human-readable key name + * \param name the human-readable key name. * \returns key code, or `SDLK_UNKNOWN` if the name wasn't recognized; call * SDL_GetError() for more information. * @@ -289,108 +311,236 @@ extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key); * \sa SDL_GetKeyName * \sa SDL_GetScancodeFromName */ -extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name); +extern SDL_DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name); + +/** + * Start accepting Unicode text input events in a window. + * + * This function will enable text input (SDL_EVENT_TEXT_INPUT and + * SDL_EVENT_TEXT_EDITING events) in the specified window. Please use this + * function paired with SDL_StopTextInput(). + * + * Text input events are not received by default. + * + * On some platforms using this function shows the screen keyboard. + * + * \param window the window to enable text input. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetTextInputArea + * \sa SDL_StartTextInputWithProperties + * \sa SDL_StopTextInput + * \sa SDL_TextInputActive + */ +extern SDL_DECLSPEC bool SDLCALL SDL_StartTextInput(SDL_Window *window); + +/** + * Text input type. + * + * These are the valid values for SDL_PROP_TEXTINPUT_TYPE_NUMBER. Not every + * value is valid on every platform, but where a value isn't supported, a + * reasonable fallback will be used. + * + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_StartTextInputWithProperties + */ +typedef enum SDL_TextInputType +{ + SDL_TEXTINPUT_TYPE_TEXT, /**< The input is text */ + SDL_TEXTINPUT_TYPE_TEXT_NAME, /**< The input is a person's name */ + SDL_TEXTINPUT_TYPE_TEXT_EMAIL, /**< The input is an e-mail address */ + SDL_TEXTINPUT_TYPE_TEXT_USERNAME, /**< The input is a username */ + SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN, /**< The input is a secure password that is hidden */ + SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE, /**< The input is a secure password that is visible */ + SDL_TEXTINPUT_TYPE_NUMBER, /**< The input is a number */ + SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN, /**< The input is a secure PIN that is hidden */ + SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE /**< The input is a secure PIN that is visible */ +} SDL_TextInputType; /** - * Start accepting Unicode text input events. + * Auto capitalization type. + * + * These are the valid values for + * SDL_PROP_TEXTINPUT_AUTOCAPITALIZATION_NUMBER. Not every value is valid on + * every platform, but where a value isn't supported, a reasonable fallback + * will be used. + * + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_StartTextInputWithProperties + */ +typedef enum SDL_Capitalization +{ + SDL_CAPITALIZE_NONE, /**< No auto-capitalization will be done */ + SDL_CAPITALIZE_SENTENCES, /**< The first letter of sentences will be capitalized */ + SDL_CAPITALIZE_WORDS, /**< The first letter of words will be capitalized */ + SDL_CAPITALIZE_LETTERS /**< All letters will be capitalized */ +} SDL_Capitalization; + +/** + * Start accepting Unicode text input events in a window, with properties + * describing the input. + * + * This function will enable text input (SDL_EVENT_TEXT_INPUT and + * SDL_EVENT_TEXT_EDITING events) in the specified window. Please use this + * function paired with SDL_StopTextInput(). + * + * Text input events are not received by default. + * + * On some platforms using this function shows the screen keyboard. + * + * These are the supported properties: * - * This function will start accepting Unicode text input events in the focused - * SDL window, and start emitting SDL_TextInputEvent (SDL_EVENT_TEXT_INPUT) - * and SDL_TextEditingEvent (SDL_EVENT_TEXT_EDITING) events. Please use this - * function in pair with SDL_StopTextInput(). + * - `SDL_PROP_TEXTINPUT_TYPE_NUMBER` - an SDL_TextInputType value that + * describes text being input, defaults to SDL_TEXTINPUT_TYPE_TEXT. + * - `SDL_PROP_TEXTINPUT_CAPITALIZATION_NUMBER` - an SDL_Capitalization value + * that describes how text should be capitalized, defaults to + * SDL_CAPITALIZE_SENTENCES for normal text entry, SDL_CAPITALIZE_WORDS for + * SDL_TEXTINPUT_TYPE_TEXT_NAME, and SDL_CAPITALIZE_NONE for e-mail + * addresses, usernames, and passwords. + * - `SDL_PROP_TEXTINPUT_AUTOCORRECT_BOOLEAN` - true to enable auto completion + * and auto correction, defaults to true. + * - `SDL_PROP_TEXTINPUT_MULTILINE_BOOLEAN` - true if multiple lines of text + * are allowed. This defaults to true if SDL_HINT_RETURN_KEY_HIDES_IME is + * "0" or is not set, and defaults to false if SDL_HINT_RETURN_KEY_HIDES_IME + * is "1". * - * Text input events are received by default. + * On Android you can directly specify the input type: * - * On some platforms using this function activates the screen keyboard. + * - `SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER` - the text input type to + * use, overriding other properties. This is documented at + * https://developer.android.com/reference/android/text/InputType + * + * \param window the window to enable text input. + * \param props the properties to use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_SetTextInputRect + * \sa SDL_SetTextInputArea + * \sa SDL_StartTextInput * \sa SDL_StopTextInput + * \sa SDL_TextInputActive */ -extern DECLSPEC void SDLCALL SDL_StartTextInput(void); +extern SDL_DECLSPEC bool SDLCALL SDL_StartTextInputWithProperties(SDL_Window *window, SDL_PropertiesID props); + +#define SDL_PROP_TEXTINPUT_TYPE_NUMBER "SDL.textinput.type" +#define SDL_PROP_TEXTINPUT_CAPITALIZATION_NUMBER "SDL.textinput.capitalization" +#define SDL_PROP_TEXTINPUT_AUTOCORRECT_BOOLEAN "SDL.textinput.autocorrect" +#define SDL_PROP_TEXTINPUT_MULTILINE_BOOLEAN "SDL.textinput.multiline" +#define SDL_PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER "SDL.textinput.android.inputtype" /** - * Check whether or not Unicode text input events are enabled. + * Check whether or not Unicode text input events are enabled for a window. * - * \returns SDL_TRUE if text input events are enabled else SDL_FALSE. + * \param window the window to check. + * \returns true if text input events are enabled else false. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput */ -extern DECLSPEC SDL_bool SDLCALL SDL_TextInputActive(void); +extern SDL_DECLSPEC bool SDLCALL SDL_TextInputActive(SDL_Window *window); /** - * Stop receiving any text input events. + * Stop receiving any text input events in a window. + * + * If SDL_StartTextInput() showed the screen keyboard, this function will hide + * it. * - * Text input events are received by default. + * \param window the window to disable text input. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput */ -extern DECLSPEC void SDLCALL SDL_StopTextInput(void); +extern SDL_DECLSPEC bool SDLCALL SDL_StopTextInput(SDL_Window *window); /** * Dismiss the composition window/IME without disabling the subsystem. * + * \param window the window to affect. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput * \sa SDL_StopTextInput */ -extern DECLSPEC void SDLCALL SDL_ClearComposition(void); +extern SDL_DECLSPEC bool SDLCALL SDL_ClearComposition(SDL_Window *window); /** - * Set the rectangle used to type Unicode text inputs. + * Set the area used to type Unicode text input. * - * Native input methods will place a window with word suggestions near it, - * without covering the text being inputted. + * Native input methods may place a window with word suggestions near the + * cursor, without covering the text being entered. * - * To start text input in a given location, this function is intended to be - * called before SDL_StartTextInput, although some platforms support moving - * the rectangle even while text input (and a composition) is active. + * \param window the window for which to set the text input area. + * \param rect the SDL_Rect representing the text input area, in window + * coordinates, or NULL to clear it. + * \param cursor the offset of the current cursor location relative to + * `rect->x`, in window coordinates. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * - * Note: If you want to use the system native IME window, try setting hint - * **SDL_HINT_IME_SHOW_UI** to **1**, otherwise this function won't give you - * any feedback. + * \since This function is available since SDL 3.0.0. * - * \param rect the SDL_Rect structure representing the rectangle to receive - * text (ignored if NULL) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \sa SDL_GetTextInputArea + * \sa SDL_StartTextInput + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextInputArea(SDL_Window *window, const SDL_Rect *rect, int cursor); + +/** + * Get the area used to type Unicode text input. + * + * This returns the values previously set by SDL_SetTextInputArea(). + * + * \param window the window for which to query the text input area. + * \param rect a pointer to an SDL_Rect filled in with the text input area, + * may be NULL. + * \param cursor a pointer to the offset of the current cursor location + * relative to `rect->x`, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_StartTextInput + * \sa SDL_SetTextInputArea */ -extern DECLSPEC int SDLCALL SDL_SetTextInputRect(const SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextInputArea(SDL_Window *window, SDL_Rect *rect, int *cursor); /** * Check whether the platform has screen keyboard support. * - * \returns SDL_TRUE if the platform has some screen keyboard support or - * SDL_FALSE if not. + * \returns true if the platform has some screen keyboard support or false if + * not. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput * \sa SDL_ScreenKeyboardShown */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasScreenKeyboardSupport(void); +extern SDL_DECLSPEC bool SDLCALL SDL_HasScreenKeyboardSupport(void); /** * Check whether the screen keyboard is shown for given window. * - * \param window the window for which screen keyboard should be queried - * \returns SDL_TRUE if screen keyboard is shown or SDL_FALSE if not. + * \param window the window for which screen keyboard should be queried. + * \returns true if screen keyboard is shown or false if not. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HasScreenKeyboardSupport */ -extern DECLSPEC SDL_bool SDLCALL SDL_ScreenKeyboardShown(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_ScreenKeyboardShown(SDL_Window *window); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_keycode.h b/libs/SDL3/include/SDL3/SDL_keycode.h index e94ace90b..28e40a352 100644 --- a/libs/SDL3/include/SDL3/SDL_keycode.h +++ b/libs/SDL3/include/SDL3/SDL_keycode.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_keycode.h + * # CategoryKeycode * - * Defines constants which identify keyboard keys and modifiers. + * Defines constants which identify keyboard keys and modifiers. */ #ifndef SDL_keycode_h_ @@ -32,325 +32,295 @@ #include /** - * The SDL virtual key representation. + * The SDL virtual key representation. * - * Values of this type are used to represent keyboard keys using the current - * layout of the keyboard. These values include Unicode values representing - * the unmodified character that would be generated by pressing the key, or - * an SDLK_* constant for those keys that do not generate characters. + * Values of this type are used to represent keyboard keys using the current + * layout of the keyboard. These values include Unicode values representing + * the unmodified character that would be generated by pressing the key, or an + * `SDLK_*` constant for those keys that do not generate characters. * - * A special exception is the number keys at the top of the keyboard which - * map to SDLK_0...SDLK_9 on AZERTY layouts. + * A special exception is the number keys at the top of the keyboard which map + * to SDLK_0...SDLK_9 on AZERTY layouts. + * + * \since This datatype is available since SDL 3.0.0. */ -typedef Sint32 SDL_Keycode; +typedef Uint32 SDL_Keycode; -#define SDLK_SCANCODE_MASK (1<<30) +#define SDLK_SCANCODE_MASK (1u<<30) #define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK) - -typedef enum -{ - SDLK_UNKNOWN = 0, - - SDLK_RETURN = '\r', - SDLK_ESCAPE = '\x1B', - SDLK_BACKSPACE = '\b', - SDLK_TAB = '\t', - SDLK_SPACE = ' ', - SDLK_EXCLAIM = '!', - SDLK_QUOTEDBL = '"', - SDLK_HASH = '#', - SDLK_PERCENT = '%', - SDLK_DOLLAR = '$', - SDLK_AMPERSAND = '&', - SDLK_QUOTE = '\'', - SDLK_LEFTPAREN = '(', - SDLK_RIGHTPAREN = ')', - SDLK_ASTERISK = '*', - SDLK_PLUS = '+', - SDLK_COMMA = ',', - SDLK_MINUS = '-', - SDLK_PERIOD = '.', - SDLK_SLASH = '/', - SDLK_0 = '0', - SDLK_1 = '1', - SDLK_2 = '2', - SDLK_3 = '3', - SDLK_4 = '4', - SDLK_5 = '5', - SDLK_6 = '6', - SDLK_7 = '7', - SDLK_8 = '8', - SDLK_9 = '9', - SDLK_COLON = ':', - SDLK_SEMICOLON = ';', - SDLK_LESS = '<', - SDLK_EQUALS = '=', - SDLK_GREATER = '>', - SDLK_QUESTION = '?', - SDLK_AT = '@', - - /* - Skip uppercase letters - */ - - SDLK_LEFTBRACKET = '[', - SDLK_BACKSLASH = '\\', - SDLK_RIGHTBRACKET = ']', - SDLK_CARET = '^', - SDLK_UNDERSCORE = '_', - SDLK_BACKQUOTE = '`', - SDLK_a = 'a', - SDLK_b = 'b', - SDLK_c = 'c', - SDLK_d = 'd', - SDLK_e = 'e', - SDLK_f = 'f', - SDLK_g = 'g', - SDLK_h = 'h', - SDLK_i = 'i', - SDLK_j = 'j', - SDLK_k = 'k', - SDLK_l = 'l', - SDLK_m = 'm', - SDLK_n = 'n', - SDLK_o = 'o', - SDLK_p = 'p', - SDLK_q = 'q', - SDLK_r = 'r', - SDLK_s = 's', - SDLK_t = 't', - SDLK_u = 'u', - SDLK_v = 'v', - SDLK_w = 'w', - SDLK_x = 'x', - SDLK_y = 'y', - SDLK_z = 'z', - - SDLK_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK), - - SDLK_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1), - SDLK_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2), - SDLK_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3), - SDLK_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4), - SDLK_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5), - SDLK_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6), - SDLK_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7), - SDLK_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8), - SDLK_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9), - SDLK_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10), - SDLK_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11), - SDLK_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12), - - SDLK_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN), - SDLK_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK), - SDLK_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE), - SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT), - SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME), - SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP), - SDLK_DELETE = '\x7F', - SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END), - SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN), - SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT), - SDLK_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT), - SDLK_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN), - SDLK_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP), - - SDLK_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR), - SDLK_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE), - SDLK_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY), - SDLK_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS), - SDLK_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS), - SDLK_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER), - SDLK_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1), - SDLK_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2), - SDLK_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3), - SDLK_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4), - SDLK_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5), - SDLK_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6), - SDLK_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7), - SDLK_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8), - SDLK_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9), - SDLK_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0), - SDLK_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD), - - SDLK_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION), - SDLK_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER), - SDLK_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS), - SDLK_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13), - SDLK_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14), - SDLK_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15), - SDLK_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16), - SDLK_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17), - SDLK_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18), - SDLK_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19), - SDLK_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20), - SDLK_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21), - SDLK_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22), - SDLK_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23), - SDLK_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24), - SDLK_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE), - SDLK_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP), - SDLK_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU), - SDLK_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT), - SDLK_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP), - SDLK_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN), - SDLK_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO), - SDLK_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT), - SDLK_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY), - SDLK_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE), - SDLK_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND), - SDLK_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE), - SDLK_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP), - SDLK_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN), - SDLK_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA), - SDLK_KP_EQUALSAS400 = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400), - - SDLK_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE), - SDLK_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ), - SDLK_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL), - SDLK_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR), - SDLK_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR), - SDLK_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2), - SDLK_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR), - SDLK_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT), - SDLK_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER), - SDLK_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN), - SDLK_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL), - SDLK_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL), - - SDLK_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00), - SDLK_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000), - SDLK_THOUSANDSSEPARATOR = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR), - SDLK_DECIMALSEPARATOR = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR), - SDLK_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT), - SDLK_CURRENCYSUBUNIT = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT), - SDLK_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN), - SDLK_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN), - SDLK_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE), - SDLK_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE), - SDLK_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB), - SDLK_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE), - SDLK_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A), - SDLK_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B), - SDLK_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C), - SDLK_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D), - SDLK_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E), - SDLK_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F), - SDLK_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR), - SDLK_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER), - SDLK_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT), - SDLK_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS), - SDLK_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER), - SDLK_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND), - SDLK_KP_DBLAMPERSAND = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND), - SDLK_KP_VERTICALBAR = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR), - SDLK_KP_DBLVERTICALBAR = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR), - SDLK_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON), - SDLK_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH), - SDLK_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE), - SDLK_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT), - SDLK_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM), - SDLK_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE), - SDLK_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL), - SDLK_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR), - SDLK_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD), - SDLK_KP_MEMSUBTRACT = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT), - SDLK_KP_MEMMULTIPLY = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY), - SDLK_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE), - SDLK_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS), - SDLK_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR), - SDLK_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY), - SDLK_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY), - SDLK_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL), - SDLK_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL), - SDLK_KP_HEXADECIMAL = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL), - - SDLK_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL), - SDLK_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT), - SDLK_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT), - SDLK_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI), - SDLK_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL), - SDLK_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT), - SDLK_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT), - SDLK_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI), - - SDLK_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE), - - SDLK_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT), - SDLK_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV), - SDLK_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP), - SDLK_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY), - SDLK_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE), - SDLK_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT), - SDLK_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW), - SDLK_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL), - SDLK_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR), - SDLK_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER), - SDLK_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH), - SDLK_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME), - SDLK_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK), - SDLK_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD), - SDLK_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP), - SDLK_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH), - SDLK_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS), - - SDLK_BRIGHTNESSDOWN = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN), - SDLK_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP), - SDLK_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH), - SDLK_KBDILLUMTOGGLE = - SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE), - SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN), - SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP), - SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT), - SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP), - SDLK_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1), - SDLK_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2), - - SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND), - SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD), - - SDLK_SOFTLEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTLEFT), - SDLK_SOFTRIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTRIGHT), - SDLK_CALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALL), - SDLK_ENDCALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ENDCALL) -} SDL_KeyCode; +#define SDLK_UNKNOWN 0x00000000u /* 0 */ +#define SDLK_RETURN 0x0000000du /* '\r' */ +#define SDLK_ESCAPE 0x0000001bu /* '\x1B' */ +#define SDLK_BACKSPACE 0x00000008u /* '\b' */ +#define SDLK_TAB 0x00000009u /* '\t' */ +#define SDLK_SPACE 0x00000020u /* ' ' */ +#define SDLK_EXCLAIM 0x00000021u /* '!' */ +#define SDLK_DBLAPOSTROPHE 0x00000022u /* '"' */ +#define SDLK_HASH 0x00000023u /* '#' */ +#define SDLK_DOLLAR 0x00000024u /* '$' */ +#define SDLK_PERCENT 0x00000025u /* '%' */ +#define SDLK_AMPERSAND 0x00000026u /* '&' */ +#define SDLK_APOSTROPHE 0x00000027u /* '\'' */ +#define SDLK_LEFTPAREN 0x00000028u /* '(' */ +#define SDLK_RIGHTPAREN 0x00000029u /* ')' */ +#define SDLK_ASTERISK 0x0000002au /* '*' */ +#define SDLK_PLUS 0x0000002bu /* '+' */ +#define SDLK_COMMA 0x0000002cu /* ',' */ +#define SDLK_MINUS 0x0000002du /* '-' */ +#define SDLK_PERIOD 0x0000002eu /* '.' */ +#define SDLK_SLASH 0x0000002fu /* '/' */ +#define SDLK_0 0x00000030u /* '0' */ +#define SDLK_1 0x00000031u /* '1' */ +#define SDLK_2 0x00000032u /* '2' */ +#define SDLK_3 0x00000033u /* '3' */ +#define SDLK_4 0x00000034u /* '4' */ +#define SDLK_5 0x00000035u /* '5' */ +#define SDLK_6 0x00000036u /* '6' */ +#define SDLK_7 0x00000037u /* '7' */ +#define SDLK_8 0x00000038u /* '8' */ +#define SDLK_9 0x00000039u /* '9' */ +#define SDLK_COLON 0x0000003au /* ':' */ +#define SDLK_SEMICOLON 0x0000003bu /* ';' */ +#define SDLK_LESS 0x0000003cu /* '<' */ +#define SDLK_EQUALS 0x0000003du /* '=' */ +#define SDLK_GREATER 0x0000003eu /* '>' */ +#define SDLK_QUESTION 0x0000003fu /* '?' */ +#define SDLK_AT 0x00000040u /* '@' */ +#define SDLK_LEFTBRACKET 0x0000005bu /* '[' */ +#define SDLK_BACKSLASH 0x0000005cu /* '\\' */ +#define SDLK_RIGHTBRACKET 0x0000005du /* ']' */ +#define SDLK_CARET 0x0000005eu /* '^' */ +#define SDLK_UNDERSCORE 0x0000005fu /* '_' */ +#define SDLK_GRAVE 0x00000060u /* '`' */ +#define SDLK_A 0x00000061u /* 'a' */ +#define SDLK_B 0x00000062u /* 'b' */ +#define SDLK_C 0x00000063u /* 'c' */ +#define SDLK_D 0x00000064u /* 'd' */ +#define SDLK_E 0x00000065u /* 'e' */ +#define SDLK_F 0x00000066u /* 'f' */ +#define SDLK_G 0x00000067u /* 'g' */ +#define SDLK_H 0x00000068u /* 'h' */ +#define SDLK_I 0x00000069u /* 'i' */ +#define SDLK_J 0x0000006au /* 'j' */ +#define SDLK_K 0x0000006bu /* 'k' */ +#define SDLK_L 0x0000006cu /* 'l' */ +#define SDLK_M 0x0000006du /* 'm' */ +#define SDLK_N 0x0000006eu /* 'n' */ +#define SDLK_O 0x0000006fu /* 'o' */ +#define SDLK_P 0x00000070u /* 'p' */ +#define SDLK_Q 0x00000071u /* 'q' */ +#define SDLK_R 0x00000072u /* 'r' */ +#define SDLK_S 0x00000073u /* 's' */ +#define SDLK_T 0x00000074u /* 't' */ +#define SDLK_U 0x00000075u /* 'u' */ +#define SDLK_V 0x00000076u /* 'v' */ +#define SDLK_W 0x00000077u /* 'w' */ +#define SDLK_X 0x00000078u /* 'x' */ +#define SDLK_Y 0x00000079u /* 'y' */ +#define SDLK_Z 0x0000007au /* 'z' */ +#define SDLK_LEFTBRACE 0x0000007bu /* '{' */ +#define SDLK_PIPE 0x0000007cu /* '|' */ +#define SDLK_RIGHTBRACE 0x0000007du /* '}' */ +#define SDLK_TILDE 0x0000007eu /* '~' */ +#define SDLK_DELETE 0x0000007fu /* '\x7F' */ +#define SDLK_PLUSMINUS 0x000000b1u /* '\xB1' */ +#define SDLK_CAPSLOCK 0x40000039u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK) */ +#define SDLK_F1 0x4000003au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1) */ +#define SDLK_F2 0x4000003bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2) */ +#define SDLK_F3 0x4000003cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3) */ +#define SDLK_F4 0x4000003du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4) */ +#define SDLK_F5 0x4000003eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5) */ +#define SDLK_F6 0x4000003fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6) */ +#define SDLK_F7 0x40000040u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7) */ +#define SDLK_F8 0x40000041u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8) */ +#define SDLK_F9 0x40000042u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9) */ +#define SDLK_F10 0x40000043u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10) */ +#define SDLK_F11 0x40000044u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11) */ +#define SDLK_F12 0x40000045u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12) */ +#define SDLK_PRINTSCREEN 0x40000046u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN) */ +#define SDLK_SCROLLLOCK 0x40000047u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK) */ +#define SDLK_PAUSE 0x40000048u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE) */ +#define SDLK_INSERT 0x40000049u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT) */ +#define SDLK_HOME 0x4000004au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME) */ +#define SDLK_PAGEUP 0x4000004bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP) */ +#define SDLK_END 0x4000004du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END) */ +#define SDLK_PAGEDOWN 0x4000004eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN) */ +#define SDLK_RIGHT 0x4000004fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT) */ +#define SDLK_LEFT 0x40000050u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT) */ +#define SDLK_DOWN 0x40000051u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN) */ +#define SDLK_UP 0x40000052u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP) */ +#define SDLK_NUMLOCKCLEAR 0x40000053u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR) */ +#define SDLK_KP_DIVIDE 0x40000054u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE) */ +#define SDLK_KP_MULTIPLY 0x40000055u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY) */ +#define SDLK_KP_MINUS 0x40000056u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS) */ +#define SDLK_KP_PLUS 0x40000057u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS) */ +#define SDLK_KP_ENTER 0x40000058u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER) */ +#define SDLK_KP_1 0x40000059u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1) */ +#define SDLK_KP_2 0x4000005au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2) */ +#define SDLK_KP_3 0x4000005bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3) */ +#define SDLK_KP_4 0x4000005cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4) */ +#define SDLK_KP_5 0x4000005du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5) */ +#define SDLK_KP_6 0x4000005eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6) */ +#define SDLK_KP_7 0x4000005fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7) */ +#define SDLK_KP_8 0x40000060u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8) */ +#define SDLK_KP_9 0x40000061u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9) */ +#define SDLK_KP_0 0x40000062u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0) */ +#define SDLK_KP_PERIOD 0x40000063u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD) */ +#define SDLK_APPLICATION 0x40000065u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION) */ +#define SDLK_POWER 0x40000066u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER) */ +#define SDLK_KP_EQUALS 0x40000067u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS) */ +#define SDLK_F13 0x40000068u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13) */ +#define SDLK_F14 0x40000069u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14) */ +#define SDLK_F15 0x4000006au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15) */ +#define SDLK_F16 0x4000006bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16) */ +#define SDLK_F17 0x4000006cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17) */ +#define SDLK_F18 0x4000006du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18) */ +#define SDLK_F19 0x4000006eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19) */ +#define SDLK_F20 0x4000006fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20) */ +#define SDLK_F21 0x40000070u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21) */ +#define SDLK_F22 0x40000071u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22) */ +#define SDLK_F23 0x40000072u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23) */ +#define SDLK_F24 0x40000073u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24) */ +#define SDLK_EXECUTE 0x40000074u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE) */ +#define SDLK_HELP 0x40000075u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP) */ +#define SDLK_MENU 0x40000076u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU) */ +#define SDLK_SELECT 0x40000077u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT) */ +#define SDLK_STOP 0x40000078u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP) */ +#define SDLK_AGAIN 0x40000079u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN) */ +#define SDLK_UNDO 0x4000007au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO) */ +#define SDLK_CUT 0x4000007bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT) */ +#define SDLK_COPY 0x4000007cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY) */ +#define SDLK_PASTE 0x4000007du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE) */ +#define SDLK_FIND 0x4000007eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND) */ +#define SDLK_MUTE 0x4000007fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE) */ +#define SDLK_VOLUMEUP 0x40000080u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP) */ +#define SDLK_VOLUMEDOWN 0x40000081u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN) */ +#define SDLK_KP_COMMA 0x40000085u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA) */ +#define SDLK_KP_EQUALSAS400 0x40000086u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400) */ +#define SDLK_ALTERASE 0x40000099u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE) */ +#define SDLK_SYSREQ 0x4000009au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ) */ +#define SDLK_CANCEL 0x4000009bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL) */ +#define SDLK_CLEAR 0x4000009cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR) */ +#define SDLK_PRIOR 0x4000009du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR) */ +#define SDLK_RETURN2 0x4000009eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2) */ +#define SDLK_SEPARATOR 0x4000009fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR) */ +#define SDLK_OUT 0x400000a0u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT) */ +#define SDLK_OPER 0x400000a1u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER) */ +#define SDLK_CLEARAGAIN 0x400000a2u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN) */ +#define SDLK_CRSEL 0x400000a3u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL) */ +#define SDLK_EXSEL 0x400000a4u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL) */ +#define SDLK_KP_00 0x400000b0u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00) */ +#define SDLK_KP_000 0x400000b1u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000) */ +#define SDLK_THOUSANDSSEPARATOR 0x400000b2u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR) */ +#define SDLK_DECIMALSEPARATOR 0x400000b3u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR) */ +#define SDLK_CURRENCYUNIT 0x400000b4u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT) */ +#define SDLK_CURRENCYSUBUNIT 0x400000b5u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT) */ +#define SDLK_KP_LEFTPAREN 0x400000b6u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN) */ +#define SDLK_KP_RIGHTPAREN 0x400000b7u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN) */ +#define SDLK_KP_LEFTBRACE 0x400000b8u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE) */ +#define SDLK_KP_RIGHTBRACE 0x400000b9u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE) */ +#define SDLK_KP_TAB 0x400000bau /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB) */ +#define SDLK_KP_BACKSPACE 0x400000bbu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE) */ +#define SDLK_KP_A 0x400000bcu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A) */ +#define SDLK_KP_B 0x400000bdu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B) */ +#define SDLK_KP_C 0x400000beu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C) */ +#define SDLK_KP_D 0x400000bfu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D) */ +#define SDLK_KP_E 0x400000c0u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E) */ +#define SDLK_KP_F 0x400000c1u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F) */ +#define SDLK_KP_XOR 0x400000c2u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR) */ +#define SDLK_KP_POWER 0x400000c3u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER) */ +#define SDLK_KP_PERCENT 0x400000c4u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT) */ +#define SDLK_KP_LESS 0x400000c5u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS) */ +#define SDLK_KP_GREATER 0x400000c6u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER) */ +#define SDLK_KP_AMPERSAND 0x400000c7u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND) */ +#define SDLK_KP_DBLAMPERSAND 0x400000c8u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND) */ +#define SDLK_KP_VERTICALBAR 0x400000c9u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR) */ +#define SDLK_KP_DBLVERTICALBAR 0x400000cau /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR) */ +#define SDLK_KP_COLON 0x400000cbu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON) */ +#define SDLK_KP_HASH 0x400000ccu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH) */ +#define SDLK_KP_SPACE 0x400000cdu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE) */ +#define SDLK_KP_AT 0x400000ceu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT) */ +#define SDLK_KP_EXCLAM 0x400000cfu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM) */ +#define SDLK_KP_MEMSTORE 0x400000d0u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE) */ +#define SDLK_KP_MEMRECALL 0x400000d1u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL) */ +#define SDLK_KP_MEMCLEAR 0x400000d2u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR) */ +#define SDLK_KP_MEMADD 0x400000d3u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD) */ +#define SDLK_KP_MEMSUBTRACT 0x400000d4u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT) */ +#define SDLK_KP_MEMMULTIPLY 0x400000d5u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY) */ +#define SDLK_KP_MEMDIVIDE 0x400000d6u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE) */ +#define SDLK_KP_PLUSMINUS 0x400000d7u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS) */ +#define SDLK_KP_CLEAR 0x400000d8u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR) */ +#define SDLK_KP_CLEARENTRY 0x400000d9u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY) */ +#define SDLK_KP_BINARY 0x400000dau /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY) */ +#define SDLK_KP_OCTAL 0x400000dbu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL) */ +#define SDLK_KP_DECIMAL 0x400000dcu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL) */ +#define SDLK_KP_HEXADECIMAL 0x400000ddu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL) */ +#define SDLK_LCTRL 0x400000e0u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL) */ +#define SDLK_LSHIFT 0x400000e1u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT) */ +#define SDLK_LALT 0x400000e2u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT) */ +#define SDLK_LGUI 0x400000e3u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI) */ +#define SDLK_RCTRL 0x400000e4u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL) */ +#define SDLK_RSHIFT 0x400000e5u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT) */ +#define SDLK_RALT 0x400000e6u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT) */ +#define SDLK_RGUI 0x400000e7u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI) */ +#define SDLK_MODE 0x40000101u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE) */ +#define SDLK_SLEEP 0x40000102u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP) */ +#define SDLK_WAKE 0x40000103u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WAKE) */ +#define SDLK_CHANNEL_INCREMENT 0x40000104u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CHANNEL_INCREMENT) */ +#define SDLK_CHANNEL_DECREMENT 0x40000105u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CHANNEL_DECREMENT) */ +#define SDLK_MEDIA_PLAY 0x40000106u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_PLAY) */ +#define SDLK_MEDIA_PAUSE 0x40000107u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_PAUSE) */ +#define SDLK_MEDIA_RECORD 0x40000108u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_RECORD) */ +#define SDLK_MEDIA_FAST_FORWARD 0x40000109u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_FAST_FORWARD) */ +#define SDLK_MEDIA_REWIND 0x4000010au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_REWIND) */ +#define SDLK_MEDIA_NEXT_TRACK 0x4000010bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_NEXT_TRACK) */ +#define SDLK_MEDIA_PREVIOUS_TRACK 0x4000010cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_PREVIOUS_TRACK) */ +#define SDLK_MEDIA_STOP 0x4000010du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_STOP) */ +#define SDLK_MEDIA_EJECT 0x4000010eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_EJECT) */ +#define SDLK_MEDIA_PLAY_PAUSE 0x4000010fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_PLAY_PAUSE) */ +#define SDLK_MEDIA_SELECT 0x40000110u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIA_SELECT) */ +#define SDLK_AC_NEW 0x40000111u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_NEW) */ +#define SDLK_AC_OPEN 0x40000112u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_OPEN) */ +#define SDLK_AC_CLOSE 0x40000113u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_CLOSE) */ +#define SDLK_AC_EXIT 0x40000114u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_EXIT) */ +#define SDLK_AC_SAVE 0x40000115u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SAVE) */ +#define SDLK_AC_PRINT 0x40000116u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_PRINT) */ +#define SDLK_AC_PROPERTIES 0x40000117u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_PROPERTIES) */ +#define SDLK_AC_SEARCH 0x40000118u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH) */ +#define SDLK_AC_HOME 0x40000119u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME) */ +#define SDLK_AC_BACK 0x4000011au /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK) */ +#define SDLK_AC_FORWARD 0x4000011bu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD) */ +#define SDLK_AC_STOP 0x4000011cu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP) */ +#define SDLK_AC_REFRESH 0x4000011du /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH) */ +#define SDLK_AC_BOOKMARKS 0x4000011eu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS) */ +#define SDLK_SOFTLEFT 0x4000011fu /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTLEFT) */ +#define SDLK_SOFTRIGHT 0x40000120u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTRIGHT) */ +#define SDLK_CALL 0x40000121u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALL) */ +#define SDLK_ENDCALL 0x40000122u /* SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ENDCALL) */ /** - * Enumeration of valid key mods (possibly OR'd together). + * Valid key modifiers (possibly OR'd together). + * + * \since This datatype is available since SDL 3.0.0. */ -typedef enum -{ - SDL_KMOD_NONE = 0x0000, - SDL_KMOD_LSHIFT = 0x0001, - SDL_KMOD_RSHIFT = 0x0002, - SDL_KMOD_LCTRL = 0x0040, - SDL_KMOD_RCTRL = 0x0080, - SDL_KMOD_LALT = 0x0100, - SDL_KMOD_RALT = 0x0200, - SDL_KMOD_LGUI = 0x0400, - SDL_KMOD_RGUI = 0x0800, - SDL_KMOD_NUM = 0x1000, - SDL_KMOD_CAPS = 0x2000, - SDL_KMOD_MODE = 0x4000, - SDL_KMOD_SCROLL = 0x8000, - - SDL_KMOD_CTRL = SDL_KMOD_LCTRL | SDL_KMOD_RCTRL, - SDL_KMOD_SHIFT = SDL_KMOD_LSHIFT | SDL_KMOD_RSHIFT, - SDL_KMOD_ALT = SDL_KMOD_LALT | SDL_KMOD_RALT, - SDL_KMOD_GUI = SDL_KMOD_LGUI | SDL_KMOD_RGUI, +typedef Uint16 SDL_Keymod; - SDL_KMOD_RESERVED = SDL_KMOD_SCROLL /* This is for source-level compatibility with SDL 2.0.0. */ -} SDL_Keymod; +#define SDL_KMOD_NONE 0x0000u /**< no modifier is applicable. */ +#define SDL_KMOD_LSHIFT 0x0001u /**< the left Shift key is down. */ +#define SDL_KMOD_RSHIFT 0x0002u /**< the right Shift key is down. */ +#define SDL_KMOD_LCTRL 0x0040u /**< the left Ctrl (Control) key is down. */ +#define SDL_KMOD_RCTRL 0x0080u /**< the right Ctrl (Control) key is down. */ +#define SDL_KMOD_LALT 0x0100u /**< the left Alt key is down. */ +#define SDL_KMOD_RALT 0x0200u /**< the right Alt key is down. */ +#define SDL_KMOD_LGUI 0x0400u /**< the left GUI key (often the Windows key) is down. */ +#define SDL_KMOD_RGUI 0x0800u /**< the right GUI key (often the Windows key) is down. */ +#define SDL_KMOD_NUM 0x1000u /**< the Num Lock key (may be located on an extended keypad) is down. */ +#define SDL_KMOD_CAPS 0x2000u /**< the Caps Lock key is down. */ +#define SDL_KMOD_MODE 0x4000u /**< the !AltGr key is down. */ +#define SDL_KMOD_SCROLL 0x8000u /**< the Scroll Lock key is down. */ +#define SDL_KMOD_CTRL (SDL_KMOD_LCTRL | SDL_KMOD_RCTRL) /**< Any Ctrl key is down. */ +#define SDL_KMOD_SHIFT (SDL_KMOD_LSHIFT | SDL_KMOD_RSHIFT) /**< Any Shift key is down. */ +#define SDL_KMOD_ALT (SDL_KMOD_LALT | SDL_KMOD_RALT) /**< Any Alt key is down. */ +#define SDL_KMOD_GUI (SDL_KMOD_LGUI | SDL_KMOD_RGUI) /**< Any GUI key is down. */ #endif /* SDL_keycode_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_loadso.h b/libs/SDL3/include/SDL3/SDL_loadso.h index c406f8d42..2d49c75fe 100644 --- a/libs/SDL3/include/SDL3/SDL_loadso.h +++ b/libs/SDL3/include/SDL3/SDL_loadso.h @@ -19,23 +19,33 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* WIKI CATEGORY: SharedObject */ + /** - * \file SDL_loadso.h - * - * System dependent library loading routines - * - * Some things to keep in mind: - * \li These functions only work on C function names. Other languages may - * have name mangling and intrinsic language support that varies from - * compiler to compiler. - * \li Make sure you declare your function pointers with the same calling - * convention as the actual library function. Your code will crash - * mysteriously if you do not do this. - * \li Avoid namespace collisions. If you load a symbol from the library, - * it is not defined whether or not it goes into the global symbol - * namespace for the application. If it does and it conflicts with - * symbols in your code or other shared libraries, you will not get - * the results you expect. :) + * # CategorySharedObject + * + * System-dependent library loading routines. + * + * Shared objects are code that is programmatically loadable at runtime. + * Windows calls these "DLLs", Linux calls them "shared libraries", etc. + * + * To use them, build such a library, then call SDL_LoadObject() on it. Once + * loaded, you can use SDL_LoadFunction() on that object to find the address + * of its exported symbols. When done with the object, call SDL_UnloadObject() + * to dispose of it. + * + * Some things to keep in mind: + * + * - These functions only work on C function names. Other languages may have + * name mangling and intrinsic language support that varies from compiler to + * compiler. + * - Make sure you declare your function pointers with the same calling + * convention as the actual library function. Your code will crash + * mysteriously if you do not do this. + * - Avoid namespace collisions. If you load a symbol from the library, it is + * not defined whether or not it goes into the global symbol namespace for + * the application. If it does and it conflicts with symbols in your code or + * other shared libraries, you will not get the results you expect. :) */ #ifndef SDL_loadso_h_ @@ -50,19 +60,32 @@ extern "C" { #endif +/** + * An opaque datatype that represents a loaded shared object. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_LoadObject + * \sa SDL_LoadFunction + * \sa SDL_UnloadObject + */ +typedef struct SDL_SharedObject SDL_SharedObject; + /** * Dynamically load a shared object. * - * \param sofile a system-dependent name of the object file - * \returns an opaque pointer to the object handle or NULL if there was an - * error; call SDL_GetError() for more information. + * \param sofile a system-dependent name of the object file. + * \returns an opaque pointer to the object handle or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadFunction * \sa SDL_UnloadObject */ -extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile); +extern SDL_DECLSPEC SDL_SharedObject * SDLCALL SDL_LoadObject(const char *sofile); /** * Look up the address of the named function in a shared object. @@ -79,27 +102,34 @@ extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile); * * If the requested function doesn't exist, NULL is returned. * - * \param handle a valid shared object handle returned by SDL_LoadObject() - * \param name the name of the function to look up - * \returns a pointer to the function or NULL if there was an error; call - * SDL_GetError() for more information. + * \param handle a valid shared object handle returned by SDL_LoadObject(). + * \param name the name of the function to look up. + * \returns a pointer to the function or NULL on failure; call SDL_GetError() + * for more information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadObject */ -extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_LoadFunction(void *handle, const char *name); +extern SDL_DECLSPEC SDL_FunctionPointer SDLCALL SDL_LoadFunction(SDL_SharedObject *handle, const char *name); /** * Unload a shared object from memory. * - * \param handle a valid shared object handle returned by SDL_LoadObject() + * Note that any pointers from this object looked up through + * SDL_LoadFunction() will no longer be valid. + * + * \param handle a valid shared object handle returned by SDL_LoadObject(). + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadObject */ -extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle); +extern SDL_DECLSPEC void SDLCALL SDL_UnloadObject(SDL_SharedObject *handle); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_locale.h b/libs/SDL3/include/SDL3/SDL_locale.h index 7ac803ca3..85d77500c 100644 --- a/libs/SDL3/include/SDL3/SDL_locale.h +++ b/libs/SDL3/include/SDL3/SDL_locale.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_locale.h + * # CategoryLocale * - * Include file for SDL locale services + * SDL locale services. */ #ifndef SDL_locale_h @@ -39,7 +39,18 @@ extern "C" { /* *INDENT-ON* */ #endif - +/** + * A struct to provide locale data. + * + * Locale data is split into a spoken language, like English, and an optional + * country, like Canada. The language will be in ISO-639 format (so English + * would be "en"), and the country, if not NULL, will be an ISO-3166 country + * code (so Canada would be "CA"). + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetPreferredLocales + */ typedef struct SDL_Locale { const char *language; /**< A language name, like "en" for English. */ @@ -49,11 +60,6 @@ typedef struct SDL_Locale /** * Report the user's preferred locale. * - * This returns an array of SDL_Locale structs, the final item zeroed out. - * When the caller is done with this array, it should call SDL_free() on the - * returned value; all the memory involved is allocated in a single block, so - * a single SDL_free() will suffice. - * * Returned language strings are in the format xx, where 'xx' is an ISO-639 * language specifier (such as "en" for English, "de" for German, etc). * Country strings are in the format YY, where "YY" is an ISO-3166 country @@ -83,12 +89,16 @@ typedef struct SDL_Locale * if possible, and you can call this function again to get an updated copy of * preferred locales. * - * \returns array of locales, terminated with a locale with a NULL language - * field. Will return NULL on error. + * \param count a pointer filled in with the number of locales returned, may + * be NULL. + * \returns a NULL terminated array of locale pointers, or NULL on failure; + * call SDL_GetError() for more information. This is a single + * allocation that should be freed with SDL_free() when it is no + * longer needed. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void); +extern SDL_DECLSPEC SDL_Locale ** SDLCALL SDL_GetPreferredLocales(int *count); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_log.h b/libs/SDL3/include/SDL3/SDL_log.h index 99d2f2c36..8feb9e0af 100644 --- a/libs/SDL3/include/SDL3/SDL_log.h +++ b/libs/SDL3/include/SDL3/SDL_log.h @@ -20,18 +20,42 @@ */ /** - * \file SDL_log.h + * # CategoryLog * - * Simple log messages with categories and priorities. + * Simple log messages with priorities and categories. A message's + * SDL_LogPriority signifies how important the message is. A message's + * SDL_LogCategory signifies from what domain it belongs to. Every category + * has a minimum priority specified: when a message belongs to that category, + * it will only be sent out if it has that minimum priority or higher. * - * By default logs are quiet, but if you're debugging SDL you might want: + * SDL's own logs are sent below the default priority threshold, so they are + * quiet by default. * - * SDL_LogSetAllPriority(SDL_LOG_PRIORITY_WARN); + * You can change the log verbosity programmatically using + * SDL_SetLogPriority() or with SDL_SetHint(SDL_HINT_LOGGING, ...), or with + * the "SDL_LOGGING" environment variable. This variable is a comma separated + * set of category=level tokens that define the default logging levels for SDL + * applications. * - * Here's where the messages go on different platforms: - * Windows: debug output stream - * Android: log output - * Others: standard error output (stderr) + * The category can be a numeric category, one of "app", "error", "assert", + * "system", "audio", "video", "render", "input", "test", or `*` for any + * unspecified category. + * + * The level can be a numeric level, one of "verbose", "debug", "info", + * "warn", "error", "critical", or "quiet" to disable that category. + * + * You can omit the category if you want to set the logging level for all + * categories. + * + * If this hint isn't set, the default log levels are equivalent to: + * + * `app=info,assert=warn,test=verbose,*=error` + * + * Here's where the messages go on different platforms: + * + * - Windows: debug output stream + * - Android: log output + * - Others: standard error output (stderr) */ #ifndef SDL_log_h_ @@ -45,23 +69,16 @@ extern "C" { #endif - /** - * The maximum size of a log message prior to SDL 2.0.24 + * The predefined log categories * - * As of 2.0.24 there is no limit to the length of SDL log messages. - */ -#define SDL_MAX_LOG_MESSAGE 4096 - -/** - * The predefined log categories + * By default the application and gpu categories are enabled at the INFO + * level, the assert category is enabled at the WARN level, test is enabled at + * the VERBOSE level and all other categories are enabled at the ERROR level. * - * By default the application category is enabled at the INFO level, - * the assert category is enabled at the WARN level, test is enabled - * at the VERBOSE level and all other categories are enabled at the - * ERROR level. + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_LogCategory { SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_CATEGORY_ERROR, @@ -72,9 +89,9 @@ typedef enum SDL_LOG_CATEGORY_RENDER, SDL_LOG_CATEGORY_INPUT, SDL_LOG_CATEGORY_TEST, + SDL_LOG_CATEGORY_GPU, /* Reserved for future SDL library use */ - SDL_LOG_CATEGORY_RESERVED1, SDL_LOG_CATEGORY_RESERVED2, SDL_LOG_CATEGORY_RESERVED3, SDL_LOG_CATEGORY_RESERVED4, @@ -97,98 +114,161 @@ typedef enum } SDL_LogCategory; /** - * The predefined log priorities + * The predefined log priorities + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_LogPriority { - SDL_LOG_PRIORITY_VERBOSE = 1, + SDL_LOG_PRIORITY_INVALID, + SDL_LOG_PRIORITY_TRACE, + SDL_LOG_PRIORITY_VERBOSE, SDL_LOG_PRIORITY_DEBUG, SDL_LOG_PRIORITY_INFO, SDL_LOG_PRIORITY_WARN, SDL_LOG_PRIORITY_ERROR, SDL_LOG_PRIORITY_CRITICAL, - SDL_NUM_LOG_PRIORITIES + SDL_LOG_PRIORITY_COUNT } SDL_LogPriority; /** * Set the priority of all log categories. * - * \param priority the SDL_LogPriority to assign + * \param priority the SDL_LogPriority to assign. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogResetPriorities - * \sa SDL_LogSetPriority + * \sa SDL_ResetLogPriorities + * \sa SDL_SetLogPriority */ -extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority); +extern SDL_DECLSPEC void SDLCALL SDL_SetLogPriorities(SDL_LogPriority priority); /** * Set the priority of a particular log category. * - * \param category the category to assign a priority to - * \param priority the SDL_LogPriority to assign + * \param category the category to assign a priority to. + * \param priority the SDL_LogPriority to assign. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogGetPriority - * \sa SDL_LogResetPriorities - * \sa SDL_LogSetAllPriority + * \sa SDL_GetLogPriority + * \sa SDL_ResetLogPriorities + * \sa SDL_SetLogPriorities */ -extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category, - SDL_LogPriority priority); +extern SDL_DECLSPEC void SDLCALL SDL_SetLogPriority(int category, SDL_LogPriority priority); /** * Get the priority of a particular log category. * - * \param category the category to query - * \returns the SDL_LogPriority for the requested category + * \param category the category to query. + * \returns the SDL_LogPriority for the requested category. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogSetPriority + * \sa SDL_SetLogPriority */ -extern DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category); +extern SDL_DECLSPEC SDL_LogPriority SDLCALL SDL_GetLogPriority(int category); /** * Reset all priorities to default. * * This is called by SDL_Quit(). * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * - * \sa SDL_LogSetAllPriority - * \sa SDL_LogSetPriority + * \sa SDL_SetLogPriorities + * \sa SDL_SetLogPriority */ -extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void); +extern SDL_DECLSPEC void SDLCALL SDL_ResetLogPriorities(void); + +/** + * Set the text prepended to log messages of a given priority. + * + * By default SDL_LOG_PRIORITY_INFO and below have no prefix, and + * SDL_LOG_PRIORITY_WARN and higher have a prefix showing their priority, e.g. + * "WARNING: ". + * + * \param priority the SDL_LogPriority to modify. + * \param prefix the prefix to use for that log priority, or NULL to use no + * prefix. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetLogPriorities + * \sa SDL_SetLogPriority + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetLogPriorityPrefix(SDL_LogPriority priority, const char *prefix); /** * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO. * - * \param fmt a printf() style message format string + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the `fmt` string, if - * any + * any. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_LogCritical + * \sa SDL_LogDebug + * \sa SDL_LogError + * \sa SDL_LogInfo + * \sa SDL_LogMessage + * \sa SDL_LogMessageV + * \sa SDL_LogTrace + * \sa SDL_LogVerbose + * \sa SDL_LogWarn + */ +extern SDL_DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); + +/** + * Log a message with SDL_LOG_PRIORITY_TRACE. + * + * \param category the category of the message. + * \param fmt a printf() style message format string. + * \param ... additional parameters matching % tokens in the **fmt** string, + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_Log * \sa SDL_LogCritical * \sa SDL_LogDebug * \sa SDL_LogError * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); +extern SDL_DECLSPEC void SDLCALL SDL_LogTrace(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_VERBOSE. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -201,15 +281,17 @@ extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, . * \sa SDL_LogMessageV * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_DEBUG. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -219,18 +301,21 @@ extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRI * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_INFO. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -240,18 +325,21 @@ extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING * \sa SDL_LogError * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_WARN. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -262,17 +350,20 @@ extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose */ -extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_ERROR. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -282,18 +373,21 @@ extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with SDL_LOG_PRIORITY_CRITICAL. * - * \param category the category of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -303,19 +397,22 @@ extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING * \sa SDL_LogInfo * \sa SDL_LogMessage * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); /** * Log a message with the specified category and priority. * - * \param category the category of the message - * \param priority the priority of the message - * \param fmt a printf() style message format string + * \param category the category of the message. + * \param priority the priority of the message. + * \param fmt a printf() style message format string. * \param ... additional parameters matching % tokens in the **fmt** string, - * if any + * if any. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -325,20 +422,23 @@ extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STR * \sa SDL_LogError * \sa SDL_LogInfo * \sa SDL_LogMessageV + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogMessage(int category, +extern SDL_DECLSPEC void SDLCALL SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3); /** * Log a message with the specified category and priority. * - * \param category the category of the message - * \param priority the priority of the message - * \param fmt a printf() style message format string - * \param ap a variable argument list + * \param category the category of the message. + * \param priority the priority of the message. + * \param fmt a printf() style message format string. + * \param ap a variable argument list. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -348,22 +448,28 @@ extern DECLSPEC void SDLCALL SDL_LogMessage(int category, * \sa SDL_LogError * \sa SDL_LogInfo * \sa SDL_LogMessage + * \sa SDL_LogTrace * \sa SDL_LogVerbose * \sa SDL_LogWarn */ -extern DECLSPEC void SDLCALL SDL_LogMessageV(int category, +extern SDL_DECLSPEC void SDLCALL SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); /** * The prototype for the log output callback function. * - * This function is called by SDL when there is new text to be logged. + * This function is called by SDL when there is new text to be logged. A mutex + * is held so that this function is never called by more than one thread at + * once. * - * \param userdata what was passed as `userdata` to SDL_SetLogOutputFunction() - * \param category the category of the message - * \param priority the priority of the message - * \param message the message being output + * \param userdata what was passed as `userdata` to + * SDL_SetLogOutputFunction(). + * \param category the category of the message. + * \param priority the priority of the message. + * \param message the message being output. + * + * \since This datatype is available since SDL 3.0.0. */ typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message); @@ -371,27 +477,31 @@ typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_ * Get the current log output function. * * \param callback an SDL_LogOutputFunction filled in with the current log - * callback + * callback. * \param userdata a pointer filled in with the pointer that is passed to - * `callback` + * `callback`. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetLogOutputFunction */ -extern DECLSPEC void SDLCALL SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata); +extern SDL_DECLSPEC void SDLCALL SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata); /** * Replace the default log output function with one of your own. * - * \param callback an SDL_LogOutputFunction to call instead of the default - * \param userdata a pointer that is passed to `callback` + * \param callback an SDL_LogOutputFunction to call instead of the default. + * \param userdata a pointer that is passed to `callback`. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetLogOutputFunction */ -extern DECLSPEC void SDLCALL SDL_SetLogOutputFunction(SDL_LogOutputFunction callback, void *userdata); +extern SDL_DECLSPEC void SDLCALL SDL_SetLogOutputFunction(SDL_LogOutputFunction callback, void *userdata); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_main.h b/libs/SDL3/include/SDL3/SDL_main.h index 0659ad61d..e173bd5c6 100644 --- a/libs/SDL3/include/SDL3/SDL_main.h +++ b/libs/SDL3/include/SDL3/SDL_main.h @@ -19,14 +19,11 @@ 3. This notice may not be removed or altered from any source distribution. */ -#ifndef SDL_main_h_ -#define SDL_main_h_ - -#include -#include -#include - -/* +/** + * # CategoryMain + * + * Redefine main() on some platforms so that it is called by SDL. + * * For details on how SDL_main works, and how to use it, please refer to: * * https://wiki.libsdl.org/SDL3/README/main-functions @@ -34,11 +31,13 @@ * (or docs/README-main-functions.md in the SDL source tree) */ -/** - * \file SDL_main.h - * - * Redefine main() on some platforms so that it is called by SDL. - */ +#ifndef SDL_main_h_ +#define SDL_main_h_ + +#include +#include +#include +#include #ifndef SDL_MAIN_HANDLED #ifdef SDL_PLATFORM_WIN32 @@ -49,20 +48,6 @@ */ #define SDL_MAIN_AVAILABLE - #elif defined(SDL_PLATFORM_WINRT) - /* On WinRT, SDL provides a main function that initializes CoreApplication, - creating an instance of IFrameworkView in the process. - - Ideally, #include'ing SDL_main.h is enough to get a main() function working. - However, that requires the source file your main() is in to be compiled - as C++ *and* with the /ZW compiler flag. If that's not feasible, add an - otherwise empty .cpp file that only contains `#include ` - and build that with /ZW (still include SDL_main.h in your other file with main()!). - In XAML apps, instead the function SDL_RunApp() must be called with a pointer - to the Direct3D-hosted XAML control passed in as the "reserved" argument. - */ - #define SDL_MAIN_NEEDED - #elif defined(SDL_PLATFORM_GDK) /* On GDK, SDL provides a main function that initializes the game runtime. @@ -93,7 +78,17 @@ #define SDL_MAIN_NEEDED /* We need to export SDL_main so it can be launched from Java */ - #define SDLMAIN_DECLSPEC DECLSPEC + #define SDLMAIN_DECLSPEC SDL_DECLSPEC + + #elif defined(SDL_PLATFORM_EMSCRIPTEN) + /* On Emscripten, SDL provides a main function that converts URL + parameters that start with "SDL_" to environment variables, so + they can be used as SDL hints, etc. + + This is 100% optional, so if you don't want this to happen, you may + define SDL_MAIN_HANDLED + */ + #define SDL_MAIN_AVAILABLE #elif defined(SDL_PLATFORM_PSP) /* On PSP SDL provides a main function that sets the module info, @@ -139,31 +134,53 @@ * * The application's main() function must be called with C linkage, * and should be declared like this: - * \code + * + * ```c * #ifdef __cplusplus * extern "C" * #endif * int main(int argc, char *argv[]) * { * } - * \endcode + * ``` */ +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + +/** + * Inform SDL to use the main callbacks instead of main. + * + * SDL does not define this macro, but will check if it is defined when + * including `SDL_main.h`. If defined, SDL will expect the app to provide + * several functions: SDL_AppInit, SDL_AppEvent, SDL_AppIterate, and + * SDL_AppQuit. The app should not provide a `main` function in this case, and + * doing so will likely cause the build to fail. + * + * Please see [README/main-functions](README/main-functions), (or + * docs/README-main-functions.md in the source tree) for a more detailed + * explanation. + * + * \since This macro is used by the headers since SDL 3.0.0. + * + * \sa SDL_AppInit + * \sa SDL_AppEvent + * \sa SDL_AppIterate + * \sa SDL_AppQuit + */ +#define SDL_MAIN_USE_CALLBACKS 1 +#endif + #if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE) || defined(SDL_MAIN_USE_CALLBACKS) #define main SDL_main #endif +#include #include #ifdef __cplusplus extern "C" { #endif -typedef int (SDLCALL *SDL_AppInit_func)(void **appstate, int argc, char *argv[]); -typedef int (SDLCALL *SDL_AppIterate_func)(void *appstate); -typedef int (SDLCALL *SDL_AppEvent_func)(void *appstate, const SDL_Event *event); -typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate); - -/** +/* * You can (optionally!) define SDL_MAIN_USE_CALLBACKS before including * SDL_main.h, and then your application will _not_ have a standard * "main" entry point. Instead, it will operate as a collection of @@ -192,34 +209,38 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate); /** * App-implemented initial entry point for SDL_MAIN_USE_CALLBACKS apps. * - * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If - * using a standard "main" function, you should not supply this. + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If using a + * standard "main" function, you should not supply this. * * This function is called by SDL once, at startup. The function should - * initialize whatever is necessary, possibly create windows and open - * audio devices, etc. The `argc` and `argv` parameters work like they would - * with a standard "main" function. + * initialize whatever is necessary, possibly create windows and open audio + * devices, etc. The `argc` and `argv` parameters work like they would with a + * standard "main" function. * * This function should not go into an infinite mainloop; it should do any * one-time setup it requires and then return. * * The app may optionally assign a pointer to `*appstate`. This pointer will * be provided on every future call to the other entry points, to allow - * application state to be preserved between functions without the app - * needing to use a global variable. If this isn't set, the pointer will - * be NULL in future entry points. - * - * If this function returns 0, the app will proceed to normal operation, - * and will begin receiving repeated calls to SDL_AppIterate and SDL_AppEvent - * for the life of the program. If this function returns < 0, SDL will - * call SDL_AppQuit and terminate the process with an exit code that reports - * an error to the platform. If it returns > 0, the SDL calls SDL_AppQuit - * and terminates with an exit code that reports success to the platform. - * - * \param appstate a place where the app can optionally store a pointer for future use. - * \param argc The standard ANSI C main's argc; number of elements in `argv` - * \param argv The standard ANSI C main's argv; array of command line arguments. - * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * application state to be preserved between functions without the app needing + * to use a global variable. If this isn't set, the pointer will be NULL in + * future entry points. + * + * If this function returns SDL_APP_CONTINUE, the app will proceed to normal + * operation, and will begin receiving repeated calls to SDL_AppIterate and + * SDL_AppEvent for the life of the program. If this function returns + * SDL_APP_FAILURE, SDL will call SDL_AppQuit and terminate the process with + * an exit code that reports an error to the platform. If it returns + * SDL_APP_SUCCESS, SDL calls SDL_AppQuit and terminates with an exit code + * that reports success to the platform. + * + * \param appstate a place where the app can optionally store a pointer for + * future use. + * \param argc the standard ANSI C main's argc; number of elements in `argv`. + * \param argv the standard ANSI C main's argv; array of command line + * arguments. + * \returns SDL_APP_FAILURE to terminate with an error, SDL_APP_SUCCESS to + * terminate with success, SDL_APP_CONTINUE to continue. * * \threadsafety This function is not thread safe. * @@ -229,28 +250,28 @@ typedef void (SDLCALL *SDL_AppQuit_func)(void *appstate); * \sa SDL_AppEvent * \sa SDL_AppQuit */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(void **appstate, int argc, char *argv[]); +extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppInit(void **appstate, int argc, char *argv[]); /** * App-implemented iteration entry point for SDL_MAIN_USE_CALLBACKS apps. * - * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If - * using a standard "main" function, you should not supply this. + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If using a + * standard "main" function, you should not supply this. * - * This function is called repeatedly by SDL after SDL_AppInit returns 0. - * The function should operate as a single iteration the program's primary - * loop; it should update whatever state it needs and draw a new frame of - * video, usually. + * This function is called repeatedly by SDL after SDL_AppInit returns 0. The + * function should operate as a single iteration the program's primary loop; + * it should update whatever state it needs and draw a new frame of video, + * usually. * - * On some platforms, this function will be called at the refresh rate of - * the display (which might change during the life of your app!). There are - * no promises made about what frequency this function might run at. You - * should use SDL's timer functions if you need to see how much time has - * passed since the last iteration. + * On some platforms, this function will be called at the refresh rate of the + * display (which might change during the life of your app!). There are no + * promises made about what frequency this function might run at. You should + * use SDL's timer functions if you need to see how much time has passed since + * the last iteration. * - * There is no need to process the SDL event queue during this function; - * SDL will send events as they arrive in SDL_AppEvent, and in most cases - * the event queue will be empty when this function runs anyhow. + * There is no need to process the SDL event queue during this function; SDL + * will send events as they arrive in SDL_AppEvent, and in most cases the + * event queue will be empty when this function runs anyhow. * * This function should not go into an infinite mainloop; it should do one * iteration of whatever the program does and return. @@ -258,15 +279,17 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(void **appstate, int argc, char * The `appstate` parameter is an optional pointer provided by the app during * SDL_AppInit(). If the app never provided a pointer, this will be NULL. * - * If this function returns 0, the app will continue normal operation, - * receiving repeated calls to SDL_AppIterate and SDL_AppEvent for the life - * of the program. If this function returns < 0, SDL will call SDL_AppQuit - * and terminate the process with an exit code that reports an error to the - * platform. If it returns > 0, the SDL calls SDL_AppQuit and terminates with - * an exit code that reports success to the platform. + * If this function returns SDL_APP_CONTINUE, the app will continue normal + * operation, receiving repeated calls to SDL_AppIterate and SDL_AppEvent for + * the life of the program. If this function returns SDL_APP_FAILURE, SDL will + * call SDL_AppQuit and terminate the process with an exit code that reports + * an error to the platform. If it returns SDL_APP_SUCCESS, SDL calls + * SDL_AppQuit and terminates with an exit code that reports success to the + * platform. * * \param appstate an optional pointer, provided by the app in SDL_AppInit. - * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * \returns SDL_APP_FAILURE to terminate with an error, SDL_APP_SUCCESS to + * terminate with success, SDL_APP_CONTINUE to continue. * * \threadsafety This function is not thread safe. * @@ -275,48 +298,45 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppInit(void **appstate, int argc, char * \sa SDL_AppInit * \sa SDL_AppEvent */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void *appstate); +extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppIterate(void *appstate); /** * App-implemented event entry point for SDL_MAIN_USE_CALLBACKS apps. * - * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If - * using a standard "main" function, you should not supply this. + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If using a + * standard "main" function, you should not supply this. * - * This function is called as needed by SDL after SDL_AppInit returns 0; - * It is called once for each new event. + * This function is called as needed by SDL after SDL_AppInit returns 0; It is + * called once for each new event. * * There is (currently) no guarantee about what thread this will be called * from; whatever thread pushes an event onto SDL's queue will trigger this - * function. SDL is responsible for pumping the event queue between - * each call to SDL_AppIterate, so in normal operation one should only - * get events in a serial fashion, but be careful if you have a thread that - * explicitly calls SDL_PushEvent. + * function. SDL is responsible for pumping the event queue between each call + * to SDL_AppIterate, so in normal operation one should only get events in a + * serial fashion, but be careful if you have a thread that explicitly calls + * SDL_PushEvent. * - * Events sent to this function are not owned by the app; if you need to - * save the data, you should copy it. + * Events sent to this function are not owned by the app; if you need to save + * the data, you should copy it. * - * You do not need to free event data (such as the `file` string in - * SDL_EVENT_DROP_FILE), as SDL will free it once this function returns. - * Note that this is different than one might expect when using a standard - * "main" function! - * - * This function should not go into an infinite mainloop; it should handle - * the provided event appropriately and return. + * This function should not go into an infinite mainloop; it should handle the + * provided event appropriately and return. * * The `appstate` parameter is an optional pointer provided by the app during * SDL_AppInit(). If the app never provided a pointer, this will be NULL. * - * If this function returns 0, the app will continue normal operation, - * receiving repeated calls to SDL_AppIterate and SDL_AppEvent for the life - * of the program. If this function returns < 0, SDL will call SDL_AppQuit - * and terminate the process with an exit code that reports an error to the - * platform. If it returns > 0, the SDL calls SDL_AppQuit and terminates with - * an exit code that reports success to the platform. + * If this function returns SDL_APP_CONTINUE, the app will continue normal + * operation, receiving repeated calls to SDL_AppIterate and SDL_AppEvent for + * the life of the program. If this function returns SDL_APP_FAILURE, SDL will + * call SDL_AppQuit and terminate the process with an exit code that reports + * an error to the platform. If it returns SDL_APP_SUCCESS, SDL calls + * SDL_AppQuit and terminates with an exit code that reports success to the + * platform. * * \param appstate an optional pointer, provided by the app in SDL_AppInit. * \param event the new event for the app to examine. - * \returns -1 to terminate with an error, 1 to terminate with success, 0 to continue. + * \returns SDL_APP_FAILURE to terminate with an error, SDL_APP_SUCCESS to + * terminate with success, SDL_APP_CONTINUE to continue. * * \threadsafety This function is not thread safe. * @@ -325,33 +345,34 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppIterate(void *appstate); * \sa SDL_AppInit * \sa SDL_AppIterate */ -extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(void *appstate, const SDL_Event *event); +extern SDLMAIN_DECLSPEC SDL_AppResult SDLCALL SDL_AppEvent(void *appstate, SDL_Event *event); /** * App-implemented deinit entry point for SDL_MAIN_USE_CALLBACKS apps. * - * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If - * using a standard "main" function, you should not supply this. + * Apps implement this function when using SDL_MAIN_USE_CALLBACKS. If using a + * standard "main" function, you should not supply this. * * This function is called once by SDL before terminating the program. * - * This function will be called no matter what, even if SDL_AppInit - * requests termination. + * This function will be called no matter what, even if SDL_AppInit requests + * termination. * * This function should not go into an infinite mainloop; it should - * deinitialize any resources necessary, perform whatever shutdown - * activities, and return. + * deinitialize any resources necessary, perform whatever shutdown activities, + * and return. * - * You do not need to call SDL_Quit() in this function, as SDL will call - * it after this function returns and before the process terminates, but - * it is safe to do so. + * You do not need to call SDL_Quit() in this function, as SDL will call it + * after this function returns and before the process terminates, but it is + * safe to do so. * * The `appstate` parameter is an optional pointer provided by the app during - * SDL_AppInit(). If the app never provided a pointer, this will be NULL. - * This function call is the last time this pointer will be provided, so - * any resources to it should be cleaned up here. + * SDL_AppInit(). If the app never provided a pointer, this will be NULL. This + * function call is the last time this pointer will be provided, so any + * resources to it should be cleaned up here. * * \param appstate an optional pointer, provided by the app in SDL_AppInit. + * \param result the result code that terminated the app (success or failure). * * \threadsafety This function is not thread safe. * @@ -359,17 +380,56 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_AppEvent(void *appstate, const SDL_Event * * \sa SDL_AppInit */ -extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate); +extern SDLMAIN_DECLSPEC void SDLCALL SDL_AppQuit(void *appstate, SDL_AppResult result); #endif /* SDL_MAIN_USE_CALLBACKS */ /** - * The prototype for the application's main() function + * The prototype for the application's main() function + * + * \param argc an ANSI-C style main function's argc. + * \param argv an ANSI-C style main function's argv. + * \returns an ANSI-C main return code; generally 0 is considered successful + * program completion, and small non-zero values are considered + * errors. + * + * \since This datatype is available since SDL 3.0.0. */ typedef int (SDLCALL *SDL_main_func)(int argc, char *argv[]); -extern SDLMAIN_DECLSPEC int SDLCALL SDL_main(int argc, char *argv[]); +/** + * An app-supplied function for program entry. + * + * Apps do not directly create this function; they should create a standard + * ANSI-C `main` function instead. If SDL needs to insert some startup code + * before `main` runs, or the platform doesn't actually _use_ a function + * called "main", SDL will do some macro magic to redefine `main` to + * `SDL_main` and provide its own `main`. + * + * Apps should include `SDL_main.h` in the same file as their `main` function, + * and they should not use that symbol for anything else in that file, as it + * might get redefined. + * + * This function is only provided by the app if it isn't using + * SDL_MAIN_USE_CALLBACKS. + * + * Program startup is a surprisingly complex topic. Please see + * [README/main-functions](README/main-functions), (or + * docs/README-main-functions.md in the source tree) for a more detailed + * explanation. + * + * \param argc an ANSI-C style main function's argc. + * \param argv an ANSI-C style main function's argv. + * \returns an ANSI-C main return code; generally 0 is considered successful + * program completion, and small non-zero values are considered + * errors. + * + * \threadsafety This is the program entry point. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDLMAIN_DECLSPEC int SDLCALL SDL_main(int argc, char *argv[]); /** * Circumvent failure of SDL_Init() when not using SDL_main() as an entry @@ -384,7 +444,7 @@ extern SDLMAIN_DECLSPEC int SDLCALL SDL_main(int argc, char *argv[]); * * \sa SDL_Init */ -extern DECLSPEC void SDLCALL SDL_SetMainReady(void); +extern SDL_DECLSPEC void SDLCALL SDL_SetMainReady(void); /** * Initializes and launches an SDL application, by doing platform-specific @@ -396,22 +456,25 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void); * using SDL_main (like when using SDL_MAIN_HANDLED). When using this, you do * *not* need SDL_SetMainReady(). * - * \param argc The argc parameter from the application's main() function, or 0 - * if the platform's main-equivalent has no argc - * \param argv The argv parameter from the application's main() function, or - * NULL if the platform's main-equivalent has no argv - * \param mainFunction Your SDL app's C-style main(), an SDL_main_func. NOT - * the function you're calling this from! Its name doesn't - * matter, but its signature must be like int my_main(int - * argc, char* argv[]) + * \param argc the argc parameter from the application's main() function, or 0 + * if the platform's main-equivalent has no argc. + * \param argv the argv parameter from the application's main() function, or + * NULL if the platform's main-equivalent has no argv. + * \param mainFunction your SDL app's C-style main(). NOT the function you're + * calling this from! Its name doesn't matter; it doesn't + * literally have to be `main`. * \param reserved should be NULL (reserved for future use, will probably be - * platform-specific then) - * \returns the return value from mainFunction: 0 on success, -1 on failure; - * SDL_GetError() might have more information on the failure + * platform-specific then). + * \returns the return value from mainFunction: 0 on success, otherwise + * failure; SDL_GetError() might have more information on the + * failure. + * + * \threadsafety Generally this is called once, near startup, from the + * process's initial thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved); +extern SDL_DECLSPEC int SDLCALL SDL_RunApp(int argc, char *argv[], SDL_main_func mainFunction, void *reserved); /** * An entry point for SDL's use in SDL_MAIN_USE_CALLBACKS. @@ -425,23 +488,23 @@ extern DECLSPEC int SDLCALL SDL_RunApp(int argc, char* argv[], SDL_main_func mai * header-only library, and you should not call this directly unless you * _really_ know what you're doing. * - * \param argc standard Unix main argc - * \param argv standard Unix main argv - * \param appinit The application's SDL_AppInit function - * \param appiter The application's SDL_AppIterate function - * \param appevent The application's SDL_AppEvent function - * \param appquit The application's SDL_AppQuit function - * \returns standard Unix main return value + * \param argc standard Unix main argc. + * \param argv standard Unix main argv. + * \param appinit the application's SDL_AppInit function. + * \param appiter the application's SDL_AppIterate function. + * \param appevent the application's SDL_AppEvent function. + * \param appquit the application's SDL_AppQuit function. + * \returns standard Unix main return value. * * \threadsafety It is not safe to call this anywhere except as the only * function call in SDL_main. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char* argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); +extern SDL_DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char *argv[], SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) /** * Register a win32 window class for SDL's use. @@ -462,12 +525,12 @@ extern DECLSPEC int SDLCALL SDL_EnterAppMainCallbacks(int argc, char* argv[], SD * what is specified here. * \param hInst the HINSTANCE to use in WNDCLASSEX::hInstance. If zero, SDL * will use `GetModuleHandle(NULL)` instead. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); +extern SDL_DECLSPEC bool SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); /** * Deregister the win32 window class from an SDL_RegisterApp call. @@ -484,9 +547,9 @@ extern DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); +extern SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void); -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ +#endif /* defined(SDL_PLATFORM_WINDOWS) */ #ifdef SDL_PLATFORM_GDK @@ -495,7 +558,7 @@ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); +extern SDL_DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #endif /* SDL_PLATFORM_GDK */ @@ -508,13 +571,14 @@ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #if !defined(SDL_MAIN_HANDLED) && !defined(SDL_MAIN_NOIMPL) /* include header-only SDL_main implementations */ #if defined(SDL_MAIN_USE_CALLBACKS) \ - || defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) \ - || defined(SDL_PLATFORM_3DS) || defined(SDL_PLATFORM_NGAGE) || defined(SDL_PLATFORM_PS2) || defined(SDL_PLATFORM_PSP) + || defined(SDL_PLATFORM_WINDOWS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) \ + || defined(SDL_PLATFORM_3DS) || defined(SDL_PLATFORM_NGAGE) || defined(SDL_PLATFORM_PS2) || defined(SDL_PLATFORM_PSP) \ + || defined(SDL_PLATFORM_EMSCRIPTEN) /* platforms which main (-equivalent) can be implemented in plain C */ #include - #elif defined(SDL_PLATFORM_WINRT) /* C++ platforms */ + #elif 0 /* C++ platforms (currently none, this used to be here for WinRT, but is left for future platforms that might arrive. */ #ifdef __cplusplus #include #else @@ -528,7 +592,7 @@ extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); #endif /* __GNUC__ */ #endif /* __cplusplus */ - #endif /* C++ platforms like SDL_PLATFORM_WINRT etc */ + #endif /* C++ platforms */ #endif #endif /* SDL_main_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_main_impl.h b/libs/SDL3/include/SDL3/SDL_main_impl.h index 1a5f921e3..feca572bc 100644 --- a/libs/SDL3/include/SDL3/SDL_main_impl.h +++ b/libs/SDL3/include/SDL3/SDL_main_impl.h @@ -19,6 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ +/* WIKI CATEGORY: Main */ + #ifndef SDL_main_impl_h_ #define SDL_main_impl_h_ @@ -65,7 +67,7 @@ /* set up the usual SDL_main stuff if we're not using callbacks or if we are but need the normal entry point. */ #if !defined(SDL_MAIN_USE_CALLBACKS) || defined(SDL_MAIN_CALLBACK_STANDARD) - #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) + #if defined(SDL_PLATFORM_WINDOWS) /* these defines/typedefs are needed for the WinMain() definition */ #ifndef WINAPI @@ -73,8 +75,8 @@ #endif typedef struct HINSTANCE__ * HINSTANCE; - typedef char* LPSTR; - typedef wchar_t* PWSTR; + typedef char *LPSTR; + typedef wchar_t *PWSTR; /* The VC++ compiler needs main/wmain defined, but not for GDK */ #if defined(_MSC_VER) && !defined(SDL_PLATFORM_GDK) @@ -122,66 +124,7 @@ } /* extern "C" */ #endif - /* end of SDL_PLATFORM_WIN32 and SDL_PLATFORM_GDK impls */ - - #elif defined(SDL_PLATFORM_WINRT) - - /* WinRT main based on SDL_winrt_main_NonXAML.cpp, placed in the public domain by David Ludwig 3/13/14 */ - - #include - - /* At least one file in any SDL/WinRT app appears to require compilation - with C++/CX, otherwise a Windows Metadata file won't get created, and - an APPX0702 build error can appear shortly after linking. - - The following set of preprocessor code forces this file to be compiled - as C++/CX, which appears to cause Visual C++ 2012's build tools to - create this .winmd file, and will help allow builds of SDL/WinRT apps - to proceed without error. - - If other files in an app's project enable C++/CX compilation, then it might - be possible for the .cpp file including SDL_main.h to be compiled without /ZW, - for Visual C++'s build tools to create a winmd file, and for the app to - build without APPX0702 errors. In this case, if - SDL_WINRT_METADATA_FILE_AVAILABLE is defined as a C/C++ macro, then - the #error (to force C++/CX compilation) will be disabled. - - Please note that /ZW can be specified on a file-by-file basis. To do this, - right click on the file in Visual C++, click Properties, then change the - setting through the dialog that comes up. - */ - #ifndef SDL_WINRT_METADATA_FILE_AVAILABLE - #if !defined(__cplusplus) || !defined(__cplusplus_winrt) - #error The C++ file that includes SDL_main.h must be compiled as C++ code with /ZW, otherwise build errors due to missing .winmd files can occur. - #endif - #endif - - /* Prevent MSVC++ from warning about threading models when defining our - custom WinMain. The threading model will instead be set via a direct - call to Windows::Foundation::Initialize (rather than via an attributed - function). - - To note, this warning (C4447) does not seem to come up unless this file - is compiled with C++/CX enabled (via the /ZW compiler flag). - */ - #ifdef _MSC_VER - #pragma warning(disable : 4447) - /* Make sure the function to initialize the Windows Runtime gets linked in. */ - #pragma comment(lib, "runtimeobject.lib") - #endif - - #ifdef __cplusplus - extern "C" { - #endif - int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) - { - return SDL_RunApp(0, NULL, SDL_main, NULL); - } - #ifdef __cplusplus - } /* extern "C" */ - #endif - - /* end of WinRT impl */ + /* end of SDL_PLATFORM_WINDOWS impls */ #elif defined(SDL_PLATFORM_NGAGE) /* same typedef as in ngage SDKs e32def.h */ diff --git a/libs/SDL3/include/SDL3/SDL_messagebox.h b/libs/SDL3/include/SDL3/SDL_messagebox.h index b9c4d93f1..ff22baf94 100644 --- a/libs/SDL3/include/SDL3/SDL_messagebox.h +++ b/libs/SDL3/include/SDL3/SDL_messagebox.h @@ -19,10 +19,17 @@ 3. This notice may not be removed or altered from any source distribution. */ +/** + * # CategoryMessagebox + * + * Message box support routines. + */ + #ifndef SDL_messagebox_h_ #define SDL_messagebox_h_ #include +#include #include /* For SDL_Window */ #include @@ -32,68 +39,84 @@ extern "C" { #endif /** - * SDL_MessageBox flags. If supported will display warning icon, etc. + * SDL_MessageBox flags. + * + * If supported will display warning icon, etc. + * + * \since This datatype is available since SDL 3.0.0. */ -typedef enum -{ - SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */ - SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */ - SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */ - SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT = 0x00000080, /**< buttons placed left to right */ - SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT = 0x00000100 /**< buttons placed right to left */ -} SDL_MessageBoxFlags; +typedef Uint32 SDL_MessageBoxFlags; + +#define SDL_MESSAGEBOX_ERROR 0x00000010u /**< error dialog */ +#define SDL_MESSAGEBOX_WARNING 0x00000020u /**< warning dialog */ +#define SDL_MESSAGEBOX_INFORMATION 0x00000040u /**< informational dialog */ +#define SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT 0x00000080u /**< buttons placed left to right */ +#define SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT 0x00000100u /**< buttons placed right to left */ /** - * Flags for SDL_MessageBoxButtonData. + * SDL_MessageBoxButtonData flags. + * + * \since This datatype is available since SDL 3.0.0. */ -typedef enum -{ - SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, /**< Marks the default button when return is hit */ - SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002 /**< Marks the default button when escape is hit */ -} SDL_MessageBoxButtonFlags; +typedef Uint32 SDL_MessageBoxButtonFlags; + +#define SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT 0x00000001u /**< Marks the default button when return is hit */ +#define SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT 0x00000002u /**< Marks the default button when escape is hit */ /** * Individual button data. + * + * \since This struct is available since SDL 3.0.0. */ -typedef struct +typedef struct SDL_MessageBoxButtonData { - Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */ + SDL_MessageBoxButtonFlags flags; int buttonID; /**< User defined button id (value returned via SDL_ShowMessageBox) */ const char *text; /**< The UTF-8 button text */ } SDL_MessageBoxButtonData; /** * RGB value used in a message box color scheme + * + * \since This struct is available since SDL 3.0.0. */ -typedef struct +typedef struct SDL_MessageBoxColor { Uint8 r, g, b; } SDL_MessageBoxColor; -typedef enum +/** + * An enumeration of indices inside the colors array of + * SDL_MessageBoxColorScheme. + */ +typedef enum SDL_MessageBoxColorType { SDL_MESSAGEBOX_COLOR_BACKGROUND, SDL_MESSAGEBOX_COLOR_TEXT, SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, - SDL_MESSAGEBOX_COLOR_MAX + SDL_MESSAGEBOX_COLOR_COUNT /**< Size of the colors array of SDL_MessageBoxColorScheme. */ } SDL_MessageBoxColorType; /** * A set of colors to use for message box dialogs + * + * \since This struct is available since SDL 3.0.0. */ -typedef struct +typedef struct SDL_MessageBoxColorScheme { - SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX]; + SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_COUNT]; } SDL_MessageBoxColorScheme; /** * MessageBox structure containing title, text, window, etc. + * + * \since This struct is available since SDL 3.0.0. */ -typedef struct +typedef struct SDL_MessageBoxData { - Uint32 flags; /**< ::SDL_MessageBoxFlags */ + SDL_MessageBoxFlags flags; SDL_Window *window; /**< Parent window, can be NULL */ const char *title; /**< UTF-8 title */ const char *message; /**< UTF-8 message text */ @@ -101,7 +124,7 @@ typedef struct int numbuttons; const SDL_MessageBoxButtonData *buttons; - const SDL_MessageBoxColorScheme *colorScheme; /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */ + const SDL_MessageBoxColorScheme *colorScheme; /**< SDL_MessageBoxColorScheme, can be NULL to use system settings */ } SDL_MessageBoxData; /** @@ -128,16 +151,17 @@ typedef struct * to stderr if you can. * * \param messageboxdata the SDL_MessageBoxData structure with title, text and - * other options - * \param buttonid the pointer to which user id of hit button should be copied - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * other options. + * \param buttonid the pointer to which user id of hit button should be + * copied. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ShowSimpleMessageBox */ -extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); /** * Display a simple modal message box. @@ -168,18 +192,18 @@ extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *message * concern, check the return value from this function and fall back to writing * to stderr if you can. * - * \param flags an SDL_MessageBoxFlags value - * \param title UTF-8 title text - * \param message UTF-8 message text - * \param window the parent window, or NULL for no parent - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param flags an SDL_MessageBoxFlags value. + * \param title uTF-8 title text. + * \param message uTF-8 message text. + * \param window the parent window, or NULL for no parent. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ShowMessageBox */ -extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char *title, const char *message, SDL_Window *window); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_metal.h b/libs/SDL3/include/SDL3/SDL_metal.h index e08ff3610..7c9aece7a 100644 --- a/libs/SDL3/include/SDL3/SDL_metal.h +++ b/libs/SDL3/include/SDL3/SDL_metal.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_metal.h + * # CategoryMetal * - * Header file for functions to creating Metal layers and views on SDL windows. + * Functions to creating Metal layers and views on SDL windows. */ #ifndef SDL_metal_h_ @@ -37,9 +37,9 @@ extern "C" { #endif /** - * A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS). + * A handle to a CAMetalLayer-backed NSView (macOS) or UIView (iOS/tvOS). * - * \note This can be cast directly to an NSView or UIView. + * \since This datatype is available since SDL 3.0.0. */ typedef void *SDL_MetalView; @@ -58,15 +58,15 @@ typedef void *SDL_MetalView; * The returned handle can be casted directly to a NSView or UIView. To access * the backing CAMetalLayer, call SDL_Metal_GetLayer(). * - * \param window the window - * \returns handle NSView or UIView + * \param window the window. + * \returns handle NSView or UIView. * * \since This function is available since SDL 3.0.0. * * \sa SDL_Metal_DestroyView * \sa SDL_Metal_GetLayer */ -extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window); +extern SDL_DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window *window); /** * Destroy an existing SDL_MetalView object. @@ -74,23 +74,23 @@ extern DECLSPEC SDL_MetalView SDLCALL SDL_Metal_CreateView(SDL_Window * window); * This should be called before SDL_DestroyWindow, if SDL_Metal_CreateView was * called after SDL_CreateWindow. * - * \param view the SDL_MetalView object + * \param view the SDL_MetalView object. * * \since This function is available since SDL 3.0.0. * * \sa SDL_Metal_CreateView */ -extern DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view); +extern SDL_DECLSPEC void SDLCALL SDL_Metal_DestroyView(SDL_MetalView view); /** * Get a pointer to the backing CAMetalLayer for the given view. * - * \param view the SDL_MetalView object - * \returns a pointer + * \param view the SDL_MetalView object. + * \returns a pointer. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void *SDLCALL SDL_Metal_GetLayer(SDL_MetalView view); +extern SDL_DECLSPEC void * SDLCALL SDL_Metal_GetLayer(SDL_MetalView view); /* @} *//* Metal support functions */ diff --git a/libs/SDL3/include/SDL3/SDL_misc.h b/libs/SDL3/include/SDL3/SDL_misc.h index e50d91bd1..2d5aa153e 100644 --- a/libs/SDL3/include/SDL3/SDL_misc.h +++ b/libs/SDL3/include/SDL3/SDL_misc.h @@ -20,15 +20,16 @@ */ /** - * \file SDL_misc.h + * # CategoryMisc * - * Include file for SDL API functions that don't fit elsewhere. + * SDL API functions that don't fit elsewhere. */ #ifndef SDL_misc_h_ #define SDL_misc_h_ #include +#include #include @@ -59,14 +60,14 @@ extern "C" { * All this to say: this function can be useful, but you should definitely * test it on every platform you target. * - * \param url A valid URL/URI to open. Use `file:///full/path/to/file` for + * \param url a valid URL/URI to open. Use `file:///full/path/to/file` for * local files, if supported. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_OpenURL(const char *url); +extern SDL_DECLSPEC bool SDLCALL SDL_OpenURL(const char *url); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_mouse.h b/libs/SDL3/include/SDL3/SDL_mouse.h index a374277c1..44060091f 100644 --- a/libs/SDL3/include/SDL3/SDL_mouse.h +++ b/libs/SDL3/include/SDL3/SDL_mouse.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_mouse.h + * # CategoryMouse * - * Include file for SDL mouse event handling. + * SDL mouse handling. */ #ifndef SDL_mouse_h_ @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -38,59 +39,111 @@ extern "C" { #endif +/** + * This is a unique ID for a mouse for the time it is connected to the system, + * and is never reused for the lifetime of the application. + * + * If the mouse is disconnected and reconnected, it will get a new ID. + * + * The value 0 is an invalid ID. + * + * \since This datatype is available since SDL 3.0.0. + */ typedef Uint32 SDL_MouseID; -typedef struct SDL_Cursor SDL_Cursor; /**< Implementation dependent */ +/** + * The structure used to identify an SDL cursor. + * + * This is opaque data. + * + * \since This struct is available since SDL 3.0.0. + */ +typedef struct SDL_Cursor SDL_Cursor; /** * Cursor types for SDL_CreateSystemCursor(). + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_SystemCursor { - SDL_SYSTEM_CURSOR_ARROW, /**< Arrow */ - SDL_SYSTEM_CURSOR_IBEAM, /**< I-beam */ - SDL_SYSTEM_CURSOR_WAIT, /**< Wait */ - SDL_SYSTEM_CURSOR_CROSSHAIR, /**< Crosshair */ - SDL_SYSTEM_CURSOR_WAITARROW, /**< Small wait cursor (or Wait if not available) */ - SDL_SYSTEM_CURSOR_SIZENWSE, /**< Double arrow pointing northwest and southeast */ - SDL_SYSTEM_CURSOR_SIZENESW, /**< Double arrow pointing northeast and southwest */ - SDL_SYSTEM_CURSOR_SIZEWE, /**< Double arrow pointing west and east */ - SDL_SYSTEM_CURSOR_SIZENS, /**< Double arrow pointing north and south */ - SDL_SYSTEM_CURSOR_SIZEALL, /**< Four pointed arrow pointing north, south, east, and west */ - SDL_SYSTEM_CURSOR_NO, /**< Slashed circle or crossbones */ - SDL_SYSTEM_CURSOR_HAND, /**< Hand */ - SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT, /**< Window resize top-left (or SIZENWSE) */ - SDL_SYSTEM_CURSOR_WINDOW_TOP, /**< Window resize top (or SIZENS) */ - SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT, /**< Window resize top-right (or SIZENESW) */ - SDL_SYSTEM_CURSOR_WINDOW_RIGHT, /**< Window resize right (or SIZEWE) */ - SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT, /**< Window resize bottom-right (or SIZENWSE) */ - SDL_SYSTEM_CURSOR_WINDOW_BOTTOM, /**< Window resize bottom (or SIZENS) */ - SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT, /**< Window resize bottom-left (or SIZENESW) */ - SDL_SYSTEM_CURSOR_WINDOW_LEFT, /**< Window resize left (or SIZEWE) */ - SDL_NUM_SYSTEM_CURSORS + SDL_SYSTEM_CURSOR_DEFAULT, /**< Default cursor. Usually an arrow. */ + SDL_SYSTEM_CURSOR_TEXT, /**< Text selection. Usually an I-beam. */ + SDL_SYSTEM_CURSOR_WAIT, /**< Wait. Usually an hourglass or watch or spinning ball. */ + SDL_SYSTEM_CURSOR_CROSSHAIR, /**< Crosshair. */ + SDL_SYSTEM_CURSOR_PROGRESS, /**< Program is busy but still interactive. Usually it's WAIT with an arrow. */ + SDL_SYSTEM_CURSOR_NWSE_RESIZE, /**< Double arrow pointing northwest and southeast. */ + SDL_SYSTEM_CURSOR_NESW_RESIZE, /**< Double arrow pointing northeast and southwest. */ + SDL_SYSTEM_CURSOR_EW_RESIZE, /**< Double arrow pointing west and east. */ + SDL_SYSTEM_CURSOR_NS_RESIZE, /**< Double arrow pointing north and south. */ + SDL_SYSTEM_CURSOR_MOVE, /**< Four pointed arrow pointing north, south, east, and west. */ + SDL_SYSTEM_CURSOR_NOT_ALLOWED, /**< Not permitted. Usually a slashed circle or crossbones. */ + SDL_SYSTEM_CURSOR_POINTER, /**< Pointer that indicates a link. Usually a pointing hand. */ + SDL_SYSTEM_CURSOR_NW_RESIZE, /**< Window resize top-left. This may be a single arrow or a double arrow like NWSE_RESIZE. */ + SDL_SYSTEM_CURSOR_N_RESIZE, /**< Window resize top. May be NS_RESIZE. */ + SDL_SYSTEM_CURSOR_NE_RESIZE, /**< Window resize top-right. May be NESW_RESIZE. */ + SDL_SYSTEM_CURSOR_E_RESIZE, /**< Window resize right. May be EW_RESIZE. */ + SDL_SYSTEM_CURSOR_SE_RESIZE, /**< Window resize bottom-right. May be NWSE_RESIZE. */ + SDL_SYSTEM_CURSOR_S_RESIZE, /**< Window resize bottom. May be NS_RESIZE. */ + SDL_SYSTEM_CURSOR_SW_RESIZE, /**< Window resize bottom-left. May be NESW_RESIZE. */ + SDL_SYSTEM_CURSOR_W_RESIZE, /**< Window resize left. May be EW_RESIZE. */ + SDL_SYSTEM_CURSOR_COUNT } SDL_SystemCursor; /** * Scroll direction types for the Scroll event + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_MouseWheelDirection { SDL_MOUSEWHEEL_NORMAL, /**< The scroll direction is normal */ SDL_MOUSEWHEEL_FLIPPED /**< The scroll direction is flipped / natural */ } SDL_MouseWheelDirection; +/** + * A bitmask of pressed mouse buttons, as reported by SDL_GetMouseState, etc. + * + * - Button 1: Left mouse button + * - Button 2: Middle mouse button + * - Button 3: Right mouse button + * - Button 4: Side mouse button 1 + * - Button 5: Side mouse button 2 + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_GetMouseState + * \sa SDL_GetGlobalMouseState + * \sa SDL_GetRelativeMouseState + */ +typedef Uint32 SDL_MouseButtonFlags; + +#define SDL_BUTTON_LEFT 1 +#define SDL_BUTTON_MIDDLE 2 +#define SDL_BUTTON_RIGHT 3 +#define SDL_BUTTON_X1 4 +#define SDL_BUTTON_X2 5 + +#define SDL_BUTTON_MASK(X) (1u << ((X)-1)) +#define SDL_BUTTON_LMASK SDL_BUTTON_MASK(SDL_BUTTON_LEFT) +#define SDL_BUTTON_MMASK SDL_BUTTON_MASK(SDL_BUTTON_MIDDLE) +#define SDL_BUTTON_RMASK SDL_BUTTON_MASK(SDL_BUTTON_RIGHT) +#define SDL_BUTTON_X1MASK SDL_BUTTON_MASK(SDL_BUTTON_X1) +#define SDL_BUTTON_X2MASK SDL_BUTTON_MASK(SDL_BUTTON_X2) + + /* Function prototypes */ /** * Return whether a mouse is currently connected. * - * \returns SDL_TRUE if a mouse is connected, SDL_FALSE otherwise. + * \returns true if a mouse is connected, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetMice */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasMouse(void); +extern SDL_DECLSPEC bool SDLCALL SDL_HasMouse(void); /** * Get a list of currently connected mice. @@ -100,24 +153,25 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasMouse(void); * You should wait for input from a device before you consider it actively in * use. * - * \param count a pointer filled in with the number of mice returned - * \returns a 0 terminated array of mouse instance IDs which should be freed - * with SDL_free(), or NULL on error; call SDL_GetError() for more - * details. + * \param count a pointer filled in with the number of mice returned, may be + * NULL. + * \returns a 0 terminated array of mouse instance IDs or NULL on failure; + * call SDL_GetError() for more information. This should be freed + * with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetMouseInstanceName + * \sa SDL_GetMouseNameForID * \sa SDL_HasMouse */ -extern DECLSPEC SDL_MouseID *SDLCALL SDL_GetMice(int *count); +extern SDL_DECLSPEC SDL_MouseID * SDLCALL SDL_GetMice(int *count); /** * Get the name of a mouse. * * This function returns "" if the mouse doesn't have a name. * - * \param instance_id the mouse instance ID + * \param instance_id the mouse instance ID. * \returns the name of the selected mouse, or NULL on failure; call * SDL_GetError() for more information. * @@ -125,7 +179,7 @@ extern DECLSPEC SDL_MouseID *SDLCALL SDL_GetMice(int *count); * * \sa SDL_GetMice */ -extern DECLSPEC const char *SDLCALL SDL_GetMouseInstanceName(SDL_MouseID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetMouseNameForID(SDL_MouseID instance_id); /** * Get the window which currently has mouse focus. @@ -134,21 +188,21 @@ extern DECLSPEC const char *SDLCALL SDL_GetMouseInstanceName(SDL_MouseID instanc * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); /** * Retrieve the current state of the mouse. * * The current button state is returned as a button bitmask, which can be - * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the + * tested using the SDL_BUTTON_MASK(X) macro (where `X` is generally 1 for the * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the * mouse cursor position relative to the focus window. You can pass NULL for * either `x` or `y`. * * \param x the x coordinate of the mouse cursor position relative to the - * focus window + * focus window. * \param y the y coordinate of the mouse cursor position relative to the - * focus window + * focus window. * \returns a 32-bit button bitmask of the current button state. * * \since This function is available since SDL 3.0.0. @@ -156,7 +210,7 @@ extern DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); * \sa SDL_GetGlobalMouseState * \sa SDL_GetRelativeMouseState */ -extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(float *x, float *y); +extern SDL_DECLSPEC SDL_MouseButtonFlags SDLCALL SDL_GetMouseState(float *x, float *y); /** * Get the current state of the mouse in relation to the desktop. @@ -175,37 +229,37 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetMouseState(float *x, float *y); * reason to use this function, you probably want SDL_GetMouseState() instead. * * \param x filled in with the current X coord relative to the desktop; can be - * NULL + * NULL. * \param y filled in with the current Y coord relative to the desktop; can be - * NULL + * NULL. * \returns the current button state as a bitmask which can be tested using - * the SDL_BUTTON(X) macros. + * the SDL_BUTTON_MASK(X) macros. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CaptureMouse * \sa SDL_GetMouseState */ -extern DECLSPEC Uint32 SDLCALL SDL_GetGlobalMouseState(float *x, float *y); +extern SDL_DECLSPEC SDL_MouseButtonFlags SDLCALL SDL_GetGlobalMouseState(float *x, float *y); /** * Retrieve the relative state of the mouse. * * The current button state is returned as a button bitmask, which can be - * tested using the `SDL_BUTTON(X)` macros (where `X` is generally 1 for the - * left, 2 for middle, 3 for the right button), and `x` and `y` are set to the - * mouse deltas since the last call to SDL_GetRelativeMouseState() or since - * event initialization. You can pass NULL for either `x` or `y`. + * tested using the `SDL_BUTTON_MASK(X)` macros (where `X` is generally 1 for + * the left, 2 for middle, 3 for the right button), and `x` and `y` are set to + * the mouse deltas since the last call to SDL_GetRelativeMouseState() or + * since event initialization. You can pass NULL for either `x` or `y`. * - * \param x a pointer filled with the last recorded x coordinate of the mouse - * \param y a pointer filled with the last recorded y coordinate of the mouse + * \param x a pointer filled with the last recorded x coordinate of the mouse. + * \param y a pointer filled with the last recorded y coordinate of the mouse. * \returns a 32-bit button bitmask of the relative button state. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetMouseState */ -extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(float *x, float *y); +extern SDL_DECLSPEC SDL_MouseButtonFlags SDLCALL SDL_GetRelativeMouseState(float *x, float *y); /** * Move the mouse cursor to the given position within the window. @@ -218,15 +272,15 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(float *x, float *y); * mouse when used over Microsoft Remote Desktop. * * \param window the window to move the mouse into, or NULL for the current - * mouse focus - * \param x the x coordinate within the window - * \param y the y coordinate within the window + * mouse focus. + * \param x the x coordinate within the window. + * \param y the y coordinate within the window. * * \since This function is available since SDL 3.0.0. * * \sa SDL_WarpMouseGlobal */ -extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, +extern SDL_DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, float x, float y); /** @@ -240,35 +294,49 @@ extern DECLSPEC void SDLCALL SDL_WarpMouseInWindow(SDL_Window * window, * Note that this function will appear to succeed, but not actually move the * mouse when used over Microsoft Remote Desktop. * - * \param x the x coordinate - * \param y the y coordinate - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param x the x coordinate. + * \param y the y coordinate. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_WarpMouseInWindow */ -extern DECLSPEC int SDLCALL SDL_WarpMouseGlobal(float x, float y); +extern SDL_DECLSPEC bool SDLCALL SDL_WarpMouseGlobal(float x, float y); /** - * Set relative mouse mode. + * Set relative mouse mode for a window. * - * While the mouse is in relative mode, the cursor is hidden, the mouse - * position is constrained to the window, and SDL will report continuous - * relative mouse motion even if the mouse is at the edge of the window. + * While the window has focus and relative mouse mode is enabled, the cursor + * is hidden, the mouse position is constrained to the window, and SDL will + * report continuous relative mouse motion even if the mouse is at the edge of + * the window. * - * This function will flush any pending mouse motion. + * This function will flush any pending mouse motion for this window. * - * \param enabled SDL_TRUE to enable relative mode, SDL_FALSE to disable. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param enabled true to enable relative mode, false to disable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetWindowRelativeMouseMode + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowRelativeMouseMode(SDL_Window *window, bool enabled); + +/** + * Query whether relative mouse mode is enabled for a window. + * + * \param window the window to query. + * \returns true if relative mode is enabled for a window or false otherwise. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetRelativeMouseMode + * \sa SDL_SetWindowRelativeMouseMode */ -extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowRelativeMouseMode(SDL_Window *window); /** * Capture the mouse and to track input outside an SDL window. @@ -285,7 +353,7 @@ extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled); * mouse while the user is dragging something, until the user releases a mouse * button. It is not recommended that you capture the mouse for long periods * of time, such as the entire time your app is running. For that, you should - * probably use SDL_SetRelativeMouseMode() or SDL_SetWindowMouseGrab(), + * probably use SDL_SetWindowRelativeMouseMode() or SDL_SetWindowMouseGrab(), * depending on your goals. * * While captured, mouse events still report coordinates relative to the @@ -297,35 +365,24 @@ extern DECLSPEC int SDLCALL SDL_SetRelativeMouseMode(SDL_bool enabled); * While capturing is enabled, the current window will have the * `SDL_WINDOW_MOUSE_CAPTURE` flag set. * - * Please note that as of SDL 2.0.22, SDL will attempt to "auto capture" the - * mouse while the user is pressing a button; this is to try and make mouse - * behavior more consistent between platforms, and deal with the common case - * of a user dragging the mouse outside of the window. This means that if you - * are calling SDL_CaptureMouse() only to deal with this situation, you no - * longer have to (although it is safe to do so). If this causes problems for - * your app, you can disable auto capture by setting the + * Please note that SDL will attempt to "auto capture" the mouse while the + * user is pressing a button; this is to try and make mouse behavior more + * consistent between platforms, and deal with the common case of a user + * dragging the mouse outside of the window. This means that if you are + * calling SDL_CaptureMouse() only to deal with this situation, you do not + * have to (although it is safe to do so). If this causes problems for your + * app, you can disable auto capture by setting the * `SDL_HINT_MOUSE_AUTO_CAPTURE` hint to zero. * - * \param enabled SDL_TRUE to enable capturing, SDL_FALSE to disable. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param enabled true to enable capturing, false to disable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetGlobalMouseState */ -extern DECLSPEC int SDLCALL SDL_CaptureMouse(SDL_bool enabled); - -/** - * Query whether relative mouse mode is enabled. - * - * \returns SDL_TRUE if relative mode is enabled or SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_SetRelativeMouseMode - */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void); +extern SDL_DECLSPEC bool SDLCALL SDL_CaptureMouse(bool enabled); /** * Create a cursor using the specified bitmap data and mask (in MSB format). @@ -348,17 +405,17 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void); * hide the cursor and draw your own as part of your game's rendering, but it * will be bound to the framerate. * - * Also, since SDL 2.0.0, SDL_CreateSystemCursor() is available, which - * provides twelve readily available system cursors to pick from. - * - * \param data the color value for each pixel of the cursor - * \param mask the mask value for each pixel of the cursor - * \param w the width of the cursor - * \param h the height of the cursor - * \param hot_x the X-axis location of the upper left corner of the cursor - * relative to the actual mouse position - * \param hot_y the Y-axis location of the upper left corner of the cursor - * relative to the actual mouse position + * Also, SDL_CreateSystemCursor() is available, which provides several + * readily-available system cursors to pick from. + * + * \param data the color value for each pixel of the cursor. + * \param mask the mask value for each pixel of the cursor. + * \param w the width of the cursor. + * \param h the height of the cursor. + * \param hot_x the x-axis offset from the left of the cursor image to the + * mouse x position, in the range of 0 to `w` - 1. + * \param hot_y the y-axis offset from the top of the cursor image to the + * mouse y position, in the range of 0 to `h` - 1. * \returns a new cursor with the specified parameters on success or NULL on * failure; call SDL_GetError() for more information. * @@ -369,7 +426,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetRelativeMouseMode(void); * \sa SDL_DestroyCursor * \sa SDL_SetCursor */ -extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 * data, const Uint8 * mask, int w, int h, int hot_x, int hot_y); @@ -377,9 +434,19 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, /** * Create a color cursor. * - * \param surface an SDL_Surface structure representing the cursor image - * \param hot_x the x position of the cursor hot spot - * \param hot_y the y position of the cursor hot spot + * If this function is passed a surface with alternate representations, the + * surface will be interpreted as the content to be used for 100% display + * scale, and the alternate representations will be used for high DPI + * situations. For example, if the original surface is 32x32, then on a 2x + * macOS display or 200% display scale on Windows, a 64x64 version of the + * image will be used, if available. If a matching version of the image isn't + * available, the closest larger size image will be downscaled to the + * appropriate size and be used instead, if available. Otherwise, the closest + * smaller image will be upscaled and be used instead. + * + * \param surface an SDL_Surface structure representing the cursor image. + * \param hot_x the x position of the cursor hot spot. + * \param hot_y the y position of the cursor hot spot. * \returns the new cursor on success or NULL on failure; call SDL_GetError() * for more information. * @@ -390,14 +457,14 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateCursor(const Uint8 * data, * \sa SDL_DestroyCursor * \sa SDL_SetCursor */ -extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y); /** * Create a system cursor. * - * \param id an SDL_SystemCursor enum value + * \param id an SDL_SystemCursor enum value. * \returns a cursor on success or NULL on failure; call SDL_GetError() for * more information. * @@ -405,7 +472,7 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateColorCursor(SDL_Surface *surface, * * \sa SDL_DestroyCursor */ -extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); /** * Set the active cursor. @@ -415,15 +482,15 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_CreateSystemCursor(SDL_SystemCursor id); * the display. SDL_SetCursor(NULL) can be used to force cursor redraw, if * this is desired for any reason. * - * \param cursor a cursor to make active - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param cursor a cursor to make active. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetCursor */ -extern DECLSPEC int SDLCALL SDL_SetCursor(SDL_Cursor * cursor); +extern SDL_DECLSPEC bool SDLCALL SDL_SetCursor(SDL_Cursor *cursor); /** * Get the active cursor. @@ -437,7 +504,7 @@ extern DECLSPEC int SDLCALL SDL_SetCursor(SDL_Cursor * cursor); * * \sa SDL_SetCursor */ -extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void); +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_GetCursor(void); /** * Get the default cursor. @@ -445,11 +512,12 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void); * You do not have to call SDL_DestroyCursor() on the return value, but it is * safe to do so. * - * \returns the default cursor on success or NULL on failure. + * \returns the default cursor on success or NULL on failuree; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void); +extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_GetDefaultCursor(void); /** * Free a previously-created cursor. @@ -457,7 +525,7 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void); * Use this function to free cursor resources created with SDL_CreateCursor(), * SDL_CreateColorCursor() or SDL_CreateSystemCursor(). * - * \param cursor the cursor to free + * \param cursor the cursor to free. * * \since This function is available since SDL 3.0.0. * @@ -465,65 +533,46 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void); * \sa SDL_CreateCursor * \sa SDL_CreateSystemCursor */ -extern DECLSPEC void SDLCALL SDL_DestroyCursor(SDL_Cursor * cursor); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyCursor(SDL_Cursor *cursor); /** * Show the cursor. * - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CursorVisible * \sa SDL_HideCursor */ -extern DECLSPEC int SDLCALL SDL_ShowCursor(void); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowCursor(void); /** * Hide the cursor. * - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CursorVisible * \sa SDL_ShowCursor */ -extern DECLSPEC int SDLCALL SDL_HideCursor(void); +extern SDL_DECLSPEC bool SDLCALL SDL_HideCursor(void); /** * Return whether the cursor is currently being shown. * - * \returns `SDL_TRUE` if the cursor is being shown, or `SDL_FALSE` if the - * cursor is hidden. + * \returns `true` if the cursor is being shown, or `false` if the cursor is + * hidden. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HideCursor * \sa SDL_ShowCursor */ -extern DECLSPEC SDL_bool SDLCALL SDL_CursorVisible(void); - -/** - * Used as a mask when testing buttons in buttonstate. - * - * - Button 1: Left mouse button - * - Button 2: Middle mouse button - * - Button 3: Right mouse button - */ -#define SDL_BUTTON(X) (1 << ((X)-1)) -#define SDL_BUTTON_LEFT 1 -#define SDL_BUTTON_MIDDLE 2 -#define SDL_BUTTON_RIGHT 3 -#define SDL_BUTTON_X1 4 -#define SDL_BUTTON_X2 5 -#define SDL_BUTTON_LMASK SDL_BUTTON(SDL_BUTTON_LEFT) -#define SDL_BUTTON_MMASK SDL_BUTTON(SDL_BUTTON_MIDDLE) -#define SDL_BUTTON_RMASK SDL_BUTTON(SDL_BUTTON_RIGHT) -#define SDL_BUTTON_X1MASK SDL_BUTTON(SDL_BUTTON_X1) -#define SDL_BUTTON_X2MASK SDL_BUTTON(SDL_BUTTON_X2) +extern SDL_DECLSPEC bool SDLCALL SDL_CursorVisible(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_mutex.h b/libs/SDL3/include/SDL3/SDL_mutex.h index 8c6c5a6da..03cb80cfb 100644 --- a/libs/SDL3/include/SDL3/SDL_mutex.h +++ b/libs/SDL3/include/SDL3/SDL_mutex.h @@ -23,13 +23,15 @@ #define SDL_mutex_h_ /** - * \file SDL_mutex.h + * # CategoryMutex * - * Functions to provide thread synchronization primitives. + * Functions to provide thread synchronization primitives. */ #include +#include #include +#include /******************************************************************************/ /* Enable thread safety attributes only with clang. @@ -115,20 +117,23 @@ extern "C" { #endif -/** - * Synchronization functions which can time out return this value - * if they time out. - */ -#define SDL_MUTEX_TIMEDOUT 1 - - /** * \name Mutex functions */ /* @{ */ -/* The SDL mutex structure, defined in SDL_sysmutex.c */ -struct SDL_Mutex; +/** + * A means to serialize access to a resource between threads. + * + * Mutexes (short for "mutual exclusion") are a synchronization primitive that + * allows exactly one thread to proceed at a time. + * + * Wikipedia has a thorough explanation of the concept: + * + * https://en.wikipedia.org/wiki/Mutex + * + * \since This struct is available since SDL 3.0.0. + */ typedef struct SDL_Mutex SDL_Mutex; /** @@ -151,7 +156,7 @@ typedef struct SDL_Mutex SDL_Mutex; * \sa SDL_TryLockMutex * \sa SDL_UnlockMutex */ -extern DECLSPEC SDL_Mutex *SDLCALL SDL_CreateMutex(void); +extern SDL_DECLSPEC SDL_Mutex * SDLCALL SDL_CreateMutex(void); /** * Lock the mutex. @@ -168,38 +173,35 @@ extern DECLSPEC SDL_Mutex *SDLCALL SDL_CreateMutex(void); * having locked nothing. If the mutex is valid, this function will always * block until it can lock the mutex, and return with it locked. * - * \param mutex the mutex to lock + * \param mutex the mutex to lock. * * \since This function is available since SDL 3.0.0. * * \sa SDL_TryLockMutex * \sa SDL_UnlockMutex */ -extern DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); +extern SDL_DECLSPEC void SDLCALL SDL_LockMutex(SDL_Mutex *mutex) SDL_ACQUIRE(mutex); /** * Try to lock a mutex without blocking. * * This works just like SDL_LockMutex(), but if the mutex is not available, - * this function returns `SDL_MUTEX_TIMEDOUT` immediately. + * this function returns false immediately. * * This technique is useful if you need exclusive access to a resource but * don't want to wait for it, and will return to it to try again later. * - * This function does not fail; if mutex is NULL, it will return 0 immediately - * having locked nothing. If the mutex is valid, this function will always - * either lock the mutex and return 0, or return SDL_MUTEX_TIMEOUT and lock - * nothing. + * This function returns true if passed a NULL mutex. * - * \param mutex the mutex to try to lock - * \returns 0 or `SDL_MUTEX_TIMEDOUT` + * \param mutex the mutex to try to lock. + * \returns true on success, false if the mutex would block. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockMutex * \sa SDL_UnlockMutex */ -extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0, mutex); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0, mutex); /** * Unlock the mutex. @@ -218,7 +220,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockMutex(SDL_Mutex *mutex) SDL_TRY_ACQUIRE(0 * \sa SDL_LockMutex * \sa SDL_TryLockMutex */ -extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex); /** * Destroy a mutex created with SDL_CreateMutex(). @@ -229,13 +231,13 @@ extern DECLSPEC void SDLCALL SDL_UnlockMutex(SDL_Mutex *mutex) SDL_RELEASE(mutex * to destroy a locked mutex, and may result in undefined behavior depending * on the platform. * - * \param mutex the mutex to destroy + * \param mutex the mutex to destroy. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateMutex */ -extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_Mutex *mutex); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_Mutex *mutex); /* @} *//* Mutex functions */ @@ -245,16 +247,25 @@ extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_Mutex *mutex); */ /* @{ */ -/* The SDL read/write lock structure, defined in SDL_sysrwlock.c */ -struct SDL_RWLock; -typedef struct SDL_RWLock SDL_RWLock; - -/* - * Synchronization functions which can time out return this value - * if they time out. +/** + * A mutex that allows read-only threads to run in parallel. + * + * A rwlock is roughly the same concept as SDL_Mutex, but allows threads that + * request read-only access to all hold the lock at the same time. If a thread + * requests write access, it will block until all read-only threads have + * released the lock, and no one else can hold the thread (for reading or + * writing) at the same time as the writing thread. + * + * This can be more efficient in cases where several threads need to access + * data frequently, but changes to that data are rare. + * + * There are other rules that apply to rwlocks that don't apply to mutexes, + * about how threads are scheduled and when they can be recursively locked. + * These are documented in the other rwlock functions. + * + * \since This struct is available since SDL 3.0.0. */ -#define SDL_RWLOCK_TIMEDOUT SDL_MUTEX_TIMEDOUT - +typedef struct SDL_RWLock SDL_RWLock; /** * Create a new read/write lock. @@ -296,7 +307,7 @@ typedef struct SDL_RWLock SDL_RWLock; * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ -extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void); +extern SDL_DECLSPEC SDL_RWLock * SDLCALL SDL_CreateRWLock(void); /** * Lock the read/write lock for _read only_ operations. @@ -325,7 +336,7 @@ extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void); * having locked nothing. If the rwlock is valid, this function will always * block until it can lock the mutex, and return with it locked. * - * \param rwlock the read/write lock to lock + * \param rwlock the read/write lock to lock. * * \since This function is available since SDL 3.0.0. * @@ -333,7 +344,7 @@ extern DECLSPEC SDL_RWLock *SDLCALL SDL_CreateRWLock(void); * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ -extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock); +extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_ACQUIRE_SHARED(rwlock); /** * Lock the read/write lock for _write_ operations. @@ -356,7 +367,7 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_AC * having locked nothing. If the rwlock is valid, this function will always * block until it can lock the mutex, and return with it locked. * - * \param rwlock the read/write lock to lock + * \param rwlock the read/write lock to lock. * * \since This function is available since SDL 3.0.0. * @@ -364,13 +375,13 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForReading(SDL_RWLock *rwlock) SDL_AC * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ -extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock); +extern SDL_DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_ACQUIRE(rwlock); /** * Try to lock a read/write lock _for reading_ without blocking. * * This works just like SDL_LockRWLockForReading(), but if the rwlock is not - * available, then this function returns `SDL_RWLOCK_TIMEDOUT` immediately. + * available, then this function returns false immediately. * * This technique is useful if you need access to a resource but don't want to * wait for it, and will return to it to try again later. @@ -378,13 +389,10 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_AC * Trying to lock for read-only access can succeed if other threads are * holding read-only locks, as this won't prevent access. * - * This function does not fail; if rwlock is NULL, it will return 0 - * immediately having locked nothing. If rwlock is valid, this function will - * always either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT - * and lock nothing. + * This function returns true if passed a NULL rwlock. * - * \param rwlock the rwlock to try to lock - * \returns 0 or `SDL_RWLOCK_TIMEDOUT` + * \param rwlock the rwlock to try to lock. + * \returns true on success, false if the lock would block. * * \since This function is available since SDL 3.0.0. * @@ -392,13 +400,13 @@ extern DECLSPEC void SDLCALL SDL_LockRWLockForWriting(SDL_RWLock *rwlock) SDL_AC * \sa SDL_TryLockRWLockForWriting * \sa SDL_UnlockRWLock */ -extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE_SHARED(0, rwlock); /** * Try to lock a read/write lock _for writing_ without blocking. * * This works just like SDL_LockRWLockForWriting(), but if the rwlock is not - * available, this function returns `SDL_RWLOCK_TIMEDOUT` immediately. + * available, then this function returns false immediately. * * This technique is useful if you need exclusive access to a resource but * don't want to wait for it, and will return to it to try again later. @@ -411,13 +419,10 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_ * read-only lock. Doing so results in undefined behavior. Unlock the * read-only lock before requesting a write lock. * - * This function does not fail; if rwlock is NULL, it will return 0 - * immediately having locked nothing. If rwlock is valid, this function will - * always either lock the rwlock and return 0, or return SDL_RWLOCK_TIMEOUT - * and lock nothing. + * This function returns true if passed a NULL rwlock. * - * \param rwlock the rwlock to try to lock - * \returns 0 or `SDL_RWLOCK_TIMEDOUT` + * \param rwlock the rwlock to try to lock. + * \returns true on success, false if the lock would block. * * \since This function is available since SDL 3.0.0. * @@ -425,7 +430,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForReading(SDL_RWLock *rwlock) SDL_ * \sa SDL_TryLockRWLockForReading * \sa SDL_UnlockRWLock */ -extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(0, rwlock); +extern SDL_DECLSPEC bool SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_TRY_ACQUIRE(0, rwlock); /** * Unlock the read/write lock. @@ -450,7 +455,7 @@ extern DECLSPEC int SDLCALL SDL_TryLockRWLockForWriting(SDL_RWLock *rwlock) SDL_ * \sa SDL_TryLockRWLockForReading * \sa SDL_TryLockRWLockForWriting */ -extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GENERIC(rwlock); /** * Destroy a read/write lock created with SDL_CreateRWLock(). @@ -461,13 +466,13 @@ extern DECLSPEC void SDLCALL SDL_UnlockRWLock(SDL_RWLock *rwlock) SDL_RELEASE_GE * is not safe to attempt to destroy a locked rwlock, and may result in * undefined behavior depending on the platform. * - * \param rwlock the rwlock to destroy + * \param rwlock the rwlock to destroy. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRWLock */ -extern DECLSPEC void SDLCALL SDL_DestroyRWLock(SDL_RWLock *rwlock); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyRWLock(SDL_RWLock *rwlock); /* @} *//* Read/write lock functions */ @@ -477,8 +482,20 @@ extern DECLSPEC void SDLCALL SDL_DestroyRWLock(SDL_RWLock *rwlock); */ /* @{ */ -/* The SDL semaphore structure, defined in SDL_syssem.c */ -struct SDL_Semaphore; +/** + * A means to manage access to a resource, by count, between threads. + * + * Semaphores (specifically, "counting semaphores"), let X number of threads + * request access at the same time, each thread granted access decrementing a + * counter. When the counter reaches zero, future requests block until a prior + * thread releases their request, incrementing the counter again. + * + * Wikipedia has a thorough explanation of the concept: + * + * https://en.wikipedia.org/wiki/Semaphore_(programming) + * + * \since This struct is available since SDL 3.0.0. + */ typedef struct SDL_Semaphore SDL_Semaphore; /** @@ -490,20 +507,20 @@ typedef struct SDL_Semaphore SDL_Semaphore; * is 0. Each post operation will atomically increment the semaphore value and * wake waiting threads and allow them to retry the wait operation. * - * \param initial_value the starting value of the semaphore + * \param initial_value the starting value of the semaphore. * \returns a new semaphore or NULL on failure; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroySemaphore - * \sa SDL_PostSemaphore + * \sa SDL_SignalSemaphore * \sa SDL_TryWaitSemaphore * \sa SDL_GetSemaphoreValue * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ -extern DECLSPEC SDL_Semaphore *SDLCALL SDL_CreateSemaphore(Uint32 initial_value); +extern SDL_DECLSPEC SDL_Semaphore * SDLCALL SDL_CreateSemaphore(Uint32 initial_value); /** * Destroy a semaphore. @@ -511,36 +528,33 @@ extern DECLSPEC SDL_Semaphore *SDLCALL SDL_CreateSemaphore(Uint32 initial_value) * It is not safe to destroy a semaphore if there are threads currently * waiting on it. * - * \param sem the semaphore to destroy + * \param sem the semaphore to destroy. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateSemaphore */ -extern DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); +extern SDL_DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_Semaphore *sem); /** * Wait until a semaphore has a positive value and then decrements it. * - * This function suspends the calling thread until either the semaphore - * pointed to by `sem` has a positive value or the call is interrupted by a - * signal or error. If the call is successful it will atomically decrement the - * semaphore value. + * This function suspends the calling thread until the semaphore pointed to by + * `sem` has a positive value, and then atomically decrement the semaphore + * value. * * This function is the equivalent of calling SDL_WaitSemaphoreTimeout() with * a time length of -1. * - * \param sem the semaphore wait on - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param sem the semaphore wait on. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_PostSemaphore + * \sa SDL_SignalSemaphore * \sa SDL_TryWaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ -extern DECLSPEC int SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); +extern SDL_DECLSPEC void SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); /** * See if a semaphore has a positive value and decrement it if it does. @@ -548,49 +562,43 @@ extern DECLSPEC int SDLCALL SDL_WaitSemaphore(SDL_Semaphore *sem); * This function checks to see if the semaphore pointed to by `sem` has a * positive value and atomically decrements the semaphore value if it does. If * the semaphore doesn't have a positive value, the function immediately - * returns SDL_MUTEX_TIMEDOUT. + * returns false. * - * \param sem the semaphore to wait on - * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait would - * block, or a negative error code on failure; call SDL_GetError() - * for more information. + * \param sem the semaphore to wait on. + * \returns true if the wait succeeds, false if the wait would block. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_PostSemaphore + * \sa SDL_SignalSemaphore * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ -extern DECLSPEC int SDLCALL SDL_TryWaitSemaphore(SDL_Semaphore *sem); +extern SDL_DECLSPEC bool SDLCALL SDL_TryWaitSemaphore(SDL_Semaphore *sem); /** * Wait until a semaphore has a positive value and then decrements it. * * This function suspends the calling thread until either the semaphore - * pointed to by `sem` has a positive value, the call is interrupted by a - * signal or error, or the specified time has elapsed. If the call is - * successful it will atomically decrement the semaphore value. - * - * \param sem the semaphore to wait on - * \param timeoutMS the length of the timeout, in milliseconds - * \returns 0 if the wait succeeds, `SDL_MUTEX_TIMEDOUT` if the wait does not - * succeed in the allotted time, or a negative error code on failure; - * call SDL_GetError() for more information. + * pointed to by `sem` has a positive value or the specified time has elapsed. + * If the call is successful it will atomically decrement the semaphore value. + * + * \param sem the semaphore to wait on. + * \param timeoutMS the length of the timeout, in milliseconds, or -1 to wait + * indefinitely. + * \returns true if the wait succeeds or false if the wait times out. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_PostSemaphore + * \sa SDL_SignalSemaphore * \sa SDL_TryWaitSemaphore * \sa SDL_WaitSemaphore */ -extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 timeoutMS); +extern SDL_DECLSPEC bool SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 timeoutMS); /** * Atomically increment a semaphore's value and wake waiting threads. * - * \param sem the semaphore to increment - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param sem the semaphore to increment. * * \since This function is available since SDL 3.0.0. * @@ -598,17 +606,17 @@ extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeout(SDL_Semaphore *sem, Sint32 * \sa SDL_WaitSemaphore * \sa SDL_WaitSemaphoreTimeout */ -extern DECLSPEC int SDLCALL SDL_PostSemaphore(SDL_Semaphore *sem); +extern SDL_DECLSPEC void SDLCALL SDL_SignalSemaphore(SDL_Semaphore *sem); /** * Get the current value of a semaphore. * - * \param sem the semaphore to query + * \param sem the semaphore to query. * \returns the current value of the semaphore. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem); /* @} *//* Semaphore functions */ @@ -618,8 +626,19 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetSemaphoreValue(SDL_Semaphore *sem); */ /* @{ */ -/* The SDL condition variable structure, defined in SDL_syscond.c */ -struct SDL_Condition; +/** + * A means to block multiple threads until a condition is satisfied. + * + * Condition variables, paired with an SDL_Mutex, let an app halt multiple + * threads until a condition has occurred, at which time the app can release + * one or all waiting threads. + * + * Wikipedia has a thorough explanation of the concept: + * + * https://en.wikipedia.org/wiki/Condition_variable + * + * \since This struct is available since SDL 3.0.0. + */ typedef struct SDL_Condition SDL_Condition; /** @@ -636,25 +655,25 @@ typedef struct SDL_Condition SDL_Condition; * \sa SDL_WaitConditionTimeout * \sa SDL_DestroyCondition */ -extern DECLSPEC SDL_Condition *SDLCALL SDL_CreateCondition(void); +extern SDL_DECLSPEC SDL_Condition * SDLCALL SDL_CreateCondition(void); /** * Destroy a condition variable. * - * \param cond the condition variable to destroy + * \param cond the condition variable to destroy. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateCondition */ -extern DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond); /** * Restart one of the threads that are waiting on the condition variable. * - * \param cond the condition variable to signal - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param cond the condition variable to signal. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -662,14 +681,14 @@ extern DECLSPEC void SDLCALL SDL_DestroyCondition(SDL_Condition *cond); * \sa SDL_WaitCondition * \sa SDL_WaitConditionTimeout */ -extern DECLSPEC int SDLCALL SDL_SignalCondition(SDL_Condition *cond); +extern SDL_DECLSPEC void SDLCALL SDL_SignalCondition(SDL_Condition *cond); /** * Restart all threads that are waiting on the condition variable. * - * \param cond the condition variable to signal - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param cond the condition variable to signal. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -677,7 +696,7 @@ extern DECLSPEC int SDLCALL SDL_SignalCondition(SDL_Condition *cond); * \sa SDL_WaitCondition * \sa SDL_WaitConditionTimeout */ -extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); +extern SDL_DECLSPEC void SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); /** * Wait until a condition variable is signaled. @@ -694,10 +713,10 @@ extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); * This function is the equivalent of calling SDL_WaitConditionTimeout() with * a time length of -1. * - * \param cond the condition variable to wait on - * \param mutex the mutex used to coordinate thread access - * \returns 0 when it is signaled or a negative error code on failure; call - * SDL_GetError() for more information. + * \param cond the condition variable to wait on. + * \param mutex the mutex used to coordinate thread access. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -705,7 +724,7 @@ extern DECLSPEC int SDLCALL SDL_BroadcastCondition(SDL_Condition *cond); * \sa SDL_SignalCondition * \sa SDL_WaitConditionTimeout */ -extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mutex); +extern SDL_DECLSPEC void SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mutex); /** * Wait until a condition variable is signaled or a certain time has passed. @@ -720,13 +739,14 @@ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mu * recursively (more than once) is not supported and leads to undefined * behavior. * - * \param cond the condition variable to wait on - * \param mutex the mutex used to coordinate thread access + * \param cond the condition variable to wait on. + * \param mutex the mutex used to coordinate thread access. * \param timeoutMS the maximum time to wait, in milliseconds, or -1 to wait - * indefinitely - * \returns 0 if the condition variable is signaled, `SDL_MUTEX_TIMEDOUT` if - * the condition is not signaled in the allotted time, or a negative - * error code on failure; call SDL_GetError() for more information. + * indefinitely. + * \returns true if the condition variable is signaled, false if the condition + * is not signaled in the allotted time. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * @@ -734,11 +754,156 @@ extern DECLSPEC int SDLCALL SDL_WaitCondition(SDL_Condition *cond, SDL_Mutex *mu * \sa SDL_SignalCondition * \sa SDL_WaitCondition */ -extern DECLSPEC int SDLCALL SDL_WaitConditionTimeout(SDL_Condition *cond, +extern SDL_DECLSPEC bool SDLCALL SDL_WaitConditionTimeout(SDL_Condition *cond, SDL_Mutex *mutex, Sint32 timeoutMS); /* @} *//* Condition variable functions */ +/** + * \name Thread-safe initialization state functions + */ +/* @{ */ + +/** + * The current status of an SDL_InitState structure. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_InitStatus +{ + SDL_INIT_STATUS_UNINITIALIZED, + SDL_INIT_STATUS_INITIALIZING, + SDL_INIT_STATUS_INITIALIZED, + SDL_INIT_STATUS_UNINITIALIZING +} SDL_InitStatus; + +/** + * A structure used for thread-safe initialization and shutdown. + * + * Here is an example of using this: + * + * ```c + * static SDL_AtomicInitState init; + * + * bool InitSystem(void) + * { + * if (!SDL_ShouldInit(&init)) { + * // The system is initialized + * return true; + * } + * + * // At this point, you should not leave this function without calling SDL_SetInitialized() + * + * bool initialized = DoInitTasks(); + * SDL_SetInitialized(&init, initialized); + * return initialized; + * } + * + * bool UseSubsystem(void) + * { + * if (SDL_ShouldInit(&init)) { + * // Error, the subsystem isn't initialized + * SDL_SetInitialized(&init, false); + * return false; + * } + * + * // Do work using the initialized subsystem + * + * return true; + * } + * + * void QuitSystem(void) + * { + * if (!SDL_ShouldQuit(&init)) { + * // The system is not initialized + * return true; + * } + * + * // At this point, you should not leave this function without calling SDL_SetInitialized() + * + * DoQuitTasks(); + * SDL_SetInitialized(&init, false); + * } + * ``` + * + * Note that this doesn't protect any resources created during initialization, + * or guarantee that nobody is using those resources during cleanup. You + * should use other mechanisms to protect those, if that's a concern for your + * code. + * + * \since This struct is available since SDL 3.0.0. + */ +typedef struct SDL_InitState +{ + SDL_AtomicInt status; + SDL_ThreadID thread; + void *reserved; +} SDL_InitState; + +/** + * Return whether initialization should be done. + * + * This function checks the passed in state and if initialization should be + * done, sets the status to `SDL_INIT_STATUS_INITIALIZING` and returns true. + * If another thread is already modifying this state, it will wait until + * that's done before returning. + * + * If this function returns true, the calling code must call + * SDL_SetInitialized() to complete the initialization. + * + * \param state the initialization state to check. + * \returns true if initialization needs to be done, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetInitialized + * \sa SDL_ShouldQuit + */ +extern SDL_DECLSPEC bool SDLCALL SDL_ShouldInit(SDL_InitState *state); + +/** + * Return whether cleanup should be done. + * + * This function checks the passed in state and if cleanup should be done, + * sets the status to `SDL_INIT_STATUS_UNINITIALIZING` and returns true. + * + * If this function returns true, the calling code must call + * SDL_SetInitialized() to complete the cleanup. + * + * \param state the initialization state to check. + * \returns true if cleanup needs to be done, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetInitialized + * \sa SDL_ShouldInit + */ +extern SDL_DECLSPEC bool SDLCALL SDL_ShouldQuit(SDL_InitState *state); + +/** + * Finish an initialization state transition. + * + * This function sets the status of the passed in state to + * `SDL_INIT_STATUS_INITIALIZED` or `SDL_INIT_STATUS_UNINITIALIZED` and allows + * any threads waiting for the status to proceed. + * + * \param state the initialization state to check. + * \param initialized the new initialization state. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ShouldInit + * \sa SDL_ShouldQuit + */ +extern SDL_DECLSPEC void SDLCALL SDL_SetInitialized(SDL_InitState *state, bool initialized); + +/* @} *//* Thread-safe initialization state functions */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_oldnames.h b/libs/SDL3/include/SDL3/SDL_oldnames.h index 36632a3b4..c99dd958a 100644 --- a/libs/SDL3/include/SDL3/SDL_oldnames.h +++ b/libs/SDL3/include/SDL3/SDL_oldnames.h @@ -19,10 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_oldnames.h - * - * Definitions to ease transition from SDL2 code +/* + * Definitions to ease transition from SDL2 code */ #ifndef SDL_oldnames_h_ @@ -40,9 +38,14 @@ #ifdef SDL_ENABLE_OLD_NAMES /* ##SDL_atomic.h */ -#define SDL_AtomicCAS SDL_AtomicCompareAndSwap -#define SDL_AtomicCASPtr SDL_AtomicCompareAndSwapPointer +#define SDL_AtomicAdd SDL_AddAtomicInt +#define SDL_AtomicCAS SDL_CompareAndSwapAtomicInt +#define SDL_AtomicCASPtr SDL_CompareAndSwapAtomicPointer +#define SDL_AtomicGet SDL_GetAtomicInt +#define SDL_AtomicGetPtr SDL_GetAtomicPointer #define SDL_AtomicLock SDL_LockSpinlock +#define SDL_AtomicSet SDL_SetAtomicInt +#define SDL_AtomicSetPtr SDL_SetAtomicPointer #define SDL_AtomicTryLock SDL_TryLockSpinlock #define SDL_AtomicUnlock SDL_UnlockSpinlock #define SDL_atomic_t SDL_AtomicInt @@ -70,8 +73,21 @@ #define SDL_FreeAudioStream SDL_DestroyAudioStream #define SDL_FreeWAV SDL_free #define SDL_LoadWAV_RW SDL_LoadWAV_IO +#define SDL_MixAudioFormat SDL_MixAudio #define SDL_NewAudioStream SDL_CreateAudioStream +/* ##SDL_cpuinfo.h */ +#define SDL_GetCPUCount SDL_GetNumLogicalCPUCores +#define SDL_SIMDGetAlignment SDL_GetSIMDAlignment + +/* ##SDL_endian.h */ +#define SDL_SwapBE16 SDL_Swap16BE +#define SDL_SwapBE32 SDL_Swap32BE +#define SDL_SwapBE64 SDL_Swap64BE +#define SDL_SwapLE16 SDL_Swap16LE +#define SDL_SwapLE32 SDL_Swap32LE +#define SDL_SwapLE64 SDL_Swap64LE + /* ##SDL_events.h */ #define SDL_APP_DIDENTERBACKGROUND SDL_EVENT_DID_ENTER_BACKGROUND #define SDL_APP_DIDENTERFOREGROUND SDL_EVENT_DID_ENTER_FOREGROUND @@ -106,6 +122,7 @@ #define SDL_DROPCOMPLETE SDL_EVENT_DROP_COMPLETE #define SDL_DROPFILE SDL_EVENT_DROP_FILE #define SDL_DROPTEXT SDL_EVENT_DROP_TEXT +#define SDL_DelEventWatch SDL_RemoveEventWatch #define SDL_FINGERDOWN SDL_EVENT_FINGER_DOWN #define SDL_FINGERMOTION SDL_EVENT_FINGER_MOTION #define SDL_FINGERUP SDL_EVENT_FINGER_UP @@ -153,7 +170,7 @@ #define SDL_WINDOWEVENT_RESTORED SDL_EVENT_WINDOW_RESTORED #define SDL_WINDOWEVENT_SHOWN SDL_EVENT_WINDOW_SHOWN #define SDL_WINDOWEVENT_SIZE_CHANGED SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED -#define SDL_WINDOWEVENT_TAKE_FOCUS SDL_EVENT_WINDOW_TAKE_FOCUS +#define SDL_eventaction SDL_EventAction /* ##SDL_gamecontroller.h */ #define SDL_CONTROLLER_AXIS_INVALID SDL_GAMEPAD_AXIS_INVALID @@ -210,7 +227,7 @@ #define SDL_GameControllerBindType SDL_GamepadBindingType #define SDL_GameControllerButton SDL_GamepadButton #define SDL_GameControllerClose SDL_CloseGamepad -#define SDL_GameControllerFromInstanceID SDL_GetGamepadFromInstanceID +#define SDL_GameControllerFromInstanceID SDL_GetGamepadFromID #define SDL_GameControllerFromPlayerIndex SDL_GetGamepadFromPlayerIndex #define SDL_GameControllerGetAppleSFSymbolsNameForAxis SDL_GetGamepadAppleSFSymbolsNameForAxis #define SDL_GameControllerGetAppleSFSymbolsNameForButton SDL_GetGamepadAppleSFSymbolsNameForButton @@ -255,6 +272,9 @@ #define SDL_INIT_GAMECONTROLLER SDL_INIT_GAMEPAD #define SDL_IsGameController SDL_IsGamepad +/* ##SDL_guid.h */ +#define SDL_GUIDFromString SDL_StringToGUID + /* ##SDL_haptic.h */ #define SDL_HapticClose SDL_CloseHaptic #define SDL_HapticDestroyEffect SDL_DestroyHapticEffect @@ -282,6 +302,7 @@ #define SDL_MouseIsHaptic SDL_IsMouseHaptic /* ##SDL_hints.h */ +#define SDL_DelHintCallback SDL_RemoveHintCallback #define SDL_HINT_ALLOW_TOPMOST SDL_HINT_WINDOW_ALLOW_TOPMOST #define SDL_HINT_DIRECTINPUT_ENABLED SDL_HINT_JOYSTICK_DIRECTINPUT #define SDL_HINT_GDK_TEXTINPUT_DEFAULT SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT @@ -290,16 +311,15 @@ #define SDL_HINT_LINUX_HAT_DEADZONES SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES #define SDL_HINT_LINUX_JOYSTICK_CLASSIC SDL_HINT_JOYSTICK_LINUX_CLASSIC #define SDL_HINT_LINUX_JOYSTICK_DEADZONES SDL_HINT_JOYSTICK_LINUX_DEADZONES -#define SDL_HINT_PS2_DYNAMIC_VSYNC SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC /* ##SDL_joystick.h */ #define SDL_JOYSTICK_TYPE_GAMECONTROLLER SDL_JOYSTICK_TYPE_GAMEPAD -#define SDL_JoystickAttachVirtual SDL_AttachVirtualJoystick -#define SDL_JoystickAttachVirtualEx SDL_AttachVirtualJoystickEx +#define SDL_JoystickAttachVirtualEx SDL_AttachVirtualJoystick #define SDL_JoystickClose SDL_CloseJoystick #define SDL_JoystickDetachVirtual SDL_DetachVirtualJoystick -#define SDL_JoystickFromInstanceID SDL_GetJoystickFromInstanceID +#define SDL_JoystickFromInstanceID SDL_GetJoystickFromID #define SDL_JoystickFromPlayerIndex SDL_GetJoystickFromPlayerIndex +#define SDL_JoystickGUID SDL_GUID #define SDL_JoystickGetAttached SDL_JoystickConnected #define SDL_JoystickGetAxis SDL_GetJoystickAxis #define SDL_JoystickGetAxisInitialState SDL_GetJoystickAxisInitialState @@ -307,8 +327,7 @@ #define SDL_JoystickGetButton SDL_GetJoystickButton #define SDL_JoystickGetFirmwareVersion SDL_GetJoystickFirmwareVersion #define SDL_JoystickGetGUID SDL_GetJoystickGUID -#define SDL_JoystickGetGUIDFromString SDL_GetJoystickGUIDFromString -#define SDL_JoystickGetGUIDString SDL_GetJoystickGUIDString +#define SDL_JoystickGetGUIDFromString SDL_StringToGUID #define SDL_JoystickGetHat SDL_GetJoystickHat #define SDL_JoystickGetPlayerIndex SDL_GetJoystickPlayerIndex #define SDL_JoystickGetProduct SDL_GetJoystickProduct @@ -316,7 +335,7 @@ #define SDL_JoystickGetSerial SDL_GetJoystickSerial #define SDL_JoystickGetType SDL_GetJoystickType #define SDL_JoystickGetVendor SDL_GetJoystickVendor -#define SDL_JoystickInstanceID SDL_GetJoystickInstanceID +#define SDL_JoystickInstanceID SDL_GetJoystickID #define SDL_JoystickIsVirtual SDL_IsJoystickVirtual #define SDL_JoystickName SDL_GetJoystickName #define SDL_JoystickNumAxes SDL_GetNumJoystickAxes @@ -353,18 +372,83 @@ #define KMOD_NUM SDL_KMOD_NUM #define KMOD_RALT SDL_KMOD_RALT #define KMOD_RCTRL SDL_KMOD_RCTRL -#define KMOD_RESERVED SDL_KMOD_RESERVED #define KMOD_RGUI SDL_KMOD_RGUI #define KMOD_RSHIFT SDL_KMOD_RSHIFT #define KMOD_SCROLL SDL_KMOD_SCROLL #define KMOD_SHIFT SDL_KMOD_SHIFT +#define SDLK_AUDIOFASTFORWARD SDLK_MEDIA_FAST_FORWARD +#define SDLK_AUDIOMUTE SDLK_MUTE +#define SDLK_AUDIONEXT SDLK_MEDIA_NEXT_TRACK +#define SDLK_AUDIOPLAY SDLK_MEDIA_PLAY +#define SDLK_AUDIOPREV SDLK_MEDIA_PREVIOUS_TRACK +#define SDLK_AUDIOREWIND SDLK_MEDIA_REWIND +#define SDLK_AUDIOSTOP SDLK_MEDIA_STOP +#define SDLK_BACKQUOTE SDLK_GRAVE +#define SDLK_EJECT SDLK_MEDIA_EJECT +#define SDLK_MEDIASELECT SDLK_MEDIA_SELECT +#define SDLK_QUOTE SDLK_APOSTROPHE +#define SDLK_QUOTEDBL SDLK_DBLAPOSTROPHE +#define SDLK_a SDLK_A +#define SDLK_b SDLK_B +#define SDLK_c SDLK_C +#define SDLK_d SDLK_D +#define SDLK_e SDLK_E +#define SDLK_f SDLK_F +#define SDLK_g SDLK_G +#define SDLK_h SDLK_H +#define SDLK_i SDLK_I +#define SDLK_j SDLK_J +#define SDLK_k SDLK_K +#define SDLK_l SDLK_L +#define SDLK_m SDLK_M +#define SDLK_n SDLK_N +#define SDLK_o SDLK_O +#define SDLK_p SDLK_P +#define SDLK_q SDLK_Q +#define SDLK_r SDLK_R +#define SDLK_s SDLK_S +#define SDLK_t SDLK_T +#define SDLK_u SDLK_U +#define SDLK_v SDLK_V +#define SDLK_w SDLK_W +#define SDLK_x SDLK_X +#define SDLK_y SDLK_Y +#define SDLK_z SDLK_Z /* ##SDL_log.h */ #define SDL_LogGetOutputFunction SDL_GetLogOutputFunction +#define SDL_LogGetPriority SDL_GetLogPriority +#define SDL_LogResetPriorities SDL_ResetLogPriorities +#define SDL_LogSetAllPriority SDL_SetLogPriorities #define SDL_LogSetOutputFunction SDL_SetLogOutputFunction +#define SDL_LogSetPriority SDL_SetLogPriority +#define SDL_NUM_LOG_PRIORITIES SDL_LOG_PRIORITY_COUNT + +/* ##SDL_messagebox.h */ +#define SDL_MESSAGEBOX_COLOR_MAX SDL_MESSAGEBOX_COLOR_COUNT /* ##SDL_mouse.h */ +#define SDL_BUTTON SDL_BUTTON_MASK #define SDL_FreeCursor SDL_DestroyCursor +#define SDL_NUM_SYSTEM_CURSORS SDL_SYSTEM_CURSOR_COUNT +#define SDL_SYSTEM_CURSOR_ARROW SDL_SYSTEM_CURSOR_DEFAULT +#define SDL_SYSTEM_CURSOR_HAND SDL_SYSTEM_CURSOR_POINTER +#define SDL_SYSTEM_CURSOR_IBEAM SDL_SYSTEM_CURSOR_TEXT +#define SDL_SYSTEM_CURSOR_NO SDL_SYSTEM_CURSOR_NOT_ALLOWED +#define SDL_SYSTEM_CURSOR_SIZEALL SDL_SYSTEM_CURSOR_MOVE +#define SDL_SYSTEM_CURSOR_SIZENESW SDL_SYSTEM_CURSOR_NESW_RESIZE +#define SDL_SYSTEM_CURSOR_SIZENS SDL_SYSTEM_CURSOR_NS_RESIZE +#define SDL_SYSTEM_CURSOR_SIZENWSE SDL_SYSTEM_CURSOR_NWSE_RESIZE +#define SDL_SYSTEM_CURSOR_SIZEWE SDL_SYSTEM_CURSOR_EW_RESIZE +#define SDL_SYSTEM_CURSOR_WAITARROW SDL_SYSTEM_CURSOR_PROGRESS +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOM SDL_SYSTEM_CURSOR_S_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT SDL_SYSTEM_CURSOR_SW_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT SDL_SYSTEM_CURSOR_SE_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_LEFT SDL_SYSTEM_CURSOR_W_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_RIGHT SDL_SYSTEM_CURSOR_E_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOP SDL_SYSTEM_CURSOR_N_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT SDL_SYSTEM_CURSOR_NW_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT SDL_SYSTEM_CURSOR_NE_RESIZE /* ##SDL_mutex.h */ #define SDL_CondBroadcast SDL_BroadcastCondition @@ -373,7 +457,7 @@ #define SDL_CondWaitTimeout SDL_WaitConditionTimeout #define SDL_CreateCond SDL_CreateCondition #define SDL_DestroyCond SDL_DestroyCondition -#define SDL_SemPost SDL_PostSemaphore +#define SDL_SemPost SDL_SignalSemaphore #define SDL_SemTryWait SDL_TryWaitSemaphore #define SDL_SemValue SDL_GetSemaphoreValue #define SDL_SemWait SDL_WaitSemaphore @@ -385,14 +469,18 @@ #define SDL_sem SDL_Semaphore /* ##SDL_pixels.h */ -#define SDL_AllocFormat SDL_CreatePixelFormat +#define SDL_AllocFormat SDL_GetPixelFormatDetails #define SDL_AllocPalette SDL_CreatePalette -#define SDL_FreeFormat SDL_DestroyPixelFormat +#define SDL_Colour SDL_Color #define SDL_FreePalette SDL_DestroyPalette -#define SDL_MasksToPixelFormatEnum SDL_GetPixelFormatEnumForMasks +#define SDL_MasksToPixelFormatEnum SDL_GetPixelFormatForMasks +#define SDL_PIXELFORMAT_BGR444 SDL_PIXELFORMAT_XBGR4444 +#define SDL_PIXELFORMAT_BGR555 SDL_PIXELFORMAT_XBGR1555 #define SDL_PIXELFORMAT_BGR888 SDL_PIXELFORMAT_XBGR8888 +#define SDL_PIXELFORMAT_RGB444 SDL_PIXELFORMAT_XRGB4444 +#define SDL_PIXELFORMAT_RGB555 SDL_PIXELFORMAT_XRGB1555 #define SDL_PIXELFORMAT_RGB888 SDL_PIXELFORMAT_XRGB8888 -#define SDL_PixelFormatEnumToMasks SDL_GetMasksForPixelFormatEnum +#define SDL_PixelFormatEnumToMasks SDL_GetMasksForPixelFormat /* ##SDL_rect.h */ #define SDL_EncloseFPoints SDL_GetRectEnclosingPointsFloat @@ -431,6 +519,7 @@ #define SDL_RenderDrawRectsF SDL_RenderRects #define SDL_RenderFillRectF SDL_RenderFillRect #define SDL_RenderFillRectsF SDL_RenderFillRects +#define SDL_RendererFlip SDL_FlipMode #define SDL_RenderFlush SDL_FlushRenderer #define SDL_RenderGetClipRect SDL_GetRenderClipRect #define SDL_RenderGetLogicalSize SDL_GetRenderLogicalPresentation @@ -447,7 +536,6 @@ #define SDL_RenderSetVSync SDL_SetRenderVSync #define SDL_RenderSetViewport SDL_SetRenderViewport #define SDL_RenderWindowToLogical SDL_RenderCoordinatesFromWindow -#define SDL_ScaleModeBest SDL_SCALEMODE_BEST #define SDL_ScaleModeLinear SDL_SCALEMODE_LINEAR #define SDL_ScaleModeNearest SDL_SCALEMODE_NEAREST @@ -478,11 +566,23 @@ #define SDL_WriteLE32 SDL_WriteU32LE #define SDL_WriteLE64 SDL_WriteU64LE +/* ##SDL_scancode.h */ +#define SDL_NUM_SCANCODES SDL_SCANCODE_COUNT +#define SDL_SCANCODE_AUDIOFASTFORWARD SDL_SCANCODE_MEDIA_FAST_FORWARD +#define SDL_SCANCODE_AUDIOMUTE SDL_SCANCODE_MUTE +#define SDL_SCANCODE_AUDIONEXT SDL_SCANCODE_MEDIA_NEXT_TRACK +#define SDL_SCANCODE_AUDIOPLAY SDL_SCANCODE_MEDIA_PLAY +#define SDL_SCANCODE_AUDIOPREV SDL_SCANCODE_MEDIA_PREVIOUS_TRACK +#define SDL_SCANCODE_AUDIOREWIND SDL_SCANCODE_MEDIA_REWIND +#define SDL_SCANCODE_AUDIOSTOP SDL_SCANCODE_MEDIA_STOP +#define SDL_SCANCODE_EJECT SDL_SCANCODE_MEDIA_EJECT +#define SDL_SCANCODE_MEDIASELECT SDL_SCANCODE_MEDIA_SELECT + /* ##SDL_sensor.h */ #define SDL_SensorClose SDL_CloseSensor -#define SDL_SensorFromInstanceID SDL_GetSensorFromInstanceID +#define SDL_SensorFromInstanceID SDL_GetSensorFromID #define SDL_SensorGetData SDL_GetSensorData -#define SDL_SensorGetInstanceID SDL_GetSensorInstanceID +#define SDL_SensorGetInstanceID SDL_GetSensorID #define SDL_SensorGetName SDL_GetSensorName #define SDL_SensorGetNonPortableType SDL_GetSensorNonPortableType #define SDL_SensorGetType SDL_GetSensorType @@ -490,9 +590,17 @@ #define SDL_SensorUpdate SDL_UpdateSensors /* ##SDL_stdinc.h */ +#define SDL_FALSE false +#define SDL_TABLESIZE SDL_arraysize +#define SDL_TRUE true +#define SDL_bool bool +#define SDL_size_add_overflow SDL_size_add_check_overflow +#define SDL_size_mul_overflow SDL_size_mul_check_overflow #define SDL_strtokr SDL_strtok_r /* ##SDL_surface.h */ +#define SDL_BlitScaled SDL_BlitSurfaceScaled +#define SDL_ConvertSurfaceFormat SDL_ConvertSurface #define SDL_FillRect SDL_FillSurfaceRect #define SDL_FillRects SDL_FillSurfaceRects #define SDL_FreeSurface SDL_DestroySurface @@ -503,15 +611,41 @@ #define SDL_LoadBMP_RW SDL_LoadBMP_IO #define SDL_LowerBlit SDL_BlitSurfaceUnchecked #define SDL_LowerBlitScaled SDL_BlitSurfaceUncheckedScaled +#define SDL_PREALLOC SDL_SURFACE_PREALLOCATED +#define SDL_SIMD_ALIGNED SDL_SURFACE_SIMD_ALIGNED #define SDL_SaveBMP_RW SDL_SaveBMP_IO #define SDL_SetClipRect SDL_SetSurfaceClipRect #define SDL_SetColorKey SDL_SetSurfaceColorKey #define SDL_UpperBlit SDL_BlitSurface #define SDL_UpperBlitScaled SDL_BlitSurfaceScaled +/* ##SDL_system.h */ +#define SDL_AndroidBackButton SDL_SendAndroidBackButton +#define SDL_AndroidGetActivity SDL_GetAndroidActivity +#define SDL_AndroidGetExternalStoragePath SDL_GetAndroidExternalStoragePath +#define SDL_AndroidGetExternalStorageState SDL_GetAndroidExternalStorageState +#define SDL_AndroidGetInternalStoragePath SDL_GetAndroidInternalStoragePath +#define SDL_AndroidGetJNIEnv SDL_GetAndroidJNIEnv +#define SDL_AndroidRequestPermission SDL_RequestAndroidPermission +#define SDL_AndroidRequestPermissionCallback SDL_RequestAndroidPermissionCallback +#define SDL_AndroidSendMessage SDL_SendAndroidMessage +#define SDL_AndroidShowToast SDL_ShowAndroidToast +#define SDL_DXGIGetOutputInfo SDL_GetDXGIOutputInfo +#define SDL_Direct3D9GetAdapterIndex SDL_GetDirect3D9AdapterIndex +#define SDL_GDKGetDefaultUser SDL_GetGDKDefaultUser +#define SDL_GDKGetTaskQueue SDL_GetGDKTaskQueue +#define SDL_LinuxSetThreadPriority SDL_SetLinuxThreadPriority +#define SDL_LinuxSetThreadPriorityAndPolicy SDL_SetLinuxThreadPriorityAndPolicy +#define SDL_OnApplicationDidBecomeActive SDL_OnApplicationDidEnterForeground +#define SDL_OnApplicationWillResignActive SDL_OnApplicationWillEnterBackground +#define SDL_iOSSetAnimationCallback SDL_SetiOSAnimationCallback +#define SDL_iOSSetEventPump SDL_SetiOSEventPump +#define SDL_iPhoneSetAnimationCallback SDL_SetiOSAnimationCallback +#define SDL_iPhoneSetEventPump SDL_SetiOSEventPump + /* ##SDL_thread.h */ +#define SDL_SetThreadPriority SDL_SetCurrentThreadPriority #define SDL_TLSCleanup SDL_CleanupTLS -#define SDL_TLSCreate SDL_CreateTLS #define SDL_TLSGet SDL_GetTLS #define SDL_TLSSet SDL_SetTLS #define SDL_threadID SDL_ThreadID @@ -520,9 +654,11 @@ #define SDL_GetTicks64 SDL_GetTicks /* ##SDL_version.h */ -#define SDL_version SDL_Version +#define SDL_COMPILEDVERSION SDL_VERSION +#define SDL_PATCHLEVEL SDL_MICRO_VERSION /* ##SDL_video.h */ +#define SDL_GL_DeleteContext SDL_GL_DestroyContext #define SDL_GetClosestDisplayMode SDL_GetClosestFullscreenDisplayMode #define SDL_GetDisplayOrientation SDL_GetCurrentDisplayOrientation #define SDL_GetPointDisplayIndex SDL_GetDisplayForPoint @@ -539,11 +675,17 @@ #elif !defined(SDL_DISABLE_OLD_NAMES) /* ##SDL_atomic.h */ -#define SDL_AtomicCAS SDL_AtomicCAS_renamed_SDL_AtomicCompareAndSwap -#define SDL_AtomicCASPtr SDL_AtomicCASPtr_renamed_SDL_AtomicCompareAndSwapPointer +#define SDL_AtomicAdd SDL_AtomicAdd_renamed_SDL_AddAtomicInt +#define SDL_AtomicCAS SDL_AtomicCAS_renamed_SDL_CompareAndSwapAtomicInt +#define SDL_AtomicCASPtr SDL_AtomicCASPtr_renamed_SDL_CompareAndSwapAtomicPointer +#define SDL_AtomicGet SDL_AtomicGet_renamed_SDL_GetAtomicInt +#define SDL_AtomicGetPtr SDL_AtomicGetPtr_renamed_SDL_GetAtomicPointer #define SDL_AtomicLock SDL_AtomicLock_renamed_SDL_LockSpinlock +#define SDL_AtomicSet SDL_AtomicSet_renamed_SDL_SetAtomicInt +#define SDL_AtomicSetPtr SDL_AtomicSetPtr_renamed_SDL_SetAtomicPointer #define SDL_AtomicTryLock SDL_AtomicTryLock_renamed_SDL_TryLockSpinlock #define SDL_AtomicUnlock SDL_AtomicUnlock_renamed_SDL_UnlockSpinlock +#define SDL_atomic_t SDL_atomic_t_renamed_SDL_AtomicInt /* ##SDL_audio.h */ #define AUDIO_F32 AUDIO_F32_renamed_SDL_AUDIO_F32LE @@ -568,8 +710,21 @@ #define SDL_FreeAudioStream SDL_FreeAudioStream_renamed_SDL_DestroyAudioStream #define SDL_FreeWAV SDL_FreeWAV_renamed_SDL_free #define SDL_LoadWAV_RW SDL_LoadWAV_RW_renamed_SDL_LoadWAV_IO +#define SDL_MixAudioFormat SDL_MixAudioFormat_renamed_SDL_MixAudio #define SDL_NewAudioStream SDL_NewAudioStream_renamed_SDL_CreateAudioStream +/* ##SDL_cpuinfo.h */ +#define SDL_GetCPUCount SDL_GetCPUCount_renamed_SDL_GetNumLogicalCPUCores +#define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_renamed_SDL_GetSIMDAlignment + +/* ##SDL_endian.h */ +#define SDL_SwapBE16 SDL_SwapBE16_renamed_SDL_Swap16BE +#define SDL_SwapBE32 SDL_SwapBE32_renamed_SDL_Swap32BE +#define SDL_SwapBE64 SDL_SwapBE64_renamed_SDL_Swap64BE +#define SDL_SwapLE16 SDL_SwapLE16_renamed_SDL_Swap16LE +#define SDL_SwapLE32 SDL_SwapLE32_renamed_SDL_Swap32LE +#define SDL_SwapLE64 SDL_SwapLE64_renamed_SDL_Swap64LE + /* ##SDL_events.h */ #define SDL_APP_DIDENTERBACKGROUND SDL_APP_DIDENTERBACKGROUND_renamed_SDL_EVENT_DID_ENTER_BACKGROUND #define SDL_APP_DIDENTERFOREGROUND SDL_APP_DIDENTERFOREGROUND_renamed_SDL_EVENT_DID_ENTER_FOREGROUND @@ -604,6 +759,7 @@ #define SDL_DROPCOMPLETE SDL_DROPCOMPLETE_renamed_SDL_EVENT_DROP_COMPLETE #define SDL_DROPFILE SDL_DROPFILE_renamed_SDL_EVENT_DROP_FILE #define SDL_DROPTEXT SDL_DROPTEXT_renamed_SDL_EVENT_DROP_TEXT +#define SDL_DelEventWatch SDL_DelEventWatch_renamed_SDL_RemoveEventWatch #define SDL_FINGERDOWN SDL_FINGERDOWN_renamed_SDL_EVENT_FINGER_DOWN #define SDL_FINGERMOTION SDL_FINGERMOTION_renamed_SDL_EVENT_FINGER_MOTION #define SDL_FINGERUP SDL_FINGERUP_renamed_SDL_EVENT_FINGER_UP @@ -651,7 +807,7 @@ #define SDL_WINDOWEVENT_RESTORED SDL_WINDOWEVENT_RESTORED_renamed_SDL_EVENT_WINDOW_RESTORED #define SDL_WINDOWEVENT_SHOWN SDL_WINDOWEVENT_SHOWN_renamed_SDL_EVENT_WINDOW_SHOWN #define SDL_WINDOWEVENT_SIZE_CHANGED SDL_WINDOWEVENT_SIZE_CHANGED_renamed_SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED -#define SDL_WINDOWEVENT_TAKE_FOCUS SDL_WINDOWEVENT_TAKE_FOCUS_renamed_SDL_EVENT_WINDOW_TAKE_FOCUS +#define SDL_eventaction SDL_eventaction_renamed_SDL_EventAction /* ##SDL_gamecontroller.h */ #define SDL_CONTROLLER_AXIS_INVALID SDL_CONTROLLER_AXIS_INVALID_renamed_SDL_GAMEPAD_AXIS_INVALID @@ -708,7 +864,7 @@ #define SDL_GameControllerBindType SDL_GameControllerBindType_renamed_SDL_GamepadBindingType #define SDL_GameControllerButton SDL_GameControllerButton_renamed_SDL_GamepadButton #define SDL_GameControllerClose SDL_GameControllerClose_renamed_SDL_CloseGamepad -#define SDL_GameControllerFromInstanceID SDL_GameControllerFromInstanceID_renamed_SDL_GetGamepadFromInstanceID +#define SDL_GameControllerFromInstanceID SDL_GameControllerFromInstanceID_renamed_SDL_GetGamepadFromID #define SDL_GameControllerFromPlayerIndex SDL_GameControllerFromPlayerIndex_renamed_SDL_GetGamepadFromPlayerIndex #define SDL_GameControllerGetAppleSFSymbolsNameForAxis SDL_GameControllerGetAppleSFSymbolsNameForAxis_renamed_SDL_GetGamepadAppleSFSymbolsNameForAxis #define SDL_GameControllerGetAppleSFSymbolsNameForButton SDL_GameControllerGetAppleSFSymbolsNameForButton_renamed_SDL_GetGamepadAppleSFSymbolsNameForButton @@ -754,6 +910,9 @@ #define SDL_INIT_GAMECONTROLLER SDL_INIT_GAMECONTROLLER_renamed_SDL_INIT_GAMEPAD #define SDL_IsGameController SDL_IsGameController_renamed_SDL_IsGamepad +/* ##SDL_guid.h */ +#define SDL_GUIDFromString SDL_GUIDFromString_renamed_SDL_StringToGUID + /* ##SDL_haptic.h */ #define SDL_HapticClose SDL_HapticClose_renamed_SDL_CloseHaptic #define SDL_HapticDestroyEffect SDL_HapticDestroyEffect_renamed_SDL_DestroyHapticEffect @@ -781,6 +940,7 @@ #define SDL_MouseIsHaptic SDL_MouseIsHaptic_renamed_SDL_IsMouseHaptic /* ##SDL_hints.h */ +#define SDL_DelHintCallback SDL_DelHintCallback_renamed_SDL_RemoveHintCallback #define SDL_HINT_ALLOW_TOPMOST SDL_HINT_ALLOW_TOPMOST_renamed_SDL_HINT_WINDOW_ALLOW_TOPMOST #define SDL_HINT_DIRECTINPUT_ENABLED SDL_HINT_DIRECTINPUT_ENABLED_renamed_SDL_HINT_JOYSTICK_DIRECTINPUT #define SDL_HINT_GDK_TEXTINPUT_DEFAULT SDL_HINT_GDK_TEXTINPUT_DEFAULT_renamed_SDL_HINT_GDK_TEXTINPUT_DEFAULT_TEXT @@ -789,16 +949,15 @@ #define SDL_HINT_LINUX_HAT_DEADZONES SDL_HINT_LINUX_HAT_DEADZONES_renamed_SDL_HINT_JOYSTICK_LINUX_HAT_DEADZONES #define SDL_HINT_LINUX_JOYSTICK_CLASSIC SDL_HINT_LINUX_JOYSTICK_CLASSIC_renamed_SDL_HINT_JOYSTICK_LINUX_CLASSIC #define SDL_HINT_LINUX_JOYSTICK_DEADZONES SDL_HINT_LINUX_JOYSTICK_DEADZONES_renamed_SDL_HINT_JOYSTICK_LINUX_DEADZONES -#define SDL_HINT_PS2_DYNAMIC_VSYNC SDL_HINT_PS2_DYNAMIC_VSYNC_renamed_SDL_HINT_RENDER_PS2_DYNAMIC_VSYNC /* ##SDL_joystick.h */ #define SDL_JOYSTICK_TYPE_GAMECONTROLLER SDL_JOYSTICK_TYPE_GAMECONTROLLER_renamed_SDL_JOYSTICK_TYPE_GAMEPAD -#define SDL_JoystickAttachVirtual SDL_JoystickAttachVirtual_renamed_SDL_AttachVirtualJoystick -#define SDL_JoystickAttachVirtualEx SDL_JoystickAttachVirtualEx_renamed_SDL_AttachVirtualJoystickEx +#define SDL_JoystickAttachVirtualEx SDL_JoystickAttachVirtualEx_renamed_SDL_AttachVirtualJoystick #define SDL_JoystickClose SDL_JoystickClose_renamed_SDL_CloseJoystick #define SDL_JoystickDetachVirtual SDL_JoystickDetachVirtual_renamed_SDL_DetachVirtualJoystick -#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_renamed_SDL_GetJoystickFromInstanceID +#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_renamed_SDL_GetJoystickFromID #define SDL_JoystickFromPlayerIndex SDL_JoystickFromPlayerIndex_renamed_SDL_GetJoystickFromPlayerIndex +#define SDL_JoystickGUID SDL_JoystickGUID_renamed_SDL_GUID #define SDL_JoystickGetAttached SDL_JoystickGetAttached_renamed_SDL_JoystickConnected #define SDL_JoystickGetAxis SDL_JoystickGetAxis_renamed_SDL_GetJoystickAxis #define SDL_JoystickGetAxisInitialState SDL_JoystickGetAxisInitialState_renamed_SDL_GetJoystickAxisInitialState @@ -806,8 +965,7 @@ #define SDL_JoystickGetButton SDL_JoystickGetButton_renamed_SDL_GetJoystickButton #define SDL_JoystickGetFirmwareVersion SDL_JoystickGetFirmwareVersion_renamed_SDL_GetJoystickFirmwareVersion #define SDL_JoystickGetGUID SDL_JoystickGetGUID_renamed_SDL_GetJoystickGUID -#define SDL_JoystickGetGUIDFromString SDL_JoystickGetGUIDFromString_renamed_SDL_GetJoystickGUIDFromString -#define SDL_JoystickGetGUIDString SDL_JoystickGetGUIDString_renamed_SDL_GetJoystickGUIDString +#define SDL_JoystickGetGUIDFromString SDL_JoystickGetGUIDFromString_renamed_SDL_GUIDFromString #define SDL_JoystickGetHat SDL_JoystickGetHat_renamed_SDL_GetJoystickHat #define SDL_JoystickGetPlayerIndex SDL_JoystickGetPlayerIndex_renamed_SDL_GetJoystickPlayerIndex #define SDL_JoystickGetProduct SDL_JoystickGetProduct_renamed_SDL_GetJoystickProduct @@ -815,7 +973,7 @@ #define SDL_JoystickGetSerial SDL_JoystickGetSerial_renamed_SDL_GetJoystickSerial #define SDL_JoystickGetType SDL_JoystickGetType_renamed_SDL_GetJoystickType #define SDL_JoystickGetVendor SDL_JoystickGetVendor_renamed_SDL_GetJoystickVendor -#define SDL_JoystickInstanceID SDL_JoystickInstanceID_renamed_SDL_GetJoystickInstanceID +#define SDL_JoystickInstanceID SDL_JoystickInstanceID_renamed_SDL_GetJoystickID #define SDL_JoystickIsVirtual SDL_JoystickIsVirtual_renamed_SDL_IsJoystickVirtual #define SDL_JoystickName SDL_JoystickName_renamed_SDL_GetJoystickName #define SDL_JoystickNumAxes SDL_JoystickNumAxes_renamed_SDL_GetNumJoystickAxes @@ -852,18 +1010,83 @@ #define KMOD_NUM KMOD_NUM_renamed_SDL_KMOD_NUM #define KMOD_RALT KMOD_RALT_renamed_SDL_KMOD_RALT #define KMOD_RCTRL KMOD_RCTRL_renamed_SDL_KMOD_RCTRL -#define KMOD_RESERVED KMOD_RESERVED_renamed_SDL_KMOD_RESERVED #define KMOD_RGUI KMOD_RGUI_renamed_SDL_KMOD_RGUI #define KMOD_RSHIFT KMOD_RSHIFT_renamed_SDL_KMOD_RSHIFT #define KMOD_SCROLL KMOD_SCROLL_renamed_SDL_KMOD_SCROLL #define KMOD_SHIFT KMOD_SHIFT_renamed_SDL_KMOD_SHIFT +#define SDLK_AUDIOFASTFORWARD SDLK_AUDIOFASTFORWARD_renamed_SDLK_MEDIA_FAST_FORWARD +#define SDLK_AUDIOMUTE SDLK_AUDIOMUTE_renamed_SDLK_MUTE +#define SDLK_AUDIONEXT SDLK_AUDIONEXT_renamed_SDLK_MEDIA_NEXT_TRACK +#define SDLK_AUDIOPLAY SDLK_AUDIOPLAY_renamed_SDLK_MEDIA_PLAY +#define SDLK_AUDIOPREV SDLK_AUDIOPREV_renamed_SDLK_MEDIA_PREVIOUS_TRACK +#define SDLK_AUDIOREWIND SDLK_AUDIOREWIND_renamed_SDLK_MEDIA_REWIND +#define SDLK_AUDIOSTOP SDLK_AUDIOSTOP_renamed_SDLK_MEDIA_STOP +#define SDLK_BACKQUOTE SDLK_BACKQUOTE_renamed_SDLK_GRAVE +#define SDLK_EJECT SDLK_EJECT_renamed_SDLK_MEDIA_EJECT +#define SDLK_MEDIASELECT SDLK_MEDIASELECT_renamed_SDLK_MEDIA_SELECT +#define SDLK_QUOTE SDLK_QUOTE_renamed_SDLK_APOSTROPHE +#define SDLK_QUOTEDBL SDLK_QUOTEDBL_renamed_SDLK_DBLAPOSTROPHE +#define SDLK_a SDLK_a_renamed_SDLK_A +#define SDLK_b SDLK_b_renamed_SDLK_B +#define SDLK_c SDLK_c_renamed_SDLK_C +#define SDLK_d SDLK_d_renamed_SDLK_D +#define SDLK_e SDLK_e_renamed_SDLK_E +#define SDLK_f SDLK_f_renamed_SDLK_F +#define SDLK_g SDLK_g_renamed_SDLK_G +#define SDLK_h SDLK_h_renamed_SDLK_H +#define SDLK_i SDLK_i_renamed_SDLK_I +#define SDLK_j SDLK_j_renamed_SDLK_J +#define SDLK_k SDLK_k_renamed_SDLK_K +#define SDLK_l SDLK_l_renamed_SDLK_L +#define SDLK_m SDLK_m_renamed_SDLK_M +#define SDLK_n SDLK_n_renamed_SDLK_N +#define SDLK_o SDLK_o_renamed_SDLK_O +#define SDLK_p SDLK_p_renamed_SDLK_P +#define SDLK_q SDLK_q_renamed_SDLK_Q +#define SDLK_r SDLK_r_renamed_SDLK_R +#define SDLK_s SDLK_s_renamed_SDLK_S +#define SDLK_t SDLK_t_renamed_SDLK_T +#define SDLK_u SDLK_u_renamed_SDLK_U +#define SDLK_v SDLK_v_renamed_SDLK_V +#define SDLK_w SDLK_w_renamed_SDLK_W +#define SDLK_x SDLK_x_renamed_SDLK_X +#define SDLK_y SDLK_y_renamed_SDLK_Y +#define SDLK_z SDLK_z_renamed_SDLK_Z /* ##SDL_log.h */ #define SDL_LogGetOutputFunction SDL_LogGetOutputFunction_renamed_SDL_GetLogOutputFunction +#define SDL_LogGetPriority SDL_LogGetPriority_renamed_SDL_GetLogPriority +#define SDL_LogResetPriorities SDL_LogResetPriorities_renamed_SDL_ResetLogPriorities +#define SDL_LogSetAllPriority SDL_LogSetAllPriority_renamed_SDL_SetLogPriorities #define SDL_LogSetOutputFunction SDL_LogSetOutputFunction_renamed_SDL_SetLogOutputFunction +#define SDL_LogSetPriority SDL_LogSetPriority_renamed_SDL_SetLogPriority +#define SDL_NUM_LOG_PRIORITIES SDL_NUM_LOG_PRIORITIES_renamed_SDL_LOG_PRIORITY_COUNT + +/* ##SDL_messagebox.h */ +#define SDL_MESSAGEBOX_COLOR_MAX SDL_MESSAGEBOX_COLOR_MAX_renamed_SDL_MESSAGEBOX_COLOR_COUNT /* ##SDL_mouse.h */ +#define SDL_BUTTON SDL_BUTTON_renamed_SDL_BUTTON_MASK #define SDL_FreeCursor SDL_FreeCursor_renamed_SDL_DestroyCursor +#define SDL_NUM_SYSTEM_CURSORS SDL_NUM_SYSTEM_CURSORS_renamed_SDL_SYSTEM_CURSOR_COUNT +#define SDL_SYSTEM_CURSOR_ARROW SDL_SYSTEM_CURSOR_ARROW_renamed_SDL_SYSTEM_CURSOR_DEFAULT +#define SDL_SYSTEM_CURSOR_HAND SDL_SYSTEM_CURSOR_HAND_renamed_SDL_SYSTEM_CURSOR_POINTER +#define SDL_SYSTEM_CURSOR_IBEAM SDL_SYSTEM_CURSOR_IBEAM_renamed_SDL_SYSTEM_CURSOR_TEXT +#define SDL_SYSTEM_CURSOR_NO SDL_SYSTEM_CURSOR_NO_renamed_SDL_SYSTEM_CURSOR_NOT_ALLOWED +#define SDL_SYSTEM_CURSOR_SIZEALL SDL_SYSTEM_CURSOR_SIZEALL_renamed_SDL_SYSTEM_CURSOR_MOVE +#define SDL_SYSTEM_CURSOR_SIZENESW SDL_SYSTEM_CURSOR_SIZENESW_renamed_SDL_SYSTEM_CURSOR_NESW_RESIZE +#define SDL_SYSTEM_CURSOR_SIZENS SDL_SYSTEM_CURSOR_SIZENS_renamed_SDL_SYSTEM_CURSOR_NS_RESIZE +#define SDL_SYSTEM_CURSOR_SIZENWSE SDL_SYSTEM_CURSOR_SIZENWSE_renamed_SDL_SYSTEM_CURSOR_NWSE_RESIZE +#define SDL_SYSTEM_CURSOR_SIZEWE SDL_SYSTEM_CURSOR_SIZEWE_renamed_SDL_SYSTEM_CURSOR_EW_RESIZE +#define SDL_SYSTEM_CURSOR_WAITARROW SDL_SYSTEM_CURSOR_WAITARROW_renamed_SDL_SYSTEM_CURSOR_PROGRESS +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOM SDL_SYSTEM_CURSOR_WINDOW_BOTTOM_renamed_SDL_SYSTEM_CURSOR_S_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT SDL_SYSTEM_CURSOR_WINDOW_BOTTOMLEFT_renamed_SDL_SYSTEM_CURSOR_SW_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT SDL_SYSTEM_CURSOR_WINDOW_BOTTOMRIGHT_renamed_SDL_SYSTEM_CURSOR_SE_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_LEFT SDL_SYSTEM_CURSOR_WINDOW_LEFT_renamed_SDL_SYSTEM_CURSOR_W_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_RIGHT SDL_SYSTEM_CURSOR_WINDOW_RIGHT_renamed_SDL_SYSTEM_CURSOR_E_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOP SDL_SYSTEM_CURSOR_WINDOW_TOP_renamed_SDL_SYSTEM_CURSOR_N_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT SDL_SYSTEM_CURSOR_WINDOW_TOPLEFT_renamed_SDL_SYSTEM_CURSOR_NW_RESIZE +#define SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT SDL_SYSTEM_CURSOR_WINDOW_TOPRIGHT_renamed_SDL_SYSTEM_CURSOR_NE_RESIZE /* ##SDL_mutex.h */ #define SDL_CondBroadcast SDL_CondBroadcast_renamed_SDL_BroadcastCondition @@ -872,7 +1095,7 @@ #define SDL_CondWaitTimeout SDL_CondWaitTimeout_renamed_SDL_WaitConditionTimeout #define SDL_CreateCond SDL_CreateCond_renamed_SDL_CreateCondition #define SDL_DestroyCond SDL_DestroyCond_renamed_SDL_DestroyCondition -#define SDL_SemPost SDL_SemPost_renamed_SDL_PostSemaphore +#define SDL_SemPost SDL_SemPost_renamed_SDL_SignalSemaphore #define SDL_SemTryWait SDL_SemTryWait_renamed_SDL_TryWaitSemaphore #define SDL_SemValue SDL_SemValue_renamed_SDL_GetSemaphoreValue #define SDL_SemWait SDL_SemWait_renamed_SDL_WaitSemaphore @@ -884,14 +1107,18 @@ #define SDL_sem SDL_sem_renamed_SDL_Semaphore /* ##SDL_pixels.h */ -#define SDL_AllocFormat SDL_AllocFormat_renamed_SDL_CreatePixelFormat +#define SDL_AllocFormat SDL_AllocFormat_renamed_SDL_GetPixelFormatDetails #define SDL_AllocPalette SDL_AllocPalette_renamed_SDL_CreatePalette -#define SDL_FreeFormat SDL_FreeFormat_renamed_SDL_DestroyPixelFormat +#define SDL_Colour SDL_Colour_renamed_SDL_Color #define SDL_FreePalette SDL_FreePalette_renamed_SDL_DestroyPalette -#define SDL_MasksToPixelFormatEnum SDL_MasksToPixelFormatEnum_renamed_SDL_GetPixelFormatEnumForMasks +#define SDL_MasksToPixelFormatEnum SDL_MasksToPixelFormatEnum_renamed_SDL_GetPixelFormatForMasks +#define SDL_PIXELFORMAT_BGR444 SDL_PIXELFORMAT_BGR444_renamed_SDL_PIXELFORMAT_XBGR4444 +#define SDL_PIXELFORMAT_BGR555 SDL_PIXELFORMAT_BGR555_renamed_SDL_PIXELFORMAT_XBGR1555 #define SDL_PIXELFORMAT_BGR888 SDL_PIXELFORMAT_BGR888_renamed_SDL_PIXELFORMAT_XBGR8888 +#define SDL_PIXELFORMAT_RGB444 SDL_PIXELFORMAT_RGB444_renamed_SDL_PIXELFORMAT_XRGB4444 +#define SDL_PIXELFORMAT_RGB555 SDL_PIXELFORMAT_RGB555_renamed_SDL_PIXELFORMAT_XRGB1555 #define SDL_PIXELFORMAT_RGB888 SDL_PIXELFORMAT_RGB888_renamed_SDL_PIXELFORMAT_XRGB8888 -#define SDL_PixelFormatEnumToMasks SDL_PixelFormatEnumToMasks_renamed_SDL_GetMasksForPixelFormatEnum +#define SDL_PixelFormatEnumToMasks SDL_PixelFormatEnumToMasks_renamed_SDL_GetMasksForPixelFormat /* ##SDL_rect.h */ #define SDL_EncloseFPoints SDL_EncloseFPoints_renamed_SDL_GetRectEnclosingPointsFloat @@ -930,6 +1157,7 @@ #define SDL_RenderDrawRectsF SDL_RenderDrawRectsF_renamed_SDL_RenderRects #define SDL_RenderFillRectF SDL_RenderFillRectF_renamed_SDL_RenderFillRect #define SDL_RenderFillRectsF SDL_RenderFillRectsF_renamed_SDL_RenderFillRects +#define SDL_RendererFlip SDL_RendererFlip_renamed_SDL_FlipMode #define SDL_RenderFlush SDL_RenderFlush_renamed_SDL_FlushRenderer #define SDL_RenderGetClipRect SDL_RenderGetClipRect_renamed_SDL_GetRenderClipRect #define SDL_RenderGetLogicalSize SDL_RenderGetLogicalSize_renamed_SDL_GetRenderLogicalPresentation @@ -946,7 +1174,6 @@ #define SDL_RenderSetVSync SDL_RenderSetVSync_renamed_SDL_SetRenderVSync #define SDL_RenderSetViewport SDL_RenderSetViewport_renamed_SDL_SetRenderViewport #define SDL_RenderWindowToLogical SDL_RenderWindowToLogical_renamed_SDL_RenderCoordinatesFromWindow -#define SDL_ScaleModeBest SDL_ScaleModeBest_renamed_SDL_SCALEMODE_BEST #define SDL_ScaleModeLinear SDL_ScaleModeLinear_renamed_SDL_SCALEMODE_LINEAR #define SDL_ScaleModeNearest SDL_ScaleModeNearest_renamed_SDL_SCALEMODE_NEAREST @@ -977,11 +1204,23 @@ #define SDL_WriteLE32 SDL_WriteLE32_renamed_SDL_WriteU32LE #define SDL_WriteLE64 SDL_WriteLE64_renamed_SDL_WriteU64LE +/* ##SDL_scancode.h */ +#define SDL_NUM_SCANCODES SDL_NUM_SCANCODES_renamed_SDL_SCANCODE_COUNT +#define SDL_SCANCODE_AUDIOFASTFORWARD SDL_SCANCODE_AUDIOFASTFORWARD_renamed_SDL_SCANCODE_MEDIA_FAST_FORWARD +#define SDL_SCANCODE_AUDIOMUTE SDL_SCANCODE_AUDIOMUTE_renamed_SDL_SCANCODE_MUTE +#define SDL_SCANCODE_AUDIONEXT SDL_SCANCODE_AUDIONEXT_renamed_SDL_SCANCODE_MEDIA_NEXT_TRACK +#define SDL_SCANCODE_AUDIOPLAY SDL_SCANCODE_AUDIOPLAY_renamed_SDL_SCANCODE_MEDIA_PLAY +#define SDL_SCANCODE_AUDIOPREV SDL_SCANCODE_AUDIOPREV_renamed_SDL_SCANCODE_MEDIA_PREVIOUS_TRACK +#define SDL_SCANCODE_AUDIOREWIND SDL_SCANCODE_AUDIOREWIND_renamed_SDL_SCANCODE_MEDIA_REWIND +#define SDL_SCANCODE_AUDIOSTOP SDL_SCANCODE_AUDIOSTOP_renamed_SDL_SCANCODE_MEDIA_STOP +#define SDL_SCANCODE_EJECT SDL_SCANCODE_EJECT_renamed_SDL_SCANCODE_MEDIA_EJECT +#define SDL_SCANCODE_MEDIASELECT SDL_SCANCODE_MEDIASELECT_renamed_SDL_SCANCODE_MEDIA_SELECT + /* ##SDL_sensor.h */ #define SDL_SensorClose SDL_SensorClose_renamed_SDL_CloseSensor -#define SDL_SensorFromInstanceID SDL_SensorFromInstanceID_renamed_SDL_GetSensorFromInstanceID +#define SDL_SensorFromInstanceID SDL_SensorFromInstanceID_renamed_SDL_GetSensorFromID #define SDL_SensorGetData SDL_SensorGetData_renamed_SDL_GetSensorData -#define SDL_SensorGetInstanceID SDL_SensorGetInstanceID_renamed_SDL_GetSensorInstanceID +#define SDL_SensorGetInstanceID SDL_SensorGetInstanceID_renamed_SDL_GetSensorID #define SDL_SensorGetName SDL_SensorGetName_renamed_SDL_GetSensorName #define SDL_SensorGetNonPortableType SDL_SensorGetNonPortableType_renamed_SDL_GetSensorNonPortableType #define SDL_SensorGetType SDL_SensorGetType_renamed_SDL_GetSensorType @@ -989,9 +1228,17 @@ #define SDL_SensorUpdate SDL_SensorUpdate_renamed_SDL_UpdateSensors /* ##SDL_stdinc.h */ +#define SDL_FALSE SDL_FALSE_renamed_false +#define SDL_TABLESIZE SDL_TABLESIZE_renamed_SDL_arraysize +#define SDL_TRUE SDL_TRUE_renamed_true +#define SDL_bool SDL_bool_renamed_bool +#define SDL_size_add_overflow SDL_size_add_overflow_renamed_SDL_size_add_check_overflow +#define SDL_size_mul_overflow SDL_size_mul_overflow_renamed_SDL_size_mul_check_overflow #define SDL_strtokr SDL_strtokr_renamed_SDL_strtok_r /* ##SDL_surface.h */ +#define SDL_BlitScaled SDL_BlitScaled_renamed_SDL_BlitSurfaceScaled +#define SDL_ConvertSurfaceFormat SDL_ConvertSurfaceFormat_renamed_SDL_ConvertSurface #define SDL_FillRect SDL_FillRect_renamed_SDL_FillSurfaceRect #define SDL_FillRects SDL_FillRects_renamed_SDL_FillSurfaceRects #define SDL_FreeSurface SDL_FreeSurface_renamed_SDL_DestroySurface @@ -1002,15 +1249,41 @@ #define SDL_LoadBMP_RW SDL_LoadBMP_RW_renamed_SDL_LoadBMP_IO #define SDL_LowerBlit SDL_LowerBlit_renamed_SDL_BlitSurfaceUnchecked #define SDL_LowerBlitScaled SDL_LowerBlitScaled_renamed_SDL_BlitSurfaceUncheckedScaled +#define SDL_PREALLOC SDL_PREALLOC_renamed_SDL_SURFACE_PREALLOCATED +#define SDL_SIMD_ALIGNED SDL_SIMD_ALIGNED_renamed_SDL_SURFACE_SIMD_ALIGNED #define SDL_SaveBMP_RW SDL_SaveBMP_RW_renamed_SDL_SaveBMP_IO #define SDL_SetClipRect SDL_SetClipRect_renamed_SDL_SetSurfaceClipRect #define SDL_SetColorKey SDL_SetColorKey_renamed_SDL_SetSurfaceColorKey #define SDL_UpperBlit SDL_UpperBlit_renamed_SDL_BlitSurface #define SDL_UpperBlitScaled SDL_UpperBlitScaled_renamed_SDL_BlitSurfaceScaled +/* ##SDL_system.h */ +#define SDL_AndroidBackButton SDL_AndroidBackButton_renamed_SDL_SendAndroidBackButton +#define SDL_AndroidGetActivity SDL_AndroidGetActivity_renamed_SDL_GetAndroidActivity +#define SDL_AndroidGetExternalStoragePath SDL_AndroidGetExternalStoragePath_renamed_SDL_GetAndroidExternalStoragePath +#define SDL_AndroidGetExternalStorageState SDL_AndroidGetExternalStorageState_renamed_SDL_GetAndroidExternalStorageState +#define SDL_AndroidGetInternalStoragePath SDL_AndroidGetInternalStoragePath_renamed_SDL_GetAndroidInternalStoragePath +#define SDL_AndroidGetJNIEnv SDL_AndroidGetJNIEnv_renamed_SDL_GetAndroidJNIEnv +#define SDL_AndroidRequestPermission SDL_AndroidRequestPermission_renamed_SDL_RequestAndroidPermission +#define SDL_AndroidRequestPermissionCallback SDL_AndroidRequestPermissionCallback_renamed_SDL_RequestAndroidPermissionCallback +#define SDL_AndroidSendMessage SDL_AndroidSendMessage_renamed_SDL_SendAndroidMessage +#define SDL_AndroidShowToast SDL_AndroidShowToast_renamed_SDL_ShowAndroidToast +#define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_renamed_SDL_GetDXGIOutputInfo +#define SDL_Direct3D9GetAdapterIndex SDL_Direct3D9GetAdapterIndex_renamed_SDL_GetDirect3D9AdapterIndex +#define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_renamed_SDL_GetGDKDefaultUser +#define SDL_GDKGetTaskQueue SDL_GDKGetTaskQueue_renamed_SDL_GetGDKTaskQueue +#define SDL_LinuxSetThreadPriority SDL_LinuxSetThreadPriority_renamed_SDL_SetLinuxThreadPriority +#define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_renamed_SDL_SetLinuxThreadPriorityAndPolicy +#define SDL_OnApplicationDidBecomeActive SDL_OnApplicationDidBecomeActive_renamed_SDL_OnApplicationDidEnterForeground +#define SDL_OnApplicationWillResignActive SDL_OnApplicationWillResignActive_renamed_SDL_OnApplicationWillEnterBackground +#define SDL_iOSSetAnimationCallback SDL_iOSSetAnimationCallback_renamed_SDL_SetiOSAnimationCallback +#define SDL_iOSSetEventPump SDL_iOSSetEventPump_renamed_SDL_SetiOSEventPump +#define SDL_iPhoneSetAnimationCallback SDL_iPhoneSetAnimationCallback_renamed_SDL_iOSSetAnimationCallback +#define SDL_iPhoneSetEventPump SDL_iPhoneSetEventPump_renamed_SDL_iOSSetEventPump + /* ##SDL_thread.h */ +#define SDL_SetThreadPriority SDL_SetThreadPriority_renamed_SDL_SetCurrentThreadPriority #define SDL_TLSCleanup SDL_TLSCleanup_renamed_SDL_CleanupTLS -#define SDL_TLSCreate SDL_TLSCreate_renamed_SDL_CreateTLS #define SDL_TLSGet SDL_TLSGet_renamed_SDL_GetTLS #define SDL_TLSSet SDL_TLSSet_renamed_SDL_SetTLS #define SDL_threadID SDL_threadID_renamed_SDL_ThreadID @@ -1019,9 +1292,11 @@ #define SDL_GetTicks64 SDL_GetTicks64_renamed_SDL_GetTicks /* ##SDL_version.h */ -#define SDL_version SDL_version_renamed_SDL_Version +#define SDL_COMPILEDVERSION SDL_COMPILEDVERSION_renamed_SDL_VERSION +#define SDL_PATCHLEVEL SDL_PATCHLEVEL_renamed_SDL_MICRO_VERSION /* ##SDL_video.h */ +#define SDL_GL_DeleteContext SDL_GL_DeleteContext_renamed_SDL_GL_DestroyContext #define SDL_GetClosestDisplayMode SDL_GetClosestDisplayMode_renamed_SDL_GetClosestFullscreenDisplayMode #define SDL_GetDisplayOrientation SDL_GetDisplayOrientation_renamed_SDL_GetCurrentDisplayOrientation #define SDL_GetPointDisplayIndex SDL_GetPointDisplayIndex_renamed_SDL_GetDisplayForPoint diff --git a/libs/SDL3/include/SDL3/SDL_opengl.h b/libs/SDL3/include/SDL3/SDL_opengl.h index 575f64616..6bdcbe008 100644 --- a/libs/SDL3/include/SDL3/SDL_opengl.h +++ b/libs/SDL3/include/SDL3/SDL_opengl.h @@ -19,17 +19,11 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_opengl.h - * - * This is a simple file to encapsulate the OpenGL API headers. - */ - -/** - * \def NO_SDL_GLEXT +/* + * This is a simple file to encapsulate the OpenGL API headers. * - * Define this if you have your own version of glext.h and want to disable the - * version included in SDL_opengl.h. + * Define NO_SDL_GLEXT if you have your own version of glext.h and want + * to disable the version included in SDL_opengl.h. */ #ifndef SDL_opengl_h_ diff --git a/libs/SDL3/include/SDL3/SDL_opengl_glext.h b/libs/SDL3/include/SDL3/SDL_opengl_glext.h index ff6ad12ce..fa0f6c2a5 100644 --- a/libs/SDL3/include/SDL3/SDL_opengl_glext.h +++ b/libs/SDL3/include/SDL3/SDL_opengl_glext.h @@ -9807,15 +9807,15 @@ typedef void (APIENTRYP PFNGLUPLOADGPUMASKNVXPROC) (GLbitfield mask); typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTPOSITIONWSCALENVXPROC) (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff); typedef void (APIENTRYP PFNGLMULTICASTSCISSORARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLint *v); -typedef GLuint (APIENTRYP PFNGLASYNCCOPYBUFFERSUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); -typedef GLuint (APIENTRYP PFNGLASYNCCOPYIMAGESUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +typedef GLuint (APIENTRYP PFNGLASYNCCOPYBUFFERSUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGPU, GLbitfield writeGPUMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +typedef GLuint (APIENTRYP PFNGLASYNCCOPYIMAGESUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGPU, GLbitfield dstGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glUploadGpuMaskNVX (GLbitfield mask); +GLAPI void APIENTRY glUploadGPUMaskNVX (GLbitfield mask); GLAPI void APIENTRY glMulticastViewportArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v); GLAPI void APIENTRY glMulticastViewportPositionWScaleNVX (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff); GLAPI void APIENTRY glMulticastScissorArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLint *v); -GLAPI GLuint APIENTRY glAsyncCopyBufferSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); -GLAPI GLuint APIENTRY glAsyncCopyImageSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +GLAPI GLuint APIENTRY glAsyncCopyBufferSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGPU, GLbitfield writeGPUMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +GLAPI GLuint APIENTRY glAsyncCopyImageSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGPU, GLbitfield dstGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); #endif #endif /* GL_NVX_gpu_multicast2 */ @@ -9824,11 +9824,11 @@ GLAPI GLuint APIENTRY glAsyncCopyImageSubDataNVX (GLsizei waitSemaphoreCount, co #define GL_LGPU_SEPARATE_STORAGE_BIT_NVX 0x0800 #define GL_MAX_LGPU_GPUS_NVX 0x92BA typedef void (APIENTRYP PFNGLLGPUNAMEDBUFFERSUBDATANVXPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); -typedef void (APIENTRYP PFNGLLGPUCOPYIMAGESUBDATANVXPROC) (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLLGPUCOPYIMAGESUBDATANVXPROC) (GLuint sourceGPU, GLbitfield destinationGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); typedef void (APIENTRYP PFNGLLGPUINTERLOCKNVXPROC) (void); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glLGPUNamedBufferSubDataNVX (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); -GLAPI void APIENTRY glLGPUCopyImageSubDataNVX (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glLGPUCopyImageSubDataNVX (GLuint sourceGPU, GLbitfield destinationGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); GLAPI void APIENTRY glLGPUInterlockNVX (void); #endif #endif /* GL_NVX_linked_gpu_multicast */ @@ -9836,13 +9836,13 @@ GLAPI void APIENTRY glLGPUInterlockNVX (void); #ifndef GL_NVX_progress_fence #define GL_NVX_progress_fence 1 typedef GLuint (APIENTRYP PFNGLCREATEPROGRESSFENCENVXPROC) (void); -typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREUI64NVXPROC) (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); -typedef void (APIENTRYP PFNGLWAITSEMAPHOREUI64NVXPROC) (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREUI64NVXPROC) (GLuint signalGPU, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +typedef void (APIENTRYP PFNGLWAITSEMAPHOREUI64NVXPROC) (GLuint waitGPU, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); typedef void (APIENTRYP PFNGLCLIENTWAITSEMAPHOREUI64NVXPROC) (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); #ifdef GL_GLEXT_PROTOTYPES GLAPI GLuint APIENTRY glCreateProgressFenceNVX (void); -GLAPI void APIENTRY glSignalSemaphoreui64NVX (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); -GLAPI void APIENTRY glWaitSemaphoreui64NVX (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +GLAPI void APIENTRY glSignalSemaphoreui64NVX (GLuint signalGPU, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +GLAPI void APIENTRY glWaitSemaphoreui64NVX (GLuint waitGPU, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); GLAPI void APIENTRY glClientWaitSemaphoreui64NVX (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); #endif #endif /* GL_NVX_progress_fence */ @@ -10433,25 +10433,25 @@ GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachmen #define GL_MULTICAST_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9549 typedef void (APIENTRYP PFNGLRENDERGPUMASKNVPROC) (GLbitfield mask); typedef void (APIENTRYP PFNGLMULTICASTBUFFERSUBDATANVPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); -typedef void (APIENTRYP PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC) (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -typedef void (APIENTRYP PFNGLMULTICASTCOPYIMAGESUBDATANVPROC) (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); -typedef void (APIENTRYP PFNGLMULTICASTBLITFRAMEBUFFERNVPROC) (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (APIENTRYP PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC) (GLuint readGPU, GLbitfield writeGPUMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLMULTICASTCOPYIMAGESUBDATANVPROC) (GLuint srcGPU, GLbitfield dstGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (APIENTRYP PFNGLMULTICASTBLITFRAMEBUFFERNVPROC) (GLuint srcGPU, GLuint dstGPU, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); typedef void (APIENTRYP PFNGLMULTICASTFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); typedef void (APIENTRYP PFNGLMULTICASTBARRIERNVPROC) (void); -typedef void (APIENTRYP PFNGLMULTICASTWAITSYNCNVPROC) (GLuint signalGpu, GLbitfield waitGpuMask); +typedef void (APIENTRYP PFNGLMULTICASTWAITSYNCNVPROC) (GLuint signalGPU, GLbitfield waitGPUMask); typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint *params); typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint64 *params); typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params); #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glRenderGpuMaskNV (GLbitfield mask); +GLAPI void APIENTRY glRenderGPUMaskNV (GLbitfield mask); GLAPI void APIENTRY glMulticastBufferSubDataNV (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); -GLAPI void APIENTRY glMulticastCopyBufferSubDataNV (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -GLAPI void APIENTRY glMulticastCopyImageSubDataNV (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); -GLAPI void APIENTRY glMulticastBlitFramebufferNV (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI void APIENTRY glMulticastCopyBufferSubDataNV (GLuint readGPU, GLbitfield writeGPUMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glMulticastCopyImageSubDataNV (GLuint srcGPU, GLbitfield dstGPUMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +GLAPI void APIENTRY glMulticastBlitFramebufferNV (GLuint srcGPU, GLuint dstGPU, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); GLAPI void APIENTRY glMulticastFramebufferSampleLocationsfvNV (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); GLAPI void APIENTRY glMulticastBarrierNV (void); -GLAPI void APIENTRY glMulticastWaitSyncNV (GLuint signalGpu, GLbitfield waitGpuMask); +GLAPI void APIENTRY glMulticastWaitSyncNV (GLuint signalGPU, GLbitfield waitGPUMask); GLAPI void APIENTRY glMulticastGetQueryObjectivNV (GLuint gpu, GLuint id, GLenum pname, GLint *params); GLAPI void APIENTRY glMulticastGetQueryObjectuivNV (GLuint gpu, GLuint id, GLenum pname, GLuint *params); GLAPI void APIENTRY glMulticastGetQueryObjecti64vNV (GLuint gpu, GLuint id, GLenum pname, GLint64 *params); diff --git a/libs/SDL3/include/SDL3/SDL_opengles.h b/libs/SDL3/include/SDL3/SDL_opengles.h index d17346393..bde4d74f1 100644 --- a/libs/SDL3/include/SDL3/SDL_opengles.h +++ b/libs/SDL3/include/SDL3/SDL_opengles.h @@ -19,11 +19,10 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_opengles.h - * - * This is a simple file to encapsulate the OpenGL ES 1.X API headers. +/* + * This is a simple file to encapsulate the OpenGL ES 1.X API headers. */ + #include #ifdef SDL_PLATFORM_IOS diff --git a/libs/SDL3/include/SDL3/SDL_opengles2.h b/libs/SDL3/include/SDL3/SDL_opengles2.h index 85abf2b81..ba1960105 100644 --- a/libs/SDL3/include/SDL3/SDL_opengles2.h +++ b/libs/SDL3/include/SDL3/SDL_opengles2.h @@ -19,11 +19,10 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_opengles2.h - * - * This is a simple file to encapsulate the OpenGL ES 2.0 API headers. +/* + * This is a simple file to encapsulate the OpenGL ES 2.0 API headers. */ + #include #if !defined(_MSC_VER) && !defined(SDL_USE_BUILTIN_OPENGL_DEFINITIONS) diff --git a/libs/SDL3/include/SDL3/SDL_pen.h b/libs/SDL3/include/SDL3/SDL_pen.h index ccb61370d..77c7bed9a 100644 --- a/libs/SDL3/include/SDL3/SDL_pen.h +++ b/libs/SDL3/include/SDL3/SDL_pen.h @@ -20,34 +20,25 @@ */ /** - * \file SDL_pen.h + * # CategoryPen * - * Include file for SDL pen event handling. + * SDL pen event handling. * - * This file describes operations for pressure-sensitive pen (stylus and/or eraser) handling, e.g., for input - * and drawing tablets or suitably equipped mobile / tablet devices. + * SDL provides an API for pressure-sensitive pen (stylus and/or eraser) + * handling, e.g., for input and drawing tablets or suitably equipped mobile / + * tablet devices. * - * To get started with pens: - * - Listen to ::SDL_PenMotionEvent and ::SDL_PenButtonEvent - * - To avoid treating pen events as mouse events, ignore ::SDL_MouseMotionEvent and ::SDL_MouseButtonEvent - * whenever "which" == ::SDL_PEN_MOUSEID. + * To get started with pens, simply handle SDL_EVENT_PEN_* events. When a pen + * starts providing input, SDL will assign it a unique SDL_PenID, which will + * remain for the life of the process, as long as the pen stays connected. * - * This header file describes advanced functionality that can be useful for managing user configuration - * and understanding the capabilities of the attached pens. - * - * We primarily identify pens by ::SDL_PenID. The implementation makes a best effort to relate each :SDL_PenID - * to the same physical device during a session. Formerly valid ::SDL_PenID values remain valid - * even if a device disappears. - * - * For identifying pens across sessions, the API provides the type ::SDL_GUID . + * Pens may provide more than simple touch input; they might have other axes, + * such as pressure, tilt, rotation, etc. */ #ifndef SDL_pen_h_ #define SDL_pen_h_ -#include -#include -#include #include /* Set up for C function definitions, even when using C++ */ @@ -55,223 +46,61 @@ extern "C" { #endif -typedef Uint32 SDL_PenID; /**< SDL_PenIDs identify pens uniquely within a session */ - -#define SDL_PEN_INVALID ((SDL_PenID)0) /**< Reserved invalid ::SDL_PenID is valid */ - -#define SDL_PEN_MOUSEID ((SDL_MouseID)-2) /**< Device ID for mouse events triggered by pen events */ - -#define SDL_PEN_INFO_UNKNOWN (-1) /**< Marks unknown information when querying the pen */ - /** - * Pen axis indices + * SDL pen instance IDs. * - * Below are the valid indices to the "axis" array from ::SDL_PenMotionEvent and ::SDL_PenButtonEvent. - * The axis indices form a contiguous range of ints from 0 to ::SDL_PEN_AXIS_LAST, inclusive. - * All "axis[]" entries are either normalised to 0..1 or report a (positive or negative) - * angle in degrees, with 0.0 representing the centre. - * Not all pens/backends support all axes: unsupported entries are always "0.0f". + * Zero is used to signify an invalid/null device. * - * To convert angles for tilt and rotation into vector representation, use - * SDL_sinf on the XTILT, YTILT, or ROTATION component, e.g., "SDL_sinf(xtilt * SDL_PI_F / 180.0)". - */ -typedef enum -{ - SDL_PEN_AXIS_PRESSURE = 0, /**< Pen pressure. Unidirectional: 0..1.0 */ - SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0..90.0 (left-to-right). - The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */ - SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0..90.0 (top-to-down). - The physical max/min tilt may be smaller than -90.0 / 90.0, cf. SDL_PenCapabilityInfo */ - SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0..1.0 */ - SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180..179.9 (clockwise, 0 is facing up, -180.0 is facing down). */ - SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0..1.0 */ - SDL_PEN_NUM_AXES, /**< Last valid axis index */ - SDL_PEN_AXIS_LAST = SDL_PEN_NUM_AXES - 1 /**< Last axis index plus 1 */ -} SDL_PenAxis; - -/* Pen flags. These share a bitmask space with ::SDL_BUTTON_LEFT and friends. */ -#define SDL_PEN_FLAG_DOWN_BIT_INDEX 13 /* Bit for storing that pen is touching the surface */ -#define SDL_PEN_FLAG_INK_BIT_INDEX 14 /* Bit for storing has-non-eraser-capability status */ -#define SDL_PEN_FLAG_ERASER_BIT_INDEX 15 /* Bit for storing is-eraser or has-eraser-capability property */ -#define SDL_PEN_FLAG_AXIS_BIT_OFFSET 16 /* Bit for storing has-axis-0 property */ - -#define SDL_PEN_CAPABILITY(capbit) (1ul << (capbit)) -#define SDL_PEN_AXIS_CAPABILITY(axis) SDL_PEN_CAPABILITY((axis) + SDL_PEN_FLAG_AXIS_BIT_OFFSET) - -/** - * Pen tips - * @{ - */ -#define SDL_PEN_TIP_INK SDL_PEN_FLAG_INK_BIT_INDEX /**< Regular pen tip (for drawing) touched the surface */ -#define SDL_PEN_TIP_ERASER SDL_PEN_FLAG_ERASER_BIT_INDEX /**< Eraser pen tip touched the surface */ -/** @} */ - - -/** - * \defgroup SDL_PEN_CAPABILITIES Pen capabilities - * Pen capabilities reported by ::SDL_GetPenCapabilities - * @{ - */ -#define SDL_PEN_DOWN_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_DOWN_BIT_INDEX) /**< Pen tip is currently touching the drawing surface. */ -#define SDL_PEN_INK_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_INK_BIT_INDEX) /**< Pen has a regular drawing tip (::SDL_GetPenCapabilities). For events (::SDL_PenButtonEvent, ::SDL_PenMotionEvent, ::SDL_GetPenStatus) this flag is mutually exclusive with ::SDL_PEN_ERASER_MASK . */ -#define SDL_PEN_ERASER_MASK SDL_PEN_CAPABILITY(SDL_PEN_FLAG_ERASER_BIT_INDEX) /**< Pen has an eraser tip (::SDL_GetPenCapabilities) or is being used as eraser (::SDL_PenButtonEvent , ::SDL_PenMotionEvent , ::SDL_GetPenStatus) */ -#define SDL_PEN_AXIS_PRESSURE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_PRESSURE) /**< Pen provides pressure information in axis ::SDL_PEN_AXIS_PRESSURE */ -#define SDL_PEN_AXIS_XTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_XTILT) /**< Pen provides horizontal tilt information in axis ::SDL_PEN_AXIS_XTILT */ -#define SDL_PEN_AXIS_YTILT_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_YTILT) /**< Pen provides vertical tilt information in axis ::SDL_PEN_AXIS_YTILT */ -#define SDL_PEN_AXIS_DISTANCE_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_DISTANCE) /**< Pen provides distance to drawing tablet in ::SDL_PEN_AXIS_DISTANCE */ -#define SDL_PEN_AXIS_ROTATION_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_ROTATION) /**< Pen provides barrel rotation information in axis ::SDL_PEN_AXIS_ROTATION */ -#define SDL_PEN_AXIS_SLIDER_MASK SDL_PEN_AXIS_CAPABILITY(SDL_PEN_AXIS_SLIDER) /**< Pen provides slider / finger wheel or similar in axis ::SDL_PEN_AXIS_SLIDER */ - -#define SDL_PEN_AXIS_BIDIRECTIONAL_MASKS (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) -/**< Masks for all axes that may be bidirectional */ -/** @} */ - -/** - * Pen types - * - * Some pens identify as a particular type of drawing device (e.g., an airbrush or a pencil). + * These show up in pen events when SDL sees input from them. They remain + * consistent as long as SDL can recognize a tool to be the same pen; but if a + * pen physically leaves the area and returns, it might get a new ID. * + * \since This datatype is available since SDL 3.0.0. */ -typedef enum -{ - SDL_PEN_TYPE_UNKNOWN = 0, - SDL_PEN_TYPE_ERASER = 1, /**< Eraser */ - SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */ - SDL_PEN_TYPE_PENCIL, /**< Pencil */ - SDL_PEN_TYPE_BRUSH, /**< Brush-like device */ - SDL_PEN_TYPE_AIRBRUSH, /**< Airbrush device that "sprays" ink */ - SDL_PEN_TYPE_LAST = SDL_PEN_TYPE_AIRBRUSH /**< Last valid pen type */ -} SDL_PenSubtype; +typedef Uint32 SDL_PenID; -/* Function prototypes */ - /** - * Retrieves all pens that are connected to the system. - * - * Yields an array of ::SDL_PenID values. These identify and track pens - * throughout a session. To track pens across sessions (program restart), use - * ::SDL_GUID . + * Pen input flags, as reported by various pen events' `pen_state` field. * - * \param count The number of pens in the array (number of array elements - * minus 1, i.e., not counting the terminator 0). - * \returns A 0 terminated array of ::SDL_PenID values, or NULL on error. The - * array must be freed with ::SDL_free(). On a NULL return, - * ::SDL_GetError() is set. - * - * \since This function is available since SDL 3.0.0 + * \since This datatype is available since SDL 3.0.0. */ -extern DECLSPEC SDL_PenID *SDLCALL SDL_GetPens(int *count); +typedef Uint32 SDL_PenInputFlags; -/** - * Retrieves the pen's current status. - * - * If the pen is detached (cf. ::SDL_PenConnected), this operation may return - * default values. - * - * \param instance_id The pen to query. - * \param x Out-mode parameter for pen x coordinate. May be NULL. - * \param y Out-mode parameter for pen y coordinate. May be NULL. - * \param axes Out-mode parameter for axis information. May be null. The axes - * are in the same order as ::SDL_PenAxis. - * \param num_axes Maximum number of axes to write to "axes". - * \returns a bit mask with the current pen button states (::SDL_BUTTON_LMASK - * etc.), possibly ::SDL_PEN_DOWN_MASK, and exactly one of - * ::SDL_PEN_INK_MASK or ::SDL_PEN_ERASER_MASK , or 0 on error (see - * ::SDL_GetError()). - * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC Uint32 SDLCALL SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes); - -/** - * Retrieves an ::SDL_PenID for the given ::SDL_GUID. - * - * \param guid A pen GUID. - * \returns A valid ::SDL_PenID, or ::SDL_PEN_INVALID if there is no matching - * SDL_PenID. - * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC SDL_PenID SDLCALL SDL_GetPenFromGUID(SDL_GUID guid); +#define SDL_PEN_INPUT_DOWN (1u << 0) /**< pen is pressed down */ +#define SDL_PEN_INPUT_BUTTON_1 (1u << 1) /**< button 1 is pressed */ +#define SDL_PEN_INPUT_BUTTON_2 (1u << 2) /**< button 2 is pressed */ +#define SDL_PEN_INPUT_BUTTON_3 (1u << 3) /**< button 3 is pressed */ +#define SDL_PEN_INPUT_BUTTON_4 (1u << 4) /**< button 4 is pressed */ +#define SDL_PEN_INPUT_BUTTON_5 (1u << 5) /**< button 5 is pressed */ +#define SDL_PEN_INPUT_ERASER_TIP (1u << 30) /**< eraser tip is used */ /** - * Retrieves the ::SDL_GUID for a given ::SDL_PenID. + * Pen axis indices. * - * \param instance_id The pen to query. - * \returns The corresponding pen GUID; persistent across multiple sessions. - * If "instance_id" is ::SDL_PEN_INVALID, returns an all-zeroes GUID. + * These are the valid values for the `axis` field in SDL_PenAxisEvent. All + * axes are either normalised to 0..1 or report a (positive or negative) angle + * in degrees, with 0.0 representing the centre. Not all pens/backends support + * all axes: unsupported axes are always zero. * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC SDL_GUID SDLCALL SDL_GetPenGUID(SDL_PenID instance_id); - -/** - * Checks whether a pen is still attached. - * - * If a pen is detached, it will not show up for ::SDL_GetPens(). Other - * operations will still be available but may return default values. - * - * \param instance_id A pen ID. - * \returns SDL_TRUE if "instance_id" is valid and the corresponding pen is - * attached, or SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC SDL_bool SDLCALL SDL_PenConnected(SDL_PenID instance_id); - -/** - * Retrieves a human-readable description for a ::SDL_PenID. + * To convert angles for tilt and rotation into vector representation, use + * SDL_sinf on the XTILT, YTILT, or ROTATION component, for example: * - * \param instance_id The pen to query. - * \returns A string that contains the name of the pen, intended for human - * consumption. The string might or might not be localised, depending - * on platform settings. It is not guaranteed to be unique; use - * ::SDL_GetPenGUID() for (best-effort) unique identifiers. The - * pointer is managed by the SDL pen subsystem and must not be - * deallocated. The pointer remains valid until SDL is shut down. - * Returns NULL on error (cf. ::SDL_GetError()) + * `SDL_sinf(xtilt * SDL_PI_F / 180.0)`. * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC const char *SDLCALL SDL_GetPenName(SDL_PenID instance_id); - -/** - * Pen capabilities, as reported by ::SDL_GetPenCapabilities() + * \since This enum is available since SDL 3.0.0 */ -typedef struct SDL_PenCapabilityInfo +typedef enum SDL_PenAxis { - float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or SDL_PEN_INFO_UNKNOWN . Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */ - Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */ - Sint8 num_buttons; /**< Number of pen buttons (not counting the pen tip), or SDL_PEN_INFO_UNKNOWN */ -} SDL_PenCapabilityInfo; - -/** - * Retrieves capability flags for a given ::SDL_PenID. - * - * \param instance_id The pen to query. - * \param capabilities Detail information about pen capabilities, such as the - * number of buttons - * \returns a set of capability flags, cf. SDL_PEN_CAPABILITIES - * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC Uint32 SDLCALL SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *capabilities); - -/** - * Retrieves the pen type for a given ::SDL_PenID. - * - * \param instance_id The pen to query. - * \returns The corresponding pen type (cf. ::SDL_PenSubtype) or 0 on error. - * Note that the pen type does not dictate whether the pen tip is - * ::SDL_PEN_TIP_INK or ::SDL_PEN_TIP_ERASER; to determine whether a - * pen is being used for drawing or in eraser mode, check either the - * pen tip on ::SDL_EVENT_PEN_DOWN, or the flag ::SDL_PEN_ERASER_MASK - * in the pen state. - * - * \since This function is available since SDL 3.0.0 - */ -extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id); + SDL_PEN_AXIS_PRESSURE, /**< Pen pressure. Unidirectional: 0 to 1.0 */ + SDL_PEN_AXIS_XTILT, /**< Pen horizontal tilt angle. Bidirectional: -90.0 to 90.0 (left-to-right). */ + SDL_PEN_AXIS_YTILT, /**< Pen vertical tilt angle. Bidirectional: -90.0 to 90.0 (top-to-down). */ + SDL_PEN_AXIS_DISTANCE, /**< Pen distance to drawing surface. Unidirectional: 0.0 to 1.0 */ + SDL_PEN_AXIS_ROTATION, /**< Pen barrel rotation. Bidirectional: -180 to 179.9 (clockwise, 0 is facing up, -180.0 is facing down). */ + SDL_PEN_AXIS_SLIDER, /**< Pen finger wheel or slider (e.g., Airbrush Pen). Unidirectional: 0 to 1.0 */ + SDL_PEN_AXIS_TANGENTIAL_PRESSURE, /**< Pressure from squeezing the pen ("barrel pressure"). */ + SDL_PEN_AXIS_COUNT /**< Total known pen axis types in this version of SDL. This number may grow in future releases! */ +} SDL_PenAxis; /* Ends C function definitions when using C++ */ #ifdef __cplusplus @@ -280,4 +109,3 @@ extern DECLSPEC SDL_PenSubtype SDLCALL SDL_GetPenType(SDL_PenID instance_id); #endif /* SDL_pen_h_ */ -/* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL3/include/SDL3/SDL_pixels.h b/libs/SDL3/include/SDL3/SDL_pixels.h index 94533f24a..820e29957 100644 --- a/libs/SDL3/include/SDL3/SDL_pixels.h +++ b/libs/SDL3/include/SDL3/SDL_pixels.h @@ -20,51 +20,16 @@ */ /** - * \file SDL_pixels.h - * - * Header for the enumerated pixel format definitions. - * - * SDL's pixel formats have the following naming convention: - * - * * Names with a list of components and a single bit count, such as - * RGB24 and ABGR32, define a platform-independent encoding into - * bytes in the order specified. For example, in RGB24 data, each - * pixel is encoded in 3 bytes (red, green, blue) in that order, - * and in ABGR32 data, each pixel is encoded in 4 bytes - * (alpha, blue, green, red) in that order. Use these names if the - * property of a format that is important to you is the order of - * the bytes in memory or on disk. - * - * * Names with a bit count per component, such as ARGB8888 and - * XRGB1555, are "packed" into an appropriately-sized integer in - * the platform's native endianness. For example, ARGB8888 is - * a sequence of 32-bit integers; in each integer, the most - * significant bits are alpha, and the least significant bits are - * blue. On a little-endian CPU such as x86, the least significant - * bits of each integer are arranged first in memory, but on a - * big-endian CPU such as s390x, the most significant bits are - * arranged first. Use these names if the property of a format that - * is important to you is the meaning of each bit position within a - * native-endianness integer. - * - * * In indexed formats such as INDEX4LSB, each pixel is represented - * by encoding an index into the palette into the indicated number - * of bits, with multiple pixels packed into each byte if appropriate. - * In LSB formats, the first (leftmost) pixel is stored in the - * least-significant bits of the byte; in MSB formats, it's stored - * in the most-significant bits. INDEX8 does not need LSB/MSB - * variants, because each pixel exactly fills one byte. - * - * The 32-bit byte-array encodings such as RGBA32 are aliases for the - * appropriate 8888 encoding for the current platform. For example, - * RGBA32 is an alias for ABGR8888 on little-endian CPUs like x86, - * or an alias for RGBA8888 on big-endian CPUs. + * # CategoryPixels + * + * Pixel management. */ #ifndef SDL_pixels_h_ #define SDL_pixels_h_ #include +#include #include #include @@ -74,17 +39,47 @@ extern "C" { #endif /** - * \name Transparency definitions + * A fully opaque 8-bit alpha value. + * + * \since This macro is available since SDL 3.0.0. * - * These define alpha as the opacity of a surface. + * \sa SDL_ALPHA_TRANSPARENT */ -/* @{ */ #define SDL_ALPHA_OPAQUE 255 + +/** + * A fully opaque floating point alpha value. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_ALPHA_TRANSPARENT_FLOAT + */ +#define SDL_ALPHA_OPAQUE_FLOAT 1.0f + +/** + * A fully transparent 8-bit alpha value. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_ALPHA_OPAQUE + */ #define SDL_ALPHA_TRANSPARENT 0 -/* @} */ -/** Pixel type. */ -typedef enum +/** + * A fully transparent floating point alpha value. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_ALPHA_OPAQUE_FLOAT + */ +#define SDL_ALPHA_TRANSPARENT_FLOAT 0.0f + +/** + * Pixel type. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_PixelType { SDL_PIXELTYPE_UNKNOWN, SDL_PIXELTYPE_INDEX1, @@ -102,16 +97,24 @@ typedef enum SDL_PIXELTYPE_INDEX2 } SDL_PixelType; -/** Bitmap pixel order, high bit -> low bit. */ -typedef enum +/** + * Bitmap pixel order, high bit -> low bit. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_BitmapOrder { SDL_BITMAPORDER_NONE, SDL_BITMAPORDER_4321, SDL_BITMAPORDER_1234 } SDL_BitmapOrder; -/** Packed component order, high bit -> low bit. */ -typedef enum +/** + * Packed component order, high bit -> low bit. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_PackedOrder { SDL_PACKEDORDER_NONE, SDL_PACKEDORDER_XRGB, @@ -124,8 +127,12 @@ typedef enum SDL_PACKEDORDER_BGRA } SDL_PackedOrder; -/** Array component order, low byte -> high byte. */ -typedef enum +/** + * Array component order, low byte -> high byte. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_ArrayOrder { SDL_ARRAYORDER_NONE, SDL_ARRAYORDER_RGB, @@ -136,8 +143,12 @@ typedef enum SDL_ARRAYORDER_ABGR } SDL_ArrayOrder; -/** Packed component layout. */ -typedef enum +/** + * Packed component layout. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_PackedLayout { SDL_PACKEDLAYOUT_NONE, SDL_PACKEDLAYOUT_332, @@ -160,7 +171,8 @@ typedef enum #define SDL_PIXELTYPE(X) (((X) >> 24) & 0x0F) #define SDL_PIXELORDER(X) (((X) >> 20) & 0x0F) #define SDL_PIXELLAYOUT(X) (((X) >> 16) & 0x0F) -#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF) +#define SDL_BITSPERPIXEL(X) \ + (SDL_ISPIXELFORMAT_FOURCC(X) ? 0 : (((X) >> 8) & 0xFF)) #define SDL_BYTESPERPIXEL(X) \ (SDL_ISPIXELFORMAT_FOURCC(X) ? \ ((((X) == SDL_PIXELFORMAT_YUY2) || \ @@ -210,178 +222,178 @@ typedef enum #define SDL_ISPIXELFORMAT_FOURCC(format) \ ((format) && (SDL_PIXELFLAG(format) != 1)) -/* Note: If you modify this list, update SDL_GetPixelFormatName() */ -typedef enum +/* Note: If you modify this enum, update SDL_GetPixelFormatName() */ + +/** + * Pixel format. + * + * SDL's pixel formats have the following naming convention: + * + * - Names with a list of components and a single bit count, such as RGB24 and + * ABGR32, define a platform-independent encoding into bytes in the order + * specified. For example, in RGB24 data, each pixel is encoded in 3 bytes + * (red, green, blue) in that order, and in ABGR32 data, each pixel is + * encoded in 4 bytes alpha, blue, green, red) in that order. Use these + * names if the property of a format that is important to you is the order + * of the bytes in memory or on disk. + * - Names with a bit count per component, such as ARGB8888 and XRGB1555, are + * "packed" into an appropriately-sized integer in the platform's native + * endianness. For example, ARGB8888 is a sequence of 32-bit integers; in + * each integer, the most significant bits are alpha, and the least + * significant bits are blue. On a little-endian CPU such as x86, the least + * significant bits of each integer are arranged first in memory, but on a + * big-endian CPU such as s390x, the most significant bits are arranged + * first. Use these names if the property of a format that is important to + * you is the meaning of each bit position within a native-endianness + * integer. + * - In indexed formats such as INDEX4LSB, each pixel is represented by + * encoding an index into the palette into the indicated number of bits, + * with multiple pixels packed into each byte if appropriate. In LSB + * formats, the first (leftmost) pixel is stored in the least-significant + * bits of the byte; in MSB formats, it's stored in the most-significant + * bits. INDEX8 does not need LSB/MSB variants, because each pixel exactly + * fills one byte. + * + * The 32-bit byte-array encodings such as RGBA32 are aliases for the + * appropriate 8888 encoding for the current platform. For example, RGBA32 is + * an alias for ABGR8888 on little-endian CPUs like x86, or an alias for + * RGBA8888 on big-endian CPUs. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_PixelFormat { - SDL_PIXELFORMAT_UNKNOWN, - SDL_PIXELFORMAT_INDEX1LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0, - 1, 0), - SDL_PIXELFORMAT_INDEX1MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, - 1, 0), - SDL_PIXELFORMAT_INDEX2LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, - 2, 0), - SDL_PIXELFORMAT_INDEX2MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, - 2, 0), - SDL_PIXELFORMAT_INDEX4LSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, - 4, 0), - SDL_PIXELFORMAT_INDEX4MSB = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0, - 4, 0), - SDL_PIXELFORMAT_INDEX8 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1), - SDL_PIXELFORMAT_RGB332 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_332, 8, 1), - SDL_PIXELFORMAT_XRGB4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_4444, 12, 2), - SDL_PIXELFORMAT_RGB444 = SDL_PIXELFORMAT_XRGB4444, - SDL_PIXELFORMAT_XBGR4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, - SDL_PACKEDLAYOUT_4444, 12, 2), - SDL_PIXELFORMAT_BGR444 = SDL_PIXELFORMAT_XBGR4444, - SDL_PIXELFORMAT_XRGB1555 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_1555, 15, 2), - SDL_PIXELFORMAT_RGB555 = SDL_PIXELFORMAT_XRGB1555, - SDL_PIXELFORMAT_XBGR1555 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, - SDL_PACKEDLAYOUT_1555, 15, 2), - SDL_PIXELFORMAT_BGR555 = SDL_PIXELFORMAT_XBGR1555, - SDL_PIXELFORMAT_ARGB4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB, - SDL_PACKEDLAYOUT_4444, 16, 2), - SDL_PIXELFORMAT_RGBA4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA, - SDL_PACKEDLAYOUT_4444, 16, 2), - SDL_PIXELFORMAT_ABGR4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR, - SDL_PACKEDLAYOUT_4444, 16, 2), - SDL_PIXELFORMAT_BGRA4444 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA, - SDL_PACKEDLAYOUT_4444, 16, 2), - SDL_PIXELFORMAT_ARGB1555 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB, - SDL_PACKEDLAYOUT_1555, 16, 2), - SDL_PIXELFORMAT_RGBA5551 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA, - SDL_PACKEDLAYOUT_5551, 16, 2), - SDL_PIXELFORMAT_ABGR1555 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR, - SDL_PACKEDLAYOUT_1555, 16, 2), - SDL_PIXELFORMAT_BGRA5551 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA, - SDL_PACKEDLAYOUT_5551, 16, 2), - SDL_PIXELFORMAT_RGB565 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_565, 16, 2), - SDL_PIXELFORMAT_BGR565 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, - SDL_PACKEDLAYOUT_565, 16, 2), - SDL_PIXELFORMAT_RGB24 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0, - 24, 3), - SDL_PIXELFORMAT_BGR24 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0, - 24, 3), - SDL_PIXELFORMAT_XRGB8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_8888, 24, 4), - SDL_PIXELFORMAT_RGBX8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX, - SDL_PACKEDLAYOUT_8888, 24, 4), - SDL_PIXELFORMAT_XBGR8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, - SDL_PACKEDLAYOUT_8888, 24, 4), - SDL_PIXELFORMAT_BGRX8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX, - SDL_PACKEDLAYOUT_8888, 24, 4), - SDL_PIXELFORMAT_ARGB8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, - SDL_PACKEDLAYOUT_8888, 32, 4), - SDL_PIXELFORMAT_RGBA8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA, - SDL_PACKEDLAYOUT_8888, 32, 4), - SDL_PIXELFORMAT_ABGR8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, - SDL_PACKEDLAYOUT_8888, 32, 4), - SDL_PIXELFORMAT_BGRA8888 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA, - SDL_PACKEDLAYOUT_8888, 32, 4), - SDL_PIXELFORMAT_XRGB2101010 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, - SDL_PACKEDLAYOUT_2101010, 32, 4), - SDL_PIXELFORMAT_XBGR2101010 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, - SDL_PACKEDLAYOUT_2101010, 32, 4), - SDL_PIXELFORMAT_ARGB2101010 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, - SDL_PACKEDLAYOUT_2101010, 32, 4), - SDL_PIXELFORMAT_ABGR2101010 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, - SDL_PACKEDLAYOUT_2101010, 32, 4), - SDL_PIXELFORMAT_RGB48 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_RGB, 0, - 48, 6), - SDL_PIXELFORMAT_BGR48 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_BGR, 0, - 48, 6), - SDL_PIXELFORMAT_RGBA64 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_RGBA, 0, - 64, 8), - SDL_PIXELFORMAT_ARGB64 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_ARGB, 0, - 64, 8), - SDL_PIXELFORMAT_BGRA64 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_BGRA, 0, - 64, 8), - SDL_PIXELFORMAT_ABGR64 = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_ABGR, 0, - 64, 8), - SDL_PIXELFORMAT_RGB48_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_RGB, 0, - 48, 6), - SDL_PIXELFORMAT_BGR48_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_BGR, 0, - 48, 6), - SDL_PIXELFORMAT_RGBA64_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_RGBA, 0, - 64, 8), - SDL_PIXELFORMAT_ARGB64_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_ARGB, 0, - 64, 8), - SDL_PIXELFORMAT_BGRA64_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_BGRA, 0, - 64, 8), - SDL_PIXELFORMAT_ABGR64_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_ABGR, 0, - 64, 8), - SDL_PIXELFORMAT_RGB96_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_RGB, 0, - 96, 12), - SDL_PIXELFORMAT_BGR96_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_BGR, 0, - 96, 12), - SDL_PIXELFORMAT_RGBA128_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_RGBA, 0, - 128, 16), - SDL_PIXELFORMAT_ARGB128_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_ARGB, 0, - 128, 16), - SDL_PIXELFORMAT_BGRA128_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_BGRA, 0, - 128, 16), - SDL_PIXELFORMAT_ABGR128_FLOAT = - SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_ABGR, 0, - 128, 16), + SDL_PIXELFORMAT_UNKNOWN = 0, + SDL_PIXELFORMAT_INDEX1LSB = 0x11100100u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_4321, 0, 1, 0), */ + SDL_PIXELFORMAT_INDEX1MSB = 0x11200100u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0, 1, 0), */ + SDL_PIXELFORMAT_INDEX2LSB = 0x1c100200u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0, 2, 0), */ + SDL_PIXELFORMAT_INDEX2MSB = 0x1c200200u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0, 2, 0), */ + SDL_PIXELFORMAT_INDEX4LSB = 0x12100400u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0, 4, 0), */ + SDL_PIXELFORMAT_INDEX4MSB = 0x12200400u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_1234, 0, 4, 0), */ + SDL_PIXELFORMAT_INDEX8 = 0x13000801u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX8, 0, 0, 8, 1), */ + SDL_PIXELFORMAT_RGB332 = 0x14110801u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED8, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_332, 8, 1), */ + SDL_PIXELFORMAT_XRGB4444 = 0x15120c02u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_4444, 12, 2), */ + SDL_PIXELFORMAT_XBGR4444 = 0x15520c02u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_4444, 12, 2), */ + SDL_PIXELFORMAT_XRGB1555 = 0x15130f02u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_1555, 15, 2), */ + SDL_PIXELFORMAT_XBGR1555 = 0x15530f02u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_1555, 15, 2), */ + SDL_PIXELFORMAT_ARGB4444 = 0x15321002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_4444, 16, 2), */ + SDL_PIXELFORMAT_RGBA4444 = 0x15421002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_4444, 16, 2), */ + SDL_PIXELFORMAT_ABGR4444 = 0x15721002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_4444, 16, 2), */ + SDL_PIXELFORMAT_BGRA4444 = 0x15821002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_4444, 16, 2), */ + SDL_PIXELFORMAT_ARGB1555 = 0x15331002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_1555, 16, 2), */ + SDL_PIXELFORMAT_RGBA5551 = 0x15441002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_5551, 16, 2), */ + SDL_PIXELFORMAT_ABGR1555 = 0x15731002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_1555, 16, 2), */ + SDL_PIXELFORMAT_BGRA5551 = 0x15841002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_5551, 16, 2), */ + SDL_PIXELFORMAT_RGB565 = 0x15151002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_565, 16, 2), */ + SDL_PIXELFORMAT_BGR565 = 0x15551002u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED16, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_565, 16, 2), */ + SDL_PIXELFORMAT_RGB24 = 0x17101803u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_RGB, 0, 24, 3), */ + SDL_PIXELFORMAT_BGR24 = 0x17401803u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU8, SDL_ARRAYORDER_BGR, 0, 24, 3), */ + SDL_PIXELFORMAT_XRGB8888 = 0x16161804u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_8888, 24, 4), */ + SDL_PIXELFORMAT_RGBX8888 = 0x16261804u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBX, SDL_PACKEDLAYOUT_8888, 24, 4), */ + SDL_PIXELFORMAT_XBGR8888 = 0x16561804u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_8888, 24, 4), */ + SDL_PIXELFORMAT_BGRX8888 = 0x16661804u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRX, SDL_PACKEDLAYOUT_8888, 24, 4), */ + SDL_PIXELFORMAT_ARGB8888 = 0x16362004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_8888, 32, 4), */ + SDL_PIXELFORMAT_RGBA8888 = 0x16462004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_RGBA, SDL_PACKEDLAYOUT_8888, 32, 4), */ + SDL_PIXELFORMAT_ABGR8888 = 0x16762004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_8888, 32, 4), */ + SDL_PIXELFORMAT_BGRA8888 = 0x16862004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_8888, 32, 4), */ + SDL_PIXELFORMAT_XRGB2101010 = 0x16172004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, SDL_PACKEDLAYOUT_2101010, 32, 4), */ + SDL_PIXELFORMAT_XBGR2101010 = 0x16572004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, SDL_PACKEDLAYOUT_2101010, 32, 4), */ + SDL_PIXELFORMAT_ARGB2101010 = 0x16372004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010, 32, 4), */ + SDL_PIXELFORMAT_ABGR2101010 = 0x16772004u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, SDL_PACKEDLAYOUT_2101010, 32, 4), */ + SDL_PIXELFORMAT_RGB48 = 0x18103006u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_RGB, 0, 48, 6), */ + SDL_PIXELFORMAT_BGR48 = 0x18403006u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_BGR, 0, 48, 6), */ + SDL_PIXELFORMAT_RGBA64 = 0x18204008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_RGBA, 0, 64, 8), */ + SDL_PIXELFORMAT_ARGB64 = 0x18304008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_ARGB, 0, 64, 8), */ + SDL_PIXELFORMAT_BGRA64 = 0x18504008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_BGRA, 0, 64, 8), */ + SDL_PIXELFORMAT_ABGR64 = 0x18604008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYU16, SDL_ARRAYORDER_ABGR, 0, 64, 8), */ + SDL_PIXELFORMAT_RGB48_FLOAT = 0x1a103006u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_RGB, 0, 48, 6), */ + SDL_PIXELFORMAT_BGR48_FLOAT = 0x1a403006u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_BGR, 0, 48, 6), */ + SDL_PIXELFORMAT_RGBA64_FLOAT = 0x1a204008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_RGBA, 0, 64, 8), */ + SDL_PIXELFORMAT_ARGB64_FLOAT = 0x1a304008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_ARGB, 0, 64, 8), */ + SDL_PIXELFORMAT_BGRA64_FLOAT = 0x1a504008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_BGRA, 0, 64, 8), */ + SDL_PIXELFORMAT_ABGR64_FLOAT = 0x1a604008u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF16, SDL_ARRAYORDER_ABGR, 0, 64, 8), */ + SDL_PIXELFORMAT_RGB96_FLOAT = 0x1b10600cu, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_RGB, 0, 96, 12), */ + SDL_PIXELFORMAT_BGR96_FLOAT = 0x1b40600cu, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_BGR, 0, 96, 12), */ + SDL_PIXELFORMAT_RGBA128_FLOAT = 0x1b208010u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_RGBA, 0, 128, 16), */ + SDL_PIXELFORMAT_ARGB128_FLOAT = 0x1b308010u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_ARGB, 0, 128, 16), */ + SDL_PIXELFORMAT_BGRA128_FLOAT = 0x1b508010u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_BGRA, 0, 128, 16), */ + SDL_PIXELFORMAT_ABGR128_FLOAT = 0x1b608010u, + /* SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_ARRAYF32, SDL_ARRAYORDER_ABGR, 0, 128, 16), */ + + SDL_PIXELFORMAT_YV12 = 0x32315659u, /**< Planar mode: Y + V + U (3 planes) */ + /* SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'), */ + SDL_PIXELFORMAT_IYUV = 0x56555949u, /**< Planar mode: Y + U + V (3 planes) */ + /* SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'), */ + SDL_PIXELFORMAT_YUY2 = 0x32595559u, /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ + /* SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'), */ + SDL_PIXELFORMAT_UYVY = 0x59565955u, /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ + /* SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'), */ + SDL_PIXELFORMAT_YVYU = 0x55595659u, /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ + /* SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'), */ + SDL_PIXELFORMAT_NV12 = 0x3231564eu, /**< Planar mode: Y + U/V interleaved (2 planes) */ + /* SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'), */ + SDL_PIXELFORMAT_NV21 = 0x3132564eu, /**< Planar mode: Y + V/U interleaved (2 planes) */ + /* SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), */ + SDL_PIXELFORMAT_P010 = 0x30313050u, /**< Planar mode: Y + U/V interleaved (2 planes) */ + /* SDL_DEFINE_PIXELFOURCC('P', '0', '1', '0'), */ + SDL_PIXELFORMAT_EXTERNAL_OES = 0x2053454fu, /**< Android video texture format */ + /* SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') */ /* Aliases for RGBA byte arrays of color data, for the current platform */ -#if SDL_BYTEORDER == SDL_BIG_ENDIAN + #if SDL_BYTEORDER == SDL_BIG_ENDIAN SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888, @@ -389,8 +401,8 @@ typedef enum SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_RGBX8888, SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_XRGB8888, SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_BGRX8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888, -#else + SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_XBGR8888 + #else SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888, SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888, @@ -398,28 +410,9 @@ typedef enum SDL_PIXELFORMAT_RGBX32 = SDL_PIXELFORMAT_XBGR8888, SDL_PIXELFORMAT_XRGB32 = SDL_PIXELFORMAT_BGRX8888, SDL_PIXELFORMAT_BGRX32 = SDL_PIXELFORMAT_XRGB8888, - SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888, -#endif - - SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */ - SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'), - SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */ - SDL_DEFINE_PIXELFOURCC('I', 'Y', 'U', 'V'), - SDL_PIXELFORMAT_YUY2 = /**< Packed mode: Y0+U0+Y1+V0 (1 plane) */ - SDL_DEFINE_PIXELFOURCC('Y', 'U', 'Y', '2'), - SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */ - SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'), - SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */ - SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'), - SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */ - SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'), - SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */ - SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), - SDL_PIXELFORMAT_P010 = /**< Planar mode: Y + U/V interleaved (2 planes) */ - SDL_DEFINE_PIXELFOURCC('P', '0', '1', '0'), - SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ - SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') -} SDL_PixelFormatEnum; + SDL_PIXELFORMAT_XBGR32 = SDL_PIXELFORMAT_RGBX8888 + #endif +} SDL_PixelFormat; /** * Pixels are a representation of a color in a particular color space. @@ -446,9 +439,11 @@ typedef enum */ /** - * The color type + * Colorspace color type. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_ColorType { SDL_COLOR_TYPE_UNKNOWN = 0, SDL_COLOR_TYPE_RGB = 1, @@ -456,9 +451,12 @@ typedef enum } SDL_ColorType; /** - * The color range, as described by https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en + * Colorspace color range, as described by + * https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_ColorRange { SDL_COLOR_RANGE_UNKNOWN = 0, SDL_COLOR_RANGE_LIMITED = 1, /**< Narrow range, e.g. 16-235 for 8-bit RGB and luma, and 16-240 for 8-bit chroma */ @@ -466,16 +464,19 @@ typedef enum } SDL_ColorRange; /** - * The color primaries, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + * Colorspace color primaries, as described by + * https://www.itu.int/rec/T-REC-H.273-201612-S/en + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_ColorPrimaries { SDL_COLOR_PRIMARIES_UNKNOWN = 0, SDL_COLOR_PRIMARIES_BT709 = 1, /**< ITU-R BT.709-6 */ SDL_COLOR_PRIMARIES_UNSPECIFIED = 2, SDL_COLOR_PRIMARIES_BT470M = 4, /**< ITU-R BT.470-6 System M */ SDL_COLOR_PRIMARIES_BT470BG = 5, /**< ITU-R BT.470-6 System B, G / ITU-R BT.601-7 625 */ - SDL_COLOR_PRIMARIES_BT601 = 6, /**< ITU-R BT.601-7 525 */ + SDL_COLOR_PRIMARIES_BT601 = 6, /**< ITU-R BT.601-7 525, SMPTE 170M */ SDL_COLOR_PRIMARIES_SMPTE240 = 7, /**< SMPTE 240M, functionally the same as SDL_COLOR_PRIMARIES_BT601 */ SDL_COLOR_PRIMARIES_GENERIC_FILM = 8, /**< Generic film (color filters using Illuminant C) */ SDL_COLOR_PRIMARIES_BT2020 = 9, /**< ITU-R BT.2020-2 / ITU-R BT.2100-0 */ @@ -487,9 +488,13 @@ typedef enum } SDL_ColorPrimaries; /** - * The transfer characteristics, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + * Colorspace transfer characteristics. + * + * These are as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_TransferCharacteristics { SDL_TRANSFER_CHARACTERISTICS_UNKNOWN = 0, SDL_TRANSFER_CHARACTERISTICS_BT709 = 1, /**< Rec. ITU-R BT.709-6 / ITU-R BT1361 */ @@ -513,14 +518,18 @@ typedef enum } SDL_TransferCharacteristics; /** - * The matrix coefficients, as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + * Colorspace matrix coefficients. + * + * These are as described by https://www.itu.int/rec/T-REC-H.273-201612-S/en + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_MatrixCoefficients { SDL_MATRIX_COEFFICIENTS_IDENTITY = 0, SDL_MATRIX_COEFFICIENTS_BT709 = 1, /**< ITU-R BT.709-6 */ SDL_MATRIX_COEFFICIENTS_UNSPECIFIED = 2, - SDL_MATRIX_COEFFICIENTS_FCC = 4, /**< US FCC */ + SDL_MATRIX_COEFFICIENTS_FCC = 4, /**< US FCC Title 47 */ SDL_MATRIX_COEFFICIENTS_BT470BG = 5, /**< ITU-R BT.470-6 System B, G / ITU-R BT.601-7 625, functionally the same as SDL_MATRIX_COEFFICIENTS_BT601 */ SDL_MATRIX_COEFFICIENTS_BT601 = 6, /**< ITU-R BT.601-7 525 */ SDL_MATRIX_COEFFICIENTS_SMPTE240 = 7, /**< SMPTE 240M */ @@ -535,9 +544,11 @@ typedef enum } SDL_MatrixCoefficients; /** - * The chroma sample location + * Colorspace chroma sample location. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_ChromaLocation { SDL_CHROMA_LOCATION_NONE = 0, /**< RGB, no chroma sampling */ SDL_CHROMA_LOCATION_LEFT = 1, /**< In MPEG-2, MPEG-4, and AVC, Cb and Cr are taken on midpoint of the left-edge of the 2x2 square. In other words, they have the same horizontal location as the top-left pixel, but is shifted one-half pixel down vertically. */ @@ -564,105 +575,121 @@ typedef enum #define SDL_ISCOLORSPACE_LIMITED_RANGE(X) (SDL_COLORSPACERANGE(X) != SDL_COLOR_RANGE_FULL) #define SDL_ISCOLORSPACE_FULL_RANGE(X) (SDL_COLORSPACERANGE(X) == SDL_COLOR_RANGE_FULL) -typedef enum +/** + * Colorspace definitions. + * + * Since similar colorspaces may vary in their details (matrix, transfer + * function, etc.), this is not an exhaustive list, but rather a + * representative sample of the kinds of colorspaces supported in SDL. + * + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_ColorPrimaries + * \sa SDL_ColorRange + * \sa SDL_ColorType + * \sa SDL_MatrixCoefficients + * \sa SDL_TransferCharacteristics + */ +typedef enum SDL_Colorspace { - SDL_COLORSPACE_UNKNOWN, + SDL_COLORSPACE_UNKNOWN = 0, /* sRGB is a gamma corrected colorspace, and the default colorspace for SDL rendering and 8-bit RGB surfaces */ - SDL_COLORSPACE_SRGB = /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT709, - SDL_TRANSFER_CHARACTERISTICS_SRGB, - SDL_MATRIX_COEFFICIENTS_IDENTITY, - SDL_CHROMA_LOCATION_NONE), + SDL_COLORSPACE_SRGB = 0x120005a0u, /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT709, + SDL_TRANSFER_CHARACTERISTICS_SRGB, + SDL_MATRIX_COEFFICIENTS_IDENTITY, + SDL_CHROMA_LOCATION_NONE), */ /* This is a linear colorspace and the default colorspace for floating point surfaces. On Windows this is the scRGB colorspace, and on Apple platforms this is kCGColorSpaceExtendedLinearSRGB for EDR content */ - SDL_COLORSPACE_SRGB_LINEAR = /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT709, - SDL_TRANSFER_CHARACTERISTICS_LINEAR, - SDL_MATRIX_COEFFICIENTS_IDENTITY, - SDL_CHROMA_LOCATION_NONE), + SDL_COLORSPACE_SRGB_LINEAR = 0x12000500u, /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT709, + SDL_TRANSFER_CHARACTERISTICS_LINEAR, + SDL_MATRIX_COEFFICIENTS_IDENTITY, + SDL_CHROMA_LOCATION_NONE), */ /* HDR10 is a non-linear HDR colorspace and the default colorspace for 10-bit surfaces */ - SDL_COLORSPACE_HDR10 = /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT2020, - SDL_TRANSFER_CHARACTERISTICS_PQ, - SDL_MATRIX_COEFFICIENTS_IDENTITY, - SDL_CHROMA_LOCATION_NONE), - - SDL_COLORSPACE_JPEG = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT709, - SDL_TRANSFER_CHARACTERISTICS_BT601, - SDL_MATRIX_COEFFICIENTS_BT601, - SDL_CHROMA_LOCATION_NONE), - - SDL_COLORSPACE_BT601_LIMITED = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_LIMITED, - SDL_COLOR_PRIMARIES_BT601, - SDL_TRANSFER_CHARACTERISTICS_BT601, - SDL_MATRIX_COEFFICIENTS_BT601, - SDL_CHROMA_LOCATION_LEFT), - - SDL_COLORSPACE_BT601_FULL = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT601, - SDL_TRANSFER_CHARACTERISTICS_BT601, - SDL_MATRIX_COEFFICIENTS_BT601, - SDL_CHROMA_LOCATION_LEFT), - - SDL_COLORSPACE_BT709_LIMITED = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_LIMITED, - SDL_COLOR_PRIMARIES_BT709, - SDL_TRANSFER_CHARACTERISTICS_BT709, - SDL_MATRIX_COEFFICIENTS_BT709, - SDL_CHROMA_LOCATION_LEFT), - - SDL_COLORSPACE_BT709_FULL = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT709, - SDL_TRANSFER_CHARACTERISTICS_BT709, - SDL_MATRIX_COEFFICIENTS_BT709, - SDL_CHROMA_LOCATION_LEFT), - - SDL_COLORSPACE_BT2020_LIMITED = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_LIMITED, - SDL_COLOR_PRIMARIES_BT2020, - SDL_TRANSFER_CHARACTERISTICS_PQ, - SDL_MATRIX_COEFFICIENTS_BT2020_NCL, - SDL_CHROMA_LOCATION_LEFT), - - SDL_COLORSPACE_BT2020_FULL = /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 */ - SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, - SDL_COLOR_RANGE_FULL, - SDL_COLOR_PRIMARIES_BT2020, - SDL_TRANSFER_CHARACTERISTICS_PQ, - SDL_MATRIX_COEFFICIENTS_BT2020_NCL, - SDL_CHROMA_LOCATION_LEFT), - - /* The default colorspace for RGB surfaces if no colorspace is specified */ - SDL_COLORSPACE_RGB_DEFAULT = SDL_COLORSPACE_SRGB, - - /* The default colorspace for YUV surfaces if no colorspace is specified */ - SDL_COLORSPACE_YUV_DEFAULT = SDL_COLORSPACE_JPEG, - + SDL_COLORSPACE_HDR10 = 0x12002600u, /**< Equivalent to DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_RGB, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT2020, + SDL_TRANSFER_CHARACTERISTICS_PQ, + SDL_MATRIX_COEFFICIENTS_IDENTITY, + SDL_CHROMA_LOCATION_NONE), */ + + SDL_COLORSPACE_JPEG = 0x220004c6u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_NONE_P709_X601 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT709, + SDL_TRANSFER_CHARACTERISTICS_BT601, + SDL_MATRIX_COEFFICIENTS_BT601, + SDL_CHROMA_LOCATION_NONE), */ + + SDL_COLORSPACE_BT601_LIMITED = 0x211018c6u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_LIMITED, + SDL_COLOR_PRIMARIES_BT601, + SDL_TRANSFER_CHARACTERISTICS_BT601, + SDL_MATRIX_COEFFICIENTS_BT601, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_BT601_FULL = 0x221018c6u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT601, + SDL_TRANSFER_CHARACTERISTICS_BT601, + SDL_MATRIX_COEFFICIENTS_BT601, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_BT709_LIMITED = 0x21100421u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_LIMITED, + SDL_COLOR_PRIMARIES_BT709, + SDL_TRANSFER_CHARACTERISTICS_BT709, + SDL_MATRIX_COEFFICIENTS_BT709, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_BT709_FULL = 0x22100421u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT709, + SDL_TRANSFER_CHARACTERISTICS_BT709, + SDL_MATRIX_COEFFICIENTS_BT709, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_BT2020_LIMITED = 0x21102609u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_LIMITED, + SDL_COLOR_PRIMARIES_BT2020, + SDL_TRANSFER_CHARACTERISTICS_PQ, + SDL_MATRIX_COEFFICIENTS_BT2020_NCL, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_BT2020_FULL = 0x22102609u, /**< Equivalent to DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 */ + /* SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, + SDL_COLOR_RANGE_FULL, + SDL_COLOR_PRIMARIES_BT2020, + SDL_TRANSFER_CHARACTERISTICS_PQ, + SDL_MATRIX_COEFFICIENTS_BT2020_NCL, + SDL_CHROMA_LOCATION_LEFT), */ + + SDL_COLORSPACE_RGB_DEFAULT = SDL_COLORSPACE_SRGB, /**< The default colorspace for RGB surfaces if no colorspace is specified */ + SDL_COLORSPACE_YUV_DEFAULT = SDL_COLORSPACE_JPEG /**< The default colorspace for YUV surfaces if no colorspace is specified */ } SDL_Colorspace; /** - * The bits of this structure can be directly reinterpreted as an integer-packed - * color which uses the SDL_PIXELFORMAT_RGBA32 format (SDL_PIXELFORMAT_ABGR8888 - * on little-endian systems and SDL_PIXELFORMAT_RGBA8888 on big-endian systems). + * A structure that represents a color as RGBA components. + * + * The bits of this structure can be directly reinterpreted as an + * integer-packed color which uses the SDL_PIXELFORMAT_RGBA32 format + * (SDL_PIXELFORMAT_ABGR8888 on little-endian systems and + * SDL_PIXELFORMAT_RGBA8888 on big-endian systems). + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_Color { @@ -671,11 +698,12 @@ typedef struct SDL_Color Uint8 b; Uint8 a; } SDL_Color; -#define SDL_Colour SDL_Color /** * The bits of this structure can be directly reinterpreted as a float-packed * color which uses the SDL_PIXELFORMAT_RGBA128_FLOAT format + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_FColor { @@ -684,23 +712,30 @@ typedef struct SDL_FColor float b; float a; } SDL_FColor; -#define SDL_FColour SDL_FColor +/** + * A set of indexed colors representing a palette. + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_SetPaletteColors + */ typedef struct SDL_Palette { - int ncolors; - SDL_Color *colors; - Uint32 version; - int refcount; + int ncolors; /**< number of elements in `colors`. */ + SDL_Color *colors; /**< an array of colors, `ncolors` long. */ + Uint32 version; /**< internal use only, do not touch. */ + int refcount; /**< internal use only, do not touch. */ } SDL_Palette; /** - * \note Everything in the pixel format structure is read-only. + * Details about the format of a pixel. + * + * \since This struct is available since SDL 3.0.0. */ -typedef struct SDL_PixelFormat +typedef struct SDL_PixelFormatDetails { - SDL_PixelFormatEnum format; - SDL_Palette *palette; + SDL_PixelFormat format; Uint8 bits_per_pixel; Uint8 bytes_per_pixel; Uint8 padding[2]; @@ -708,51 +743,48 @@ typedef struct SDL_PixelFormat Uint32 Gmask; Uint32 Bmask; Uint32 Amask; - Uint8 Rloss; - Uint8 Gloss; - Uint8 Bloss; - Uint8 Aloss; + Uint8 Rbits; + Uint8 Gbits; + Uint8 Bbits; + Uint8 Abits; Uint8 Rshift; Uint8 Gshift; Uint8 Bshift; Uint8 Ashift; - int refcount; - struct SDL_PixelFormat *next; -} SDL_PixelFormat; +} SDL_PixelFormatDetails; /** * Get the human readable name of a pixel format. * - * \param format the pixel format to query + * \param format the pixel format to query. * \returns the human readable name of the specified pixel format or - * `SDL_PIXELFORMAT_UNKNOWN` if the format isn't recognized. + * "SDL_PIXELFORMAT_UNKNOWN" if the format isn't recognized. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char* SDLCALL SDL_GetPixelFormatName(SDL_PixelFormatEnum format); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetPixelFormatName(SDL_PixelFormat format); /** * Convert one of the enumerated pixel formats to a bpp value and RGBA masks. * - * \param format one of the SDL_PixelFormatEnum values - * \param bpp a bits per pixel value; usually 15, 16, or 32 - * \param Rmask a pointer filled in with the red mask for the format - * \param Gmask a pointer filled in with the green mask for the format - * \param Bmask a pointer filled in with the blue mask for the format - * \param Amask a pointer filled in with the alpha mask for the format - * \returns SDL_TRUE on success or SDL_FALSE if the conversion wasn't - * possible; call SDL_GetError() for more information. + * \param format one of the SDL_PixelFormat values. + * \param bpp a bits per pixel value; usually 15, 16, or 32. + * \param Rmask a pointer filled in with the red mask for the format. + * \param Gmask a pointer filled in with the green mask for the format. + * \param Bmask a pointer filled in with the blue mask for the format. + * \param Amask a pointer filled in with the alpha mask for the format. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetPixelFormatEnumForMasks + * \sa SDL_GetPixelFormatForMasks */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetMasksForPixelFormatEnum(SDL_PixelFormatEnum format, - int *bpp, - Uint32 * Rmask, - Uint32 * Gmask, - Uint32 * Bmask, - Uint32 * Amask); +extern SDL_DECLSPEC bool SDLCALL SDL_GetMasksForPixelFormat(SDL_PixelFormat format, int *bpp, Uint32 *Rmask, Uint32 *Gmask, Uint32 *Bmask, Uint32 *Amask); /** * Convert a bpp value and RGBA masks to an enumerated pixel format. @@ -760,110 +792,89 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetMasksForPixelFormatEnum(SDL_PixelFormatE * This will return `SDL_PIXELFORMAT_UNKNOWN` if the conversion wasn't * possible. * - * \param bpp a bits per pixel value; usually 15, 16, or 32 - * \param Rmask the red mask for the format - * \param Gmask the green mask for the format - * \param Bmask the blue mask for the format - * \param Amask the alpha mask for the format - * \returns the SDL_PixelFormatEnum value corresponding to the format masks, - * or SDL_PIXELFORMAT_UNKNOWN if there isn't a match. + * \param bpp a bits per pixel value; usually 15, 16, or 32. + * \param Rmask the red mask for the format. + * \param Gmask the green mask for the format. + * \param Bmask the blue mask for the format. + * \param Amask the alpha mask for the format. + * \returns the SDL_PixelFormat value corresponding to the format masks, or + * SDL_PIXELFORMAT_UNKNOWN if there isn't a match. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetMasksForPixelFormatEnum + * \sa SDL_GetMasksForPixelFormat */ -extern DECLSPEC SDL_PixelFormatEnum SDLCALL SDL_GetPixelFormatEnumForMasks(int bpp, - Uint32 Rmask, - Uint32 Gmask, - Uint32 Bmask, - Uint32 Amask); +extern SDL_DECLSPEC SDL_PixelFormat SDLCALL SDL_GetPixelFormatForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); /** - * Create an SDL_PixelFormat structure corresponding to a pixel format. + * Create an SDL_PixelFormatDetails structure corresponding to a pixel format. * * Returned structure may come from a shared global cache (i.e. not newly * allocated), and hence should not be modified, especially the palette. Weird * errors such as `Blit combination not supported` may occur. * - * \param pixel_format one of the SDL_PixelFormatEnum values - * \returns the new SDL_PixelFormat structure or NULL on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_DestroyPixelFormat - * \sa SDL_SetPixelFormatPalette - */ -extern DECLSPEC SDL_PixelFormat * SDLCALL SDL_CreatePixelFormat(SDL_PixelFormatEnum pixel_format); - -/** - * Free an SDL_PixelFormat structure allocated by SDL_CreatePixelFormat(). + * \param format one of the SDL_PixelFormat values. + * \returns a pointer to a SDL_PixelFormatDetails structure or NULL on + * failure; call SDL_GetError() for more information. * - * \param format the SDL_PixelFormat structure to free + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_CreatePixelFormat */ -extern DECLSPEC void SDLCALL SDL_DestroyPixelFormat(SDL_PixelFormat *format); +extern SDL_DECLSPEC const SDL_PixelFormatDetails * SDLCALL SDL_GetPixelFormatDetails(SDL_PixelFormat format); /** * Create a palette structure with the specified number of color entries. * * The palette entries are initialized to white. * - * \param ncolors represents the number of color entries in the color palette + * \param ncolors represents the number of color entries in the color palette. * \returns a new SDL_Palette structure on success or NULL on failure (e.g. if * there wasn't enough memory); call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroyPalette * \sa SDL_SetPaletteColors - * \sa SDL_SetPixelFormatPalette - */ -extern DECLSPEC SDL_Palette *SDLCALL SDL_CreatePalette(int ncolors); - -/** - * Set the palette for a pixel format structure. - * - * \param format the SDL_PixelFormat structure that will use the palette - * \param palette the SDL_Palette structure that will be used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. + * \sa SDL_SetSurfacePalette */ -extern DECLSPEC int SDLCALL SDL_SetPixelFormatPalette(SDL_PixelFormat * format, - SDL_Palette *palette); +extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreatePalette(int ncolors); /** * Set a range of colors in a palette. * - * \param palette the SDL_Palette structure to modify - * \param colors an array of SDL_Color structures to copy into the palette - * \param firstcolor the index of the first palette entry to modify - * \param ncolors the number of entries to modify - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param palette the SDL_Palette structure to modify. + * \param colors an array of SDL_Color structures to copy into the palette. + * \param firstcolor the index of the first palette entry to modify. + * \param ncolors the number of entries to modify. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified or destroyed in another thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetPaletteColors(SDL_Palette * palette, - const SDL_Color * colors, - int firstcolor, int ncolors); +extern SDL_DECLSPEC bool SDLCALL SDL_SetPaletteColors(SDL_Palette *palette, const SDL_Color *colors, int firstcolor, int ncolors); /** * Free a palette created with SDL_CreatePalette(). * - * \param palette the SDL_Palette structure to be freed + * \param palette the SDL_Palette structure to be freed. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified or destroyed in another thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreatePalette */ -extern DECLSPEC void SDLCALL SDL_DestroyPalette(SDL_Palette * palette); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyPalette(SDL_Palette *palette); /** * Map an RGB triple to an opaque pixel value for a given pixel format. @@ -883,20 +894,25 @@ extern DECLSPEC void SDLCALL SDL_DestroyPalette(SDL_Palette * palette); * format the return value can be assigned to a Uint16, and similarly a Uint8 * for an 8-bpp format). * - * \param format an SDL_PixelFormat structure describing the pixel format - * \param r the red component of the pixel in the range 0-255 - * \param g the green component of the pixel in the range 0-255 - * \param b the blue component of the pixel in the range 0-255 - * \returns a pixel value + * \param format a pointer to SDL_PixelFormatDetails describing the pixel + * format. + * \param palette an optional palette for indexed formats, may be NULL. + * \param r the red component of the pixel in the range 0-255. + * \param g the green component of the pixel in the range 0-255. + * \param b the blue component of the pixel in the range 0-255. + * \returns a pixel value. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetPixelFormatDetails * \sa SDL_GetRGB - * \sa SDL_GetRGBA * \sa SDL_MapRGBA + * \sa SDL_MapSurfaceRGB */ -extern DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format, - Uint8 r, Uint8 g, Uint8 b); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b); /** * Map an RGBA quadruple to a pixel value for a given pixel format. @@ -916,23 +932,26 @@ extern DECLSPEC Uint32 SDLCALL SDL_MapRGB(const SDL_PixelFormat * format, * format the return value can be assigned to a Uint16, and similarly a Uint8 * for an 8-bpp format). * - * \param format an SDL_PixelFormat structure describing the format of the - * pixel - * \param r the red component of the pixel in the range 0-255 - * \param g the green component of the pixel in the range 0-255 - * \param b the blue component of the pixel in the range 0-255 - * \param a the alpha component of the pixel in the range 0-255 - * \returns a pixel value + * \param format a pointer to SDL_PixelFormatDetails describing the pixel + * format. + * \param palette an optional palette for indexed formats, may be NULL. + * \param r the red component of the pixel in the range 0-255. + * \param g the green component of the pixel in the range 0-255. + * \param b the blue component of the pixel in the range 0-255. + * \param a the alpha component of the pixel in the range 0-255. + * \returns a pixel value. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetRGB + * \sa SDL_GetPixelFormatDetails * \sa SDL_GetRGBA * \sa SDL_MapRGB + * \sa SDL_MapSurfaceRGBA */ -extern DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format, - Uint8 r, Uint8 g, Uint8 b, - Uint8 a); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /** * Get RGB values from a pixel in the specified format. @@ -942,22 +961,25 @@ extern DECLSPEC Uint32 SDLCALL SDL_MapRGBA(const SDL_PixelFormat * format, * (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff, * 0xff, 0xff] not [0xf8, 0xfc, 0xf8]). * - * \param pixel a pixel value - * \param format an SDL_PixelFormat structure describing the format of the - * pixel - * \param r a pointer filled in with the red component - * \param g a pointer filled in with the green component - * \param b a pointer filled in with the blue component + * \param pixel a pixel value. + * \param format a pointer to SDL_PixelFormatDetails describing the pixel + * format. + * \param palette an optional palette for indexed formats, may be NULL. + * \param r a pointer filled in with the red component, may be NULL. + * \param g a pointer filled in with the green component, may be NULL. + * \param b a pointer filled in with the blue component, may be NULL. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetPixelFormatDetails * \sa SDL_GetRGBA * \sa SDL_MapRGB * \sa SDL_MapRGBA */ -extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, - const SDL_PixelFormat * format, - Uint8 * r, Uint8 * g, Uint8 * b); +extern SDL_DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b); /** * Get RGBA values from a pixel in the specified format. @@ -970,24 +992,26 @@ extern DECLSPEC void SDLCALL SDL_GetRGB(Uint32 pixel, * If the surface has no alpha component, the alpha will be returned as 0xff * (100% opaque). * - * \param pixel a pixel value - * \param format an SDL_PixelFormat structure describing the format of the - * pixel - * \param r a pointer filled in with the red component - * \param g a pointer filled in with the green component - * \param b a pointer filled in with the blue component - * \param a a pointer filled in with the alpha component + * \param pixel a pixel value. + * \param format a pointer to SDL_PixelFormatDetails describing the pixel + * format. + * \param palette an optional palette for indexed formats, may be NULL. + * \param r a pointer filled in with the red component, may be NULL. + * \param g a pointer filled in with the green component, may be NULL. + * \param b a pointer filled in with the blue component, may be NULL. + * \param a a pointer filled in with the alpha component, may be NULL. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the palette is not modified. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_GetPixelFormatDetails * \sa SDL_GetRGB * \sa SDL_MapRGB * \sa SDL_MapRGBA */ -extern DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, - const SDL_PixelFormat * format, - Uint8 * r, Uint8 * g, Uint8 * b, - Uint8 * a); +extern SDL_DECLSPEC void SDLCALL SDL_GetRGBA(Uint32 pixel, const SDL_PixelFormatDetails *format, const SDL_Palette *palette, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_platform.h b/libs/SDL3/include/SDL3/SDL_platform.h index 289d02dac..bfdfa3a41 100644 --- a/libs/SDL3/include/SDL3/SDL_platform.h +++ b/libs/SDL3/include/SDL3/SDL_platform.h @@ -20,9 +20,10 @@ */ /** - * \file SDL_platform.h + * # CategoryPlatform * - * Header file for platform functions. + * SDL provides a means to identify the app's platform, both at compile time + * and runtime. */ #ifndef SDL_platform_h_ @@ -52,7 +53,7 @@ extern "C" { * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char * SDLCALL SDL_GetPlatform (void); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetPlatform(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_platform_defines.h b/libs/SDL3/include/SDL3/SDL_platform_defines.h index de0908f45..4f878e3b2 100644 --- a/libs/SDL3/include/SDL3/SDL_platform_defines.h +++ b/libs/SDL3/include/SDL3/SDL_platform_defines.h @@ -19,184 +19,461 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_platform_defines.h - * - * Try to get a standard set of platform defines. +/* WIKI CATEGORY: Platform */ + +/* + * SDL_platform_defines.h tries to get a standard set of platform defines. */ #ifndef SDL_platform_defines_h_ #define SDL_platform_defines_h_ #ifdef _AIX -#define SDL_PLATFORM_AIX 1 + +/** + * A preprocessor macro that is only defined if compiling for AIX. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_AIX 1 #endif + #ifdef __HAIKU__ -#define SDL_PLATFORM_HAIKU 1 + +/** + * A preprocessor macro that is only defined if compiling for Haiku OS. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_HAIKU 1 #endif + #if defined(bsdi) || defined(__bsdi) || defined(__bsdi__) -#define SDL_PLATFORM_BSDI 1 + +/** + * A preprocessor macro that is only defined if compiling for BSDi + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_BSDI 1 #endif + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + +/** + * A preprocessor macro that is only defined if compiling for FreeBSD. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_FREEBSD 1 #endif + #if defined(hpux) || defined(__hpux) || defined(__hpux__) -#define SDL_PLATFORM_HPUX 1 + +/** + * A preprocessor macro that is only defined if compiling for HP-UX. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_HPUX 1 #endif + #if defined(sgi) || defined(__sgi) || defined(__sgi__) || defined(_SGI_SOURCE) -#define SDL_PLATFORM_IRIX 1 + +/** + * A preprocessor macro that is only defined if compiling for IRIX. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_IRIX 1 #endif + #if (defined(linux) || defined(__linux) || defined(__linux__)) -#define SDL_PLATFORM_LINUX 1 + +/** + * A preprocessor macro that is only defined if compiling for Linux. + * + * Note that Android, although ostensibly a Linux-based system, will not + * define this. It defines SDL_PLATFORM_ANDROID instead. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_LINUX 1 #endif + #if defined(ANDROID) || defined(__ANDROID__) -#undef SDL_PLATFORM_LINUX /* do we need to do this? */ -#define SDL_PLATFORM_ANDROID 1 + +/** + * A preprocessor macro that is only defined if compiling for Android. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_ANDROID 1 +#undef SDL_PLATFORM_LINUX #endif + #ifdef __NGAGE__ + +/** + * A preprocessor macro that is only defined if compiling for Nokia N-Gage. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_NGAGE 1 #endif #if defined(__unix__) || defined(__unix) || defined(unix) -#define SDL_PLATFORM_UNIX 1 + +/** + * A preprocessor macro that is only defined if compiling for a Unix-like + * system. + * + * Other platforms, like Linux, might define this in addition to their primary + * define. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_UNIX 1 #endif #ifdef __APPLE__ -#define SDL_PLATFORM_APPLE 1 + +/** + * A preprocessor macro that is only defined if compiling for Apple platforms. + * + * iOS, macOS, etc will additionally define a more specific platform macro. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_MACOS + * \sa SDL_PLATFORM_IOS + * \sa SDL_PLATFORM_TVOS + * \sa SDL_PLATFORM_VISIONOS + */ +#define SDL_PLATFORM_APPLE 1 + /* lets us know what version of macOS we're compiling on */ #include -#include +#ifndef __has_extension /* Older compilers don't support this */ + #define __has_extension(x) 0 + #include + #undef __has_extension +#else + #include +#endif /* Fix building with older SDKs that don't define these - See this for more information: - https://stackoverflow.com/questions/12132933/preprocessor-macro-for-os-x-targets + See this for more information: + https://stackoverflow.com/questions/12132933/preprocessor-macro-for-os-x-targets */ #ifndef TARGET_OS_MACCATALYST -#define TARGET_OS_MACCATALYST 0 + #define TARGET_OS_MACCATALYST 0 #endif #ifndef TARGET_OS_IOS -#define TARGET_OS_IOS 0 + #define TARGET_OS_IOS 0 #endif #ifndef TARGET_OS_IPHONE -#define TARGET_OS_IPHONE 0 + #define TARGET_OS_IPHONE 0 #endif #ifndef TARGET_OS_TV -#define TARGET_OS_TV 0 + #define TARGET_OS_TV 0 #endif #ifndef TARGET_OS_SIMULATOR -#define TARGET_OS_SIMULATOR 0 + #define TARGET_OS_SIMULATOR 0 #endif #ifndef TARGET_OS_VISION -#define TARGET_OS_VISION 0 + #define TARGET_OS_VISION 0 #endif #if TARGET_OS_TV -#define SDL_PLATFORM_TVOS 1 + +/** + * A preprocessor macro that is only defined if compiling for tvOS. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_APPLE + */ +#define SDL_PLATFORM_TVOS 1 #endif + #if TARGET_OS_VISION + +/** + * A preprocessor macro that is only defined if compiling for VisionOS. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_APPLE + */ #define SDL_PLATFORM_VISIONOS 1 #endif + #if TARGET_OS_IPHONE -#define SDL_PLATFORM_IOS 1 + +/** + * A preprocessor macro that is only defined if compiling for iOS. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_APPLE + */ +#define SDL_PLATFORM_IOS 1 + #else -#define SDL_PLATFORM_MACOS 1 + +/** + * A preprocessor macro that is only defined if compiling for macOS. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_APPLE + */ +#define SDL_PLATFORM_MACOS 1 + #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 -# error SDL for macOS only supports deploying on 10.7 and above. + #error SDL for macOS only supports deploying on 10.7 and above. #endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1070 */ #endif /* TARGET_OS_IPHONE */ -#endif /* defined(SDL_PLATFORM_APPLE) */ +#endif /* defined(__APPLE__) */ #ifdef __EMSCRIPTEN__ + +/** + * A preprocessor macro that is only defined if compiling for Emscripten. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_EMSCRIPTEN 1 #endif + #ifdef __NetBSD__ + +/** + * A preprocessor macro that is only defined if compiling for NetBSD. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_NETBSD 1 #endif + #ifdef __OpenBSD__ -#define SDL_PLATFORM_OPENBSD 1 + +/** + * A preprocessor macro that is only defined if compiling for OpenBSD. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_OPENBSD 1 #endif + #if defined(__OS2__) || defined(__EMX__) -#define SDL_PLATFORM_OS2 1 + +/** + * A preprocessor macro that is only defined if compiling for OS/2. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_OS2 1 #endif + #if defined(osf) || defined(__osf) || defined(__osf__) || defined(_OSF_SOURCE) -#define SDL_PLATFORM_OSF 1 + +/** + * A preprocessor macro that is only defined if compiling for Tru64 (OSF/1). + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_OSF 1 #endif + #ifdef __QNXNTO__ + +/** + * A preprocessor macro that is only defined if compiling for QNX Neutrino. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_QNXNTO 1 #endif + #if defined(riscos) || defined(__riscos) || defined(__riscos__) + +/** + * A preprocessor macro that is only defined if compiling for RISC OS. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_RISCOS 1 #endif + #if defined(__sun) && defined(__SVR4) -#define SDL_PLATFORM_SOLARIS 1 + +/** + * A preprocessor macro that is only defined if compiling for SunOS/Solaris. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_SOLARIS 1 #endif #if defined(__CYGWIN__) + +/** + * A preprocessor macro that is only defined if compiling for Cygwin. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_CYGWIN 1 #endif #if defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) -#define SDL_PLATFORM_WINDOWS 1 /* Win32 api and Windows-based OSs */ + +/** + * A preprocessor macro that is only defined if compiling for Windows. + * + * This also covers several other platforms, like Microsoft GDK, Xbox, WinRT, + * etc. Each will have their own more-specific platform macros, too. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_PLATFORM_WIN32 + * \sa SDL_PLATFORM_XBOXONE + * \sa SDL_PLATFORM_XBOXSERIES + * \sa SDL_PLATFORM_WINGDK + * \sa SDL_PLATFORM_GDK + */ +#define SDL_PLATFORM_WINDOWS 1 /* Try to find out if we're compiling for WinRT, GDK or non-WinRT/GDK */ #if defined(_MSC_VER) && defined(__has_include) -#if __has_include() -#define HAVE_WINAPIFAMILY_H 1 -#else -#define HAVE_WINAPIFAMILY_H 0 -#endif + #if __has_include() + #define HAVE_WINAPIFAMILY_H 1 + #else + #define HAVE_WINAPIFAMILY_H 0 + #endif -/* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */ + /* If _USING_V110_SDK71_ is defined it means we are using the Windows XP toolset. */ #elif defined(_MSC_VER) && (_MSC_VER >= 1700 && !_USING_V110_SDK71_) /* _MSC_VER == 1700 for Visual Studio 2012 */ -#define HAVE_WINAPIFAMILY_H 1 + #define HAVE_WINAPIFAMILY_H 1 #else -#define HAVE_WINAPIFAMILY_H 0 + #define HAVE_WINAPIFAMILY_H 0 #endif #if HAVE_WINAPIFAMILY_H -#include -#define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) + #include + #define WINAPI_FAMILY_WINRT (!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) #else -#define WINAPI_FAMILY_WINRT 0 + #define WINAPI_FAMILY_WINRT 0 #endif /* HAVE_WINAPIFAMILY_H */ #if HAVE_WINAPIFAMILY_H && HAVE_WINAPIFAMILY_H -#define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + #define SDL_WINAPI_FAMILY_PHONE (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) #else -#define SDL_WINAPI_FAMILY_PHONE 0 + #define SDL_WINAPI_FAMILY_PHONE 0 #endif #if WINAPI_FAMILY_WINRT -#define SDL_PLATFORM_WINRT 1 +#error Windows RT/UWP is no longer supported in SDL + #elif defined(_GAMING_DESKTOP) /* GDK project configuration always defines _GAMING_XXX */ + +/** + * A preprocessor macro that is only defined if compiling for Microsoft GDK + * for Windows. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_WINGDK 1 + #elif defined(_GAMING_XBOX_XBOXONE) -#define SDL_PLATFORM_XBOXONE 1 + +/** + * A preprocessor macro that is only defined if compiling for Xbox One. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_XBOXONE 1 + #elif defined(_GAMING_XBOX_SCARLETT) + +/** + * A preprocessor macro that is only defined if compiling for Xbox Series. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_PLATFORM_XBOXSERIES 1 + #else -#define SDL_PLATFORM_WIN32 1 + +/** + * A preprocessor macro that is only defined if compiling for desktop Windows. + * + * Despite the "32", this also covers 64-bit Windows; as an informal + * convention, its system layer tends to still be referred to as "the Win32 + * API." + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_WIN32 1 + #endif -#endif /* defined(WIN32) || defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) */ +#endif /* defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) */ + /* This is to support generic "any GDK" separate from a platform-specific GDK */ #if defined(SDL_PLATFORM_WINGDK) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) -#define SDL_PLATFORM_GDK 1 + +/** + * A preprocessor macro that is only defined if compiling for Microsoft GDK on + * any platform. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_GDK 1 #endif + #if defined(__PSP__) || defined(__psp__) -#define SDL_PLATFORM_PSP 1 + +/** + * A preprocessor macro that is only defined if compiling for Sony PSP. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_PSP 1 #endif + #if defined(__PS2__) || defined(PS2) -#define SDL_PLATFORM_PS2 1 + +/** + * A preprocessor macro that is only defined if compiling for Sony PlayStation + * 2. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_PS2 1 #endif #if defined(__vita__) || defined(__psp2__) -#define SDL_PLATFORM_VITA 1 + +/** + * A preprocessor macro that is only defined if compiling for Sony Vita. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_VITA 1 #endif #ifdef __3DS__ + +/** + * A preprocessor macro that is only defined if compiling for Nintendo 3DS. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_PLATFORM_3DS 1 + #undef __3DS__ -#define SDL_PLATFORM_3DS 1 #endif #endif /* SDL_platform_defines_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_power.h b/libs/SDL3/include/SDL3/SDL_power.h index 117fc0fc1..1fdef78ee 100644 --- a/libs/SDL3/include/SDL3/SDL_power.h +++ b/libs/SDL3/include/SDL3/SDL_power.h @@ -23,12 +23,13 @@ #define SDL_power_h_ /** - * \file SDL_power.h + * # CategoryPower * - * Header for the SDL power management routines. + * SDL power management routines. */ #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -37,9 +38,13 @@ extern "C" { #endif /** - * The basic state for the system's power supply. + * The basic state for the system's power supply. + * + * These are results returned by SDL_GetPowerInfo(). + * + * \since This enum is available since SDL 3.0.0 */ -typedef enum +typedef enum SDL_PowerState { SDL_POWERSTATE_ERROR = -1, /**< error determining power status */ SDL_POWERSTATE_UNKNOWN, /**< cannot determine power status */ @@ -77,7 +82,7 @@ typedef enum * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *seconds, int *percent); +extern SDL_DECLSPEC SDL_PowerState SDLCALL SDL_GetPowerInfo(int *seconds, int *percent); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_process.h b/libs/SDL3/include/SDL3/SDL_process.h new file mode 100644 index 000000000..1dfac1917 --- /dev/null +++ b/libs/SDL3/include/SDL3/SDL_process.h @@ -0,0 +1,417 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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. +*/ + +/** + * # CategoryProcess + * + * Process control support. + * + * These functions provide a cross-platform way to spawn and manage OS-level + * processes. + * + * You can create a new subprocess with SDL_CreateProcess() and optionally + * read and write to it using SDL_ReadProcess() or SDL_GetProcessInput() and + * SDL_GetProcessOutput(). If more advanced functionality like chaining input + * between processes is necessary, you can use + * SDL_CreateProcessWithProperties(). + * + * You can get the status of a created process with SDL_WaitProcess(), or + * terminate the process with SDL_KillProcess(). + * + * Don't forget to call SDL_DestroyProcess() to clean up, whether the process + * process was killed, terminated on its own, or is still running! + */ + +#ifndef SDL_process_h_ +#define SDL_process_h_ + +#include +#include +#include +#include + +#include +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SDL_Process SDL_Process; + +/** + * Create a new process. + * + * The path to the executable is supplied in args[0]. args[1..N] are + * additional arguments passed on the command line of the new process, and the + * argument list should be terminated with a NULL, e.g.: + * + * ```c + * const char *args[] = { "myprogram", "argument", NULL }; + * ``` + * + * Setting pipe_stdio to true is equivalent to setting + * `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER` and + * `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER` to `SDL_PROCESS_STDIO_APP`, and + * will allow the use of SDL_ReadProcess() or SDL_GetProcessInput() and + * SDL_GetProcessOutput(). + * + * See SDL_CreateProcessWithProperties() for more details. + * + * \param args the path and arguments for the new process. + * \param pipe_stdio true to create pipes to the process's standard input and + * from the process's standard output, false for the process + * to have no input and inherit the application's standard + * output. + * \returns the newly created and running process, or NULL if the process + * couldn't be created. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcessWithProperties + * \sa SDL_GetProcessProperties + * \sa SDL_ReadProcess + * \sa SDL_GetProcessInput + * \sa SDL_GetProcessOutput + * \sa SDL_KillProcess + * \sa SDL_WaitProcess + * \sa SDL_DestroyProcess + */ +extern SDL_DECLSPEC SDL_Process *SDLCALL SDL_CreateProcess(const char * const *args, bool pipe_stdio); + +/** + * Description of where standard I/O should be directed when creating a + * process. + * + * If a standard I/O stream is set to SDL_PROCESS_STDIO_INHERIT, it will go to + * the same place as the application's I/O stream. This is the default for + * standard output and standard error. + * + * If a standard I/O stream is set to SDL_PROCESS_STDIO_NULL, it is connected + * to `NUL:` on Windows and `/dev/null` on POSIX systems. This is the default + * for standard input. + * + * If a standard I/O stream is set to SDL_PROCESS_STDIO_APP, it is connected + * to a new SDL_IOStream that is available to the application. Standard input + * will be available as `SDL_PROP_PROCESS_STDIN_POINTER` and allows + * SDL_GetProcessInput(), standard output will be available as + * `SDL_PROP_PROCESS_STDOUT_POINTER` and allows SDL_ReadProcess() and + * SDL_GetProcessOutput(), and standard error will be available as + * `SDL_PROP_PROCESS_STDERR_POINTER` in the properties for the created + * process. + * + * If a standard I/O stream is set to SDL_PROCESS_STDIO_REDIRECT, it is + * connected to an existing SDL_IOStream provided by the application. Standard + * input is provided using `SDL_PROP_PROCESS_CREATE_STDIN_POINTER`, standard + * output is provided using `SDL_PROP_PROCESS_CREATE_STDOUT_POINTER`, and + * standard error is provided using `SDL_PROP_PROCESS_CREATE_STDERR_POINTER` + * in the creation properties. These existing streams should be closed by the + * application once the new process is created. + * + * In order to use an SDL_IOStream with SDL_PROCESS_STDIO_REDIRECT, it must + * have `SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER` or + * `SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER` set. This is true for streams + * representing files and process I/O. + * + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_CreateProcessWithProperties + * \sa SDL_GetProcessProperties + * \sa SDL_ReadProcess + * \sa SDL_GetProcessInput + * \sa SDL_GetProcessOutput + */ +typedef enum SDL_ProcessIO +{ + SDL_PROCESS_STDIO_INHERITED, /**< The I/O stream is inherited from the application. */ + SDL_PROCESS_STDIO_NULL, /**< The I/O stream is ignored. */ + SDL_PROCESS_STDIO_APP, /**< The I/O stream is connected to a new SDL_IOStream that the application can read or write */ + SDL_PROCESS_STDIO_REDIRECT /**< The I/O stream is redirected to an existing SDL_IOStream. */ +} SDL_ProcessIO; + +/** + * Create a new process with the specified properties. + * + * These are the supported properties: + * + * - `SDL_PROP_PROCESS_CREATE_ARGS_POINTER`: an array of strings containing + * the program to run, any arguments, and a NULL pointer, e.g. const char + * *args[] = { "myprogram", "argument", NULL }. This is a required property. + * - `SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER`: an SDL_Environment + * pointer. If this property is set, it will be the entire environment for + * the process, otherwise the current environment is used. + * - `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER`: an SDL_ProcessIO value describing + * where standard input for the process comes from, defaults to + * `SDL_PROCESS_STDIO_NULL`. + * - `SDL_PROP_PROCESS_CREATE_STDIN_POINTER`: an SDL_IOStream pointer used for + * standard input when `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER` is set to + * `SDL_PROCESS_STDIO_REDIRECT`. + * - `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER`: an SDL_ProcessIO value + * describing where standard output for the process goes go, defaults to + * `SDL_PROCESS_STDIO_INHERITED`. + * - `SDL_PROP_PROCESS_CREATE_STDOUT_POINTER`: an SDL_IOStream pointer used + * for standard output when `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER` is set + * to `SDL_PROCESS_STDIO_REDIRECT`. + * - `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER`: an SDL_ProcessIO value + * describing where standard error for the process goes go, defaults to + * `SDL_PROCESS_STDIO_INHERITED`. + * - `SDL_PROP_PROCESS_CREATE_STDERR_POINTER`: an SDL_IOStream pointer used + * for standard error when `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER` is set to + * `SDL_PROCESS_STDIO_REDIRECT`. + * - `SDL_PROP_PROCESS_CREATE_STDERR_TO_STDOUT_BOOLEAN`: true if the error + * output of the process should be redirected into the standard output of + * the process. This property has no effect if + * `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER` is set. + * - `SDL_PROP_PROCESS_CREATE_BACKGROUND_BOOLEAN`: true if the process should + * run in the background. In this case the default input and output is + * `SDL_PROCESS_STDIO_NULL` and the exitcode of the process is not + * available, and will always be 0. + * + * On POSIX platforms, wait() and waitpid(-1, ...) should not be called, and + * SIGCHLD should not be ignored or handled because those would prevent SDL + * from properly tracking the lifetime of the underlying process. You should + * use SDL_WaitProcess() instead. + * + * \param props the properties to use. + * \returns the newly created and running process, or NULL if the process + * couldn't be created. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_GetProcessProperties + * \sa SDL_ReadProcess + * \sa SDL_GetProcessInput + * \sa SDL_GetProcessOutput + * \sa SDL_KillProcess + * \sa SDL_WaitProcess + * \sa SDL_DestroyProcess + */ +extern SDL_DECLSPEC SDL_Process *SDLCALL SDL_CreateProcessWithProperties(SDL_PropertiesID props); + +#define SDL_PROP_PROCESS_CREATE_ARGS_POINTER "SDL.process.create.args" +#define SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER "SDL.process.create.environment" +#define SDL_PROP_PROCESS_CREATE_STDIN_NUMBER "SDL.process.create.stdin_option" +#define SDL_PROP_PROCESS_CREATE_STDIN_POINTER "SDL.process.create.stdin_source" +#define SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER "SDL.process.create.stdout_option" +#define SDL_PROP_PROCESS_CREATE_STDOUT_POINTER "SDL.process.create.stdout_source" +#define SDL_PROP_PROCESS_CREATE_STDERR_NUMBER "SDL.process.create.stderr_option" +#define SDL_PROP_PROCESS_CREATE_STDERR_POINTER "SDL.process.create.stderr_source" +#define SDL_PROP_PROCESS_CREATE_STDERR_TO_STDOUT_BOOLEAN "SDL.process.create.stderr_to_stdout" +#define SDL_PROP_PROCESS_CREATE_BACKGROUND_BOOLEAN "SDL.process.create.background" + +/** + * Get the properties associated with a process. + * + * The following read-only properties are provided by SDL: + * + * - `SDL_PROP_PROCESS_PID_NUMBER`: the process ID of the process. + * - `SDL_PROP_PROCESS_STDIN_POINTER`: an SDL_IOStream that can be used to + * write input to the process, if it was created with + * `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER` set to `SDL_PROCESS_STDIO_APP`. + * - `SDL_PROP_PROCESS_STDOUT_POINTER`: a non-blocking SDL_IOStream that can + * be used to read output from the process, if it was created with + * `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER` set to `SDL_PROCESS_STDIO_APP`. + * - `SDL_PROP_PROCESS_STDERR_POINTER`: a non-blocking SDL_IOStream that can + * be used to read error output from the process, if it was created with + * `SDL_PROP_PROCESS_CREATE_STDERR_NUMBER` set to `SDL_PROCESS_STDIO_APP`. + * - `SDL_PROP_PROCESS_BACKGROUND_BOOLEAN`: true if the process is running in + * the background. + * + * \param process the process to query. + * \returns a valid property ID on success or 0 on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetProcessProperties(SDL_Process *process); + +#define SDL_PROP_PROCESS_PID_NUMBER "SDL.process.pid" +#define SDL_PROP_PROCESS_STDIN_POINTER "SDL.process.stdin" +#define SDL_PROP_PROCESS_STDOUT_POINTER "SDL.process.stdout" +#define SDL_PROP_PROCESS_STDERR_POINTER "SDL.process.stderr" +#define SDL_PROP_PROCESS_BACKGROUND_BOOLEAN "SDL.process.background" + +/** + * Read all the output from a process. + * + * If a process was created with I/O enabled, you can use this function to + * read the output. This function blocks until the process is complete, + * capturing all output, and providing the process exit code. + * + * The data is allocated with a zero byte at the end (null terminated) for + * convenience. This extra byte is not included in the value reported via + * `datasize`. + * + * The data should be freed with SDL_free(). + * + * \param process The process to read. + * \param datasize a pointer filled in with the number of bytes read, may be + * NULL. + * \param exitcode a pointer filled in with the process exit code if the + * process has exited, may be NULL. + * \returns the data or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_DestroyProcess + */ +extern SDL_DECLSPEC void * SDLCALL SDL_ReadProcess(SDL_Process *process, size_t *datasize, int *exitcode); + +/** + * Get the SDL_IOStream associated with process standard input. + * + * The process must have been created with SDL_CreateProcess() and pipe_stdio + * set to true, or with SDL_CreateProcessWithProperties() and + * `SDL_PROP_PROCESS_CREATE_STDIN_NUMBER` set to `SDL_PROCESS_STDIO_APP`. + * + * Writing to this stream can return less data than expected if the process + * hasn't read its input. It may be blocked waiting for its output to be read, + * so if you may need to call SDL_GetOutputStream() and read the output in + * parallel with writing input. + * + * \param process The process to get the input stream for. + * \returns the input stream or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_GetProcessOutput + */ +extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_GetProcessInput(SDL_Process *process); + +/** + * Get the SDL_IOStream associated with process standard output. + * + * The process must have been created with SDL_CreateProcess() and pipe_stdio + * set to true, or with SDL_CreateProcessWithProperties() and + * `SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER` set to `SDL_PROCESS_STDIO_APP`. + * + * Reading from this stream can return 0 with SDL_GetIOStatus() returning + * SDL_IO_STATUS_NOT_READY if no output is available yet. + * + * \param process The process to get the output stream for. + * \returns the output stream or NULL on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_GetProcessInput + */ +extern SDL_DECLSPEC SDL_IOStream *SDLCALL SDL_GetProcessOutput(SDL_Process *process); + +/** + * Stop a process. + * + * \param process The process to stop. + * \param force true to terminate the process immediately, false to try to + * stop the process gracefully. In general you should try to stop + * the process gracefully first as terminating a process may + * leave it with half-written data or in some other unstable + * state. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_WaitProcess + * \sa SDL_DestroyProcess + */ +extern SDL_DECLSPEC bool SDLCALL SDL_KillProcess(SDL_Process *process, bool force); + +/** + * Wait for a process to finish. + * + * This can be called multiple times to get the status of a process. + * + * The exit code will be the exit code of the process if it terminates + * normally, a negative signal if it terminated due to a signal, or -255 + * otherwise. It will not be changed if the process is still running. + * + * \param process The process to wait for. + * \param block If true, block until the process finishes; otherwise, report + * on the process' status. + * \param exitcode a pointer filled in with the process exit code if the + * process has exited, may be NULL. + * \returns true if the process exited, false otherwise. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_KillProcess + * \sa SDL_DestroyProcess + */ +extern SDL_DECLSPEC bool SDLCALL SDL_WaitProcess(SDL_Process *process, bool block, int *exitcode); + +/** + * Destroy a previously created process object. + * + * Note that this does not stop the process, just destroys the SDL object used + * to track it. If you want to stop the process you should use + * SDL_KillProcess(). + * + * \param process The process object to destroy. + * + * \threadsafety This function is not thread safe. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateProcess + * \sa SDL_CreateProcessWithProperties + * \sa SDL_KillProcess + */ +extern SDL_DECLSPEC void SDLCALL SDL_DestroyProcess(SDL_Process *process); + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include + +#endif /* SDL_process_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_properties.h b/libs/SDL3/include/SDL3/SDL_properties.h index 80c2f5239..e48466ed7 100644 --- a/libs/SDL3/include/SDL3/SDL_properties.h +++ b/libs/SDL3/include/SDL3/SDL_properties.h @@ -1,5 +1,5 @@ /* - Simple DiretMedia Layer + Simple DirectMedia Layer Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied @@ -20,15 +20,37 @@ */ /** - * \file SDL_properties.h + * # CategoryProperties * - * Header file for SDL properties. + * A property is a variable that can be created and retrieved by name at + * runtime. + * + * All properties are part of a property group (SDL_PropertiesID). A property + * group can be created with the SDL_CreateProperties function and destroyed + * with the SDL_DestroyProperties function. + * + * Properties can be added to and retrieved from a property group through the + * following functions: + * + * - SDL_SetPointerProperty and SDL_GetPointerProperty operate on `void*` + * pointer types. + * - SDL_SetStringProperty and SDL_GetStringProperty operate on string types. + * - SDL_SetNumberProperty and SDL_GetNumberProperty operate on signed 64-bit + * integer types. + * - SDL_SetFloatProperty and SDL_GetFloatProperty operate on floating point + * types. + * - SDL_SetBooleanProperty and SDL_GetBooleanProperty operate on boolean + * types. + * + * Properties can be removed from a group by using SDL_ClearProperty. */ + #ifndef SDL_properties_h_ #define SDL_properties_h_ #include +#include #include /* Set up for C function definitions, even when using C++ */ @@ -38,41 +60,42 @@ extern "C" { /** * SDL properties ID + * + * \since This datatype is available since SDL 3.0.0. */ typedef Uint32 SDL_PropertiesID; /** * SDL property type + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_PropertyType { SDL_PROPERTY_TYPE_INVALID, SDL_PROPERTY_TYPE_POINTER, SDL_PROPERTY_TYPE_STRING, SDL_PROPERTY_TYPE_NUMBER, SDL_PROPERTY_TYPE_FLOAT, - SDL_PROPERTY_TYPE_BOOLEAN, + SDL_PROPERTY_TYPE_BOOLEAN } SDL_PropertyType; /** - * Get the global SDL properties + * Get the global SDL properties. * * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); /** - * Create a set of properties + * Create a group of properties. * * All properties are automatically destroyed when SDL_Quit() is called. * - * \returns an ID for a new set of properties, or 0 on failure; call + * \returns an ID for a new group of properties, or 0 on failure; call * SDL_GetError() for more information. * * \threadsafety It is safe to call this function from any thread. @@ -81,29 +104,29 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetGlobalProperties(void); * * \sa SDL_DestroyProperties */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_CreateProperties(void); /** - * Copy a set of properties + * Copy a group of properties. * - * Copy all the properties from one set of properties to another, with the + * Copy all the properties from one group of properties to another, with the * exception of properties requiring cleanup (set using - * SDL_SetPropertyWithCleanup()), which will not be copied. Any property that - * already exists on `dst` will be overwritten. + * SDL_SetPointerPropertyWithCleanup()), which will not be copied. Any + * property that already exists on `dst` will be overwritten. * - * \param src the properties to copy - * \param dst the destination properties - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param src the properties to copy. + * \param dst the destination properties. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst); +extern SDL_DECLSPEC bool SDLCALL SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst); /** - * Lock a set of properties + * Lock a group of properties. * * Obtain a multi-threaded lock for these properties. Other threads will wait * while trying to lock these properties until they are unlocked. Properties @@ -114,9 +137,9 @@ extern DECLSPEC int SDLCALL SDL_CopyProperties(SDL_PropertiesID src, SDL_Propert * or want to guarantee that properties being queried aren't freed in another * thread. * - * \param props the properties to lock - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to lock. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * @@ -124,12 +147,12 @@ extern DECLSPEC int SDLCALL SDL_CopyProperties(SDL_PropertiesID src, SDL_Propert * * \sa SDL_UnlockProperties */ -extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props); +extern SDL_DECLSPEC bool SDLCALL SDL_LockProperties(SDL_PropertiesID props); /** - * Unlock a set of properties + * Unlock a group of properties. * - * \param props the properties to unlock + * \param props the properties to unlock. * * \threadsafety It is safe to call this function from any thread. * @@ -137,67 +160,97 @@ extern DECLSPEC int SDLCALL SDL_LockProperties(SDL_PropertiesID props); * * \sa SDL_LockProperties */ -extern DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockProperties(SDL_PropertiesID props); + +/** + * A callback used to free resources when a property is deleted. + * + * This should release any resources associated with `value` that are no + * longer needed. + * + * This callback is set per-property. Different properties in the same group + * can have different cleanup callbacks. + * + * This callback will be called _during_ SDL_SetPointerPropertyWithCleanup if + * the function fails for any reason. + * + * \param userdata an app-defined pointer passed to the callback. + * \param value the pointer assigned to the property to clean up. + * + * \threadsafety This callback may fire without any locks held; if this is a + * concern, the app should provide its own locking. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_SetPointerPropertyWithCleanup + */ +typedef void (SDLCALL *SDL_CleanupPropertyCallback)(void *userdata, void *value); /** - * Set a property on a set of properties with a cleanup function that is - * called when the property is deleted + * Set a pointer property in a group of properties with a cleanup function + * that is called when the property is deleted. * * The cleanup function is also called if setting the property fails for any * reason. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property, or NULL to delete the property + * For simply setting basic data types, like numbers, bools, or strings, use + * SDL_SetNumberProperty, SDL_SetBooleanProperty, or SDL_SetStringProperty + * instead, as those functions will handle cleanup on your behalf. This + * function is only for more complex, custom data. + * + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property, or NULL to delete the property. * \param cleanup the function to call when this property is deleted, or NULL - * if no cleanup is necessary - * \param userdata a pointer that is passed to the cleanup function - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * if no cleanup is necessary. + * \param userdata a pointer that is passed to the cleanup function. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetProperty - * \sa SDL_SetProperty + * \sa SDL_GetPointerProperty + * \sa SDL_SetPointerProperty + * \sa SDL_CleanupPropertyCallback */ -extern DECLSPEC int SDLCALL SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata); +extern SDL_DECLSPEC bool SDLCALL SDL_SetPointerPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, SDL_CleanupPropertyCallback cleanup, void *userdata); /** - * Set a property on a set of properties + * Set a pointer property in a group of properties. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property, or NULL to delete the property - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property, or NULL to delete the property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetProperty + * \sa SDL_GetPointerProperty * \sa SDL_HasProperty * \sa SDL_SetBooleanProperty * \sa SDL_SetFloatProperty * \sa SDL_SetNumberProperty - * \sa SDL_SetPropertyWithCleanup + * \sa SDL_SetPointerPropertyWithCleanup * \sa SDL_SetStringProperty */ -extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetPointerProperty(SDL_PropertiesID props, const char *name, void *value); /** - * Set a string property on a set of properties + * Set a string property in a group of properties. * * This function makes a copy of the string; the caller does not have to * preserve the data after this call completes. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property, or NULL to delete the property - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property, or NULL to delete the property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * @@ -205,16 +258,16 @@ extern DECLSPEC int SDLCALL SDL_SetProperty(SDL_PropertiesID props, const char * * * \sa SDL_GetStringProperty */ -extern DECLSPEC int SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value); /** - * Set an integer property on a set of properties + * Set an integer property in a group of properties. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * @@ -222,16 +275,16 @@ extern DECLSPEC int SDLCALL SDL_SetStringProperty(SDL_PropertiesID props, const * * \sa SDL_GetNumberProperty */ -extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value); /** - * Set a floating point property on a set of properties + * Set a floating point property in a group of properties. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * @@ -239,16 +292,16 @@ extern DECLSPEC int SDLCALL SDL_SetNumberProperty(SDL_PropertiesID props, const * * \sa SDL_GetFloatProperty */ -extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value); /** - * Set a boolean property on a set of properties + * Set a boolean property in a group of properties. * - * \param props the properties to modify - * \param name the name of the property to modify - * \param value the new value of the property - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to modify. + * \param value the new value of the property. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * @@ -256,14 +309,14 @@ extern DECLSPEC int SDLCALL SDL_SetFloatProperty(SDL_PropertiesID props, const c * * \sa SDL_GetBooleanProperty */ -extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value); +extern SDL_DECLSPEC bool SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, bool value); /** - * Return whether a property exists in a set of properties. + * Return whether a property exists in a group of properties. * - * \param props the properties to query - * \param name the name of the property to query - * \returns SDL_TRUE if the property exists, or SDL_FALSE if it doesn't. + * \param props the properties to query. + * \param name the name of the property to query. + * \returns true if the property exists, or false if it doesn't. * * \threadsafety It is safe to call this function from any thread. * @@ -271,13 +324,13 @@ extern DECLSPEC int SDLCALL SDL_SetBooleanProperty(SDL_PropertiesID props, const * * \sa SDL_GetPropertyType */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasProperty(SDL_PropertiesID props, const char *name); +extern SDL_DECLSPEC bool SDLCALL SDL_HasProperty(SDL_PropertiesID props, const char *name); /** - * Get the type of a property on a set of properties + * Get the type of a property in a group of properties. * - * \param props the properties to query - * \param name the name of the property to query + * \param props the properties to query. + * \param name the name of the property to query. * \returns the type of the property, or SDL_PROPERTY_TYPE_INVALID if it is * not set. * @@ -287,27 +340,28 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasProperty(SDL_PropertiesID props, const c * * \sa SDL_HasProperty */ -extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name); +extern SDL_DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID props, const char *name); /** - * Get a property on a set of properties + * Get a pointer property from a group of properties. * * By convention, the names of properties that SDL exposes on objects will * start with "SDL.", and properties that SDL uses internally will start with * "SDL.internal.". These should be considered read-only and should not be * modified by applications. * - * \param props the properties to query - * \param name the name of the property to query - * \param default_value the default value of the property + * \param props the properties to query. + * \param name the name of the property to query. + * \param default_value the default value of the property. * \returns the value of the property, or `default_value` if it is not set or * not a pointer property. * * \threadsafety It is safe to call this function from any thread, although * the data returned is not protected and could potentially be - * freed if you call SDL_SetProperty() or SDL_ClearProperty() on - * these properties from another thread. If you need to avoid - * this, use SDL_LockProperties() and SDL_UnlockProperties(). + * freed if you call SDL_SetPointerProperty() or + * SDL_ClearProperty() on these properties from another thread. + * If you need to avoid this, use SDL_LockProperties() and + * SDL_UnlockProperties(). * * \since This function is available since SDL 3.0.0. * @@ -317,20 +371,25 @@ extern DECLSPEC SDL_PropertyType SDLCALL SDL_GetPropertyType(SDL_PropertiesID pr * \sa SDL_GetPropertyType * \sa SDL_GetStringProperty * \sa SDL_HasProperty - * \sa SDL_SetProperty + * \sa SDL_SetPointerProperty */ -extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value); +extern SDL_DECLSPEC void * SDLCALL SDL_GetPointerProperty(SDL_PropertiesID props, const char *name, void *default_value); /** - * Get a string property on a set of properties + * Get a string property from a group of properties. * - * \param props the properties to query - * \param name the name of the property to query - * \param default_value the default value of the property + * \param props the properties to query. + * \param name the name of the property to query. + * \param default_value the default value of the property. * \returns the value of the property, or `default_value` if it is not set or * not a string property. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It is safe to call this function from any thread, although + * the data returned is not protected and could potentially be + * freed if you call SDL_SetStringProperty() or + * SDL_ClearProperty() on these properties from another thread. + * If you need to avoid this, use SDL_LockProperties() and + * SDL_UnlockProperties(). * * \since This function is available since SDL 3.0.0. * @@ -338,17 +397,17 @@ extern DECLSPEC void *SDLCALL SDL_GetProperty(SDL_PropertiesID props, const char * \sa SDL_HasProperty * \sa SDL_SetStringProperty */ -extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetStringProperty(SDL_PropertiesID props, const char *name, const char *default_value); /** - * Get a number property on a set of properties + * Get a number property from a group of properties. * * You can use SDL_GetPropertyType() to query whether the property exists and * is a number property. * - * \param props the properties to query - * \param name the name of the property to query - * \param default_value the default value of the property + * \param props the properties to query. + * \param name the name of the property to query. + * \param default_value the default value of the property. * \returns the value of the property, or `default_value` if it is not set or * not a number property. * @@ -360,17 +419,17 @@ extern DECLSPEC const char *SDLCALL SDL_GetStringProperty(SDL_PropertiesID props * \sa SDL_HasProperty * \sa SDL_SetNumberProperty */ -extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value); +extern SDL_DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 default_value); /** - * Get a floating point property on a set of properties + * Get a floating point property from a group of properties. * * You can use SDL_GetPropertyType() to query whether the property exists and * is a floating point property. * - * \param props the properties to query - * \param name the name of the property to query - * \param default_value the default value of the property + * \param props the properties to query. + * \param name the name of the property to query. + * \param default_value the default value of the property. * \returns the value of the property, or `default_value` if it is not set or * not a float property. * @@ -382,19 +441,19 @@ extern DECLSPEC Sint64 SDLCALL SDL_GetNumberProperty(SDL_PropertiesID props, con * \sa SDL_HasProperty * \sa SDL_SetFloatProperty */ -extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value); +extern SDL_DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float default_value); /** - * Get a boolean property on a set of properties + * Get a boolean property from a group of properties. * * You can use SDL_GetPropertyType() to query whether the property exists and * is a boolean property. * - * \param props the properties to query - * \param name the name of the property to query - * \param default_value the default value of the property + * \param props the properties to query. + * \param name the name of the property to query. + * \param default_value the default value of the property. * \returns the value of the property, or `default_value` if it is not set or - * not a float property. + * not a boolean property. * * \threadsafety It is safe to call this function from any thread. * @@ -404,49 +463,66 @@ extern DECLSPEC float SDLCALL SDL_GetFloatProperty(SDL_PropertiesID props, const * \sa SDL_HasProperty * \sa SDL_SetBooleanProperty */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value); +extern SDL_DECLSPEC bool SDLCALL SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, bool default_value); /** - * Clear a property on a set of properties + * Clear a property from a group of properties. * - * \param props the properties to modify - * \param name the name of the property to clear - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to modify. + * \param name the name of the property to clear. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); +extern SDL_DECLSPEC bool SDLCALL SDL_ClearProperty(SDL_PropertiesID props, const char *name); +/** + * A callback used to enumerate all the properties in a group of properties. + * + * This callback is called from SDL_EnumerateProperties(), and is called once + * per property in the set. + * + * \param userdata an app-defined pointer passed to the callback. + * \param props the SDL_PropertiesID that is being enumerated. + * \param name the next property name in the enumeration. + * + * \threadsafety SDL_EnumerateProperties holds a lock on `props` during this + * callback. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_EnumerateProperties + */ typedef void (SDLCALL *SDL_EnumeratePropertiesCallback)(void *userdata, SDL_PropertiesID props, const char *name); /** - * Enumerate the properties on a set of properties + * Enumerate the properties contained in a group of properties. * - * The callback function is called for each property on the set of properties. - * The properties are locked during enumeration. + * The callback function is called for each property in the group of + * properties. The properties are locked during enumeration. * - * \param props the properties to query - * \param callback the function to call for each property - * \param userdata a pointer that is passed to `callback` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param props the properties to query. + * \param callback the function to call for each property. + * \param userdata a pointer that is passed to `callback`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata); +extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata); /** - * Destroy a set of properties + * Destroy a group of properties. * * All properties are deleted and their cleanup functions will be called, if * any. * - * \param props the properties to destroy + * \param props the properties to destroy. * * \threadsafety This function should not be called while these properties are * locked or other threads might be setting or getting values @@ -456,7 +532,7 @@ extern DECLSPEC int SDLCALL SDL_EnumerateProperties(SDL_PropertiesID props, SDL_ * * \sa SDL_CreateProperties */ -extern DECLSPEC void SDLCALL SDL_DestroyProperties(SDL_PropertiesID props); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyProperties(SDL_PropertiesID props); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_quit.h b/libs/SDL3/include/SDL3/SDL_quit.h deleted file mode 100644 index 1361dff4d..000000000 --- a/libs/SDL3/include/SDL3/SDL_quit.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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. -*/ - -/** - * \file SDL_quit.h - * - * Include file for SDL quit event handling. - */ - -#ifndef SDL_quit_h_ -#define SDL_quit_h_ - -#include -#include - -/** - * \file SDL_quit.h - * - * ::SDL_EVENT_QUIT is generated when the user tries to close the application - * window. If it is ignored or filtered out, the window will remain open. - * If it is not ignored or filtered, it is queued normally and the window - * is allowed to close. When the window is closed, screen updates will - * complete, but have no effect. - * - * SDL_Init() installs signal handlers for SIGINT (keyboard interrupt) - * and SIGTERM (system termination request), if handlers do not already - * exist, that generate ::SDL_EVENT_QUIT as well. There is no way - * to determine the cause of an ::SDL_EVENT_QUIT, but setting a signal - * handler in your application will override the default generation of - * quit events for that signal. - * - * \sa SDL_Quit() - */ - -/* There are no functions directly affecting the quit event */ - -#define SDL_QuitRequested() \ - (SDL_PumpEvents(), (SDL_PeepEvents(NULL,0,SDL_PEEKEVENT,SDL_EVENT_QUIT,SDL_EVENT_QUIT) > 0)) - -#endif /* SDL_quit_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_rect.h b/libs/SDL3/include/SDL3/SDL_rect.h index 4b496e348..d0f0bbcba 100644 --- a/libs/SDL3/include/SDL3/SDL_rect.h +++ b/libs/SDL3/include/SDL3/SDL_rect.h @@ -20,9 +20,10 @@ */ /** - * \file SDL_rect.h + * # CategoryRect * - * Header file for SDL_rect definition and management functions. + * Some helper functions for managing rectangles and 2D points, in both + * integer and floating point versions. */ #ifndef SDL_rect_h_ @@ -38,7 +39,9 @@ extern "C" { #endif /** - * The structure that defines a point (integer) + * The structure that defines a point (using integers). + * + * \since This struct is available since SDL 3.0.0. * * \sa SDL_GetRectEnclosingPoints * \sa SDL_PointInRect @@ -50,7 +53,9 @@ typedef struct SDL_Point } SDL_Point; /** - * The structure that defines a point (floating point) + * The structure that defines a point (using floating point values). + * + * \since This struct is available since SDL 3.0.0. * * \sa SDL_GetRectEnclosingPointsFloat * \sa SDL_PointInRectFloat @@ -63,7 +68,9 @@ typedef struct SDL_FPoint /** - * A rectangle, with the origin at the upper left (integer). + * A rectangle, with the origin at the upper left (using integers). + * + * \since This struct is available since SDL 3.0.0. * * \sa SDL_RectEmpty * \sa SDL_RectsEqual @@ -81,7 +88,10 @@ typedef struct SDL_Rect /** - * A rectangle, with the origin at the upper left (floating point). + * A rectangle, with the origin at the upper left (using floating point + * values). + * + * \since This struct is available since SDL 3.0.0. * * \sa SDL_RectEmptyFloat * \sa SDL_RectsEqualFloat @@ -103,81 +113,146 @@ typedef struct SDL_FRect /** - * Returns true if point resides inside a rectangle. + * Convert an SDL_Rect to SDL_FRect + * + * \param rect a pointer to an SDL_Rect. + * \param frect a pointer filled in with the floating point representation of + * `rect`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE SDL_bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r) +SDL_FORCE_INLINE void SDL_RectToFRect(const SDL_Rect *rect, SDL_FRect *frect) { - return ( (p->x >= r->x) && (p->x < (r->x + r->w)) && - (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE; + frect->x = (float)rect->x; + frect->y = (float)rect->y; + frect->w = (float)rect->w; + frect->h = (float)rect->h; } /** - * Returns true if the rectangle has no area. + * Determine whether a point resides inside a rectangle. + * + * A point is considered part of a rectangle if both `p` and `r` are not NULL, + * and `p`'s x and y coordinates are >= to the rectangle's top left corner, + * and < the rectangle's x+w and y+h. So a 1x1 rectangle considers point (0,0) + * as "inside" and (0,1) as not. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param p the point to test. + * \param r the rectangle to test. + * \returns true if `p` is contained by `r`, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r) +SDL_FORCE_INLINE bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r) { - return ((!r) || (r->w <= 0) || (r->h <= 0)) ? SDL_TRUE : SDL_FALSE; + return ( p && r && (p->x >= r->x) && (p->x < (r->x + r->w)) && + (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? true : false; } /** - * Returns true if the two rectangles are equal. + * Determine whether a rectangle has no area. + * + * A rectangle is considered "empty" for this function if `r` is NULL, or if + * `r`'s width and/or height are <= 0. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param r the rectangle to test. + * \returns true if the rectangle is "empty", false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +SDL_FORCE_INLINE bool SDL_RectEmpty(const SDL_Rect *r) +{ + return ((!r) || (r->w <= 0) || (r->h <= 0)) ? true : false; +} + +/** + * Determine whether two rectangles are equal. + * + * Rectangles are considered equal if both are not NULL and each of their x, + * y, width and height match. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param a the first rectangle to test. + * \param b the second rectangle to test. + * \returns true if the rectangles are equal, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE SDL_bool SDL_RectsEqual(const SDL_Rect *a, const SDL_Rect *b) +SDL_FORCE_INLINE bool SDL_RectsEqual(const SDL_Rect *a, const SDL_Rect *b) { return (a && b && (a->x == b->x) && (a->y == b->y) && - (a->w == b->w) && (a->h == b->h)) ? SDL_TRUE : SDL_FALSE; + (a->w == b->w) && (a->h == b->h)) ? true : false; } /** * Determine whether two rectangles intersect. * - * If either pointer is NULL the function will return SDL_FALSE. + * If either pointer is NULL the function will return false. * - * \param A an SDL_Rect structure representing the first rectangle - * \param B an SDL_Rect structure representing the second rectangle - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * \param A an SDL_Rect structure representing the first rectangle. + * \param B an SDL_Rect structure representing the second rectangle. + * \returns true if there is an intersection, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRectIntersection */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasRectIntersection(const SDL_Rect * A, - const SDL_Rect * B); +extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersection(const SDL_Rect *A, const SDL_Rect *B); /** * Calculate the intersection of two rectangles. * - * If `result` is NULL then this function will return SDL_FALSE. + * If `result` is NULL then this function will return false. * - * \param A an SDL_Rect structure representing the first rectangle - * \param B an SDL_Rect structure representing the second rectangle + * \param A an SDL_Rect structure representing the first rectangle. + * \param B an SDL_Rect structure representing the second rectangle. * \param result an SDL_Rect structure filled in with the intersection of - * rectangles `A` and `B` - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * rectangles `A` and `B`. + * \returns true if there is an intersection, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HasRectIntersection */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectIntersection(const SDL_Rect * A, - const SDL_Rect * B, - SDL_Rect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersection(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result); /** * Calculate the union of two rectangles. * - * \param A an SDL_Rect structure representing the first rectangle - * \param B an SDL_Rect structure representing the second rectangle + * \param A an SDL_Rect structure representing the first rectangle. + * \param B an SDL_Rect structure representing the second rectangle. * \param result an SDL_Rect structure filled in with the union of rectangles - * `A` and `B` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * `A` and `B`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetRectUnion(const SDL_Rect * A, - const SDL_Rect * B, - SDL_Rect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnion(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result); /** * Calculate a minimal rectangle enclosing a set of points. @@ -186,20 +261,17 @@ extern DECLSPEC int SDLCALL SDL_GetRectUnion(const SDL_Rect * A, * considered. * * \param points an array of SDL_Point structures representing points to be - * enclosed - * \param count the number of structures in the `points` array - * \param clip an SDL_Rect used for clipping or NULL to enclose all points + * enclosed. + * \param count the number of structures in the `points` array. + * \param clip an SDL_Rect used for clipping or NULL to enclose all points. * \param result an SDL_Rect structure filled in with the minimal enclosing - * rectangle - * \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the - * points were outside of the clipping rectangle. + * rectangle. + * \returns true if any points were enclosed or false if all the points were + * outside of the clipping rectangle. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point * points, - int count, - const SDL_Rect * clip, - SDL_Rect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point *points, int count, const SDL_Rect *clip, SDL_Rect *result); /** * Calculate the intersection of a rectangle and line segment. @@ -210,63 +282,131 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point * po * both ends will be clipped to the boundary of the rectangle and the new * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary. * - * \param rect an SDL_Rect structure representing the rectangle to intersect - * \param X1 a pointer to the starting X-coordinate of the line - * \param Y1 a pointer to the starting Y-coordinate of the line - * \param X2 a pointer to the ending X-coordinate of the line - * \param Y2 a pointer to the ending Y-coordinate of the line - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * \param rect an SDL_Rect structure representing the rectangle to intersect. + * \param X1 a pointer to the starting X-coordinate of the line. + * \param Y1 a pointer to the starting Y-coordinate of the line. + * \param X2 a pointer to the ending X-coordinate of the line. + * \param Y2 a pointer to the ending Y-coordinate of the line. + * \returns true if there is an intersection, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectAndLineIntersection(const SDL_Rect * - rect, int *X1, - int *Y1, int *X2, - int *Y2); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersection(const SDL_Rect *rect, int *X1, int *Y1, int *X2, int *Y2); /* SDL_FRect versions... */ /** - * Returns true if point resides inside a rectangle. + * Determine whether a point resides inside a floating point rectangle. + * + * A point is considered part of a rectangle if both `p` and `r` are not NULL, + * and `p`'s x and y coordinates are >= to the rectangle's top left corner, + * and <= the rectangle's x+w and y+h. So a 1x1 rectangle considers point + * (0,0) and (0,1) as "inside" and (0,2) as not. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param p the point to test. + * \param r the rectangle to test. + * \returns true if `p` is contained by `r`, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE SDL_bool SDL_PointInRectFloat(const SDL_FPoint *p, const SDL_FRect *r) +SDL_FORCE_INLINE bool SDL_PointInRectFloat(const SDL_FPoint *p, const SDL_FRect *r) { - return ( (p->x >= r->x) && (p->x < (r->x + r->w)) && - (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? SDL_TRUE : SDL_FALSE; + return ( p && r && (p->x >= r->x) && (p->x <= (r->x + r->w)) && + (p->y >= r->y) && (p->y <= (r->y + r->h)) ) ? true : false; } /** - * Returns true if the rectangle has no area. + * Determine whether a floating point rectangle can contain any point. + * + * A rectangle is considered "empty" for this function if `r` is NULL, or if + * `r`'s width and/or height are < 0.0f. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param r the rectangle to test. + * \returns true if the rectangle is "empty", false otherwise. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE SDL_bool SDL_RectEmptyFloat(const SDL_FRect *r) +SDL_FORCE_INLINE bool SDL_RectEmptyFloat(const SDL_FRect *r) { - return ((!r) || (r->w <= 0.0f) || (r->h <= 0.0f)) ? SDL_TRUE : SDL_FALSE; + return ((!r) || (r->w < 0.0f) || (r->h < 0.0f)) ? true : false; } /** - * Returns true if the two rectangles are equal, within some given epsilon. + * Determine whether two floating point rectangles are equal, within some + * given epsilon. + * + * Rectangles are considered equal if both are not NULL and each of their x, + * y, width and height are within `epsilon` of each other. If you don't know + * what value to use for `epsilon`, you should call the SDL_RectsEqualFloat + * function instead. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param a the first rectangle to test. + * \param b the second rectangle to test. + * \param epsilon the epsilon value for comparison. + * \returns true if the rectangles are equal, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RectsEqualFloat */ -SDL_FORCE_INLINE SDL_bool SDL_RectsEqualEpsilon(const SDL_FRect *a, const SDL_FRect *b, const float epsilon) +SDL_FORCE_INLINE bool SDL_RectsEqualEpsilon(const SDL_FRect *a, const SDL_FRect *b, const float epsilon) { return (a && b && ((a == b) || ((SDL_fabsf(a->x - b->x) <= epsilon) && (SDL_fabsf(a->y - b->y) <= epsilon) && (SDL_fabsf(a->w - b->w) <= epsilon) && (SDL_fabsf(a->h - b->h) <= epsilon)))) - ? SDL_TRUE : SDL_FALSE; + ? true : false; } /** - * Returns true if the two rectangles are equal, using a default epsilon. + * Determine whether two floating point rectangles are equal, within a default + * epsilon. + * + * Rectangles are considered equal if both are not NULL and each of their x, + * y, width and height are within SDL_FLT_EPSILON of each other. This is often + * a reasonable way to compare two floating point rectangles and deal with the + * slight precision variations in floating point calculations that tend to pop + * up. + * + * Note that this is a forced-inline function in a header, and not a public + * API function available in the SDL library (which is to say, the code is + * embedded in the calling program and the linker and dynamic loader will not + * be able to find this function inside SDL itself). + * + * \param a the first rectangle to test. + * \param b the second rectangle to test. + * \returns true if the rectangles are equal, false otherwise. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RectsEqualEpsilon */ -SDL_FORCE_INLINE SDL_bool SDL_RectsEqualFloat(const SDL_FRect *a, const SDL_FRect *b) +SDL_FORCE_INLINE bool SDL_RectsEqualFloat(const SDL_FRect *a, const SDL_FRect *b) { return SDL_RectsEqualEpsilon(a, b, SDL_FLT_EPSILON); } @@ -274,53 +414,48 @@ SDL_FORCE_INLINE SDL_bool SDL_RectsEqualFloat(const SDL_FRect *a, const SDL_FRec /** * Determine whether two rectangles intersect with float precision. * - * If either pointer is NULL the function will return SDL_FALSE. + * If either pointer is NULL the function will return false. * - * \param A an SDL_FRect structure representing the first rectangle - * \param B an SDL_FRect structure representing the second rectangle - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * \param A an SDL_FRect structure representing the first rectangle. + * \param B an SDL_FRect structure representing the second rectangle. + * \returns true if there is an intersection, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRectIntersection */ -extern DECLSPEC SDL_bool SDLCALL SDL_HasRectIntersectionFloat(const SDL_FRect * A, - const SDL_FRect * B); +extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersectionFloat(const SDL_FRect *A, const SDL_FRect *B); /** * Calculate the intersection of two rectangles with float precision. * - * If `result` is NULL then this function will return SDL_FALSE. + * If `result` is NULL then this function will return false. * - * \param A an SDL_FRect structure representing the first rectangle - * \param B an SDL_FRect structure representing the second rectangle + * \param A an SDL_FRect structure representing the first rectangle. + * \param B an SDL_FRect structure representing the second rectangle. * \param result an SDL_FRect structure filled in with the intersection of - * rectangles `A` and `B` - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * rectangles `A` and `B`. + * \returns true if there is an intersection, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HasRectIntersectionFloat */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectIntersectionFloat(const SDL_FRect * A, - const SDL_FRect * B, - SDL_FRect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersectionFloat(const SDL_FRect *A, const SDL_FRect *B, SDL_FRect *result); /** * Calculate the union of two rectangles with float precision. * - * \param A an SDL_FRect structure representing the first rectangle - * \param B an SDL_FRect structure representing the second rectangle + * \param A an SDL_FRect structure representing the first rectangle. + * \param B an SDL_FRect structure representing the second rectangle. * \param result an SDL_FRect structure filled in with the union of rectangles - * `A` and `B` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * `A` and `B`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetRectUnionFloat(const SDL_FRect * A, - const SDL_FRect * B, - SDL_FRect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnionFloat(const SDL_FRect *A, const SDL_FRect *B, SDL_FRect *result); /** * Calculate a minimal rectangle enclosing a set of points with float @@ -330,20 +465,17 @@ extern DECLSPEC int SDLCALL SDL_GetRectUnionFloat(const SDL_FRect * A, * considered. * * \param points an array of SDL_FPoint structures representing points to be - * enclosed - * \param count the number of structures in the `points` array - * \param clip an SDL_FRect used for clipping or NULL to enclose all points + * enclosed. + * \param count the number of structures in the `points` array. + * \param clip an SDL_FRect used for clipping or NULL to enclose all points. * \param result an SDL_FRect structure filled in with the minimal enclosing - * rectangle - * \returns SDL_TRUE if any points were enclosed or SDL_FALSE if all the - * points were outside of the clipping rectangle. + * rectangle. + * \returns true if any points were enclosed or false if all the points were + * outside of the clipping rectangle. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoint * points, - int count, - const SDL_FRect * clip, - SDL_FRect * result); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoint *points, int count, const SDL_FRect *clip, SDL_FRect *result); /** * Calculate the intersection of a rectangle and line segment with float @@ -355,19 +487,16 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoin * both ends will be clipped to the boundary of the rectangle and the new * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary. * - * \param rect an SDL_FRect structure representing the rectangle to intersect - * \param X1 a pointer to the starting X-coordinate of the line - * \param Y1 a pointer to the starting Y-coordinate of the line - * \param X2 a pointer to the ending X-coordinate of the line - * \param Y2 a pointer to the ending Y-coordinate of the line - * \returns SDL_TRUE if there is an intersection, SDL_FALSE otherwise. + * \param rect an SDL_FRect structure representing the rectangle to intersect. + * \param X1 a pointer to the starting X-coordinate of the line. + * \param Y1 a pointer to the starting Y-coordinate of the line. + * \param X2 a pointer to the ending X-coordinate of the line. + * \param Y2 a pointer to the ending Y-coordinate of the line. + * \returns true if there is an intersection, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetRectAndLineIntersectionFloat(const SDL_FRect * - rect, float *X1, - float *Y1, float *X2, - float *Y2); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersectionFloat(const SDL_FRect *rect, float *X1, float *Y1, float *X2, float *Y2); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_render.h b/libs/SDL3/include/SDL3/SDL_render.h index 46cf94a62..820fa5a43 100644 --- a/libs/SDL3/include/SDL3/SDL_render.h +++ b/libs/SDL3/include/SDL3/SDL_render.h @@ -20,38 +20,44 @@ */ /** - * \file SDL_render.h + * # CategoryRender * - * Header file for SDL 2D rendering functions. + * Header file for SDL 2D rendering functions. * - * This API supports the following features: - * * single pixel points - * * single pixel lines - * * filled rectangles - * * texture images + * This API supports the following features: * - * The primitives may be drawn in opaque, blended, or additive modes. + * - single pixel points + * - single pixel lines + * - filled rectangles + * - texture images + * - 2D polygons * - * The texture images may be drawn in opaque, blended, or additive modes. - * They can have an additional color tint or alpha modulation applied to - * them, and may also be stretched with linear interpolation. + * The primitives may be drawn in opaque, blended, or additive modes. * - * This API is designed to accelerate simple 2D operations. You may - * want more functionality such as polygons and particle effects and - * in that case you should use SDL's OpenGL/Direct3D support or one - * of the many good 3D engines. + * The texture images may be drawn in opaque, blended, or additive modes. They + * can have an additional color tint or alpha modulation applied to them, and + * may also be stretched with linear interpolation. * - * These functions must be called from the main thread. - * See this bug for details: https://github.com/libsdl-org/SDL/issues/986 + * This API is designed to accelerate simple 2D operations. You may want more + * functionality such as polygons and particle effects and in that case you + * should use SDL's OpenGL/Direct3D support, the SDL3 GPU API, or one of the + * many good 3D engines. + * + * These functions must be called from the main thread. See this bug for + * details: https://github.com/libsdl-org/SDL/issues/986 */ #ifndef SDL_render_h_ #define SDL_render_h_ #include +#include +#include #include +#include #include #include +#include #include #include @@ -61,32 +67,16 @@ extern "C" { #endif /** - * Flags used when creating a rendering context - */ -typedef enum -{ - SDL_RENDERER_SOFTWARE = 0x00000001, /**< The renderer is a software fallback */ - SDL_RENDERER_ACCELERATED = 0x00000002, /**< The renderer uses hardware - acceleration */ - SDL_RENDERER_PRESENTVSYNC = 0x00000004 /**< Present is synchronized - with the refresh rate */ -} SDL_RendererFlags; - -/** - * Information on the capabilities of a render driver or context. + * The name of the software renderer. + * + * \since This macro is available since SDL 3.0.0. */ -typedef struct SDL_RendererInfo -{ - const char *name; /**< The name of the renderer */ - Uint32 flags; /**< Supported ::SDL_RendererFlags */ - int num_texture_formats; /**< The number of available texture formats */ - SDL_PixelFormatEnum texture_formats[16]; /**< The available texture formats */ - int max_texture_width; /**< The maximum texture width */ - int max_texture_height; /**< The maximum texture height */ -} SDL_RendererInfo; +#define SDL_SOFTWARE_RENDERER "software" /** - * Vertex structure + * Vertex structure. + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_Vertex { @@ -97,8 +87,10 @@ typedef struct SDL_Vertex /** * The access pattern allowed for a texture. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_TextureAccess { SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */ SDL_TEXTUREACCESS_STREAMING, /**< Changes frequently, lockable */ @@ -106,9 +98,11 @@ typedef enum } SDL_TextureAccess; /** - * How the logical size is mapped to the output + * How the logical size is mapped to the output. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_RendererLogicalPresentation { SDL_LOGICAL_PRESENTATION_DISABLED, /**< There is no logical size in effect */ SDL_LOGICAL_PRESENTATION_STRETCH, /**< The rendered content is stretched to the output resolution */ @@ -119,14 +113,33 @@ typedef enum /** * A structure representing rendering state + * + * \since This struct is available since SDL 3.0.0. */ -struct SDL_Renderer; typedef struct SDL_Renderer SDL_Renderer; +#ifndef SDL_INTERNAL + /** * An efficient driver-specific representation of pixel data + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_CreateTexture + * \sa SDL_CreateTextureFromSurface + * \sa SDL_CreateTextureWithProperties + * \sa SDL_DestroyTexture */ -struct SDL_Texture; +struct SDL_Texture +{ + SDL_PixelFormat format; /**< The format of the texture, read-only */ + int w; /**< The width of the texture, read-only. */ + int h; /**< The height of the texture, read-only. */ + + int refcount; /**< Application reference count, used when freeing texture */ +}; +#endif /* !SDL_INTERNAL */ + typedef struct SDL_Texture SDL_Texture; /* Function prototypes */ @@ -140,15 +153,16 @@ typedef struct SDL_Texture SDL_Texture; * * There may be none if SDL was compiled without render support. * - * \returns a number >= 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns the number of built in render drivers. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRenderer * \sa SDL_GetRenderDriver */ -extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); /** * Use this function to get the name of a built in 2D rendering driver. @@ -161,38 +175,40 @@ extern DECLSPEC int SDLCALL SDL_GetNumRenderDrivers(void); * "direct3d12" or "metal". These never have Unicode characters, and are not * meant to be proper names. * - * The returned value points to a static, read-only string; do not modify or - * free it! - * * \param index the index of the rendering driver; the value ranges from 0 to - * SDL_GetNumRenderDrivers() - 1 + * SDL_GetNumRenderDrivers() - 1. * \returns the name of the rendering driver at the requested index, or NULL * if an invalid index was specified. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetNumRenderDrivers */ -extern DECLSPEC const char *SDLCALL SDL_GetRenderDriver(int index); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetRenderDriver(int index); /** * Create a window and default renderer. * - * \param width the width of the window - * \param height the height of the window + * \param title the title of the window, in UTF-8 encoding. + * \param width the width of the window. + * \param height the height of the window. * \param window_flags the flags used to create the window (see - * SDL_CreateWindow()) - * \param window a pointer filled with the window, or NULL on error - * \param renderer a pointer filled with the renderer, or NULL on error - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * SDL_CreateWindow()). + * \param window a pointer filled with the window, or NULL on error. + * \param renderer a pointer filled with the renderer, or NULL on error. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRenderer * \sa SDL_CreateWindow */ -extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_CreateWindowAndRenderer(const char *title, int width, int height, SDL_WindowFlags window_flags, SDL_Window **window, SDL_Renderer **renderer); /** * Create a 2D rendering context for a window. @@ -203,21 +219,18 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, S * need a specific renderer, specify NULL and SDL will attempt to choose the * best option for you, based on what is available on the user's system. * - * If you pass SDL_RENDERER_SOFTWARE in the flags, you will get a software - * renderer, otherwise you will get a hardware accelerated renderer if - * available. - * * By default the rendering size matches the window size in pixels, but you * can call SDL_SetRenderLogicalPresentation() to change the content size and * scaling options. * - * \param window the window where rendering is displayed + * \param window the window where rendering is displayed. * \param name the name of the rendering driver to initialize, or NULL to - * initialize the first one supporting the requested flags - * \param flags 0, or one or more SDL_RendererFlags OR'd together + * initialize the first one supporting the requested flags. * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRendererWithProperties @@ -225,9 +238,9 @@ extern DECLSPEC int SDLCALL SDL_CreateWindowAndRenderer(int width, int height, S * \sa SDL_DestroyRenderer * \sa SDL_GetNumRenderDrivers * \sa SDL_GetRenderDriver - * \sa SDL_GetRendererInfo + * \sa SDL_GetRendererName */ -extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name, Uint32 flags); +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, const char *name); /** * Create a 2D rendering context for a window, with the specified properties. @@ -247,8 +260,9 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * supports HDR output. If you select SDL_COLORSPACE_SRGB_LINEAR, drawing * still uses the sRGB colorspace, but values can go beyond 1.0 and float * (linear) format textures can be used for HDR content. - * - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN`: true if you want - * present synchronized with the refresh rate + * - `SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER`: non-zero if you want + * present synchronized with the refresh rate. This property can take any + * value that is supported by SDL_SetRenderVSync() for the renderer. * * With the vulkan renderer: * @@ -265,31 +279,33 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRenderer(SDL_Window *window, co * - `SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER`: the * queue family index used for presentation. * - * \param props the properties to use + * \param props the properties to use. * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateProperties * \sa SDL_CreateRenderer * \sa SDL_CreateSoftwareRenderer * \sa SDL_DestroyRenderer - * \sa SDL_GetRendererInfo + * \sa SDL_GetRendererName */ -extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_PropertiesID props); -#define SDL_PROP_RENDERER_CREATE_NAME_STRING "name" -#define SDL_PROP_RENDERER_CREATE_WINDOW_POINTER "window" -#define SDL_PROP_RENDERER_CREATE_SURFACE_POINTER "surface" -#define SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER "output_colorspace" -#define SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_BOOLEAN "present_vsync" -#define SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER "vulkan.instance" -#define SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER "vulkan.surface" -#define SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER "vulkan.physical_device" -#define SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER "vulkan.device" -#define SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "vulkan.graphics_queue_family_index" -#define SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "vulkan.present_queue_family_index" +#define SDL_PROP_RENDERER_CREATE_NAME_STRING "SDL.renderer.create.name" +#define SDL_PROP_RENDERER_CREATE_WINDOW_POINTER "SDL.renderer.create.window" +#define SDL_PROP_RENDERER_CREATE_SURFACE_POINTER "SDL.renderer.create.surface" +#define SDL_PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.create.output_colorspace" +#define SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER "SDL.renderer.create.present_vsync" +#define SDL_PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER "SDL.renderer.create.vulkan.instance" +#define SDL_PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER "SDL.renderer.create.vulkan.surface" +#define SDL_PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER "SDL.renderer.create.vulkan.physical_device" +#define SDL_PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER "SDL.renderer.create.vulkan.device" +#define SDL_PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.create.vulkan.graphics_queue_family_index" +#define SDL_PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER "SDL.renderer.create.vulkan.present_queue_family_index" /** * Create a 2D software rendering context for a surface. @@ -300,53 +316,59 @@ extern DECLSPEC SDL_Renderer * SDLCALL SDL_CreateRendererWithProperties(SDL_Prop * SDL_Window as the final destination and not an SDL_Surface. * * \param surface the SDL_Surface structure representing the surface where - * rendering is done + * rendering is done. * \returns a valid rendering context or NULL if there was an error; call * SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroyRenderer */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface *surface); +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_CreateSoftwareRenderer(SDL_Surface *surface); /** * Get the renderer associated with a window. * - * \param window the window to query + * \param window the window to query. * \returns the rendering context on success or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRenderer(SDL_Window *window); +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_GetRenderer(SDL_Window *window); /** * Get the window associated with a renderer. * - * \param renderer the renderer to query + * \param renderer the renderer to query. * \returns the window on success or NULL on failure; call SDL_GetError() for * more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Window *SDLCALL SDL_GetRenderWindow(SDL_Renderer *renderer); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetRenderWindow(SDL_Renderer *renderer); /** - * Get information about a rendering context. + * Get the name of a renderer. * - * \param renderer the rendering context - * \param info an SDL_RendererInfo structure filled with information about the - * current renderer - * \returns 0 on success or a negative error code on failure; call + * \param renderer the rendering context. + * \returns the name of the selected renderer, or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRenderer * \sa SDL_CreateRendererWithProperties */ -extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_RendererInfo *info); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetRendererName(SDL_Renderer *renderer); /** * Get the properties associated with a renderer. @@ -358,6 +380,12 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * displayed, if any * - `SDL_PROP_RENDERER_SURFACE_POINTER`: the surface where rendering is * displayed, if this is a software renderer without a window + * - `SDL_PROP_RENDERER_VSYNC_NUMBER`: the current vsync setting + * - `SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER`: the maximum texture width + * and height + * - `SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER`: a (const SDL_PixelFormat *) + * array of pixel formats, terminated with SDL_PIXELFORMAT_UNKNOWN, + * representing the available texture formats for this renderer. * - `SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER`: an SDL_ColorSpace value * describing the colorspace for output to the display, defaults to * SDL_COLORSPACE_SRGB. @@ -383,11 +411,15 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * * - `SDL_PROP_RENDERER_D3D11_DEVICE_POINTER`: the ID3D11Device associated * with the renderer + * - `SDL_PROP_RENDERER_D3D11_SWAPCHAIN_POINTER`: the IDXGISwapChain1 + * associated with the renderer. This may change when the window is resized. * * With the direct3d12 renderer: * * - `SDL_PROP_RENDERER_D3D12_DEVICE_POINTER`: the ID3D12Device associated * with the renderer + * - `SDL_PROP_RENDERER_D3D12_SWAPCHAIN_POINTER`: the IDXGISwapChain4 + * associated with the renderer. * - `SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER`: the ID3D12CommandQueue * associated with the renderer * @@ -409,27 +441,31 @@ extern DECLSPEC int SDLCALL SDL_GetRendererInfo(SDL_Renderer *renderer, SDL_Rend * swapchain images, or potential frames in flight, used by the Vulkan * renderer * - * \param renderer the rendering context + * \param renderer the rendering context. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0. + * \threadsafety It is safe to call this function from any thread. * - * \sa SDL_GetProperty - * \sa SDL_SetProperty + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer *renderer); #define SDL_PROP_RENDERER_NAME_STRING "SDL.renderer.name" #define SDL_PROP_RENDERER_WINDOW_POINTER "SDL.renderer.window" #define SDL_PROP_RENDERER_SURFACE_POINTER "SDL.renderer.surface" +#define SDL_PROP_RENDERER_VSYNC_NUMBER "SDL.renderer.vsync" +#define SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER "SDL.renderer.max_texture_size" +#define SDL_PROP_RENDERER_TEXTURE_FORMATS_POINTER "SDL.renderer.texture_formats" #define SDL_PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER "SDL.renderer.output_colorspace" #define SDL_PROP_RENDERER_HDR_ENABLED_BOOLEAN "SDL.renderer.HDR_enabled" #define SDL_PROP_RENDERER_SDR_WHITE_POINT_FLOAT "SDL.renderer.SDR_white_point" #define SDL_PROP_RENDERER_HDR_HEADROOM_FLOAT "SDL.renderer.HDR_headroom" #define SDL_PROP_RENDERER_D3D9_DEVICE_POINTER "SDL.renderer.d3d9.device" #define SDL_PROP_RENDERER_D3D11_DEVICE_POINTER "SDL.renderer.d3d11.device" +#define SDL_PROP_RENDERER_D3D11_SWAPCHAIN_POINTER "SDL.renderer.d3d11.swap_chain" #define SDL_PROP_RENDERER_D3D12_DEVICE_POINTER "SDL.renderer.d3d12.device" +#define SDL_PROP_RENDERER_D3D12_SWAPCHAIN_POINTER "SDL.renderer.d3d12.swap_chain" #define SDL_PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER "SDL.renderer.d3d12.command_queue" #define SDL_PROP_RENDERER_VULKAN_INSTANCE_POINTER "SDL.renderer.vulkan.instance" #define SDL_PROP_RENDERER_VULKAN_SURFACE_NUMBER "SDL.renderer.vulkan.surface" @@ -445,17 +481,19 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetRendererProperties(SDL_Renderer * This returns the true output size in pixels, ignoring any render targets or * logical size and presentation. * - * \param renderer the rendering context - * \param w a pointer filled in with the width in pixels - * \param h a pointer filled in with the height in pixels - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param w a pointer filled in with the width in pixels. + * \param h a pointer filled in with the height in pixels. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetCurrentRenderOutputSize */ -extern DECLSPEC int SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); /** * Get the current output size in pixels of a rendering context. @@ -465,42 +503,45 @@ extern DECLSPEC int SDLCALL SDL_GetRenderOutputSize(SDL_Renderer *renderer, int * logical size, otherwise it will return the value of * SDL_GetRenderOutputSize(). * - * \param renderer the rendering context - * \param w a pointer filled in with the current width - * \param h a pointer filled in with the current height - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param w a pointer filled in with the current width. + * \param h a pointer filled in with the current height. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderOutputSize */ -extern DECLSPEC int SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetCurrentRenderOutputSize(SDL_Renderer *renderer, int *w, int *h); /** * Create a texture for a rendering context. * - * You can set the texture scaling method by setting - * `SDL_HINT_RENDER_SCALE_QUALITY` before creating the texture. + * The contents of a texture when first created are not defined. * - * \param renderer the rendering context - * \param format one of the enumerated values in SDL_PixelFormatEnum - * \param access one of the enumerated values in SDL_TextureAccess - * \param w the width of the texture in pixels - * \param h the height of the texture in pixels + * \param renderer the rendering context. + * \param format one of the enumerated values in SDL_PixelFormat. + * \param access one of the enumerated values in SDL_TextureAccess. + * \param w the width of the texture in pixels. + * \param h the height of the texture in pixels. * \returns a pointer to the created texture or NULL if no rendering context * was active, the format was unsupported, or the width or height * were out of range; call SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTextureFromSurface * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture - * \sa SDL_QueryTexture + * \sa SDL_GetTextureSize * \sa SDL_UpdateTexture */ -extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, SDL_PixelFormatEnum format, int access, int w, int h); +extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, SDL_PixelFormat format, SDL_TextureAccess access, int w, int h); /** * Create a texture from an existing surface. @@ -511,23 +552,24 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTexture(SDL_Renderer *renderer, S * `SDL_TEXTUREACCESS_STATIC`. * * The pixel format of the created texture may be different from the pixel - * format of the surface. Use SDL_QueryTexture() to query the pixel format of - * the texture. + * format of the surface, and can be queried using the + * SDL_PROP_TEXTURE_FORMAT_NUMBER property. * - * \param renderer the rendering context + * \param renderer the rendering context. * \param surface the SDL_Surface structure containing pixel data used to fill - * the texture + * the texture. * \returns the created texture or NULL on failure; call SDL_GetError() for * more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTexture * \sa SDL_CreateTextureWithProperties * \sa SDL_DestroyTexture - * \sa SDL_QueryTexture */ -extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); +extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface); /** * Create a texture for a rendering context with the specified properties. @@ -540,7 +582,7 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * SDL_COLORSPACE_SRGB for other RGB textures and SDL_COLORSPACE_JPEG for * YUV textures. * - `SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER`: one of the enumerated values in - * SDL_PixelFormatEnum, defaults to the best RGBA format for the renderer + * SDL_PixelFormat, defaults to the best RGBA format for the renderer * - `SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER`: one of the enumerated values in * SDL_TextureAccess, defaults to SDL_TEXTUREACCESS_STATIC * - `SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER`: the width of the texture in @@ -623,46 +665,48 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureFromSurface(SDL_Renderer * * VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL associated with the texture, if * you want to wrap an existing texture. * - * \param renderer the rendering context - * \param props the properties to use + * \param renderer the rendering context. + * \param props the properties to use. * \returns a pointer to the created texture or NULL if no rendering context * was active, the format was unsupported, or the width or height * were out of range; call SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateProperties * \sa SDL_CreateTexture * \sa SDL_CreateTextureFromSurface * \sa SDL_DestroyTexture - * \sa SDL_QueryTexture + * \sa SDL_GetTextureSize * \sa SDL_UpdateTexture */ -extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); - -#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "colorspace" -#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "format" -#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "access" -#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "width" -#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "height" -#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDR_white_point" -#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "HDR_headroom" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "d3d11.texture" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "d3d11.texture_u" -#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "d3d11.texture_v" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "d3d12.texture" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "d3d12.texture_u" -#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "d3d12.texture_v" -#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "metal.pixelbuffer" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "opengl.texture" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "opengl.texture_uv" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "opengl.texture_u" -#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "opengl.texture_v" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "opengles2.texture" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "opengles2.texture_uv" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "opengles2.texture_u" -#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "opengles2.texture_v" -#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "vulkan.texture" +extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_CreateTextureWithProperties(SDL_Renderer *renderer, SDL_PropertiesID props); + +#define SDL_PROP_TEXTURE_CREATE_COLORSPACE_NUMBER "SDL.texture.create.colorspace" +#define SDL_PROP_TEXTURE_CREATE_FORMAT_NUMBER "SDL.texture.create.format" +#define SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER "SDL.texture.create.access" +#define SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER "SDL.texture.create.width" +#define SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER "SDL.texture.create.height" +#define SDL_PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT "SDL.texture.create.SDR_white_point" +#define SDL_PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT "SDL.texture.create.HDR_headroom" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER "SDL.texture.create.d3d11.texture" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER "SDL.texture.create.d3d11.texture_u" +#define SDL_PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER "SDL.texture.create.d3d11.texture_v" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER "SDL.texture.create.d3d12.texture" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER "SDL.texture.create.d3d12.texture_u" +#define SDL_PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER "SDL.texture.create.d3d12.texture_v" +#define SDL_PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER "SDL.texture.create.metal.pixelbuffer" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER "SDL.texture.create.opengl.texture" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER "SDL.texture.create.opengl.texture_uv" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER "SDL.texture.create.opengl.texture_u" +#define SDL_PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER "SDL.texture.create.opengl.texture_v" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER "SDL.texture.create.opengles2.texture" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER "SDL.texture.create.opengles2.texture_uv" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER "SDL.texture.create.opengles2.texture_u" +#define SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER "SDL.texture.create.opengles2.texture_v" +#define SDL_PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER "SDL.texture.create.vulkan.texture" /** * Get the properties associated with a texture. @@ -670,7 +714,13 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * The following read-only properties are provided by SDL: * * - `SDL_PROP_TEXTURE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing - * the colorspace used by the texture + * the texture colorspace. + * - `SDL_PROP_TEXTURE_FORMAT_NUMBER`: one of the enumerated values in + * SDL_PixelFormat. + * - `SDL_PROP_TEXTURE_ACCESS_NUMBER`: one of the enumerated values in + * SDL_TextureAccess. + * - `SDL_PROP_TEXTURE_WIDTH_NUMBER`: the width of the texture in pixels. + * - `SDL_PROP_TEXTURE_HEIGHT_NUMBER`: the height of the texture in pixels. * - `SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point * textures, this defines the value of 100% diffuse white, with higher * values being displayed in the High Dynamic Range headroom. This defaults @@ -747,18 +797,21 @@ extern DECLSPEC SDL_Texture *SDLCALL SDL_CreateTextureWithProperties(SDL_Rendere * - `SDL_PROP_TEXTURE_VULKAN_TEXTURE_NUMBER`: the VkImage associated with the * texture * - * \param texture the texture to query + * \param texture the texture to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0. + * \threadsafety It is safe to call this function from any thread. * - * \sa SDL_GetProperty - * \sa SDL_SetProperty + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *texture); #define SDL_PROP_TEXTURE_COLORSPACE_NUMBER "SDL.texture.colorspace" +#define SDL_PROP_TEXTURE_FORMAT_NUMBER "SDL.texture.format" +#define SDL_PROP_TEXTURE_ACCESS_NUMBER "SDL.texture.access" +#define SDL_PROP_TEXTURE_WIDTH_NUMBER "SDL.texture.width" +#define SDL_PROP_TEXTURE_HEIGHT_NUMBER "SDL.texture.height" #define SDL_PROP_TEXTURE_SDR_WHITE_POINT_FLOAT "SDL.texture.SDR_white_point" #define SDL_PROP_TEXTURE_HDR_HEADROOM_FLOAT "SDL.texture.HDR_headroom" #define SDL_PROP_TEXTURE_D3D11_TEXTURE_POINTER "SDL.texture.d3d11.texture" @@ -784,7 +837,7 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t /** * Get the renderer that created an SDL_Texture. * - * \param texture the texture to query + * \param texture the texture to query. * \returns a pointer to the SDL_Renderer that created the texture, or NULL on * failure; call SDL_GetError() for more information. * @@ -792,29 +845,24 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetTextureProperties(SDL_Texture *t * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Renderer *SDLCALL SDL_GetRendererFromTexture(SDL_Texture *texture); +extern SDL_DECLSPEC SDL_Renderer * SDLCALL SDL_GetRendererFromTexture(SDL_Texture *texture); /** - * Query the attributes of a texture. + * Get the size of a texture, as floating point values. * - * \param texture the texture to query - * \param format a pointer filled in with the raw format of the texture; the - * actual format may differ, but pixel transfers will use this - * format (one of the SDL_PixelFormatEnum values). This argument - * can be NULL if you don't need this information. - * \param access a pointer filled in with the actual access to the texture - * (one of the SDL_TextureAccess values). This argument can be - * NULL if you don't need this information. + * \param texture the texture to query. * \param w a pointer filled in with the width of the texture in pixels. This * argument can be NULL if you don't need this information. * \param h a pointer filled in with the height of the texture in pixels. This * argument can be NULL if you don't need this information. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture *texture, SDL_PixelFormatEnum *format, int *access, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureSize(SDL_Texture *texture, float *w, float *h); /** * Set an additional color value multiplied into render copy operations. @@ -825,15 +873,17 @@ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture *texture, SDL_PixelForm * * `srcC = srcC * (color / 255)` * - * Color modulation is not always supported by the renderer; it will return -1 - * if color modulation is not supported. + * Color modulation is not always supported by the renderer; it will return + * false if color modulation is not supported. * - * \param texture the texture to update - * \param r the red color value multiplied into copy operations - * \param g the green color value multiplied into copy operations - * \param b the blue color value multiplied into copy operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to update. + * \param r the red color value multiplied into copy operations. + * \param g the green color value multiplied into copy operations. + * \param b the blue color value multiplied into copy operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -841,7 +891,7 @@ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_Texture *texture, SDL_PixelForm * \sa SDL_SetTextureAlphaMod * \sa SDL_SetTextureColorModFloat */ -extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r, Uint8 g, Uint8 b); /** @@ -853,15 +903,17 @@ extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r * * `srcC = srcC * color` * - * Color modulation is not always supported by the renderer; it will return -1 - * if color modulation is not supported. + * Color modulation is not always supported by the renderer; it will return + * false if color modulation is not supported. * - * \param texture the texture to update - * \param r the red color value multiplied into copy operations - * \param g the green color value multiplied into copy operations - * \param b the blue color value multiplied into copy operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to update. + * \param r the red color value multiplied into copy operations. + * \param g the green color value multiplied into copy operations. + * \param b the blue color value multiplied into copy operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -869,18 +921,20 @@ extern DECLSPEC int SDLCALL SDL_SetTextureColorMod(SDL_Texture *texture, Uint8 r * \sa SDL_SetTextureAlphaModFloat * \sa SDL_SetTextureColorMod */ -extern DECLSPEC int SDLCALL SDL_SetTextureColorModFloat(SDL_Texture *texture, float r, float g, float b); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureColorModFloat(SDL_Texture *texture, float r, float g, float b); /** * Get the additional color value multiplied into render copy operations. * - * \param texture the texture to query - * \param r a pointer filled in with the current red color value - * \param g a pointer filled in with the current green color value - * \param b a pointer filled in with the current blue color value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to query. + * \param r a pointer filled in with the current red color value. + * \param g a pointer filled in with the current green color value. + * \param b a pointer filled in with the current blue color value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -888,17 +942,19 @@ extern DECLSPEC int SDLCALL SDL_SetTextureColorModFloat(SDL_Texture *texture, fl * \sa SDL_GetTextureColorModFloat * \sa SDL_SetTextureColorMod */ -extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 *r, Uint8 *g, Uint8 *b); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 *r, Uint8 *g, Uint8 *b); /** * Get the additional color value multiplied into render copy operations. * - * \param texture the texture to query - * \param r a pointer filled in with the current red color value - * \param g a pointer filled in with the current green color value - * \param b a pointer filled in with the current blue color value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to query. + * \param r a pointer filled in with the current red color value. + * \param g a pointer filled in with the current green color value. + * \param b a pointer filled in with the current blue color value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -906,7 +962,7 @@ extern DECLSPEC int SDLCALL SDL_GetTextureColorMod(SDL_Texture *texture, Uint8 * * \sa SDL_GetTextureColorMod * \sa SDL_SetTextureColorModFloat */ -extern DECLSPEC int SDLCALL SDL_GetTextureColorModFloat(SDL_Texture *texture, float *r, float *g, float *b); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureColorModFloat(SDL_Texture *texture, float *r, float *g, float *b); /** * Set an additional alpha value multiplied into render copy operations. @@ -916,13 +972,15 @@ extern DECLSPEC int SDLCALL SDL_GetTextureColorModFloat(SDL_Texture *texture, fl * * `srcA = srcA * (alpha / 255)` * - * Alpha modulation is not always supported by the renderer; it will return -1 - * if alpha modulation is not supported. + * Alpha modulation is not always supported by the renderer; it will return + * false if alpha modulation is not supported. * - * \param texture the texture to update - * \param alpha the source alpha value multiplied into copy operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to update. + * \param alpha the source alpha value multiplied into copy operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -930,7 +988,7 @@ extern DECLSPEC int SDLCALL SDL_GetTextureColorModFloat(SDL_Texture *texture, fl * \sa SDL_SetTextureAlphaModFloat * \sa SDL_SetTextureColorMod */ -extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 alpha); /** * Set an additional alpha value multiplied into render copy operations. @@ -940,13 +998,15 @@ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 a * * `srcA = srcA * alpha` * - * Alpha modulation is not always supported by the renderer; it will return -1 - * if alpha modulation is not supported. + * Alpha modulation is not always supported by the renderer; it will return + * false if alpha modulation is not supported. * - * \param texture the texture to update - * \param alpha the source alpha value multiplied into copy operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to update. + * \param alpha the source alpha value multiplied into copy operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -954,15 +1014,17 @@ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaMod(SDL_Texture *texture, Uint8 a * \sa SDL_SetTextureAlphaMod * \sa SDL_SetTextureColorModFloat */ -extern DECLSPEC int SDLCALL SDL_SetTextureAlphaModFloat(SDL_Texture *texture, float alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureAlphaModFloat(SDL_Texture *texture, float alpha); /** * Get the additional alpha value multiplied into render copy operations. * - * \param texture the texture to query - * \param alpha a pointer filled in with the current alpha value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to query. + * \param alpha a pointer filled in with the current alpha value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -970,15 +1032,17 @@ extern DECLSPEC int SDLCALL SDL_SetTextureAlphaModFloat(SDL_Texture *texture, fl * \sa SDL_GetTextureColorMod * \sa SDL_SetTextureAlphaMod */ -extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 *alpha); /** * Get the additional alpha value multiplied into render copy operations. * - * \param texture the texture to query - * \param alpha a pointer filled in with the current alpha value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to query. + * \param alpha a pointer filled in with the current alpha value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -986,38 +1050,42 @@ extern DECLSPEC int SDLCALL SDL_GetTextureAlphaMod(SDL_Texture *texture, Uint8 * * \sa SDL_GetTextureColorModFloat * \sa SDL_SetTextureAlphaModFloat */ -extern DECLSPEC int SDLCALL SDL_GetTextureAlphaModFloat(SDL_Texture *texture, float *alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureAlphaModFloat(SDL_Texture *texture, float *alpha); /** * Set the blend mode for a texture, used by SDL_RenderTexture(). * * If the blend mode is not supported, the closest supported mode is chosen - * and this function returns -1. + * and this function returns false. * - * \param texture the texture to update - * \param blendMode the SDL_BlendMode to use for texture blending - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to update. + * \param blendMode the SDL_BlendMode to use for texture blending. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTextureBlendMode */ -extern DECLSPEC int SDLCALL SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode blendMode); /** * Get the blend mode used for texture copy operations. * - * \param texture the texture to query - * \param blendMode a pointer filled in with the current SDL_BlendMode - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param texture the texture to query. + * \param blendMode a pointer filled in with the current SDL_BlendMode. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetTextureBlendMode */ -extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_BlendMode *blendMode); /** * Set the scale mode used for texture scale operations. @@ -1026,36 +1094,40 @@ extern DECLSPEC int SDLCALL SDL_GetTextureBlendMode(SDL_Texture *texture, SDL_Bl * * If the scale mode is not supported, the closest supported mode is chosen. * - * \param texture The texture to update. + * \param texture the texture to update. * \param scaleMode the SDL_ScaleMode to use for texture scaling. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTextureScaleMode */ -extern DECLSPEC int SDLCALL SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode scaleMode); /** * Get the scale mode used for texture scale operations. * * \param texture the texture to query. * \param scaleMode a pointer filled in with the current scale mode. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetTextureScaleMode */ -extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_ScaleMode *scaleMode); /** * Update the given texture rectangle with new pixel data. * - * The pixel data must be in the pixel format of the texture. Use - * SDL_QueryTexture() to query the pixel format of the texture. + * The pixel data must be in the pixel format of the texture, which can be + * queried using the SDL_PROP_TEXTURE_FORMAT_NUMBER property. * * This is a fairly slow function, intended for use with static textures that * do not change often. @@ -1065,14 +1137,16 @@ extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_Sc * While this function will work with streaming textures, for optimization * reasons you may not get the pixels back if you lock the texture afterward. * - * \param texture the texture to update + * \param texture the texture to update. * \param rect an SDL_Rect structure representing the area to update, or NULL - * to update the entire texture - * \param pixels the raw pixel data in the format of the texture + * to update the entire texture. + * \param pixels the raw pixel data in the format of the texture. * \param pitch the number of bytes in a row of pixel data, including padding - * between lines - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * between lines. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * @@ -1081,7 +1155,7 @@ extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_Texture *texture, SDL_Sc * \sa SDL_UpdateNVTexture * \sa SDL_UpdateYUVTexture */ -extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateTexture(SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch); /** * Update a rectangle within a planar YV12 or IYUV texture with new pixel @@ -1091,27 +1165,29 @@ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture *texture, const SDL_Re * block of Y and U/V planes in the proper order, but this function is * available if your pixel data is not contiguous. * - * \param texture the texture to update + * \param texture the texture to update. * \param rect a pointer to the rectangle of pixels to update, or NULL to - * update the entire texture - * \param Yplane the raw pixel data for the Y plane + * update the entire texture. + * \param Yplane the raw pixel data for the Y plane. * \param Ypitch the number of bytes between rows of pixel data for the Y - * plane - * \param Uplane the raw pixel data for the U plane + * plane. + * \param Uplane the raw pixel data for the U plane. * \param Upitch the number of bytes between rows of pixel data for the U - * plane - * \param Vplane the raw pixel data for the V plane + * plane. + * \param Vplane the raw pixel data for the V plane. * \param Vpitch the number of bytes between rows of pixel data for the V - * plane - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * plane. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_UpdateNVTexture * \sa SDL_UpdateTexture */ -extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture *texture, +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateYUVTexture(SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *Uplane, int Upitch, @@ -1124,7 +1200,7 @@ extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture *texture, * block of NV12/21 planes in the proper order, but this function is available * if your pixel data is not contiguous. * - * \param texture the texture to update + * \param texture the texture to update. * \param rect a pointer to the rectangle of pixels to update, or NULL to * update the entire texture. * \param Yplane the raw pixel data for the Y plane. @@ -1133,15 +1209,17 @@ extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture *texture, * \param UVplane the raw pixel data for the UV plane. * \param UVpitch the number of bytes between rows of pixel data for the UV * plane. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_UpdateTexture * \sa SDL_UpdateYUVTexture */ -extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture *texture, +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateNVTexture(SDL_Texture *texture, const SDL_Rect *rect, const Uint8 *Yplane, int Ypitch, const Uint8 *UVplane, int UVpitch); @@ -1158,23 +1236,25 @@ extern DECLSPEC int SDLCALL SDL_UpdateNVTexture(SDL_Texture *texture, * changes. * * \param texture the texture to lock for access, which was created with - * `SDL_TEXTUREACCESS_STREAMING` + * `SDL_TEXTUREACCESS_STREAMING`. * \param rect an SDL_Rect structure representing the area to lock for access; - * NULL to lock the entire texture + * NULL to lock the entire texture. * \param pixels this is filled in with a pointer to the locked pixels, - * appropriately offset by the locked area + * appropriately offset by the locked area. * \param pitch this is filled in with the pitch of the locked pixels; the - * pitch is the length of one row in bytes - * \returns 0 on success or a negative error code if the texture is not valid - * or was not created with `SDL_TEXTUREACCESS_STREAMING`; call - * SDL_GetError() for more information. + * pitch is the length of one row in bytes. + * \returns true on success or false if the texture is not valid or was not + * created with `SDL_TEXTUREACCESS_STREAMING`; call SDL_GetError() + * for more information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockTextureToSurface * \sa SDL_UnlockTexture */ -extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture *texture, +extern SDL_DECLSPEC bool SDLCALL SDL_LockTexture(SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch); @@ -1197,22 +1277,22 @@ extern DECLSPEC int SDLCALL SDL_LockTexture(SDL_Texture *texture, * or SDL_DestroyTexture(). The caller should not free it. * * \param texture the texture to lock for access, which must be created with - * `SDL_TEXTUREACCESS_STREAMING` + * `SDL_TEXTUREACCESS_STREAMING`. * \param rect a pointer to the rectangle to lock for access. If the rect is - * NULL, the entire texture will be locked + * NULL, the entire texture will be locked. * \param surface this is filled in with an SDL surface representing the - * locked area - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * locked area. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockTexture * \sa SDL_UnlockTexture */ -extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture, - const SDL_Rect *rect, - SDL_Surface **surface); +extern SDL_DECLSPEC bool SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture, const SDL_Rect *rect, SDL_Surface **surface); /** * Unlock a texture, uploading the changes to video memory, if needed. @@ -1225,13 +1305,15 @@ extern DECLSPEC int SDLCALL SDL_LockTextureToSurface(SDL_Texture *texture, * Which is to say: locking and immediately unlocking a texture can result in * corrupted textures, depending on the renderer in use. * - * \param texture a texture locked by SDL_LockTexture() + * \param texture a texture locked by SDL_LockTexture(). + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockTexture */ -extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture *texture); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture *texture); /** * Set a texture as the current rendering target. @@ -1240,18 +1322,20 @@ extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_Texture *texture); * To stop rendering to a texture and render to the window again, call this * function with a NULL `texture`. * - * \param renderer the rendering context + * \param renderer the rendering context. * \param texture the targeted texture, which must be created with the * `SDL_TEXTUREACCESS_TARGET` flag, or NULL to render to the * window instead of a texture. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderTarget */ -extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture); /** * Get the current render target. @@ -1259,43 +1343,57 @@ extern DECLSPEC int SDLCALL SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Text * The default render target is the window for which the renderer was created, * and is reported a NULL here. * - * \param renderer the rendering context + * \param renderer the rendering context. * \returns the current render target or NULL for the default render target. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderTarget */ -extern DECLSPEC SDL_Texture *SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer); +extern SDL_DECLSPEC SDL_Texture * SDLCALL SDL_GetRenderTarget(SDL_Renderer *renderer); /** * Set a device independent resolution and presentation mode for rendering. * - * This function sets the width and height of the logical rendering output. A - * render target is created at the specified size and used for rendering and - * then copied to the output during presentation. + * This function sets the width and height of the logical rendering output. + * The renderer will act as if the window is always the requested dimensions, + * scaling to the actual window resolution as necessary. + * + * This can be useful for games that expect a fixed size, but would like to + * scale the output to whatever is available, regardless of how a user resizes + * a window, or if the display is high DPI. * * You can disable logical coordinates by setting the mode to * SDL_LOGICAL_PRESENTATION_DISABLED, and in that case you get the full pixel - * resolution of the output window. + * resolution of the output window; it is safe to toggle logical presentation + * during the rendering of a frame: perhaps most of the rendering is done to + * specific dimensions but to make fonts look sharp, the app turns off logical + * presentation while drawing text. + * + * Letterboxing will only happen if logical presentation is enabled during + * SDL_RenderPresent; be sure to reenable it first if you were using it. * * You can convert coordinates in an event into rendering coordinates using * SDL_ConvertEventToRenderCoordinates(). * - * \param renderer the rendering context - * \param w the width of the logical resolution - * \param h the height of the logical resolution - * \param mode the presentation mode used - * \param scale_mode the scale mode used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param w the width of the logical resolution. + * \param h the height of the logical resolution. + * \param mode the presentation mode used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ConvertEventToRenderCoordinates * \sa SDL_GetRenderLogicalPresentation + * \sa SDL_GetRenderLogicalPresentationRect */ -extern DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode, SDL_ScaleMode scale_mode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode); /** * Get device independent resolution and presentation mode for rendering. @@ -1303,107 +1401,168 @@ extern DECLSPEC int SDLCALL SDL_SetRenderLogicalPresentation(SDL_Renderer *rende * This function gets the width and height of the logical rendering output, or * the output size in pixels if a logical resolution is not enabled. * - * \param renderer the rendering context - * \param w an int to be filled with the width - * \param h an int to be filled with the height - * \param mode a pointer filled in with the presentation mode - * \param scale_mode a pointer filled in with the scale mode - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param w an int to be filled with the width. + * \param h an int to be filled with the height. + * \param mode the presentation mode used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetRenderLogicalPresentation + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode); + +/** + * Get the final presentation rectangle for rendering. + * + * This function returns the calculated rectangle used for logical + * presentation, based on the presentation mode and output size. If logical + * presentation is disabled, it will fill the rectangle with the output size, + * in pixels. + * + * \param renderer the rendering context. + * \param rect a pointer filled in with the final presentation rectangle, may + * be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderLogicalPresentation */ -extern DECLSPEC int SDLCALL SDL_GetRenderLogicalPresentation(SDL_Renderer *renderer, int *w, int *h, SDL_RendererLogicalPresentation *mode, SDL_ScaleMode *scale_mode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderLogicalPresentationRect(SDL_Renderer *renderer, SDL_FRect *rect); /** * Get a point in render coordinates when given a point in window coordinates. * - * \param renderer the rendering context - * \param window_x the x coordinate in window coordinates - * \param window_y the y coordinate in window coordinates - * \param x a pointer filled with the x coordinate in render coordinates - * \param y a pointer filled with the y coordinate in render coordinates - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * This takes into account several states: + * + * - The window dimensions. + * - The logical presentation settings (SDL_SetRenderLogicalPresentation) + * - The scale (SDL_SetRenderScale) + * - The viewport (SDL_SetRenderViewport) + * + * \param renderer the rendering context. + * \param window_x the x coordinate in window coordinates. + * \param window_y the y coordinate in window coordinates. + * \param x a pointer filled with the x coordinate in render coordinates. + * \param y a pointer filled with the y coordinate in render coordinates. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderLogicalPresentation * \sa SDL_SetRenderScale */ -extern DECLSPEC int SDLCALL SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, float window_y, float *x, float *y); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderCoordinatesFromWindow(SDL_Renderer *renderer, float window_x, float window_y, float *x, float *y); /** * Get a point in window coordinates when given a point in render coordinates. * - * \param renderer the rendering context - * \param x the x coordinate in render coordinates - * \param y the y coordinate in render coordinates + * This takes into account several states: + * + * - The window dimensions. + * - The logical presentation settings (SDL_SetRenderLogicalPresentation) + * - The scale (SDL_SetRenderScale) + * - The viewport (SDL_SetRenderViewport) + * + * \param renderer the rendering context. + * \param x the x coordinate in render coordinates. + * \param y the y coordinate in render coordinates. * \param window_x a pointer filled with the x coordinate in window - * coordinates + * coordinates. * \param window_y a pointer filled with the y coordinate in window - * coordinates - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * coordinates. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderLogicalPresentation * \sa SDL_SetRenderScale + * \sa SDL_SetRenderViewport */ -extern DECLSPEC int SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderCoordinatesToWindow(SDL_Renderer *renderer, float x, float y, float *window_x, float *window_y); /** * Convert the coordinates in an event to render coordinates. * + * This takes into account several states: + * + * - The window dimensions. + * - The logical presentation settings (SDL_SetRenderLogicalPresentation) + * - The scale (SDL_SetRenderScale) + * - The viewport (SDL_SetRenderViewport) + * * Touch coordinates are converted from normalized coordinates in the window * to non-normalized rendering coordinates. * * Once converted, the coordinates may be outside the rendering area. * - * \param renderer the rendering context - * \param event the event to modify - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param event the event to modify. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetRenderCoordinatesFromWindowCoordinates + * \sa SDL_RenderCoordinatesFromWindow */ -extern DECLSPEC int SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event); +extern SDL_DECLSPEC bool SDLCALL SDL_ConvertEventToRenderCoordinates(SDL_Renderer *renderer, SDL_Event *event); /** * Set the drawing area for rendering on the current target. * - * \param renderer the rendering context + * Drawing will clip to this area (separately from any clipping done with + * SDL_SetRenderClipRect), and the top left of the area will become coordinate + * (0, 0) for future drawing commands. + * + * The area's width and height must be >= 0. + * + * \param renderer the rendering context. * \param rect the SDL_Rect structure representing the drawing area, or NULL - * to set the viewport to the entire target - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * to set the viewport to the entire target. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderViewport * \sa SDL_RenderViewportSet */ -extern DECLSPEC int SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderViewport(SDL_Renderer *renderer, const SDL_Rect *rect); /** * Get the drawing area for the current target. * - * \param renderer the rendering context - * \param rect an SDL_Rect structure filled in with the current drawing area - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param rect an SDL_Rect structure filled in with the current drawing area. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderViewportSet * \sa SDL_SetRenderViewport */ -extern DECLSPEC int SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Rect *rect); /** * Return whether an explicit rectangle was set as the viewport. @@ -1412,62 +1571,92 @@ extern DECLSPEC int SDLCALL SDL_GetRenderViewport(SDL_Renderer *renderer, SDL_Re * whether you should restore a specific rectangle or NULL. Note that the * viewport is always reset when changing rendering targets. * - * \param renderer the rendering context - * \returns SDL_TRUE if the viewport was set to a specific rectangle, or - * SDL_FALSE if it was set to NULL (the entire target) + * \param renderer the rendering context. + * \returns true if the viewport was set to a specific rectangle, or false if + * it was set to NULL (the entire target). + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderViewport * \sa SDL_SetRenderViewport */ -extern DECLSPEC SDL_bool SDLCALL SDL_RenderViewportSet(SDL_Renderer *renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderViewportSet(SDL_Renderer *renderer); + +/** + * Get the safe area for rendering within the current viewport. + * + * Some devices have portions of the screen which are partially obscured or + * not interactive, possibly due to on-screen controls, curved edges, camera + * notches, TV overscan, etc. This function provides the area of the current + * viewport which is safe to have interactible content. You should continue + * rendering into the rest of the render target, but it should not contain + * visually important or interactible content. + * + * \param renderer the rendering context. + * \param rect a pointer filled in with the area that is safe for interactive + * content. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderSafeArea(SDL_Renderer *renderer, SDL_Rect *rect); /** * Set the clip rectangle for rendering on the specified target. * - * \param renderer the rendering context + * \param renderer the rendering context. * \param rect an SDL_Rect structure representing the clip area, relative to - * the viewport, or NULL to disable clipping - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the viewport, or NULL to disable clipping. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderClipRect * \sa SDL_RenderClipEnabled */ -extern DECLSPEC int SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderClipRect(SDL_Renderer *renderer, const SDL_Rect *rect); /** * Get the clip rectangle for the current target. * - * \param renderer the rendering context + * \param renderer the rendering context. * \param rect an SDL_Rect structure filled in with the current clipping area - * or an empty rectangle if clipping is disabled - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * or an empty rectangle if clipping is disabled. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderClipEnabled * \sa SDL_SetRenderClipRect */ -extern DECLSPEC int SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderClipRect(SDL_Renderer *renderer, SDL_Rect *rect); /** * Get whether clipping is enabled on the given renderer. * - * \param renderer the rendering context - * \returns SDL_TRUE if clipping is enabled or SDL_FALSE if not; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \returns true if clipping is enabled or false if not; call SDL_GetError() + * for more information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderClipRect * \sa SDL_SetRenderClipRect */ -extern DECLSPEC SDL_bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); /** * Set the drawing scale for rendering on the current target. @@ -1480,32 +1669,36 @@ extern DECLSPEC SDL_bool SDLCALL SDL_RenderClipEnabled(SDL_Renderer *renderer); * will be handled using the appropriate quality hints. For best results use * integer scaling factors. * - * \param renderer the rendering context - * \param scaleX the horizontal scaling factor - * \param scaleY the vertical scaling factor - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param scaleX the horizontal scaling factor. + * \param scaleY the vertical scaling factor. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderScale */ -extern DECLSPEC int SDLCALL SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderScale(SDL_Renderer *renderer, float scaleX, float scaleY); /** * Get the drawing scale for the current target. * - * \param renderer the rendering context - * \param scaleX a pointer filled in with the horizontal scaling factor - * \param scaleY a pointer filled in with the vertical scaling factor - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param scaleX a pointer filled in with the horizontal scaling factor. + * \param scaleY a pointer filled in with the vertical scaling factor. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderScale */ -extern DECLSPEC int SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *scaleX, float *scaleY); /** * Set the color used for drawing operations. @@ -1513,22 +1706,24 @@ extern DECLSPEC int SDLCALL SDL_GetRenderScale(SDL_Renderer *renderer, float *sc * Set the color for drawing or filling rectangles, lines, and points, and for * SDL_RenderClear(). * - * \param renderer the rendering context - * \param r the red value used to draw on the rendering target - * \param g the green value used to draw on the rendering target - * \param b the blue value used to draw on the rendering target + * \param renderer the rendering context. + * \param r the red value used to draw on the rendering target. + * \param g the green value used to draw on the rendering target. + * \param b the blue value used to draw on the rendering target. * \param a the alpha value used to draw on the rendering target; usually * `SDL_ALPHA_OPAQUE` (255). Use SDL_SetRenderDrawBlendMode to - * specify how the alpha channel is used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * specify how the alpha channel is used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawColor * \sa SDL_SetRenderDrawColorFloat */ -extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /** * Set the color used for drawing operations (Rect, Line and Clear). @@ -1536,66 +1731,72 @@ extern DECLSPEC int SDLCALL SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 * Set the color for drawing or filling rectangles, lines, and points, and for * SDL_RenderClear(). * - * \param renderer the rendering context - * \param r the red value used to draw on the rendering target - * \param g the green value used to draw on the rendering target - * \param b the blue value used to draw on the rendering target + * \param renderer the rendering context. + * \param r the red value used to draw on the rendering target. + * \param g the green value used to draw on the rendering target. + * \param b the blue value used to draw on the rendering target. * \param a the alpha value used to draw on the rendering target. Use * SDL_SetRenderDrawBlendMode to specify how the alpha channel is - * used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawColorFloat * \sa SDL_SetRenderDrawColor */ -extern DECLSPEC int SDLCALL SDL_SetRenderDrawColorFloat(SDL_Renderer *renderer, float r, float g, float b, float a); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderDrawColorFloat(SDL_Renderer *renderer, float r, float g, float b, float a); /** * Get the color used for drawing operations (Rect, Line and Clear). * - * \param renderer the rendering context + * \param renderer the rendering context. * \param r a pointer filled in with the red value used to draw on the - * rendering target + * rendering target. * \param g a pointer filled in with the green value used to draw on the - * rendering target + * rendering target. * \param b a pointer filled in with the blue value used to draw on the - * rendering target + * rendering target. * \param a a pointer filled in with the alpha value used to draw on the - * rendering target; usually `SDL_ALPHA_OPAQUE` (255) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * rendering target; usually `SDL_ALPHA_OPAQUE` (255). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawColorFloat * \sa SDL_SetRenderDrawColor */ -extern DECLSPEC int SDLCALL SDL_GetRenderDrawColor(SDL_Renderer *renderer, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderDrawColor(SDL_Renderer *renderer, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); /** * Get the color used for drawing operations (Rect, Line and Clear). * - * \param renderer the rendering context + * \param renderer the rendering context. * \param r a pointer filled in with the red value used to draw on the - * rendering target + * rendering target. * \param g a pointer filled in with the green value used to draw on the - * rendering target + * rendering target. * \param b a pointer filled in with the blue value used to draw on the - * rendering target + * rendering target. * \param a a pointer filled in with the alpha value used to draw on the - * rendering target - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * rendering target. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderDrawColorFloat * \sa SDL_GetRenderDrawColor */ -extern DECLSPEC int SDLCALL SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, float *r, float *g, float *b, float *a); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, float *r, float *g, float *b, float *a); /** * Set the color scale used for render operations. @@ -1608,266 +1809,368 @@ extern DECLSPEC int SDLCALL SDL_GetRenderDrawColorFloat(SDL_Renderer *renderer, * The color scale does not affect the alpha channel, only the color * brightness. * - * \param renderer the rendering context - * \param scale the color scale value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param scale the color scale value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderColorScale */ -extern DECLSPEC int SDLCALL SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderColorScale(SDL_Renderer *renderer, float scale); /** * Get the color scale used for render operations. * - * \param renderer the rendering context - * \param scale a pointer filled in with the current color scale value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param scale a pointer filled in with the current color scale value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderColorScale */ -extern DECLSPEC int SDLCALL SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderColorScale(SDL_Renderer *renderer, float *scale); /** * Set the blend mode used for drawing operations (Fill and Line). * * If the blend mode is not supported, the closest supported mode is chosen. * - * \param renderer the rendering context - * \param blendMode the SDL_BlendMode to use for blending - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param blendMode the SDL_BlendMode to use for blending. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderDrawBlendMode */ -extern DECLSPEC int SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode); /** * Get the blend mode used for drawing operations. * - * \param renderer the rendering context - * \param blendMode a pointer filled in with the current SDL_BlendMode - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \param blendMode a pointer filled in with the current SDL_BlendMode. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderDrawBlendMode */ -extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode *blendMode); /** * Clear the current rendering target with the drawing color. * * This function clears the entire rendering target, ignoring the viewport and - * the clip rectangle. + * the clip rectangle. Note, that clearing will also set/fill all pixels of + * the rendering target to current renderer draw color, so make sure to invoke + * SDL_SetRenderDrawColor() when needed. * - * \param renderer the rendering context - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderDrawColor */ -extern DECLSPEC int SDLCALL SDL_RenderClear(SDL_Renderer *renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderClear(SDL_Renderer *renderer); /** * Draw a point on the current rendering target at subpixel precision. * - * \param renderer The renderer which should draw a point. - * \param x The x coordinate of the point. - * \param y The y coordinate of the point. - * \returns 0 on success, or -1 on error + * \param renderer the renderer which should draw a point. + * \param x the x coordinate of the point. + * \param y the y coordinate of the point. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderPoints */ -extern DECLSPEC int SDLCALL SDL_RenderPoint(SDL_Renderer *renderer, float x, float y); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderPoint(SDL_Renderer *renderer, float x, float y); /** * Draw multiple points on the current rendering target at subpixel precision. * - * \param renderer The renderer which should draw multiple points. - * \param points The points to draw - * \param count The number of points to draw - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the renderer which should draw multiple points. + * \param points the points to draw. + * \param count the number of points to draw. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderPoint */ -extern DECLSPEC int SDLCALL SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count); /** * Draw a line on the current rendering target at subpixel precision. * - * \param renderer The renderer which should draw a line. - * \param x1 The x coordinate of the start point. - * \param y1 The y coordinate of the start point. - * \param x2 The x coordinate of the end point. - * \param y2 The y coordinate of the end point. - * \returns 0 on success, or -1 on error + * \param renderer the renderer which should draw a line. + * \param x1 the x coordinate of the start point. + * \param y1 the y coordinate of the start point. + * \param x2 the x coordinate of the end point. + * \param y2 the y coordinate of the end point. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderLines */ -extern DECLSPEC int SDLCALL SDL_RenderLine(SDL_Renderer *renderer, float x1, float y1, float x2, float y2); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderLine(SDL_Renderer *renderer, float x1, float y1, float x2, float y2); /** * Draw a series of connected lines on the current rendering target at * subpixel precision. * - * \param renderer The renderer which should draw multiple lines. - * \param points The points along the lines - * \param count The number of points, drawing count-1 lines - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the renderer which should draw multiple lines. + * \param points the points along the lines. + * \param count the number of points, drawing count-1 lines. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderLine */ -extern DECLSPEC int SDLCALL SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count); /** * Draw a rectangle on the current rendering target at subpixel precision. * - * \param renderer The renderer which should draw a rectangle. - * \param rect A pointer to the destination rectangle, or NULL to outline the + * \param renderer the renderer which should draw a rectangle. + * \param rect a pointer to the destination rectangle, or NULL to outline the * entire rendering target. - * \returns 0 on success, or -1 on error + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderRects */ -extern DECLSPEC int SDLCALL SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderRect(SDL_Renderer *renderer, const SDL_FRect *rect); /** * Draw some number of rectangles on the current rendering target at subpixel * precision. * - * \param renderer The renderer which should draw multiple rectangles. - * \param rects A pointer to an array of destination rectangles. - * \param count The number of rectangles. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the renderer which should draw multiple rectangles. + * \param rects a pointer to an array of destination rectangles. + * \param count the number of rectangles. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderRect */ -extern DECLSPEC int SDLCALL SDL_RenderRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count); /** * Fill a rectangle on the current rendering target with the drawing color at * subpixel precision. * - * \param renderer The renderer which should fill a rectangle. - * \param rect A pointer to the destination rectangle, or NULL for the entire + * \param renderer the renderer which should fill a rectangle. + * \param rect a pointer to the destination rectangle, or NULL for the entire * rendering target. - * \returns 0 on success, or -1 on error + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderFillRects */ -extern DECLSPEC int SDLCALL SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderFillRect(SDL_Renderer *renderer, const SDL_FRect *rect); /** * Fill some number of rectangles on the current rendering target with the * drawing color at subpixel precision. * - * \param renderer The renderer which should fill multiple rectangles. - * \param rects A pointer to an array of destination rectangles. - * \param count The number of rectangles. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the renderer which should fill multiple rectangles. + * \param rects a pointer to an array of destination rectangles. + * \param count the number of rectangles. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderFillRect */ -extern DECLSPEC int SDLCALL SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count); /** * Copy a portion of the texture to the current rendering target at subpixel * precision. * - * \param renderer The renderer which should copy parts of a texture. - * \param texture The source texture. - * \param srcrect A pointer to the source rectangle, or NULL for the entire + * \param renderer the renderer which should copy parts of a texture. + * \param texture the source texture. + * \param srcrect a pointer to the source rectangle, or NULL for the entire * texture. - * \param dstrect A pointer to the destination rectangle, or NULL for the + * \param dstrect a pointer to the destination rectangle, or NULL for the * entire rendering target. - * \returns 0 on success, or -1 on error + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderTextureRotated + * \sa SDL_RenderTextureTiled */ -extern DECLSPEC int SDLCALL SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect); /** * Copy a portion of the source texture to the current rendering target, with * rotation and flipping, at subpixel precision. * - * \param renderer The renderer which should copy parts of a texture. - * \param texture The source texture. - * \param srcrect A pointer to the source rectangle, or NULL for the entire + * \param renderer the renderer which should copy parts of a texture. + * \param texture the source texture. + * \param srcrect a pointer to the source rectangle, or NULL for the entire * texture. - * \param dstrect A pointer to the destination rectangle, or NULL for the + * \param dstrect a pointer to the destination rectangle, or NULL for the * entire rendering target. - * \param angle An angle in degrees that indicates the rotation that will be - * applied to dstrect, rotating it in a clockwise direction - * \param center A pointer to a point indicating the point around which + * \param angle an angle in degrees that indicates the rotation that will be + * applied to dstrect, rotating it in a clockwise direction. + * \param center a pointer to a point indicating the point around which * dstrect will be rotated (if NULL, rotation will be done * around dstrect.w/2, dstrect.h/2). - * \param flip An SDL_FlipMode value stating which flipping actions should be - * performed on the texture - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param flip an SDL_FlipMode value stating which flipping actions should be + * performed on the texture. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderTexture */ -extern DECLSPEC int SDLCALL SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, +extern SDL_DECLSPEC bool SDLCALL SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, const SDL_FRect *dstrect, - const double angle, const SDL_FPoint *center, - const SDL_FlipMode flip); + double angle, const SDL_FPoint *center, + SDL_FlipMode flip); + +/** + * Tile a portion of the texture to the current rendering target at subpixel + * precision. + * + * The pixels in `srcrect` will be repeated as many times as needed to + * completely fill `dstrect`. + * + * \param renderer the renderer which should copy parts of a texture. + * \param texture the source texture. + * \param srcrect a pointer to the source rectangle, or NULL for the entire + * texture. + * \param scale the scale used to transform srcrect into the destination + * rectangle, e.g. a 32x32 texture with a scale of 2 would fill + * 64x64 tiles. + * \param dstrect a pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RenderTexture + */ +extern SDL_DECLSPEC bool SDLCALL SDL_RenderTextureTiled(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float scale, const SDL_FRect *dstrect); + +/** + * Perform a scaled copy using the 9-grid algorithm to the current rendering + * target at subpixel precision. + * + * The pixels in the texture are split into a 3x3 grid, using the different + * corner sizes for each corner, and the sides and center making up the + * remaining pixels. The corners are then scaled using `scale` and fit into + * the corners of the destination rectangle. The sides and center are then + * stretched into place to cover the remaining destination rectangle. + * + * \param renderer the renderer which should copy parts of a texture. + * \param texture the source texture. + * \param srcrect the SDL_Rect structure representing the rectangle to be used + * for the 9-grid, or NULL to use the entire texture. + * \param left_width the width, in pixels, of the left corners in `srcrect`. + * \param right_width the width, in pixels, of the right corners in `srcrect`. + * \param top_height the height, in pixels, of the top corners in `srcrect`. + * \param bottom_height the height, in pixels, of the bottom corners in + * `srcrect`. + * \param scale the scale used to transform the corner of `srcrect` into the + * corner of `dstrect`, or 0.0f for an unscaled copy. + * \param dstrect a pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RenderTexture + */ +extern SDL_DECLSPEC bool SDLCALL SDL_RenderTexture9Grid(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FRect *srcrect, float left_width, float right_width, float top_height, float bottom_height, float scale, const SDL_FRect *dstrect); /** * Render a list of triangles, optionally using a texture and indices into the * vertex array Color and alpha modulation is done per vertex * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). * - * \param renderer The rendering context. + * \param renderer the rendering context. * \param texture (optional) The SDL texture to use. - * \param vertices Vertices. - * \param num_vertices Number of vertices. + * \param vertices vertices. + * \param num_vertices number of vertices. * \param indices (optional) An array of integer indices into the 'vertices' * array, if NULL all vertices will be rendered in sequential * order. - * \param num_indices Number of indices. - * \returns 0 on success, or -1 if the operation is not supported + * \param num_indices number of indices. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderGeometryRaw */ -extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, +extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Vertex *vertices, int num_vertices, const int *indices, int num_indices); @@ -1877,61 +2180,29 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometry(SDL_Renderer *renderer, * vertex arrays Color and alpha modulation is done per vertex * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). * - * \param renderer The rendering context. + * \param renderer the rendering context. * \param texture (optional) The SDL texture to use. - * \param xy Vertex positions - * \param xy_stride Byte size to move from one element to the next element - * \param color Vertex colors (as SDL_Color) - * \param color_stride Byte size to move from one element to the next element - * \param uv Vertex normalized texture coordinates - * \param uv_stride Byte size to move from one element to the next element - * \param num_vertices Number of vertices. + * \param xy vertex positions. + * \param xy_stride byte size to move from one element to the next element. + * \param color vertex colors (as SDL_FColor). + * \param color_stride byte size to move from one element to the next element. + * \param uv vertex normalized texture coordinates. + * \param uv_stride byte size to move from one element to the next element. + * \param num_vertices number of vertices. * \param indices (optional) An array of indices into the 'vertices' arrays, * if NULL all vertices will be rendered in sequential order. - * \param num_indices Number of indices. - * \param size_indices Index size: 1 (byte), 2 (short), 4 (int) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_RenderGeometry - */ -extern DECLSPEC int SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, - SDL_Texture *texture, - const float *xy, int xy_stride, - const SDL_Color *color, int color_stride, - const float *uv, int uv_stride, - int num_vertices, - const void *indices, int num_indices, int size_indices); - -/** - * Render a list of triangles, optionally using a texture and indices into the - * vertex arrays Color and alpha modulation is done per vertex - * (SDL_SetTextureColorMod and SDL_SetTextureAlphaMod are ignored). + * \param num_indices number of indices. + * \param size_indices index size: 1 (byte), 2 (short), 4 (int). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * - * \param renderer The rendering context. - * \param texture (optional) The SDL texture to use. - * \param xy Vertex positions - * \param xy_stride Byte size to move from one element to the next element - * \param color Vertex colors (as SDL_FColor) - * \param color_stride Byte size to move from one element to the next element - * \param uv Vertex normalized texture coordinates - * \param uv_stride Byte size to move from one element to the next element - * \param num_vertices Number of vertices. - * \param indices (optional) An array of indices into the 'vertices' arrays, - * if NULL all vertices will be rendered in sequential order. - * \param num_indices Number of indices. - * \param size_indices Index size: 1 (byte), 2 (short), 4 (int) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_RenderGeometry - * \sa SDL_RenderGeometryRaw */ -extern DECLSPEC int SDLCALL SDL_RenderGeometryRawFloat(SDL_Renderer *renderer, +extern SDL_DECLSPEC bool SDLCALL SDL_RenderGeometryRaw(SDL_Renderer *renderer, SDL_Texture *texture, const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, @@ -1948,15 +2219,17 @@ extern DECLSPEC int SDLCALL SDL_RenderGeometryRawFloat(SDL_Renderer *renderer, * frequently. If you're using this on the main rendering target, it should be * called after rendering and before SDL_RenderPresent(). * - * \param renderer the rendering context + * \param renderer the rendering context. * \param rect an SDL_Rect structure representing the area in pixels relative - * to the to current viewport, or NULL for the entire viewport + * to the to current viewport, or NULL for the entire viewport. * \returns a new SDL_Surface on success or NULL on failure; call * SDL_GetError() for more information. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect); /** * Update the screen with any rendering performed since the previous call. @@ -1977,27 +2250,36 @@ extern DECLSPEC SDL_Surface * SDLCALL SDL_RenderReadPixels(SDL_Renderer *rendere * starting each new frame's drawing, even if you plan to overwrite every * pixel. * - * \param renderer the rendering context - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * Please note, that in case of rendering to a texture - there is **no need** + * to call `SDL_RenderPresent` after drawing needed objects to a texture, and + * should not be done; you are only required to change back the rendering + * target to default via `SDL_SetRenderTarget(renderer, NULL)` afterwards, as + * textures by themselves do not have a concept of backbuffers. Calling + * SDL_RenderPresent while rendering to a texture will still update the screen + * with any current drawing that has been done _to the window itself_. * - * \threadsafety You may only call this function on the main thread. + * \param renderer the rendering context. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateRenderer * \sa SDL_RenderClear + * \sa SDL_RenderFillRect + * \sa SDL_RenderFillRects * \sa SDL_RenderLine * \sa SDL_RenderLines * \sa SDL_RenderPoint * \sa SDL_RenderPoints * \sa SDL_RenderRect * \sa SDL_RenderRects - * \sa SDL_RenderFillRect - * \sa SDL_RenderFillRects * \sa SDL_SetRenderDrawBlendMode * \sa SDL_SetRenderDrawColor */ -extern DECLSPEC int SDLCALL SDL_RenderPresent(SDL_Renderer *renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_RenderPresent(SDL_Renderer *renderer); /** * Destroy the specified texture. @@ -2005,32 +2287,32 @@ extern DECLSPEC int SDLCALL SDL_RenderPresent(SDL_Renderer *renderer); * Passing NULL or an otherwise invalid texture will set the SDL error message * to "Invalid texture". * - * \param texture the texture to destroy + * \param texture the texture to destroy. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateTexture * \sa SDL_CreateTextureFromSurface */ -extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture *texture); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture *texture); /** - * Destroy the rendering context for a window and free associated textures. + * Destroy the rendering context for a window and free all associated + * textures. * - * If `renderer` is NULL, this function will return immediately after setting - * the SDL error message to "Invalid renderer". See SDL_GetError(). + * This should be called before destroying the associated window. * - * Note that destroying a window implicitly destroys the associated renderer, - * so this should not be called if the window associated with the renderer has - * already been destroyed. + * \param renderer the rendering context. * - * \param renderer the rendering context + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateRenderer */ -extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); /** * Force the rendering context to flush any pending commands and state. @@ -2052,16 +2334,18 @@ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer *renderer); * * This means you do not need to save state in your rendering code to protect * the SDL renderer. However, there lots of arbitrary pieces of Direct3D and - * OpenGL state that can confuse things; you should use your best judgement - * and be prepared to make changes if specific state needs to be protected. + * OpenGL state that can confuse things; you should use your best judgment and + * be prepared to make changes if specific state needs to be protected. * - * \param renderer the rendering context - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the rendering context. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer); +extern SDL_DECLSPEC bool SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer); /** * Get the CAMetalLayer associated with the given Metal renderer. @@ -2069,36 +2353,40 @@ extern DECLSPEC int SDLCALL SDL_FlushRenderer(SDL_Renderer *renderer); * This function returns `void *`, so SDL doesn't have to include Metal's * headers, but it can be safely cast to a `CAMetalLayer *`. * - * \param renderer The renderer to query + * \param renderer the renderer to query. * \returns a `CAMetalLayer *` on success, or NULL if the renderer isn't a - * Metal renderer + * Metal renderer. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderMetalCommandEncoder */ -extern DECLSPEC void *SDLCALL SDL_GetRenderMetalLayer(SDL_Renderer *renderer); +extern SDL_DECLSPEC void * SDLCALL SDL_GetRenderMetalLayer(SDL_Renderer *renderer); /** - * Get the Metal command encoder for the current frame + * Get the Metal command encoder for the current frame. * * This function returns `void *`, so SDL doesn't have to include Metal's * headers, but it can be safely cast to an `id`. * - * Note that as of SDL 2.0.18, this will return NULL if Metal refuses to give - * SDL a drawable to render to, which might happen if the window is - * hidden/minimized/offscreen. This doesn't apply to command encoders for - * render targets, just the window's backbuffer. Check your return values! + * This will return NULL if Metal refuses to give SDL a drawable to render to, + * which might happen if the window is hidden/minimized/offscreen. This + * doesn't apply to command encoders for render targets, just the window's + * backbuffer. Check your return values! * - * \param renderer The renderer to query + * \param renderer the renderer to query. * \returns an `id` on success, or NULL if the * renderer isn't a Metal renderer or there was an error. * + * \threadsafety You may only call this function from the main thread. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderMetalLayer */ -extern DECLSPEC void *SDLCALL SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer); +extern SDL_DECLSPEC void * SDLCALL SDL_GetRenderMetalCommandEncoder(SDL_Renderer *renderer); /** @@ -2114,48 +2402,67 @@ extern DECLSPEC void *SDLCALL SDL_GetRenderMetalCommandEncoder(SDL_Renderer *ren * SDL_PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER will give you the * maximum number of semaphores you'll need. * - * \param renderer the rendering context - * \param wait_stage_mask the VkPipelineStageFlags for the wait + * \param renderer the rendering context. + * \param wait_stage_mask the VkPipelineStageFlags for the wait. * \param wait_semaphore a VkSempahore to wait on before rendering the current - * frame, or 0 if not needed + * frame, or 0 if not needed. * \param signal_semaphore a VkSempahore that SDL will signal when rendering * for the current frame is complete, or 0 if not - * needed - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * needed. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is **NOT** safe to call this function from two threads at + * once. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_AddVulkanRenderSemaphores(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore); +extern SDL_DECLSPEC bool SDLCALL SDL_AddVulkanRenderSemaphores(SDL_Renderer *renderer, Uint32 wait_stage_mask, Sint64 wait_semaphore, Sint64 signal_semaphore); /** * Toggle VSync of the given renderer. * - * \param renderer The renderer to toggle - * \param vsync 1 for on, 0 for off. All other values are reserved - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * When a renderer is created, vsync defaults to SDL_RENDERER_VSYNC_DISABLED. + * + * The `vsync` parameter can be 1 to synchronize present with every vertical + * refresh, 2 to synchronize present with every second vertical refresh, etc., + * SDL_WINDOW_SURFACE_VSYNC_ADAPTIVE for late swap tearing (adaptive vsync), + * or SDL_WINDOW_SURFACE_VSYNC_DISABLED to disable. Not every value is + * supported by every driver, so you should check the return value to see + * whether the requested setting is supported. + * + * \param renderer the renderer to toggle. + * \param vsync the vertical refresh sync interval. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRenderVSync */ -extern DECLSPEC int SDLCALL SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync); +extern SDL_DECLSPEC bool SDLCALL SDL_SetRenderVSync(SDL_Renderer *renderer, int vsync); + +#define SDL_RENDERER_VSYNC_DISABLED 0 +#define SDL_RENDERER_VSYNC_ADAPTIVE (-1) /** * Get VSync of the given renderer. * - * \param renderer The renderer to toggle - * \param vsync an int filled with 1 for on, 0 for off. All other values are - * reserved - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param renderer the renderer to toggle. + * \param vsync an int filled with the current vertical refresh sync interval. + * See SDL_SetRenderVSync() for the meaning of the value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety You may only call this function from the main thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetRenderVSync */ -extern DECLSPEC int SDLCALL SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync); +extern SDL_DECLSPEC bool SDLCALL SDL_GetRenderVSync(SDL_Renderer *renderer, int *vsync); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_revision.h b/libs/SDL3/include/SDL3/SDL_revision.h index badf017d1..f78e5d9d0 100644 --- a/libs/SDL3/include/SDL3/SDL_revision.h +++ b/libs/SDL3/include/SDL3/SDL_revision.h @@ -19,16 +19,35 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** - * \file SDL_revision.h - * - * Header file containing the SDL revision +/* WIKI CATEGORY: Version */ + +/* + * SDL_revision.h contains the SDL revision, which might be defined on the + * compiler command line, or generated right into the header itself by the + * build system. */ #ifndef SDL_revision_h_ #define SDL_revision_h_ -#ifdef SDL_VENDOR_INFO +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + +/** + * This macro is a string describing the source at a particular point in + * development. + * + * This string is often generated from revision control's state at build time. + * + * This string can be quite complex and does not follow any standard. For + * example, it might be something like "SDL-prerelease-3.1.1-47-gf687e0732". + * It might also be user-defined at build time, so it's best to treat it as a + * clue in debugging forensics and not something the app will parse in any + * way. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_REVISION "Some arbitrary string decided at SDL build time" +#elif defined(SDL_VENDOR_INFO) #define SDL_REVISION SDL_VENDOR_INFO #else #define SDL_REVISION "" diff --git a/libs/SDL3/include/SDL3/SDL_scancode.h b/libs/SDL3/include/SDL3/SDL_scancode.h index 336d6f0ba..16fb2a828 100644 --- a/libs/SDL3/include/SDL3/SDL_scancode.h +++ b/libs/SDL3/include/SDL3/SDL_scancode.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_scancode.h + * # CategoryScancode * - * Defines keyboard scancodes. + * Defines keyboard scancodes. */ #ifndef SDL_scancode_h_ @@ -31,19 +31,20 @@ #include /** - * The SDL keyboard scancode representation. + * The SDL keyboard scancode representation. * - * An SDL scancode is the physical representation of a key on the keyboard, - * independent of language and keyboard mapping. + * An SDL scancode is the physical representation of a key on the keyboard, + * independent of language and keyboard mapping. * - * Values of this type are used to represent keyboard keys, among other places - * in the \link SDL_Keysym::scancode key.keysym.scancode \endlink field of the - * SDL_Event structure. + * Values of this type are used to represent keyboard keys, among other places + * in the `scancode` field of the SDL_KeyboardEvent structure. * - * The values in this enumeration are based on the USB usage page standard: - * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf + * The values in this enumeration are based on the USB usage page standard: + * https://usb.org/sites/default/files/hut1_5.pdf + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_Scancode { SDL_SCANCODE_UNKNOWN = 0, @@ -348,7 +349,6 @@ typedef enum * \name Usage page 0x0C * * These values are mapped from usage page 0x0C (USB consumer page). - * See https://usb.org/sites/default/files/hut1_2.pdf * * There are way more keys in the spec than we can represent in the * current scancode range, so pick the ones that commonly come up in @@ -356,59 +356,42 @@ typedef enum */ /* @{ */ - SDL_SCANCODE_AUDIONEXT = 258, - SDL_SCANCODE_AUDIOPREV = 259, - SDL_SCANCODE_AUDIOSTOP = 260, - SDL_SCANCODE_AUDIOPLAY = 261, - SDL_SCANCODE_AUDIOMUTE = 262, - SDL_SCANCODE_MEDIASELECT = 263, - SDL_SCANCODE_WWW = 264, /**< AL Internet Browser */ - SDL_SCANCODE_MAIL = 265, - SDL_SCANCODE_CALCULATOR = 266, /**< AL Calculator */ - SDL_SCANCODE_COMPUTER = 267, - SDL_SCANCODE_AC_SEARCH = 268, /**< AC Search */ - SDL_SCANCODE_AC_HOME = 269, /**< AC Home */ - SDL_SCANCODE_AC_BACK = 270, /**< AC Back */ - SDL_SCANCODE_AC_FORWARD = 271, /**< AC Forward */ - SDL_SCANCODE_AC_STOP = 272, /**< AC Stop */ - SDL_SCANCODE_AC_REFRESH = 273, /**< AC Refresh */ - SDL_SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */ + SDL_SCANCODE_SLEEP = 258, /**< Sleep */ + SDL_SCANCODE_WAKE = 259, /**< Wake */ + + SDL_SCANCODE_CHANNEL_INCREMENT = 260, /**< Channel Increment */ + SDL_SCANCODE_CHANNEL_DECREMENT = 261, /**< Channel Decrement */ + + SDL_SCANCODE_MEDIA_PLAY = 262, /**< Play */ + SDL_SCANCODE_MEDIA_PAUSE = 263, /**< Pause */ + SDL_SCANCODE_MEDIA_RECORD = 264, /**< Record */ + SDL_SCANCODE_MEDIA_FAST_FORWARD = 265, /**< Fast Forward */ + SDL_SCANCODE_MEDIA_REWIND = 266, /**< Rewind */ + SDL_SCANCODE_MEDIA_NEXT_TRACK = 267, /**< Next Track */ + SDL_SCANCODE_MEDIA_PREVIOUS_TRACK = 268, /**< Previous Track */ + SDL_SCANCODE_MEDIA_STOP = 269, /**< Stop */ + SDL_SCANCODE_MEDIA_EJECT = 270, /**< Eject */ + SDL_SCANCODE_MEDIA_PLAY_PAUSE = 271, /**< Play / Pause */ + SDL_SCANCODE_MEDIA_SELECT = 272, /* Media Select */ + + SDL_SCANCODE_AC_NEW = 273, /**< AC New */ + SDL_SCANCODE_AC_OPEN = 274, /**< AC Open */ + SDL_SCANCODE_AC_CLOSE = 275, /**< AC Close */ + SDL_SCANCODE_AC_EXIT = 276, /**< AC Exit */ + SDL_SCANCODE_AC_SAVE = 277, /**< AC Save */ + SDL_SCANCODE_AC_PRINT = 278, /**< AC Print */ + SDL_SCANCODE_AC_PROPERTIES = 279, /**< AC Properties */ + + SDL_SCANCODE_AC_SEARCH = 280, /**< AC Search */ + SDL_SCANCODE_AC_HOME = 281, /**< AC Home */ + SDL_SCANCODE_AC_BACK = 282, /**< AC Back */ + SDL_SCANCODE_AC_FORWARD = 283, /**< AC Forward */ + SDL_SCANCODE_AC_STOP = 284, /**< AC Stop */ + SDL_SCANCODE_AC_REFRESH = 285, /**< AC Refresh */ + SDL_SCANCODE_AC_BOOKMARKS = 286, /**< AC Bookmarks */ /* @} *//* Usage page 0x0C */ - /** - * \name Walther keys - * - * These are values that Christian Walther added (for mac keyboard?). - */ - /* @{ */ - - SDL_SCANCODE_BRIGHTNESSDOWN = 275, - SDL_SCANCODE_BRIGHTNESSUP = 276, - SDL_SCANCODE_DISPLAYSWITCH = 277, /**< display mirroring/dual display - switch, video mode switch */ - SDL_SCANCODE_KBDILLUMTOGGLE = 278, - SDL_SCANCODE_KBDILLUMDOWN = 279, - SDL_SCANCODE_KBDILLUMUP = 280, - SDL_SCANCODE_EJECT = 281, - SDL_SCANCODE_SLEEP = 282, /**< SC System Sleep */ - - SDL_SCANCODE_APP1 = 283, - SDL_SCANCODE_APP2 = 284, - - /* @} *//* Walther keys */ - - /** - * \name Usage page 0x0C (additional media keys) - * - * These values are mapped from usage page 0x0C (USB consumer page). - */ - /* @{ */ - - SDL_SCANCODE_AUDIOREWIND = 285, - SDL_SCANCODE_AUDIOFASTFORWARD = 286, - - /* @} *//* Usage page 0x0C (additional media keys) */ /** * \name Mobile keys @@ -432,8 +415,10 @@ typedef enum /* Add any other keys here. */ - SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes - for array bounds */ + SDL_SCANCODE_RESERVED = 400, /**< 400-500 reserved for dynamic keycodes */ + + SDL_SCANCODE_COUNT = 512 /**< not a key, just marks the number of scancodes for array bounds */ + } SDL_Scancode; #endif /* SDL_scancode_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_sensor.h b/libs/SDL3/include/SDL3/SDL_sensor.h index 6db5beb38..2ad2fc029 100644 --- a/libs/SDL3/include/SDL3/SDL_sensor.h +++ b/libs/SDL3/include/SDL3/SDL_sensor.h @@ -20,9 +20,13 @@ */ /** - * \file SDL_sensor.h + * # CategorySensor * - * Include file for SDL sensor event handling + * SDL sensor management. + * + * In order to use these functions, SDL_Init() must have been called with the + * SDL_INIT_SENSOR flag. This causes SDL to scan the system for sensors, and + * load appropriate drivers. */ #ifndef SDL_sensor_h_ @@ -40,234 +44,249 @@ extern "C" { /* *INDENT-ON* */ #endif -/** - * SDL_sensor.h - * - * In order to use these functions, SDL_Init() must have been called - * with the ::SDL_INIT_SENSOR flag. This causes SDL to scan the system - * for sensors, and load appropriate drivers. - */ - -struct SDL_Sensor; typedef struct SDL_Sensor SDL_Sensor; /** - * This is a unique ID for a sensor for the time it is connected to the system, - * and is never reused for the lifetime of the application. + * This is a unique ID for a sensor for the time it is connected to the + * system, and is never reused for the lifetime of the application. + * + * The value 0 is an invalid ID. * - * The ID value starts at 1 and increments from there. The value 0 is an invalid ID. + * \since This datatype is available since SDL 3.0.0. */ typedef Uint32 SDL_SensorID; -/* The different sensors defined by SDL +/** + * A constant to represent standard gravity for accelerometer sensors. * - * Additional sensors may be available, using platform dependent semantics. + * The accelerometer returns the current acceleration in SI meters per second + * squared. This measurement includes the force of gravity, so a device at + * rest will have an value of SDL_STANDARD_GRAVITY away from the center of the + * earth, which is a positive Y value. * - * Hare are the additional Android sensors: - * https://developer.android.com/reference/android/hardware/SensorEvent.html#values + * \since This macro is available since SDL 3.0.0. */ -typedef enum -{ - SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */ - SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */ - SDL_SENSOR_ACCEL, /**< Accelerometer */ - SDL_SENSOR_GYRO, /**< Gyroscope */ - SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */ - SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */ - SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */ - SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */ -} SDL_SensorType; +#define SDL_STANDARD_GRAVITY 9.80665f /** - * Accelerometer sensor + * The different sensors defined by SDL. * - * The accelerometer returns the current acceleration in SI meters per - * second squared. This measurement includes the force of gravity, so - * a device at rest will have an value of SDL_STANDARD_GRAVITY away - * from the center of the earth, which is a positive Y value. + * Additional sensors may be available, using platform dependent semantics. * - * values[0]: Acceleration on the x axis - * values[1]: Acceleration on the y axis - * values[2]: Acceleration on the z axis + * Here are the additional Android sensors: * - * For phones and tablets held in natural orientation and game controllers held in front of you, the axes are defined as follows: - * -X ... +X : left ... right - * -Y ... +Y : bottom ... top - * -Z ... +Z : farther ... closer + * https://developer.android.com/reference/android/hardware/SensorEvent.html#values * - * The axis data is not changed when the device is rotated. + * Accelerometer sensor notes: * - * \sa SDL_GetCurrentDisplayOrientation() - */ -#define SDL_STANDARD_GRAVITY 9.80665f - -/** - * Gyroscope sensor + * The accelerometer returns the current acceleration in SI meters per second + * squared. This measurement includes the force of gravity, so a device at + * rest will have an value of SDL_STANDARD_GRAVITY away from the center of the + * earth, which is a positive Y value. + * + * - `values[0]`: Acceleration on the x axis + * - `values[1]`: Acceleration on the y axis + * - `values[2]`: Acceleration on the z axis + * + * For phones and tablets held in natural orientation and game controllers + * held in front of you, the axes are defined as follows: + * + * - -X ... +X : left ... right + * - -Y ... +Y : bottom ... top + * - -Z ... +Z : farther ... closer + * + * The accelerometer axis data is not changed when the device is rotated. + * + * Gyroscope sensor notes: * * The gyroscope returns the current rate of rotation in radians per second. - * The rotation is positive in the counter-clockwise direction. That is, - * an observer looking from a positive location on one of the axes would - * see positive rotation on that axis when it appeared to be rotating + * The rotation is positive in the counter-clockwise direction. That is, an + * observer looking from a positive location on one of the axes would see + * positive rotation on that axis when it appeared to be rotating * counter-clockwise. * - * values[0]: Angular speed around the x axis (pitch) - * values[1]: Angular speed around the y axis (yaw) - * values[2]: Angular speed around the z axis (roll) + * - `values[0]`: Angular speed around the x axis (pitch) + * - `values[1]`: Angular speed around the y axis (yaw) + * - `values[2]`: Angular speed around the z axis (roll) + * + * For phones and tablets held in natural orientation and game controllers + * held in front of you, the axes are defined as follows: * - * For phones and tablets held in natural orientation and game controllers held in front of you, the axes are defined as follows: - * -X ... +X : left ... right - * -Y ... +Y : bottom ... top - * -Z ... +Z : farther ... closer + * - -X ... +X : left ... right + * - -Y ... +Y : bottom ... top + * - -Z ... +Z : farther ... closer * - * The axis data is not changed when the device is rotated. + * The gyroscope axis data is not changed when the device is rotated. * - * \sa SDL_GetCurrentDisplayOrientation() + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_GetCurrentDisplayOrientation */ +typedef enum SDL_SensorType +{ + SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */ + SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */ + SDL_SENSOR_ACCEL, /**< Accelerometer */ + SDL_SENSOR_GYRO, /**< Gyroscope */ + SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */ + SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */ + SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */ + SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */ +} SDL_SensorType; + /* Function prototypes */ /** * Get a list of currently connected sensors. * - * \param count a pointer filled in with the number of sensors returned - * \returns a 0 terminated array of sensor instance IDs which should be freed - * with SDL_free(), or NULL on error; call SDL_GetError() for more - * details. + * \param count a pointer filled in with the number of sensors returned, may + * be NULL. + * \returns a 0 terminated array of sensor instance IDs or NULL on failure; + * call SDL_GetError() for more information. This should be freed + * with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_SensorID *SDLCALL SDL_GetSensors(int *count); +extern SDL_DECLSPEC SDL_SensorID * SDLCALL SDL_GetSensors(int *count); /** * Get the implementation dependent name of a sensor. * - * \param instance_id the sensor instance ID - * \returns the sensor name, or NULL if `instance_id` is not valid + * This can be called before any sensors are opened. + * + * \param instance_id the sensor instance ID. + * \returns the sensor name, or NULL if `instance_id` is not valid. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char *SDLCALL SDL_GetSensorInstanceName(SDL_SensorID instance_id); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetSensorNameForID(SDL_SensorID instance_id); /** * Get the type of a sensor. * - * \param instance_id the sensor instance ID + * This can be called before any sensors are opened. + * + * \param instance_id the sensor instance ID. * \returns the SDL_SensorType, or `SDL_SENSOR_INVALID` if `instance_id` is - * not valid + * not valid. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorInstanceType(SDL_SensorID instance_id); +extern SDL_DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorTypeForID(SDL_SensorID instance_id); /** * Get the platform dependent type of a sensor. * - * \param instance_id the sensor instance ID + * This can be called before any sensors are opened. + * + * \param instance_id the sensor instance ID. * \returns the sensor platform dependent type, or -1 if `instance_id` is not - * valid + * valid. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetSensorInstanceNonPortableType(SDL_SensorID instance_id); +extern SDL_DECLSPEC int SDLCALL SDL_GetSensorNonPortableTypeForID(SDL_SensorID instance_id); /** * Open a sensor for use. * - * \param instance_id the sensor instance ID - * \returns an SDL_Sensor sensor object, or NULL if an error occurred. + * \param instance_id the sensor instance ID. + * \returns an SDL_Sensor object or NULL on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Sensor *SDLCALL SDL_OpenSensor(SDL_SensorID instance_id); +extern SDL_DECLSPEC SDL_Sensor * SDLCALL SDL_OpenSensor(SDL_SensorID instance_id); /** * Return the SDL_Sensor associated with an instance ID. * - * \param instance_id the sensor instance ID - * \returns an SDL_Sensor object. + * \param instance_id the sensor instance ID. + * \returns an SDL_Sensor object or NULL on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Sensor *SDLCALL SDL_GetSensorFromInstanceID(SDL_SensorID instance_id); +extern SDL_DECLSPEC SDL_Sensor * SDLCALL SDL_GetSensorFromID(SDL_SensorID instance_id); /** * Get the properties associated with a sensor. * - * \param sensor The SDL_Sensor object + * \param sensor the SDL_Sensor object. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSensorProperties(SDL_Sensor *sensor); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSensorProperties(SDL_Sensor *sensor); /** - * Get the implementation dependent name of a sensor + * Get the implementation dependent name of a sensor. * - * \param sensor The SDL_Sensor object - * \returns the sensor name, or NULL if `sensor` is NULL. + * \param sensor the SDL_Sensor object. + * \returns the sensor name or NULL on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char *SDLCALL SDL_GetSensorName(SDL_Sensor *sensor); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetSensorName(SDL_Sensor *sensor); /** * Get the type of a sensor. * - * \param sensor The SDL_Sensor object to inspect + * \param sensor the SDL_Sensor object to inspect. * \returns the SDL_SensorType type, or `SDL_SENSOR_INVALID` if `sensor` is * NULL. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorType(SDL_Sensor *sensor); +extern SDL_DECLSPEC SDL_SensorType SDLCALL SDL_GetSensorType(SDL_Sensor *sensor); /** * Get the platform dependent type of a sensor. * - * \param sensor The SDL_Sensor object to inspect + * \param sensor the SDL_Sensor object to inspect. * \returns the sensor platform dependent type, or -1 if `sensor` is NULL. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetSensorNonPortableType(SDL_Sensor *sensor); +extern SDL_DECLSPEC int SDLCALL SDL_GetSensorNonPortableType(SDL_Sensor *sensor); /** * Get the instance ID of a sensor. * - * \param sensor The SDL_Sensor object to inspect - * \returns the sensor instance ID, or 0 if `sensor` is NULL. + * \param sensor the SDL_Sensor object to inspect. + * \returns the sensor instance ID, or 0 on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_SensorID SDLCALL SDL_GetSensorInstanceID(SDL_Sensor *sensor); +extern SDL_DECLSPEC SDL_SensorID SDLCALL SDL_GetSensorID(SDL_Sensor *sensor); /** * Get the current state of an opened sensor. * * The number of values and interpretation of the data is sensor dependent. * - * \param sensor The SDL_Sensor object to query - * \param data A pointer filled with the current sensor state - * \param num_values The number of values to write to data - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param sensor the SDL_Sensor object to query. + * \param data a pointer filled with the current sensor state. + * \param num_values the number of values to write to data. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetSensorData(SDL_Sensor *sensor, float *data, int num_values); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSensorData(SDL_Sensor *sensor, float *data, int num_values); /** * Close a sensor previously opened with SDL_OpenSensor(). * - * \param sensor The SDL_Sensor object to close + * \param sensor the SDL_Sensor object to close. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_CloseSensor(SDL_Sensor *sensor); +extern SDL_DECLSPEC void SDLCALL SDL_CloseSensor(SDL_Sensor *sensor); /** * Update the current state of the open sensors. @@ -280,7 +299,7 @@ extern DECLSPEC void SDLCALL SDL_CloseSensor(SDL_Sensor *sensor); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_UpdateSensors(void); +extern SDL_DECLSPEC void SDLCALL SDL_UpdateSensors(void); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_stdinc.h b/libs/SDL3/include/SDL3/SDL_stdinc.h index e6a387c31..c484c3712 100644 --- a/libs/SDL3/include/SDL3/SDL_stdinc.h +++ b/libs/SDL3/include/SDL3/SDL_stdinc.h @@ -20,9 +20,13 @@ */ /** - * \file SDL_stdinc.h + * # CategoryStdinc * - * This is a general header that includes C language support. + * This is a general header that includes C language support. It implements a + * subset of the C runtime APIs, but with an `SDL_` prefix. For most common + * use cases, these should behave the same way as their C runtime equivalents, + * but they may differ in how or whether they handle certain edge cases. When + * in doubt, consult the documentation for details. */ #ifndef SDL_stdinc_h_ @@ -30,14 +34,29 @@ #include -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#endif #include #include #include #include +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + defined(SDL_INCLUDE_INTTYPES_H) +#include +#endif + +#ifndef __cplusplus +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1910 /* Visual Studio 2017 */)) || \ + defined(SDL_INCLUDE_STDBOOL_H) +#include +#elif !defined(__bool_true_false_are_defined) && !defined(bool) +#define bool unsigned char +#define false 0 +#define true 1 +#define __bool_true_false_are_defined 1 +#endif +#endif /* !__cplusplus */ + #ifndef SDL_DISABLE_ALLOCA # ifndef alloca # ifdef HAVE_ALLOCA_H @@ -64,7 +83,7 @@ # elif defined(__MRC__) void *alloca(unsigned); # else -char *alloca(); +void *alloca(size_t); # endif # endif #endif @@ -75,6 +94,25 @@ char *alloca(); # define SDL_SIZE_MAX ((size_t) -1) #endif +#ifndef SDL_COMPILE_TIME_ASSERT +#if defined(__cplusplus) +/* Keep C++ case alone: Some versions of gcc will define __STDC_VERSION__ even when compiling in C++ mode. */ +#if (__cplusplus >= 201103L) +#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x) +#endif +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202311L) +#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x) +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x) +#endif +#endif /* !SDL_COMPILE_TIME_ASSERT */ + +#ifndef SDL_COMPILE_TIME_ASSERT +/* universal, but may trigger -Wunused-local-typedefs */ +#define SDL_COMPILE_TIME_ASSERT(name, x) \ + typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1] +#endif + /** * Check if the compiler supports a given builtin. * Supported by virtually all clang versions and recent gcc. Use this @@ -87,15 +125,26 @@ char *alloca(); #endif /** - * The number of elements in an array. + * The number of elements in an array. + * + * This macro looks like it double-evaluates the argument, but it does so + * inside of `sizeof`, so there are no side-effects here, as expressions do + * not actually run any code in these cases. + * + * \since This macro is available since SDL 3.0.0. */ -#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) -#define SDL_TABLESIZE(table) SDL_arraysize(table) +#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0])) /** - * Macro useful for building other macros with strings in them + * Macro useful for building other macros with strings in them. + * + * For example: * - * e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n") + * ```c + * #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")` + * ``` + * + * \since This macro is available since SDL 3.0.0. */ #define SDL_STRINGIFY_ARG(arg) #arg @@ -106,7 +155,76 @@ char *alloca(); * -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above). */ /* @{ */ -#ifdef __cplusplus + +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + +/** + * Handle a Reinterpret Cast properly whether using C or C++. + * + * If compiled as C++, this macro offers a proper C++ reinterpret_cast<>. + * + * If compiled as C, this macro does a normal C-style cast. + * + * This is helpful to avoid compiler warnings in C++. + * + * \param type the type to cast the expression to. + * \param expression the expression to cast to a different type. + * \returns `expression`, cast to `type`. + * + * \threadsafety It is safe to call this macro from any thread. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_static_cast + * \sa SDL_const_cast + */ +#define SDL_reinterpret_cast(type, expression) reinterpret_cast(expression) /* or `((type)(expression))` in C */ + +/** + * Handle a Static Cast properly whether using C or C++. + * + * If compiled as C++, this macro offers a proper C++ static_cast<>. + * + * If compiled as C, this macro does a normal C-style cast. + * + * This is helpful to avoid compiler warnings in C++. + * + * \param type the type to cast the expression to. + * \param expression the expression to cast to a different type. + * \returns `expression`, cast to `type`. + * + * \threadsafety It is safe to call this macro from any thread. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_reinterpret_cast + * \sa SDL_const_cast + */ +#define SDL_static_cast(type, expression) static_cast(expression) /* or `((type)(expression))` in C */ + +/** + * Handle a Const Cast properly whether using C or C++. + * + * If compiled as C++, this macro offers a proper C++ const_cast<>. + * + * If compiled as C, this macro does a normal C-style cast. + * + * This is helpful to avoid compiler warnings in C++. + * + * \param type the type to cast the expression to. + * \param expression the expression to cast to a different type. + * \returns `expression`, cast to `type`. + * + * \threadsafety It is safe to call this macro from any thread. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_reinterpret_cast + * \sa SDL_static_cast + */ +#define SDL_const_cast(type, expression) const_cast(expression) /* or `((type)(expression))` in C */ + +#elif defined(__cplusplus) #define SDL_reinterpret_cast(type, expression) reinterpret_cast(expression) #define SDL_static_cast(type, expression) static_cast(expression) #define SDL_const_cast(type, expression) const_cast(expression) @@ -115,86 +233,168 @@ char *alloca(); #define SDL_static_cast(type, expression) ((type)(expression)) #define SDL_const_cast(type, expression) ((type)(expression)) #endif + /* @} *//* Cast operators */ -/* Define a four character code as a Uint32 */ +/** + * Define a four character code as a Uint32. + * + * \param A the first ASCII character. + * \param B the second ASCII character. + * \param C the third ASCII character. + * \param D the fourth ASCII character. + * \returns the four characters converted into a Uint32, one character + * per-byte. + * + * \threadsafety It is safe to call this macro from any thread. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_FOURCC(A, B, C, D) \ ((SDL_static_cast(Uint32, SDL_static_cast(Uint8, (A))) << 0) | \ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (B))) << 8) | \ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (C))) << 16) | \ (SDL_static_cast(Uint32, SDL_static_cast(Uint8, (D))) << 24)) +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + /** - * \name Basic data types + * Append the 64 bit integer suffix to a signed integer literal. + * + * This helps compilers that might believe a integer literal larger than + * 0xFFFFFFFF is overflowing a 32-bit value. Use `SDL_SINT64_C(0xFFFFFFFF1)` + * instead of `0xFFFFFFFF1` by itself. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_UINT64_C */ -/* @{ */ +#define SDL_SINT64_C(c) c ## LL /* or whatever the current compiler uses. */ + +/** + * Append the 64 bit integer suffix to an unsigned integer literal. + * + * This helps compilers that might believe a integer literal larger than + * 0xFFFFFFFF is overflowing a 32-bit value. Use `SDL_UINT64_C(0xFFFFFFFF1)` + * instead of `0xFFFFFFFF1` by itself. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_SINT64_C + */ +#define SDL_UINT64_C(c) c ## ULL /* or whatever the current compiler uses. */ + +#elif defined(INT64_C) +#define SDL_SINT64_C(c) INT64_C(c) +#define SDL_UINT64_C(c) UINT64_C(c) +#elif defined(_MSC_VER) +#define SDL_SINT64_C(c) c ## i64 +#define SDL_UINT64_C(c) c ## ui64 +#elif defined(__LP64__) || defined(_LP64) +#define SDL_SINT64_C(c) c ## L +#define SDL_UINT64_C(c) c ## UL +#else +#define SDL_SINT64_C(c) c ## LL +#define SDL_UINT64_C(c) c ## ULL +#endif /** - * A boolean type. + * \name Basic data types */ -#define SDL_FALSE 0 -#define SDL_TRUE 1 -typedef int SDL_bool; +/* @{ */ /** * A signed 8-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef int8_t Sint8; #define SDL_MAX_SINT8 ((Sint8)0x7F) /* 127 */ #define SDL_MIN_SINT8 ((Sint8)(~0x7F)) /* -128 */ -typedef int8_t Sint8; + /** * An unsigned 8-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef uint8_t Uint8; #define SDL_MAX_UINT8 ((Uint8)0xFF) /* 255 */ #define SDL_MIN_UINT8 ((Uint8)0x00) /* 0 */ -typedef uint8_t Uint8; + /** * A signed 16-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef int16_t Sint16; #define SDL_MAX_SINT16 ((Sint16)0x7FFF) /* 32767 */ #define SDL_MIN_SINT16 ((Sint16)(~0x7FFF)) /* -32768 */ -typedef int16_t Sint16; + /** * An unsigned 16-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef uint16_t Uint16; #define SDL_MAX_UINT16 ((Uint16)0xFFFF) /* 65535 */ #define SDL_MIN_UINT16 ((Uint16)0x0000) /* 0 */ -typedef uint16_t Uint16; + /** * A signed 32-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef int32_t Sint32; #define SDL_MAX_SINT32 ((Sint32)0x7FFFFFFF) /* 2147483647 */ #define SDL_MIN_SINT32 ((Sint32)(~0x7FFFFFFF)) /* -2147483648 */ -typedef int32_t Sint32; + /** * An unsigned 32-bit integer type. + * + * \since This macro is available since SDL 3.0.0. */ +typedef uint32_t Uint32; #define SDL_MAX_UINT32 ((Uint32)0xFFFFFFFFu) /* 4294967295 */ #define SDL_MIN_UINT32 ((Uint32)0x00000000) /* 0 */ -typedef uint32_t Uint32; /** * A signed 64-bit integer type. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_SINT64_C */ -#define SDL_MAX_SINT64 ((Sint64)0x7FFFFFFFFFFFFFFFll) /* 9223372036854775807 */ -#define SDL_MIN_SINT64 ((Sint64)(~0x7FFFFFFFFFFFFFFFll)) /* -9223372036854775808 */ typedef int64_t Sint64; +#define SDL_MAX_SINT64 SDL_SINT64_C(0x7FFFFFFFFFFFFFFF) /* 9223372036854775807 */ +#define SDL_MIN_SINT64 ~SDL_SINT64_C(0x7FFFFFFFFFFFFFFF) /* -9223372036854775808 */ + /** * An unsigned 64-bit integer type. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_UINT64_C */ -#define SDL_MAX_UINT64 ((Uint64)0xFFFFFFFFFFFFFFFFull) /* 18446744073709551615 */ -#define SDL_MIN_UINT64 ((Uint64)(0x0000000000000000ull)) /* 0 */ typedef uint64_t Uint64; +#define SDL_MAX_UINT64 SDL_UINT64_C(0xFFFFFFFFFFFFFFFF) /* 18446744073709551615 */ +#define SDL_MIN_UINT64 SDL_UINT64_C(0x0000000000000000) /* 0 */ /** - * SDL times are signed, 64-bit integers representing nanoseconds since the Unix epoch (Jan 1, 1970) + * SDL times are signed, 64-bit integers representing nanoseconds since the + * Unix epoch (Jan 1, 1970). + * + * They can be converted between POSIX time_t values with SDL_NS_TO_SECONDS() + * and SDL_SECONDS_TO_NS(), and between Windows FILETIME values with + * SDL_TimeToWindows() and SDL_TimeFromWindows(). * - * They can be converted between POSIX time_t values with SDL_NS_TO_SECONDS() and SDL_SECONDS_TO_NS(), - * and between Windows FILETIME values with SDL_TimeToWindows() and SDL_TimeFromWindows(). + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_MAX_SINT64 + * \sa SDL_MIN_SINT64 */ +typedef Sint64 SDL_Time; #define SDL_MAX_TIME SDL_MAX_SINT64 #define SDL_MIN_TIME SDL_MIN_SINT64 -typedef Sint64 SDL_Time; /* @} *//* Basic data types */ @@ -206,19 +406,28 @@ typedef Sint64 SDL_Time; #ifdef FLT_EPSILON #define SDL_FLT_EPSILON FLT_EPSILON #else + +/** + * Epsilon constant, used for comparing floating-point numbers. + * + * Equals by default to platform-defined `FLT_EPSILON`, or + * `1.1920928955078125e-07F` if that's not available. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_FLT_EPSILON 1.1920928955078125e-07F /* 0x0.000002p0 */ #endif /* @} *//* Floating-point constants */ /* Make sure we have macros for printing width-based integers. - * should define these but this is not true all platforms. + * should define these but this is not true all platforms. * (for example win32) */ #ifndef SDL_PRIs64 -#ifdef PRIs64 -#define SDL_PRIs64 PRIs64 -#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #define SDL_PRIs64 "I64d" +#elif defined(PRIs64) +#define SDL_PRIs64 PRIs64 #elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIs64 "ld" #else @@ -226,10 +435,10 @@ typedef Sint64 SDL_Time; #endif #endif #ifndef SDL_PRIu64 -#ifdef PRIu64 -#define SDL_PRIu64 PRIu64 -#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #define SDL_PRIu64 "I64u" +#elif defined(PRIu64) +#define SDL_PRIu64 PRIu64 #elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIu64 "lu" #else @@ -237,10 +446,10 @@ typedef Sint64 SDL_Time; #endif #endif #ifndef SDL_PRIx64 -#ifdef PRIx64 -#define SDL_PRIx64 PRIx64 -#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #define SDL_PRIx64 "I64x" +#elif defined(PRIx64) +#define SDL_PRIx64 PRIx64 #elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIx64 "lx" #else @@ -248,10 +457,10 @@ typedef Sint64 SDL_Time; #endif #endif #ifndef SDL_PRIX64 -#ifdef PRIX64 -#define SDL_PRIX64 PRIX64 -#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #define SDL_PRIX64 "I64X" +#elif defined(PRIX64) +#define SDL_PRIX64 PRIX64 #elif defined(__LP64__) && !defined(SDL_PLATFORM_APPLE) #define SDL_PRIX64 "lX" #else @@ -286,6 +495,25 @@ typedef Sint64 SDL_Time; #define SDL_PRIX32 "X" #endif #endif +/* Specifically for the `long long` -- SDL-specific. */ +#ifdef SDL_PLATFORM_WINDOWS +SDL_COMPILE_TIME_ASSERT(longlong_size64, sizeof(long long) == 8); /* using I64 for windows - make sure `long long` is 64 bits. */ +#define SDL_PRILL_PREFIX "I64" +#else +#define SDL_PRILL_PREFIX "ll" +#endif +#ifndef SDL_PRILLd +#define SDL_PRILLd SDL_PRILL_PREFIX "d" +#endif +#ifndef SDL_PRILLu +#define SDL_PRILLu SDL_PRILL_PREFIX "u" +#endif +#ifndef SDL_PRILLx +#define SDL_PRILLx SDL_PRILL_PREFIX "x" +#endif +#ifndef SDL_PRILLX +#define SDL_PRILLX SDL_PRILL_PREFIX "X" +#endif /* Annotations to help code analysis tools */ #ifdef SDL_DISABLE_ANALYZE_MACROS @@ -302,7 +530,7 @@ typedef Sint64 SDL_Time; #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) #define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) +#define SDL_WPRINTF_VARARG_FUNCV( fmtargnumber ) #else #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ #include @@ -332,43 +560,37 @@ typedef Sint64 SDL_Time; #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) __attribute__ (( format( __scanf__, fmtargnumber, fmtargnumber+1 ))) #define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) __attribute__(( format( __scanf__, fmtargnumber, 0 ))) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) /* __attribute__ (( format( __wprintf__, fmtargnumber, fmtargnumber+1 ))) */ -#define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) /* __attribute__ (( format( __wscanf__, fmtargnumber, fmtargnumber+1 ))) */ +#define SDL_WPRINTF_VARARG_FUNCV( fmtargnumber ) /* __attribute__ (( format( __wprintf__, fmtargnumber, 0 ))) */ #else #define SDL_PRINTF_VARARG_FUNC( fmtargnumber ) #define SDL_PRINTF_VARARG_FUNCV( fmtargnumber ) #define SDL_SCANF_VARARG_FUNC( fmtargnumber ) #define SDL_SCANF_VARARG_FUNCV( fmtargnumber ) #define SDL_WPRINTF_VARARG_FUNC( fmtargnumber ) -#define SDL_WSCANF_VARARG_FUNC( fmtargnumber ) +#define SDL_WPRINTF_VARARG_FUNCV( fmtargnumber ) #endif #endif /* SDL_DISABLE_ANALYZE_MACROS */ -#ifndef SDL_COMPILE_TIME_ASSERT -#ifdef __cplusplus -#if (__cplusplus >= 201103L) -#define SDL_COMPILE_TIME_ASSERT(name, x) static_assert(x, #x) -#endif -#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -#define SDL_COMPILE_TIME_ASSERT(name, x) _Static_assert(x, #x) -#endif -#endif /* !SDL_COMPILE_TIME_ASSERT */ - -#ifndef SDL_COMPILE_TIME_ASSERT -/* universal, but may trigger -Wunused-local-typedefs */ -#define SDL_COMPILE_TIME_ASSERT(name, x) \ - typedef int SDL_compile_time_assert_ ## name[(x) * 2 - 1] -#endif - /** \cond */ #ifndef DOXYGEN_SHOULD_IGNORE_THIS -SDL_COMPILE_TIME_ASSERT(uint8, sizeof(Uint8) == 1); -SDL_COMPILE_TIME_ASSERT(sint8, sizeof(Sint8) == 1); -SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); -SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); -SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); -SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); -SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8); -SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); +SDL_COMPILE_TIME_ASSERT(bool_size, sizeof(bool) == 1); +SDL_COMPILE_TIME_ASSERT(uint8_size, sizeof(Uint8) == 1); +SDL_COMPILE_TIME_ASSERT(sint8_size, sizeof(Sint8) == 1); +SDL_COMPILE_TIME_ASSERT(uint16_size, sizeof(Uint16) == 2); +SDL_COMPILE_TIME_ASSERT(sint16_size, sizeof(Sint16) == 2); +SDL_COMPILE_TIME_ASSERT(uint32_size, sizeof(Uint32) == 4); +SDL_COMPILE_TIME_ASSERT(sint32_size, sizeof(Sint32) == 4); +SDL_COMPILE_TIME_ASSERT(uint64_size, sizeof(Uint64) == 8); +SDL_COMPILE_TIME_ASSERT(sint64_size, sizeof(Sint64) == 8); +SDL_COMPILE_TIME_ASSERT(uint64_longlong, sizeof(Uint64) <= sizeof(unsigned long long)); +SDL_COMPILE_TIME_ASSERT(size_t_longlong, sizeof(size_t) <= sizeof(unsigned long long)); +typedef struct SDL_alignment_test +{ + Uint8 a; + void *b; +} SDL_alignment_test; +SDL_COMPILE_TIME_ASSERT(struct_alignment, sizeof(SDL_alignment_test) == (2 * sizeof(void *))); +SDL_COMPILE_TIME_ASSERT(two_s_complement, (int)~(int)0 == (int)(-1)); #endif /* DOXYGEN_SHOULD_IGNORE_THIS */ /** \endcond */ @@ -382,7 +604,7 @@ SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); #ifndef DOXYGEN_SHOULD_IGNORE_THIS #if !defined(SDL_PLATFORM_VITA) && !defined(SDL_PLATFORM_3DS) /* TODO: include/SDL_stdinc.h:390: error: size of array 'SDL_dummy_enum' is negative */ -typedef enum +typedef enum SDL_DUMMY_ENUM { DUMMY_ENUM_VALUE } SDL_DUMMY_ENUM; @@ -398,6 +620,51 @@ SDL_COMPILE_TIME_ASSERT(enum, sizeof(SDL_DUMMY_ENUM) == sizeof(int)); extern "C" { #endif +/** + * A macro to initialize an SDL interface. + * + * This macro will initialize an SDL interface structure and should be called + * before you fill out the fields with your implementation. + * + * You can use it like this: + * + * ```c + * SDL_IOStreamInterface iface; + * + * SDL_INIT_INTERFACE(&iface); + * + * // Fill in the interface function pointers with your implementation + * iface.seek = ... + * + * stream = SDL_OpenIO(&iface, NULL); + * ``` + * + * If you are using designated initializers, you can use the size of the + * interface as the version, e.g. + * + * ```c + * SDL_IOStreamInterface iface = { + * .version = sizeof(iface), + * .seek = ... + * }; + * stream = SDL_OpenIO(&iface, NULL); + * ``` + * + * \threadsafety It is safe to call this macro from any thread. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_IOStreamInterface + * \sa SDL_StorageInterface + * \sa SDL_VirtualJoystickDesc + */ +#define SDL_INIT_INTERFACE(iface) \ + do { \ + SDL_zerop(iface); \ + (iface)->version = sizeof(*(iface)); \ + } while (0) + + #ifndef SDL_DISABLE_ALLOCA #define SDL_stack_alloc(type, count) (type*)alloca(sizeof(type)*(count)) #define SDL_stack_free(data) @@ -406,796 +673,3407 @@ extern "C" { #define SDL_stack_free(data) SDL_free(data) #endif -extern DECLSPEC SDL_MALLOC void *SDLCALL SDL_malloc(size_t size); -extern DECLSPEC SDL_MALLOC SDL_ALLOC_SIZE2(1, 2) void *SDLCALL SDL_calloc(size_t nmemb, size_t size); -extern DECLSPEC SDL_ALLOC_SIZE(2) void *SDLCALL SDL_realloc(void *mem, size_t size); -extern DECLSPEC void SDLCALL SDL_free(void *mem); - -typedef void *(SDLCALL *SDL_malloc_func)(size_t size); -typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size); -typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size); -typedef void (SDLCALL *SDL_free_func)(void *mem); - /** - * Get the original set of SDL memory functions + * Allocate uninitialized memory. * - * \param malloc_func filled with malloc function - * \param calloc_func filled with calloc function - * \param realloc_func filled with realloc function - * \param free_func filled with free function + * The allocated memory returned by this function must be freed with + * SDL_free(). * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_GetOriginalMemoryFunctions(SDL_malloc_func *malloc_func, - SDL_calloc_func *calloc_func, - SDL_realloc_func *realloc_func, - SDL_free_func *free_func); - -/** - * Get the current set of SDL memory functions + * If `size` is 0, it will be set to 1. * - * \param malloc_func filled with malloc function - * \param calloc_func filled with calloc function - * \param realloc_func filled with realloc function - * \param free_func filled with free function + * If you want to allocate memory aligned to a specific alignment, consider + * using SDL_aligned_alloc(). * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func, - SDL_calloc_func *calloc_func, - SDL_realloc_func *realloc_func, - SDL_free_func *free_func); - -/** - * Replace SDL's memory allocation functions with a custom set + * \param size the size to allocate. + * \returns a pointer to the allocated memory, or NULL if allocation failed. * - * \param malloc_func custom malloc function - * \param calloc_func custom calloc function - * \param realloc_func custom realloc function - * \param free_func custom free function - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_free + * \sa SDL_calloc + * \sa SDL_realloc + * \sa SDL_aligned_alloc */ -extern DECLSPEC int SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func, - SDL_calloc_func calloc_func, - SDL_realloc_func realloc_func, - SDL_free_func free_func); +extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_malloc(size_t size); /** - * Allocate memory aligned to a specific value + * Allocate a zero-initialized array. * - * If `alignment` is less than the size of `void *`, then it will be increased - * to match that. + * The memory returned by this function must be freed with SDL_free(). * - * The returned memory address will be a multiple of the alignment value, and - * the amount of memory allocated will be a multiple of the alignment value. + * If either of `nmemb` or `size` is 0, they will both be set to 1. * - * The memory returned by this function must be freed with SDL_aligned_free() + * \param nmemb the number of elements in the array. + * \param size the size of each element of the array. + * \returns a pointer to the allocated array, or NULL if allocation failed. * - * \param alignment the alignment requested - * \param size the size to allocate - * \returns a pointer to the aligned memory + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_aligned_free + * \sa SDL_free + * \sa SDL_malloc + * \sa SDL_realloc */ -extern DECLSPEC SDL_MALLOC void *SDLCALL SDL_aligned_alloc(size_t alignment, size_t size); +extern SDL_DECLSPEC SDL_MALLOC SDL_ALLOC_SIZE2(1, 2) void * SDLCALL SDL_calloc(size_t nmemb, size_t size); /** - * Free memory allocated by SDL_aligned_alloc() + * Change the size of allocated memory. + * + * The memory returned by this function must be freed with SDL_free(). + * + * If `size` is 0, it will be set to 1. Note that this is unlike some other C + * runtime `realloc` implementations, which may treat `realloc(mem, 0)` the + * same way as `free(mem)`. + * + * If `mem` is NULL, the behavior of this function is equivalent to + * SDL_malloc(). Otherwise, the function can have one of three possible + * outcomes: + * + * - If it returns the same pointer as `mem`, it means that `mem` was resized + * in place without freeing. + * - If it returns a different non-NULL pointer, it means that `mem` was freed + * and cannot be dereferenced anymore. + * - If it returns NULL (indicating failure), then `mem` will remain valid and + * must still be freed with SDL_free(). + * + * \param mem a pointer to allocated memory to reallocate, or NULL. + * \param size the new size of the memory. + * \returns a pointer to the newly allocated memory, or NULL if allocation + * failed. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_aligned_alloc + * \sa SDL_free + * \sa SDL_malloc + * \sa SDL_calloc */ -extern DECLSPEC void SDLCALL SDL_aligned_free(void *mem); +extern SDL_DECLSPEC SDL_ALLOC_SIZE(2) void * SDLCALL SDL_realloc(void *mem, size_t size); /** - * Get the number of outstanding (unfreed) allocations + * Free allocated memory. + * + * The pointer is no longer valid after this call and cannot be dereferenced + * anymore. + * + * If `mem` is NULL, this function does nothing. + * + * \param mem a pointer to allocated memory, or NULL. * - * \returns the number of allocations + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_malloc + * \sa SDL_calloc + * \sa SDL_realloc */ -extern DECLSPEC int SDLCALL SDL_GetNumAllocations(void); - -extern DECLSPEC char *SDLCALL SDL_getenv(const char *name); -extern DECLSPEC int SDLCALL SDL_setenv(const char *name, const char *value, int overwrite); - -extern DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, int (SDLCALL *compare) (const void *, const void *)); -extern DECLSPEC void * SDLCALL SDL_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (SDLCALL *compare) (const void *, const void *)); - -extern DECLSPEC void SDLCALL SDL_qsort_r(void *base, size_t nmemb, size_t size, int (SDLCALL *compare) (void *, const void *, const void *), void *userdata); -extern DECLSPEC void * SDLCALL SDL_bsearch_r(const void *key, const void *base, size_t nmemb, size_t size, int (SDLCALL *compare) (void *, const void *, const void *), void *userdata); - -extern DECLSPEC int SDLCALL SDL_abs(int x); - -/* NOTE: these double-evaluate their arguments, so you should never have side effects in the parameters */ -#define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) -#define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) -#define SDL_clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))) +extern SDL_DECLSPEC void SDLCALL SDL_free(void *mem); /** - * Query if a character is alphabetic (a letter). + * A callback used to implement SDL_malloc(). * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * for English 'a-z' and 'A-Z' as true. + * SDL will always ensure that the passed `size` is greater than 0. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * \param size the size to allocate. + * \returns a pointer to the allocated memory, or NULL if allocation failed. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It should be safe to call this callback from any thread. * - * \since This function is available since SDL 3.0.0. + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_malloc + * \sa SDL_GetOriginalMemoryFunctions + * \sa SDL_GetMemoryFunctions + * \sa SDL_SetMemoryFunctions */ -extern DECLSPEC int SDLCALL SDL_isalpha(int x); +typedef void *(SDLCALL *SDL_malloc_func)(size_t size); /** - * Query if a character is alphabetic (a letter) or a number. + * A callback used to implement SDL_calloc(). * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * for English 'a-z', 'A-Z', and '0-9' as true. + * SDL will always ensure that the passed `nmemb` and `size` are both greater + * than 0. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * \param nmemb the number of elements in the array. + * \param size the size of each element of the array. + * \returns a pointer to the allocated array, or NULL if allocation failed. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It should be safe to call this callback from any thread. * - * \since This function is available since SDL 3.0.0. + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_calloc + * \sa SDL_GetOriginalMemoryFunctions + * \sa SDL_GetMemoryFunctions + * \sa SDL_SetMemoryFunctions */ -extern DECLSPEC int SDLCALL SDL_isalnum(int x); +typedef void *(SDLCALL *SDL_calloc_func)(size_t nmemb, size_t size); /** - * Report if a character is blank (a space or tab). + * A callback used to implement SDL_realloc(). * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * 0x20 (space) or 0x9 (tab) as true. + * SDL will always ensure that the passed `size` is greater than 0. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * \param mem a pointer to allocated memory to reallocate, or NULL. + * \param size the new size of the memory. + * \returns a pointer to the newly allocated memory, or NULL if allocation + * failed. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It should be safe to call this callback from any thread. * - * \since This function is available since SDL 3.0.0. + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_realloc + * \sa SDL_GetOriginalMemoryFunctions + * \sa SDL_GetMemoryFunctions + * \sa SDL_SetMemoryFunctions */ -extern DECLSPEC int SDLCALL SDL_isblank(int x); +typedef void *(SDLCALL *SDL_realloc_func)(void *mem, size_t size); /** - * Report if a character is a control character. + * A callback used to implement SDL_free(). * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * 0 through 0x1F, and 0x7F, as true. + * SDL will always ensure that the passed `mem` is a non-NULL pointer. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * \param mem a pointer to allocated memory. * - * \threadsafety It is safe to call this function from any thread. + * \threadsafety It should be safe to call this callback from any thread. * - * \since This function is available since SDL 3.0.0. + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_free + * \sa SDL_GetOriginalMemoryFunctions + * \sa SDL_GetMemoryFunctions + * \sa SDL_SetMemoryFunctions */ -extern DECLSPEC int SDLCALL SDL_iscntrl(int x); +typedef void (SDLCALL *SDL_free_func)(void *mem); /** - * Report if a character is a numeric digit. + * Get the original set of SDL memory functions. * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * '0' (0x30) through '9' (0x39), as true. + * This is what SDL_malloc and friends will use by default, if there has been + * no call to SDL_SetMemoryFunctions. This is not necessarily using the C + * runtime's `malloc` functions behind the scenes! Different platforms and + * build configurations might do any number of unexpected things. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * \param malloc_func filled with malloc function. + * \param calloc_func filled with calloc function. + * \param realloc_func filled with realloc function. + * \param free_func filled with free function. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_isdigit(int x); +extern SDL_DECLSPEC void SDLCALL SDL_GetOriginalMemoryFunctions(SDL_malloc_func *malloc_func, + SDL_calloc_func *calloc_func, + SDL_realloc_func *realloc_func, + SDL_free_func *free_func); + +/** + * Get the current set of SDL memory functions. + * + * \param malloc_func filled with malloc function. + * \param calloc_func filled with calloc function. + * \param realloc_func filled with realloc function. + * \param free_func filled with free function. + * + * \threadsafety This does not hold a lock, so do not call this in the + * unlikely event of a background thread calling + * SDL_SetMemoryFunctions simultaneously. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetMemoryFunctions + * \sa SDL_GetOriginalMemoryFunctions + */ +extern SDL_DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_func, + SDL_calloc_func *calloc_func, + SDL_realloc_func *realloc_func, + SDL_free_func *free_func); + +/** + * Replace SDL's memory allocation functions with a custom set. + * + * It is not safe to call this function once any allocations have been made, + * as future calls to SDL_free will use the new allocator, even if they came + * from an SDL_malloc made with the old one! + * + * If used, usually this needs to be the first call made into the SDL library, + * if not the very first thing done at program startup time. + * + * \param malloc_func custom malloc function. + * \param calloc_func custom calloc function. + * \param realloc_func custom realloc function. + * \param free_func custom free function. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread, but one + * should not replace the memory functions once any allocations + * are made! + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetMemoryFunctions + * \sa SDL_GetOriginalMemoryFunctions + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func, + SDL_calloc_func calloc_func, + SDL_realloc_func realloc_func, + SDL_free_func free_func); + +/** + * Allocate memory aligned to a specific alignment. + * + * The memory returned by this function must be freed with SDL_aligned_free(), + * _not_ SDL_free(). + * + * If `alignment` is less than the size of `void *`, it will be increased to + * match that. + * + * The returned memory address will be a multiple of the alignment value, and + * the size of the memory allocated will be a multiple of the alignment value. + * + * \param alignment the alignment of the memory. + * \param size the size to allocate. + * \returns a pointer to the aligned memory, or NULL if allocation failed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_aligned_free + */ +extern SDL_DECLSPEC SDL_MALLOC void * SDLCALL SDL_aligned_alloc(size_t alignment, size_t size); + +/** + * Free memory allocated by SDL_aligned_alloc(). + * + * The pointer is no longer valid after this call and cannot be dereferenced + * anymore. + * + * If `mem` is NULL, this function does nothing. + * + * \param mem a pointer previously returned by SDL_aligned_alloc(), or NULL. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_aligned_alloc + */ +extern SDL_DECLSPEC void SDLCALL SDL_aligned_free(void *mem); + +/** + * Get the number of outstanding (unfreed) allocations. + * + * \returns the number of allocations. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_GetNumAllocations(void); + +/** + * A thread-safe set of environment variables + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironment + * \sa SDL_CreateEnvironment + * \sa SDL_GetEnvironmentVariable + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + * \sa SDL_DestroyEnvironment + */ +typedef struct SDL_Environment SDL_Environment; + +/** + * Get the process environment. + * + * This is initialized at application start and is not affected by setenv() + * and unsetenv() calls after that point. Use SDL_SetEnvironmentVariable() and + * SDL_UnsetEnvironmentVariable() if you want to modify this environment, or + * SDL_setenv_unsafe() or SDL_unsetenv_unsafe() if you want changes to persist + * in the C runtime environment after SDL_Quit(). + * + * \returns a pointer to the environment for the process or NULL on failure; + * call SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironmentVariable + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_GetEnvironment(void); + +/** + * Create a set of environment variables + * + * \param populated true to initialize it from the C runtime environment, + * false to create an empty environment. + * \returns a pointer to the new environment or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety If `populated` is false, it is safe to call this function + * from any thread, otherwise it is safe if no other threads are + * calling setenv() or unsetenv() + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironmentVariable + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + * \sa SDL_DestroyEnvironment + */ +extern SDL_DECLSPEC SDL_Environment * SDLCALL SDL_CreateEnvironment(bool populated); + +/** + * Get the value of a variable in the environment. + * + * \param env the environment to query. + * \param name the name of the variable to get. + * \returns a pointer to the value of the variable or NULL if it can't be + * found. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironment + * \sa SDL_CreateEnvironment + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC const char * SDLCALL SDL_GetEnvironmentVariable(SDL_Environment *env, const char *name); + +/** + * Get all variables in the environment. + * + * \param env the environment to query. + * \returns a NULL terminated array of pointers to environment variables in + * the form "variable=value" or NULL on failure; call SDL_GetError() + * for more information. This is a single allocation that should be + * freed with SDL_free() when it is no longer needed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironment + * \sa SDL_CreateEnvironment + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC char ** SDLCALL SDL_GetEnvironmentVariables(SDL_Environment *env); + +/** + * Set the value of a variable in the environment. + * + * \param env the environment to modify. + * \param name the name of the variable to set. + * \param value the value of the variable to set. + * \param overwrite true to overwrite the variable if it exists, false to + * return success without setting the variable if it already + * exists. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironment + * \sa SDL_CreateEnvironment + * \sa SDL_GetEnvironmentVariable + * \sa SDL_GetEnvironmentVariables + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetEnvironmentVariable(SDL_Environment *env, const char *name, const char *value, bool overwrite); + +/** + * Clear a variable from the environment. + * + * \param env the environment to modify. + * \param name the name of the variable to unset. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetEnvironment + * \sa SDL_CreateEnvironment + * \sa SDL_GetEnvironmentVariable + * \sa SDL_GetEnvironmentVariables + * \sa SDL_SetEnvironmentVariable + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC bool SDLCALL SDL_UnsetEnvironmentVariable(SDL_Environment *env, const char *name); + +/** + * Destroy a set of environment variables. + * + * \param env the environment to destroy. + * + * \threadsafety It is safe to call this function from any thread, as long as + * the environment is no longer in use. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreateEnvironment + */ +extern SDL_DECLSPEC void SDLCALL SDL_DestroyEnvironment(SDL_Environment *env); + +/** + * Get the value of a variable in the environment. + * + * This function uses SDL's cached copy of the environment and is thread-safe. + * + * \param name the name of the variable to get. + * \returns a pointer to the value of the variable or NULL if it can't be + * found. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC const char * SDLCALL SDL_getenv(const char *name); + +/** + * Get the value of a variable in the environment. + * + * This function bypasses SDL's cached copy of the environment and is not + * thread-safe. + * + * \param name the name of the variable to get. + * \returns a pointer to the value of the variable or NULL if it can't be + * found. + * + * \threadsafety This function is not thread safe, consider using SDL_getenv() + * instead. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_getenv + */ +extern SDL_DECLSPEC const char * SDLCALL SDL_getenv_unsafe(const char *name); + +/** + * Set the value of a variable in the environment. + * + * \param name the name of the variable to set. + * \param value the value of the variable to set. + * \param overwrite 1 to overwrite the variable if it exists, 0 to return + * success without setting the variable if it already exists. + * \returns 0 on success, -1 on error. + * + * \threadsafety This function is not thread safe, consider using + * SDL_SetEnvironmentVariable() instead. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetEnvironmentVariable + */ +extern SDL_DECLSPEC int SDLCALL SDL_setenv_unsafe(const char *name, const char *value, int overwrite); + +/** + * Clear a variable from the environment. + * + * \param name the name of the variable to unset. + * \returns 0 on success, -1 on error. + * + * \threadsafety This function is not thread safe, consider using + * SDL_UnsetEnvironmentVariable() instead. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_UnsetEnvironmentVariable + */ +extern SDL_DECLSPEC int SDLCALL SDL_unsetenv_unsafe(const char *name); + +/** + * A callback used with SDL sorting and binary search functions. + * + * \param a a pointer to the first element being compared. + * \param b a pointer to the second element being compared. + * \returns -1 if `a` should be sorted before `b`, 1 if `b` should be sorted + * before `a`, 0 if they are equal. If two elements are equal, their + * order in the sorted array is undefined. + * + * \since This callback is available since SDL 3.0.0. + * + * \sa SDL_bsearch + * \sa SDL_qsort + */ +typedef int (SDLCALL *SDL_CompareCallback)(const void *a, const void *b); + +/** + * Sort an array. + * + * For example: + * + * ```c + * typedef struct { + * int key; + * const char *string; + * } data; + * + * int SDLCALL compare(const void *a, const void *b) + * { + * const data *A = (const data *)a; + * const data *B = (const data *)b; + * + * if (A->n < B->n) { + * return -1; + * } else if (B->n < A->n) { + * return 1; + * } else { + * return 0; + * } + * } + * + * data values[] = { + * { 3, "third" }, { 1, "first" }, { 2, "second" } + * }; + * + * SDL_qsort(values, SDL_arraysize(values), sizeof(values[0]), compare); + * ``` + * + * \param base a pointer to the start of the array. + * \param nmemb the number of elements in the array. + * \param size the size of the elements in the array. + * \param compare a function used to compare elements in the array. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_bsearch + * \sa SDL_qsort_r + */ +extern SDL_DECLSPEC void SDLCALL SDL_qsort(void *base, size_t nmemb, size_t size, SDL_CompareCallback compare); + +/** + * Perform a binary search on a previously sorted array. + * + * For example: + * + * ```c + * typedef struct { + * int key; + * const char *string; + * } data; + * + * int SDLCALL compare(const void *a, const void *b) + * { + * const data *A = (const data *)a; + * const data *B = (const data *)b; + * + * if (A->n < B->n) { + * return -1; + * } else if (B->n < A->n) { + * return 1; + * } else { + * return 0; + * } + * } + * + * data values[] = { + * { 1, "first" }, { 2, "second" }, { 3, "third" } + * }; + * data key = { 2, NULL }; + * + * data *result = SDL_bsearch(&key, values, SDL_arraysize(values), sizeof(values[0]), compare); + * ``` + * + * \param key a pointer to a key equal to the element being searched for. + * \param base a pointer to the start of the array. + * \param nmemb the number of elements in the array. + * \param size the size of the elements in the array. + * \param compare a function used to compare elements in the array. + * \returns a pointer to the matching element in the array, or NULL if not + * found. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_bsearch_r + * \sa SDL_qsort + */ +extern SDL_DECLSPEC void * SDLCALL SDL_bsearch(const void *key, const void *base, size_t nmemb, size_t size, SDL_CompareCallback compare); + +/** + * A callback used with SDL sorting and binary search functions. + * + * \param userdata the `userdata` pointer passed to the sort function. + * \param a a pointer to the first element being compared. + * \param b a pointer to the second element being compared. + * \returns -1 if `a` should be sorted before `b`, 1 if `b` should be sorted + * before `a`, 0 if they are equal. If two elements are equal, their + * order in the sorted array is undefined. + * + * \since This callback is available since SDL 3.0.0. + * + * \sa SDL_qsort_r + * \sa SDL_bsearch_r + */ +typedef int (SDLCALL *SDL_CompareCallback_r)(void *userdata, const void *a, const void *b); + +/** + * Sort an array, passing a userdata pointer to the compare function. + * + * For example: + * + * ```c + * typedef enum { + * sort_increasing, + * sort_decreasing, + * } sort_method; + * + * typedef struct { + * int key; + * const char *string; + * } data; + * + * int SDLCALL compare(const void *userdata, const void *a, const void *b) + * { + * sort_method method = (sort_method)(uintptr_t)userdata; + * const data *A = (const data *)a; + * const data *B = (const data *)b; + * + * if (A->n < B->n) { + * return (method == sort_increasing) ? -1 : 1; + * } else if (B->n < A->n) { + * return (method == sort_increasing) ? 1 : -1; + * } else { + * return 0; + * } + * } + * + * data values[] = { + * { 3, "third" }, { 1, "first" }, { 2, "second" } + * }; + * + * SDL_qsort_r(values, SDL_arraysize(values), sizeof(values[0]), compare, (const void *)(uintptr_t)sort_increasing); + * ``` + * + * \param base a pointer to the start of the array. + * \param nmemb the number of elements in the array. + * \param size the size of the elements in the array. + * \param compare a function used to compare elements in the array. + * \param userdata a pointer to pass to the compare function. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_bsearch_r + * \sa SDL_qsort + */ +extern SDL_DECLSPEC void SDLCALL SDL_qsort_r(void *base, size_t nmemb, size_t size, SDL_CompareCallback_r compare, void *userdata); + +/** + * Perform a binary search on a previously sorted array, passing a userdata + * pointer to the compare function. + * + * For example: + * + * ```c + * typedef enum { + * sort_increasing, + * sort_decreasing, + * } sort_method; + * + * typedef struct { + * int key; + * const char *string; + * } data; + * + * int SDLCALL compare(const void *userdata, const void *a, const void *b) + * { + * sort_method method = (sort_method)(uintptr_t)userdata; + * const data *A = (const data *)a; + * const data *B = (const data *)b; + * + * if (A->n < B->n) { + * return (method == sort_increasing) ? -1 : 1; + * } else if (B->n < A->n) { + * return (method == sort_increasing) ? 1 : -1; + * } else { + * return 0; + * } + * } + * + * data values[] = { + * { 1, "first" }, { 2, "second" }, { 3, "third" } + * }; + * data key = { 2, NULL }; + * + * data *result = SDL_bsearch_r(&key, values, SDL_arraysize(values), sizeof(values[0]), compare, (const void *)(uintptr_t)sort_increasing); + * ``` + * + * \param key a pointer to a key equal to the element being searched for. + * \param base a pointer to the start of the array. + * \param nmemb the number of elements in the array. + * \param size the size of the elements in the array. + * \param compare a function used to compare elements in the array. + * \param userdata a pointer to pass to the compare function. + * \returns a pointer to the matching element in the array, or NULL if not + * found. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_bsearch + * \sa SDL_qsort_r + */ +extern SDL_DECLSPEC void * SDLCALL SDL_bsearch_r(const void *key, const void *base, size_t nmemb, size_t size, SDL_CompareCallback_r compare, void *userdata); + +extern SDL_DECLSPEC int SDLCALL SDL_abs(int x); + +/* NOTE: these double-evaluate their arguments, so you should never have side effects in the parameters */ +#define SDL_min(x, y) (((x) < (y)) ? (x) : (y)) +#define SDL_max(x, y) (((x) > (y)) ? (x) : (y)) +#define SDL_clamp(x, a, b) (((x) < (a)) ? (a) : (((x) > (b)) ? (b) : (x))) + +/** + * Query if a character is alphabetic (a letter). + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * for English 'a-z' and 'A-Z' as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isalpha(int x); + +/** + * Query if a character is alphabetic (a letter) or a number. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * for English 'a-z', 'A-Z', and '0-9' as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isalnum(int x); + +/** + * Report if a character is blank (a space or tab). + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * 0x20 (space) or 0x9 (tab) as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isblank(int x); + +/** + * Report if a character is a control character. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * 0 through 0x1F, and 0x7F, as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_iscntrl(int x); + +/** + * Report if a character is a numeric digit. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * '0' (0x30) through '9' (0x39), as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isdigit(int x); + +/** + * Report if a character is a hexadecimal digit. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * 'A' through 'F', 'a' through 'f', and '0' through '9', as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isxdigit(int x); + +/** + * Report if a character is a punctuation mark. + * + * **WARNING**: Regardless of system locale, this is equivalent to + * `((SDL_isgraph(x)) && (!SDL_isalnum(x)))`. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isgraph + * \sa SDL_isalnum + */ +extern SDL_DECLSPEC int SDLCALL SDL_ispunct(int x); + +/** + * Report if a character is whitespace. + * + * **WARNING**: Regardless of system locale, this will only treat the + * following ASCII values as true: + * + * - space (0x20) + * - tab (0x09) + * - newline (0x0A) + * - vertical tab (0x0B) + * - form feed (0x0C) + * - return (0x0D) + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isspace(int x); + +/** + * Report if a character is upper case. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * 'A' through 'Z' as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isupper(int x); + +/** + * Report if a character is lower case. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * 'a' through 'z' as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_islower(int x); + +/** + * Report if a character is "printable". + * + * Be advised that "printable" has a definition that goes back to text + * terminals from the dawn of computing, making this a sort of special case + * function that is not suitable for Unicode (or most any) text management. + * + * **WARNING**: Regardless of system locale, this will only treat ASCII values + * ' ' (0x20) through '~' (0x7E) as true. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_isprint(int x); + +/** + * Report if a character is any "printable" except space. + * + * Be advised that "printable" has a definition that goes back to text + * terminals from the dawn of computing, making this a sort of special case + * function that is not suitable for Unicode (or most any) text management. + * + * **WARNING**: Regardless of system locale, this is equivalent to + * `(SDL_isprint(x)) && ((x) != ' ')`. + * + * \param x character value to check. + * \returns non-zero if x falls within the character class, zero otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isprint + */ +extern SDL_DECLSPEC int SDLCALL SDL_isgraph(int x); + +/** + * Convert low-ASCII English letters to uppercase. + * + * **WARNING**: Regardless of system locale, this will only convert ASCII + * values 'a' through 'z' to uppercase. + * + * This function returns the uppercase equivalent of `x`. If a character + * cannot be converted, or is already uppercase, this function returns `x`. + * + * \param x character value to check. + * \returns capitalized version of x, or x if no conversion available. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_toupper(int x); + +/** + * Convert low-ASCII English letters to lowercase. + * + * **WARNING**: Regardless of system locale, this will only convert ASCII + * values 'A' through 'Z' to lowercase. + * + * This function returns the lowercase equivalent of `x`. If a character + * cannot be converted, or is already lowercase, this function returns `x`. + * + * \param x character value to check. + * \returns lowercase version of x, or x if no conversion available. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_tolower(int x); + +extern SDL_DECLSPEC Uint16 SDLCALL SDL_crc16(Uint16 crc, const void *data, size_t len); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t len); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_murmur3_32(const void *data, size_t len, Uint32 seed); + +/** + * Copy non-overlapping memory. + * + * The memory regions must not overlap. If they do, use SDL_memmove() instead. + * + * \param dst The destination memory region. Must not be NULL, and must not + * overlap with `src`. + * \param src The source memory region. Must not be NULL, and must not overlap + * with `dst`. + * \param len The length in bytes of both `dst` and `src`. + * \returns `dst`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_memmove + */ +extern SDL_DECLSPEC void * SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); + +/* Take advantage of compiler optimizations for memcpy */ +#ifndef SDL_SLOW_MEMCPY +#ifdef SDL_memcpy +#undef SDL_memcpy +#endif +#define SDL_memcpy memcpy +#endif + +#define SDL_copyp(dst, src) \ + { SDL_COMPILE_TIME_ASSERT(SDL_copyp, sizeof (*(dst)) == sizeof (*(src))); } \ + SDL_memcpy((dst), (src), sizeof(*(src))) + +/** + * Copy memory. + * + * It is okay for the memory regions to overlap. If you are confident that the + * regions never overlap, using SDL_memcpy() may improve performance. + * + * \param dst The destination memory region. Must not be NULL. + * \param src The source memory region. Must not be NULL. + * \param len The length in bytes of both `dst` and `src`. + * \returns `dst`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_memcpy + */ +extern SDL_DECLSPEC void * SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); + +/* Take advantage of compiler optimizations for memmove */ +#ifndef SDL_SLOW_MEMMOVE +#ifdef SDL_memmove +#undef SDL_memmove +#endif +#define SDL_memmove memmove +#endif + +extern SDL_DECLSPEC void * SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len); +extern SDL_DECLSPEC void * SDLCALL SDL_memset4(void *dst, Uint32 val, size_t dwords); + +/* Take advantage of compiler optimizations for memset */ +#ifndef SDL_SLOW_MEMSET +#ifdef SDL_memset +#undef SDL_memset +#endif +#define SDL_memset memset +#endif + +#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x))) +#define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x))) +#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x))) + +extern SDL_DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len); + +extern SDL_DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr); +extern SDL_DECLSPEC size_t SDLCALL SDL_wcsnlen(const wchar_t *wstr, size_t maxlen); + +/** + * Copy a wide string. + * + * This function copies `maxlen` - 1 wide characters from `src` to `dst`, then + * appends a null terminator. + * + * `src` and `dst` must not overlap. + * + * If `maxlen` is 0, no wide characters are copied and no null terminator is + * written. + * + * \param dst The destination buffer. Must not be NULL, and must not overlap + * with `src`. + * \param src The null-terminated wide string to copy. Must not be NULL, and + * must not overlap with `dst`. + * \param maxlen The length (in wide characters) of the destination buffer. + * \returns The length (in wide characters, excluding the null terminator) of + * `src`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_wcslcat + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); + +/** + * Concatenate wide strings. + * + * This function appends up to `maxlen` - SDL_wcslen(dst) - 1 wide characters + * from `src` to the end of the wide string in `dst`, then appends a null + * terminator. + * + * `src` and `dst` must not overlap. + * + * If `maxlen` - SDL_wcslen(dst) - 1 is less than or equal to 0, then `dst` is + * unmodified. + * + * \param dst The destination buffer already containing the first + * null-terminated wide string. Must not be NULL and must not + * overlap with `src`. + * \param src The second null-terminated wide string. Must not be NULL, and + * must not overlap with `dst`. + * \param maxlen The length (in wide characters) of the destination buffer. + * \returns The length (in wide characters, excluding the null terminator) of + * the string in `dst` plus the length of `src`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_wcslcpy + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); + +extern SDL_DECLSPEC wchar_t * SDLCALL SDL_wcsdup(const wchar_t *wstr); +extern SDL_DECLSPEC wchar_t * SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle); +extern SDL_DECLSPEC wchar_t * SDLCALL SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen); + +/** + * Compare two null-terminated wide strings. + * + * This only compares wchar_t values until it hits a null-terminating + * character; it does not care if the string is well-formed UTF-16 (or UTF-32, + * depending on your platform's wchar_t size), or uses valid Unicode values. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2); + +/** + * Compare two wide strings up to a number of wchar_t values. + * + * This only compares wchar_t values; it does not care if the string is + * well-formed UTF-16 (or UTF-32, depending on your platform's wchar_t size), + * or uses valid Unicode values. + * + * Note that while this function is intended to be used with UTF-16 (or + * UTF-32, depending on your platform's definition of wchar_t), it is + * comparing raw wchar_t values and not Unicode codepoints: `maxlen` specifies + * a wchar_t limit! If the limit lands in the middle of a multi-wchar UTF-16 + * sequence, it will only compare a portion of the final character. + * + * `maxlen` specifies a maximum number of wchar_t to compare; if the strings + * match to this number of wide chars (or both have matched to a + * null-terminator character before this count), they will be considered + * equal. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \param maxlen the maximum number of wchar_t to compare. + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); + +/** + * Compare two null-terminated wide strings, case-insensitively. + * + * This will work with Unicode strings, using a technique called + * "case-folding" to handle the vast majority of case-sensitive human + * languages regardless of system locale. It can deal with expanding values: a + * German Eszett character can compare against two ASCII 's' chars and be + * considered a match, for example. A notable exception: it does not handle + * the Turkish 'i' character; human language is complicated! + * + * Depending on your platform, "wchar_t" might be 2 bytes, and expected to be + * UTF-16 encoded (like Windows), or 4 bytes in UTF-32 format. Since this + * handles Unicode, it expects the string to be well-formed and not a + * null-terminated string of arbitrary bytes. Characters that are not valid + * UTF-16 (or UTF-32) are treated as Unicode character U+FFFD (REPLACEMENT + * CHARACTER), which is to say two strings of random bits may turn out to + * match if they convert to the same amount of replacement characters. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2); + +/** + * Compare two wide strings, case-insensitively, up to a number of wchar_t. + * + * This will work with Unicode strings, using a technique called + * "case-folding" to handle the vast majority of case-sensitive human + * languages regardless of system locale. It can deal with expanding values: a + * German Eszett character can compare against two ASCII 's' chars and be + * considered a match, for example. A notable exception: it does not handle + * the Turkish 'i' character; human language is complicated! + * + * Depending on your platform, "wchar_t" might be 2 bytes, and expected to be + * UTF-16 encoded (like Windows), or 4 bytes in UTF-32 format. Since this + * handles Unicode, it expects the string to be well-formed and not a + * null-terminated string of arbitrary bytes. Characters that are not valid + * UTF-16 (or UTF-32) are treated as Unicode character U+FFFD (REPLACEMENT + * CHARACTER), which is to say two strings of random bits may turn out to + * match if they convert to the same amount of replacement characters. + * + * Note that while this function might deal with variable-sized characters, + * `maxlen` specifies a _wchar_ limit! If the limit lands in the middle of a + * multi-byte UTF-16 sequence, it may convert a portion of the final character + * to one or more Unicode character U+FFFD (REPLACEMENT CHARACTER) so as not + * to overflow a buffer. + * + * `maxlen` specifies a maximum number of wchar_t values to compare; if the + * strings match to this number of wchar_t (or both have matched to a + * null-terminator character before this number of bytes), they will be + * considered equal. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \param maxlen the maximum number of wchar_t values to compare. + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); + +/** + * Parse a `long` from a wide string. + * + * If `str` starts with whitespace, then those whitespace characters are + * skipped before attempting to parse the number. + * + * If the parsed number does not fit inside a `long`, the result is clamped to + * the minimum and maximum representable `long` values. + * + * \param str The null-terminated wide string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid wide character + * (i.e. the next character after the parsed number) will be + * written to this pointer. + * \param base The base of the integer to read. Supported values are 0 and 2 + * to 36 inclusive. If 0, the base will be inferred from the + * number's prefix (0x for hexadecimal, 0 for octal, decimal + * otherwise). + * \returns The parsed `long`, or 0 if no number could be parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strtol + */ +extern SDL_DECLSPEC long SDLCALL SDL_wcstol(const wchar_t *str, wchar_t **endp, int base); + +extern SDL_DECLSPEC size_t SDLCALL SDL_strlen(const char *str); +extern SDL_DECLSPEC size_t SDLCALL SDL_strnlen(const char *str, size_t maxlen); + +/** + * Copy a string. + * + * This function copies up to `maxlen` - 1 characters from `src` to `dst`, + * then appends a null terminator. + * + * If `maxlen` is 0, no characters are copied and no null terminator is + * written. + * + * If you want to copy an UTF-8 string but need to ensure that multi-byte + * sequences are not truncated, consider using SDL_utf8strlcpy(). + * + * \param dst The destination buffer. Must not be NULL, and must not overlap + * with `src`. + * \param src The null-terminated string to copy. Must not be NULL, and must + * not overlap with `dst`. + * \param maxlen The length (in characters) of the destination buffer. + * \returns The length (in characters, excluding the null terminator) of + * `src`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strlcat + * \sa SDL_utf8strlcpy + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); + +/** + * Copy an UTF-8 string. + * + * This function copies up to `dst_bytes` - 1 bytes from `src` to `dst` while + * also ensuring that the string written to `dst` does not end in a truncated + * multi-byte sequence. Finally, it appends a null terminator. + * + * `src` and `dst` must not overlap. + * + * Note that unlike SDL_strlcpy(), this function returns the number of bytes + * written, not the length of `src`. + * + * \param dst The destination buffer. Must not be NULL, and must not overlap + * with `src`. + * \param src The null-terminated UTF-8 string to copy. Must not be NULL, and + * must not overlap with `dst`. + * \param dst_bytes The length (in bytes) of the destination buffer. Must not + * be 0. + * \returns The number of bytes written, excluding the null terminator. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strlcpy + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes); + +/** + * Concatenate strings. + * + * This function appends up to `maxlen` - SDL_strlen(dst) - 1 characters from + * `src` to the end of the string in `dst`, then appends a null terminator. + * + * `src` and `dst` must not overlap. + * + * If `maxlen` - SDL_strlen(dst) - 1 is less than or equal to 0, then `dst` is + * unmodified. + * + * \param dst The destination buffer already containing the first + * null-terminated string. Must not be NULL and must not overlap + * with `src`. + * \param src The second null-terminated string. Must not be NULL, and must + * not overlap with `dst`. + * \param maxlen The length (in characters) of the destination buffer. + * \returns The length (in characters, excluding the null terminator) of the + * string in `dst` plus the length of `src`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strlcpy + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); + +extern SDL_DECLSPEC SDL_MALLOC char * SDLCALL SDL_strdup(const char *str); +extern SDL_DECLSPEC SDL_MALLOC char * SDLCALL SDL_strndup(const char *str, size_t maxlen); +extern SDL_DECLSPEC char * SDLCALL SDL_strrev(char *str); + +/** + * Convert a string to uppercase. + * + * **WARNING**: Regardless of system locale, this will only convert ASCII + * values 'A' through 'Z' to uppercase. + * + * This function operates on a null-terminated string of bytes--even if it is + * malformed UTF-8!--and converts ASCII characters 'a' through 'z' to their + * uppercase equivalents in-place, returning the original `str` pointer. + * + * \param str the string to convert in-place. Can not be NULL. + * \returns the `str` pointer passed into this function. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strlwr + */ +extern SDL_DECLSPEC char * SDLCALL SDL_strupr(char *str); + +/** + * Convert a string to lowercase. + * + * **WARNING**: Regardless of system locale, this will only convert ASCII + * values 'A' through 'Z' to lowercase. + * + * This function operates on a null-terminated string of bytes--even if it is + * malformed UTF-8!--and converts ASCII characters 'A' through 'Z' to their + * lowercase equivalents in-place, returning the original `str` pointer. + * + * \param str the string to convert in-place. Can not be NULL. + * \returns the `str` pointer passed into this function. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_strupr + */ +extern SDL_DECLSPEC char * SDLCALL SDL_strlwr(char *str); + +extern SDL_DECLSPEC char * SDLCALL SDL_strchr(const char *str, int c); +extern SDL_DECLSPEC char * SDLCALL SDL_strrchr(const char *str, int c); +extern SDL_DECLSPEC char * SDLCALL SDL_strstr(const char *haystack, const char *needle); +extern SDL_DECLSPEC char * SDLCALL SDL_strnstr(const char *haystack, const char *needle, size_t maxlen); +extern SDL_DECLSPEC char * SDLCALL SDL_strcasestr(const char *haystack, const char *needle); +extern SDL_DECLSPEC char * SDLCALL SDL_strtok_r(char *s1, const char *s2, char **saveptr); +extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str); +extern SDL_DECLSPEC size_t SDLCALL SDL_utf8strnlen(const char *str, size_t bytes); + +extern SDL_DECLSPEC char * SDLCALL SDL_itoa(int value, char *str, int radix); +extern SDL_DECLSPEC char * SDLCALL SDL_uitoa(unsigned int value, char *str, int radix); +extern SDL_DECLSPEC char * SDLCALL SDL_ltoa(long value, char *str, int radix); +extern SDL_DECLSPEC char * SDLCALL SDL_ultoa(unsigned long value, char *str, int radix); +extern SDL_DECLSPEC char * SDLCALL SDL_lltoa(long long value, char *str, int radix); +extern SDL_DECLSPEC char * SDLCALL SDL_ulltoa(unsigned long long value, char *str, int radix); + +/** + * Parse an `int` from a string. + * + * The result of calling `SDL_atoi(str)` is equivalent to + * `(int)SDL_strtol(str, NULL, 10)`. + * + * \param str The null-terminated string to read. Must not be NULL. + * \returns The parsed `int`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atof + * \sa SDL_strtol + * \sa SDL_strtoul + * \sa SDL_strtoll + * \sa SDL_strtoull + * \sa SDL_strtod + * \sa SDL_itoa + */ +extern SDL_DECLSPEC int SDLCALL SDL_atoi(const char *str); + +/** + * Parse a `double` from a string. + * + * The result of calling `SDL_atof(str)` is equivalent to `SDL_strtod(str, + * NULL)`. + * + * \param str The null-terminated string to read. Must not be NULL. + * \returns The parsed `double`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_strtol + * \sa SDL_strtoul + * \sa SDL_strtoll + * \sa SDL_strtoull + * \sa SDL_strtod + */ +extern SDL_DECLSPEC double SDLCALL SDL_atof(const char *str); + +/** + * Parse a `long` from a string. + * + * If `str` starts with whitespace, then those whitespace characters are + * skipped before attempting to parse the number. + * + * If the parsed number does not fit inside a `long`, the result is clamped to + * the minimum and maximum representable `long` values. + * + * \param str The null-terminated string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid character (i.e. + * the next character after the parsed number) will be written to + * this pointer. + * \param base The base of the integer to read. Supported values are 0 and 2 + * to 36 inclusive. If 0, the base will be inferred from the + * number's prefix (0x for hexadecimal, 0 for octal, decimal + * otherwise). + * \returns The parsed `long`, or 0 if no number could be parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_atof + * \sa SDL_strtoul + * \sa SDL_strtoll + * \sa SDL_strtoull + * \sa SDL_strtod + * \sa SDL_ltoa + * \sa SDL_wcstol + */ +extern SDL_DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base); + +/** + * Parse an `unsigned long` from a string. + * + * If `str` starts with whitespace, then those whitespace characters are + * skipped before attempting to parse the number. + * + * If the parsed number does not fit inside an `unsigned long`, the result is + * clamped to the maximum representable `unsigned long` value. + * + * \param str The null-terminated string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid character (i.e. + * the next character after the parsed number) will be written to + * this pointer. + * \param base The base of the integer to read. Supported values are 0 and 2 + * to 36 inclusive. If 0, the base will be inferred from the + * number's prefix (0x for hexadecimal, 0 for octal, decimal + * otherwise). + * \returns The parsed `unsigned long`, or 0 if no number could be parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_atof + * \sa SDL_strtol + * \sa SDL_strtoll + * \sa SDL_strtoull + * \sa SDL_strtod + * \sa SDL_ultoa + */ +extern SDL_DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base); + +/** + * Parse a `long long` from a string. + * + * If `str` starts with whitespace, then those whitespace characters are + * skipped before attempting to parse the number. + * + * If the parsed number does not fit inside a `long long`, the result is + * clamped to the minimum and maximum representable `long long` values. + * + * \param str The null-terminated string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid character (i.e. + * the next character after the parsed number) will be written to + * this pointer. + * \param base The base of the integer to read. Supported values are 0 and 2 + * to 36 inclusive. If 0, the base will be inferred from the + * number's prefix (0x for hexadecimal, 0 for octal, decimal + * otherwise). + * \returns The parsed `long long`, or 0 if no number could be parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_atof + * \sa SDL_strtol + * \sa SDL_strtoul + * \sa SDL_strtoull + * \sa SDL_strtod + * \sa SDL_lltoa + */ +extern SDL_DECLSPEC long long SDLCALL SDL_strtoll(const char *str, char **endp, int base); + +/** + * Parse an `unsigned long long` from a string. + * + * If `str` starts with whitespace, then those whitespace characters are + * skipped before attempting to parse the number. + * + * If the parsed number does not fit inside an `unsigned long long`, the + * result is clamped to the maximum representable `unsigned long long` value. + * + * \param str The null-terminated string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid character (i.e. + * the next character after the parsed number) will be written to + * this pointer. + * \param base The base of the integer to read. Supported values are 0 and 2 + * to 36 inclusive. If 0, the base will be inferred from the + * number's prefix (0x for hexadecimal, 0 for octal, decimal + * otherwise). + * \returns The parsed `unsigned long long`, or 0 if no number could be + * parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_atof + * \sa SDL_strtol + * \sa SDL_strtoll + * \sa SDL_strtoul + * \sa SDL_strtod + * \sa SDL_ulltoa + */ +extern SDL_DECLSPEC unsigned long long SDLCALL SDL_strtoull(const char *str, char **endp, int base); + +/** + * Parse a `double` from a string. + * + * This function makes fewer guarantees than the C runtime `strtod`: + * + * - Only decimal notation is guaranteed to be supported. The handling of + * scientific and hexadecimal notation is unspecified. + * - Whether or not INF and NAN can be parsed is unspecified. + * - The precision of the result is unspecified. + * + * \param str The null-terminated string to read. Must not be NULL. + * \param endp If not NULL, the address of the first invalid character (i.e. + * the next character after the parsed number) will be written to + * this pointer. + * \returns The parsed `double`, or 0 if no number could be parsed. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atoi + * \sa SDL_atof + * \sa SDL_strtol + * \sa SDL_strtoll + * \sa SDL_strtoul + * \sa SDL_strtoull + */ +extern SDL_DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp); + +/** + * Compare two null-terminated UTF-8 strings. + * + * Due to the nature of UTF-8 encoding, this will work with Unicode strings, + * since effectively this function just compares bytes until it hits a + * null-terminating character. Also due to the nature of UTF-8, this can be + * used with SDL_qsort() to put strings in (roughly) alphabetical order. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2); + +/** + * Compare two UTF-8 strings up to a number of bytes. + * + * Due to the nature of UTF-8 encoding, this will work with Unicode strings, + * since effectively this function just compares bytes until it hits a + * null-terminating character. Also due to the nature of UTF-8, this can be + * used with SDL_qsort() to put strings in (roughly) alphabetical order. + * + * Note that while this function is intended to be used with UTF-8, it is + * doing a bytewise comparison, and `maxlen` specifies a _byte_ limit! If the + * limit lands in the middle of a multi-byte UTF-8 sequence, it will only + * compare a portion of the final character. + * + * `maxlen` specifies a maximum number of bytes to compare; if the strings + * match to this number of bytes (or both have matched to a null-terminator + * character before this number of bytes), they will be considered equal. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \param maxlen the maximum number of _bytes_ to compare. + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen); + +/** + * Compare two null-terminated UTF-8 strings, case-insensitively. + * + * This will work with Unicode strings, using a technique called + * "case-folding" to handle the vast majority of case-sensitive human + * languages regardless of system locale. It can deal with expanding values: a + * German Eszett character can compare against two ASCII 's' chars and be + * considered a match, for example. A notable exception: it does not handle + * the Turkish 'i' character; human language is complicated! + * + * Since this handles Unicode, it expects the string to be well-formed UTF-8 + * and not a null-terminated string of arbitrary bytes. Bytes that are not + * valid UTF-8 are treated as Unicode character U+FFFD (REPLACEMENT + * CHARACTER), which is to say two strings of random bits may turn out to + * match if they convert to the same amount of replacement characters. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); + + +/** + * Compare two UTF-8 strings, case-insensitively, up to a number of bytes. + * + * This will work with Unicode strings, using a technique called + * "case-folding" to handle the vast majority of case-sensitive human + * languages regardless of system locale. It can deal with expanding values: a + * German Eszett character can compare against two ASCII 's' chars and be + * considered a match, for example. A notable exception: it does not handle + * the Turkish 'i' character; human language is complicated! + * + * Since this handles Unicode, it expects the string to be well-formed UTF-8 + * and not a null-terminated string of arbitrary bytes. Bytes that are not + * valid UTF-8 are treated as Unicode character U+FFFD (REPLACEMENT + * CHARACTER), which is to say two strings of random bits may turn out to + * match if they convert to the same amount of replacement characters. + * + * Note that while this function is intended to be used with UTF-8, `maxlen` + * specifies a _byte_ limit! If the limit lands in the middle of a multi-byte + * UTF-8 sequence, it may convert a portion of the final character to one or + * more Unicode character U+FFFD (REPLACEMENT CHARACTER) so as not to overflow + * a buffer. + * + * `maxlen` specifies a maximum number of bytes to compare; if the strings + * match to this number of bytes (or both have matched to a null-terminator + * character before this number of bytes), they will be considered equal. + * + * \param str1 the first string to compare. NULL is not permitted! + * \param str2 the second string to compare. NULL is not permitted! + * \param maxlen the maximum number of bytes to compare. + * \returns less than zero if str1 is "less than" str2, greater than zero if + * str1 is "greater than" str2, and zero if the strings match + * exactly. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen); + +/** + * Searches a string for the first occurence of any character contained in a + * breakset, and returns a pointer from the string to that character. + * + * \param str The null-terminated string to be searched. Must not be NULL, and + * must not overlap with `breakset`. + * \param breakset A null-terminated string containing the list of characters + * to look for. Must not be NULL, and must not overlap with + * `str`. + * \returns A pointer to the location, in str, of the first occurence of a + * character present in the breakset, or NULL if none is found. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC char * SDLCALL SDL_strpbrk(const char *str, const char *breakset); + +/** + * The Unicode REPLACEMENT CHARACTER codepoint. + * + * SDL_StepUTF8() reports this codepoint when it encounters a UTF-8 string + * with encoding errors. + * + * This tends to render as something like a question mark in most places. + * + * \since This macro is available since SDL 3.0.0. + * + * \sa SDL_StepUTF8 + */ +#define SDL_INVALID_UNICODE_CODEPOINT 0xFFFD + +/** + * Decode a UTF-8 string, one Unicode codepoint at a time. + * + * This will return the first Unicode codepoint in the UTF-8 encoded string in + * `*pstr`, and then advance `*pstr` past any consumed bytes before returning. + * + * It will not access more than `*pslen` bytes from the string. `*pslen` will + * be adjusted, as well, subtracting the number of bytes consumed. + * + * `pslen` is allowed to be NULL, in which case the string _must_ be + * NULL-terminated, as the function will blindly read until it sees the NULL + * char. + * + * if `*pslen` is zero, it assumes the end of string is reached and returns a + * zero codepoint regardless of the contents of the string buffer. + * + * If the resulting codepoint is zero (a NULL terminator), or `*pslen` is + * zero, it will not advance `*pstr` or `*pslen` at all. + * + * Generally this function is called in a loop until it returns zero, + * adjusting its parameters each iteration. + * + * If an invalid UTF-8 sequence is encountered, this function returns + * SDL_INVALID_UNICODE_CODEPOINT and advances the string/length by one byte + * (which is to say, a multibyte sequence might produce several + * SDL_INVALID_UNICODE_CODEPOINT returns before it syncs to the next valid + * UTF-8 sequence). + * + * Several things can generate invalid UTF-8 sequences, including overlong + * encodings, the use of UTF-16 surrogate values, and truncated data. Please + * refer to + * [RFC3629](https://www.ietf.org/rfc/rfc3629.txt) + * for details. + * + * \param pstr a pointer to a UTF-8 string pointer to be read and adjusted. + * \param pslen a pointer to the number of bytes in the string, to be read and + * adjusted. NULL is allowed. + * \returns the first Unicode codepoint in the string. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_StepUTF8(const char **pstr, size_t *pslen); + +/** + * Convert a single Unicode codepoint to UTF-8. + * + * The buffer pointed to by `dst` must be at least 4 bytes long, as this + * function may generate between 1 and 4 bytes of output. + * + * This function returns the first byte _after_ the newly-written UTF-8 + * sequence, which is useful for encoding multiple codepoints in a loop, or + * knowing where to write a NULL-terminator character to end the string (in + * either case, plan to have a buffer of _more_ than 4 bytes!). + * + * If `codepoint` is an invalid value (outside the Unicode range, or a UTF-16 + * surrogate value, etc), this will use U+FFFD (REPLACEMENT CHARACTER) for the + * codepoint instead, and not set an error. + * + * If `dst` is NULL, this returns NULL immediately without writing to the + * pointer and without setting an error. + * + * \param codepoint a Unicode codepoint to convert to UTF-8. + * \param dst the location to write the encoded UTF-8. Must point to at least + * 4 bytes! + * \returns the first byte past the newly-written UTF-8 sequence. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC char * SDLCALL SDL_UCS4ToUTF8(Uint32 codepoint, char *dst); + + +extern SDL_DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); +extern SDL_DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); +extern SDL_DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3); +extern SDL_DECLSPEC int SDLCALL SDL_swprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ...) SDL_WPRINTF_VARARG_FUNC(3); +extern SDL_DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); +extern SDL_DECLSPEC int SDLCALL SDL_vswprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, va_list ap) SDL_WPRINTF_VARARG_FUNCV(3); +extern SDL_DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +extern SDL_DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); + +/** + * Seeds the pseudo-random number generator. + * + * Reusing the seed number will cause SDL_rand_*() to repeat the same stream + * of 'random' numbers. + * + * \param seed the value to use as a random number seed, or 0 to use + * SDL_GetPerformanceCounter(). + * + * \threadsafety This should be called on the same thread that calls + * SDL_rand*() + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_rand + * \sa SDL_rand_bits + * \sa SDL_randf + */ +extern SDL_DECLSPEC void SDLCALL SDL_srand(Uint64 seed); + +/** + * Generate a pseudo-random number less than n for positive n + * + * The method used is faster and of better quality than `rand() % n`. Odds are + * roughly 99.9% even for n = 1 million. Evenness is better for smaller n, and + * much worse as n gets bigger. + * + * Example: to simulate a d6 use `SDL_rand(6) + 1` The +1 converts 0..5 to + * 1..6 + * + * If you want to generate a pseudo-random number in the full range of Sint32, + * you should use: (Sint32)SDL_rand_bits() + * + * If you want reproducible output, be sure to initialize with SDL_srand() + * first. + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \param n the number of possible outcomes. n must be positive. + * \returns a random value in the range of [0 .. n-1]. + * + * \threadsafety All calls should be made from a single thread + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_srand + * \sa SDL_randf + */ +extern SDL_DECLSPEC Sint32 SDLCALL SDL_rand(Sint32 n); + +/** + * Generate a uniform pseudo-random floating point number less than 1.0 + * + * If you want reproducible output, be sure to initialize with SDL_srand() + * first. + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \returns a random value in the range of [0.0, 1.0). + * + * \threadsafety All calls should be made from a single thread + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_srand + * \sa SDL_rand + */ +extern SDL_DECLSPEC float SDLCALL SDL_randf(void); + +/** + * Generate 32 pseudo-random bits. + * + * You likely want to use SDL_rand() to get a psuedo-random number instead. + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \returns a random value in the range of [0-SDL_MAX_UINT32]. + * + * \threadsafety All calls should be made from a single thread + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_rand + * \sa SDL_randf + * \sa SDL_srand + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_rand_bits(void); + +/** + * Generate a pseudo-random number less than n for positive n + * + * The method used is faster and of better quality than `rand() % n`. Odds are + * roughly 99.9% even for n = 1 million. Evenness is better for smaller n, and + * much worse as n gets bigger. + * + * Example: to simulate a d6 use `SDL_rand_r(state, 6) + 1` The +1 converts + * 0..5 to 1..6 + * + * If you want to generate a pseudo-random number in the full range of Sint32, + * you should use: (Sint32)SDL_rand_bits_r(state) + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \param state a pointer to the current random number state, this may not be + * NULL. + * \param n the number of possible outcomes. n must be positive. + * \returns a random value in the range of [0 .. n-1]. + * + * \threadsafety This function is thread-safe, as long as the state pointer + * isn't shared between threads. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_rand + * \sa SDL_rand_bits_r + * \sa SDL_randf_r + */ +extern SDL_DECLSPEC Sint32 SDLCALL SDL_rand_r(Uint64 *state, Sint32 n); + +/** + * Generate a uniform pseudo-random floating point number less than 1.0 + * + * If you want reproducible output, be sure to initialize with SDL_srand() + * first. + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \param state a pointer to the current random number state, this may not be + * NULL. + * \returns a random value in the range of [0.0, 1.0). + * + * \threadsafety This function is thread-safe, as long as the state pointer + * isn't shared between threads. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_rand_bits_r + * \sa SDL_rand_r + * \sa SDL_randf + */ +extern SDL_DECLSPEC float SDLCALL SDL_randf_r(Uint64 *state); + +/** + * Generate 32 pseudo-random bits. + * + * You likely want to use SDL_rand_r() to get a psuedo-random number instead. + * + * There are no guarantees as to the quality of the random sequence produced, + * and this should not be used for security (cryptography, passwords) or where + * money is on the line (loot-boxes, casinos). There are many random number + * libraries available with different characteristics and you should pick one + * of those to meet any serious needs. + * + * \param state a pointer to the current random number state, this may not be + * NULL. + * \returns a random value in the range of [0-SDL_MAX_UINT32]. + * + * \threadsafety This function is thread-safe, as long as the state pointer + * isn't shared between threads. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_rand_r + * \sa SDL_randf_r + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_rand_bits_r(Uint64 *state); + + +#ifndef SDL_PI_D +#define SDL_PI_D 3.141592653589793238462643383279502884 /**< pi (double) */ +#endif +#ifndef SDL_PI_F +#define SDL_PI_F 3.141592653589793238462643383279502884F /**< pi (float) */ +#endif + +/** + * Compute the arc cosine of `x`. + * + * The definition of `y = acos(x)` is `x = cos(y)`. + * + * Domain: `-1 <= x <= 1` + * + * Range: `0 <= y <= Pi` + * + * This function operates on double-precision floating point values, use + * SDL_acosf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc cosine of `x`, in radians. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_acosf + * \sa SDL_asin + * \sa SDL_cos + */ +extern SDL_DECLSPEC double SDLCALL SDL_acos(double x); + +/** + * Compute the arc cosine of `x`. + * + * The definition of `y = acos(x)` is `x = cos(y)`. + * + * Domain: `-1 <= x <= 1` + * + * Range: `0 <= y <= Pi` + * + * This function operates on single-precision floating point values, use + * SDL_acos for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc cosine of `x`, in radians. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_acos + * \sa SDL_asinf + * \sa SDL_cosf + */ +extern SDL_DECLSPEC float SDLCALL SDL_acosf(float x); + +/** + * Compute the arc sine of `x`. + * + * The definition of `y = asin(x)` is `x = sin(y)`. + * + * Domain: `-1 <= x <= 1` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on double-precision floating point values, use + * SDL_asinf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc sine of `x`, in radians. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_asinf + * \sa SDL_acos + * \sa SDL_sin + */ +extern SDL_DECLSPEC double SDLCALL SDL_asin(double x); + +/** + * Compute the arc sine of `x`. + * + * The definition of `y = asin(x)` is `x = sin(y)`. + * + * Domain: `-1 <= x <= 1` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on single-precision floating point values, use + * SDL_asin for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc sine of `x`, in radians. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_asin + * \sa SDL_acosf + * \sa SDL_sinf + */ +extern SDL_DECLSPEC float SDLCALL SDL_asinf(float x); + +/** + * Compute the arc tangent of `x`. + * + * The definition of `y = atan(x)` is `x = tan(y)`. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on double-precision floating point values, use + * SDL_atanf for single-precision floats. + * + * To calculate the arc tangent of y / x, use SDL_atan2. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc tangent of of `x` in radians, or 0 if `x = 0`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atanf + * \sa SDL_atan2 + * \sa SDL_tan + */ +extern SDL_DECLSPEC double SDLCALL SDL_atan(double x); + +/** + * Compute the arc tangent of `x`. + * + * The definition of `y = atan(x)` is `x = tan(y)`. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on single-precision floating point values, use + * SDL_atan for dboule-precision floats. + * + * To calculate the arc tangent of y / x, use SDL_atan2f. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns arc tangent of of `x` in radians, or 0 if `x = 0`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atan + * \sa SDL_atan2f + * \sa SDL_tanf + */ +extern SDL_DECLSPEC float SDLCALL SDL_atanf(float x); + +/** + * Compute the arc tangent of `y / x`, using the signs of x and y to adjust + * the result's quadrant. + * + * The definition of `z = atan2(x, y)` is `y = x tan(z)`, where the quadrant + * of z is determined based on the signs of x and y. + * + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on double-precision floating point values, use + * SDL_atan2f for single-precision floats. + * + * To calculate the arc tangent of a single value, use SDL_atan. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param y floating point value of the numerator (y coordinate). + * \param x floating point value of the denominator (x coordinate). + * \returns arc tangent of of `y / x` in radians, or, if `x = 0`, either + * `-Pi/2`, `0`, or `Pi/2`, depending on the value of `y`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atan2f + * \sa SDL_atan + * \sa SDL_tan + */ +extern SDL_DECLSPEC double SDLCALL SDL_atan2(double y, double x); + +/** + * Compute the arc tangent of `y / x`, using the signs of x and y to adjust + * the result's quadrant. + * + * The definition of `z = atan2(x, y)` is `y = x tan(z)`, where the quadrant + * of z is determined based on the signs of x and y. + * + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` + * + * Range: `-Pi/2 <= y <= Pi/2` + * + * This function operates on single-precision floating point values, use + * SDL_atan2 for double-precision floats. + * + * To calculate the arc tangent of a single value, use SDL_atanf. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param y floating point value of the numerator (y coordinate). + * \param x floating point value of the denominator (x coordinate). + * \returns arc tangent of of `y / x` in radians, or, if `x = 0`, either + * `-Pi/2`, `0`, or `Pi/2`, depending on the value of `y`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_atan2f + * \sa SDL_atan + * \sa SDL_tan + */ +extern SDL_DECLSPEC float SDLCALL SDL_atan2f(float y, float x); + +/** + * Compute the ceiling of `x`. + * + * The ceiling of `x` is the smallest integer `y` such that `y > x`, i.e `x` + * rounded up to the nearest integer. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on double-precision floating point values, use + * SDL_ceilf for single-precision floats. + * + * \param x floating point value. + * \returns the ceiling of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ceilf + * \sa SDL_floor + * \sa SDL_trunc + * \sa SDL_round + * \sa SDL_lround + */ +extern SDL_DECLSPEC double SDLCALL SDL_ceil(double x); + +/** + * Compute the ceiling of `x`. + * + * The ceiling of `x` is the smallest integer `y` such that `y > x`, i.e `x` + * rounded up to the nearest integer. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on single-precision floating point values, use + * SDL_ceil for double-precision floats. + * + * \param x floating point value. + * \returns the ceiling of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_ceil + * \sa SDL_floorf + * \sa SDL_truncf + * \sa SDL_roundf + * \sa SDL_lroundf + */ +extern SDL_DECLSPEC float SDLCALL SDL_ceilf(float x); + +/** + * Copy the sign of one floating-point value to another. + * + * The definition of copysign is that ``copysign(x, y) = abs(x) * sign(y)``. + * + * Domain: `-INF <= x <= INF`, ``-INF <= y <= f`` + * + * Range: `-INF <= z <= INF` + * + * This function operates on double-precision floating point values, use + * SDL_copysignf for single-precision floats. + * + * \param x floating point value to use as the magnitude. + * \param y floating point value to use as the sign. + * \returns the floating point value with the sign of y and the magnitude of + * x. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_copysignf + * \sa SDL_fabs + */ +extern SDL_DECLSPEC double SDLCALL SDL_copysign(double x, double y); + +/** + * Copy the sign of one floating-point value to another. + * + * The definition of copysign is that ``copysign(x, y) = abs(x) * sign(y)``. + * + * Domain: `-INF <= x <= INF`, ``-INF <= y <= f`` + * + * Range: `-INF <= z <= INF` + * + * This function operates on single-precision floating point values, use + * SDL_copysign for double-precision floats. + * + * \param x floating point value to use as the magnitude. + * \param y floating point value to use as the sign. + * \returns the floating point value with the sign of y and the magnitude of + * x. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_copysignf + * \sa SDL_fabsf + */ +extern SDL_DECLSPEC float SDLCALL SDL_copysignf(float x, float y); + +/** + * Compute the cosine of `x`. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-1 <= y <= 1` + * + * This function operates on double-precision floating point values, use + * SDL_cosf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value, in radians. + * \returns cosine of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_cosf + * \sa SDL_acos + * \sa SDL_sin + */ +extern SDL_DECLSPEC double SDLCALL SDL_cos(double x); + +/** + * Compute the cosine of `x`. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-1 <= y <= 1` + * + * This function operates on single-precision floating point values, use + * SDL_cos for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value, in radians. + * \returns cosine of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_cos + * \sa SDL_acosf + * \sa SDL_sinf + */ +extern SDL_DECLSPEC float SDLCALL SDL_cosf(float x); /** - * Report if a character is a hexadecimal digit. + * Compute the exponential of `x`. * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * 'A' through 'F', 'a' through 'f', and '0' through '9', as true. + * The definition of `y = exp(x)` is `y = e^x`, where `e` is the base of the + * natural logarithm. The inverse is the natural logarithm, SDL_log. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Domain: `-INF <= x <= INF` + * + * Range: `0 <= y <= INF` + * + * The output will overflow if `exp(x)` is too large to be represented. + * + * This function operates on double-precision floating point values, use + * SDL_expf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns value of `e^x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_expf + * \sa SDL_log */ -extern DECLSPEC int SDLCALL SDL_isxdigit(int x); +extern SDL_DECLSPEC double SDLCALL SDL_exp(double x); /** - * Report if a character is a punctuation mark. + * Compute the exponential of `x`. * - * **WARNING**: Regardless of system locale, this is equivalent to - * `((SDL_isgraph(x)) && (!SDL_isalnum(x)))`. + * The definition of `y = exp(x)` is `y = e^x`, where `e` is the base of the + * natural logarithm. The inverse is the natural logarithm, SDL_logf. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Domain: `-INF <= x <= INF` + * + * Range: `0 <= y <= INF` + * + * The output will overflow if `exp(x)` is too large to be represented. + * + * This function operates on single-precision floating point values, use + * SDL_exp for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. + * \returns value of `e^x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_isgraph - * \sa SDL_isalnum + * \sa SDL_exp + * \sa SDL_logf */ -extern DECLSPEC int SDLCALL SDL_ispunct(int x); +extern SDL_DECLSPEC float SDLCALL SDL_expf(float x); /** - * Report if a character is whitespace. + * Compute the absolute value of `x` * - * **WARNING**: Regardless of system locale, this will only treat the - * following ASCII values as true: + * Domain: `-INF <= x <= INF` * - * - space (0x20) - * - tab (0x09) - * - newline (0x0A) - * - vertical tab (0x0B) - * - form feed (0x0C) - * - return (0x0D) + * Range: `0 <= y <= INF` * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * This function operates on double-precision floating point values, use + * SDL_copysignf for single-precision floats. + * + * \param x floating point value to use as the magnitude. + * \returns the absolute value of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_fabsf */ -extern DECLSPEC int SDLCALL SDL_isspace(int x); +extern SDL_DECLSPEC double SDLCALL SDL_fabs(double x); /** - * Report if a character is upper case. + * Compute the absolute value of `x` * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * 'A' through 'Z' as true. + * Domain: `-INF <= x <= INF` * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Range: `0 <= y <= INF` + * + * This function operates on single-precision floating point values, use + * SDL_copysignf for double-precision floats. + * + * \param x floating point value to use as the magnitude. + * \returns the absolute value of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_fabs */ -extern DECLSPEC int SDLCALL SDL_isupper(int x); +extern SDL_DECLSPEC float SDLCALL SDL_fabsf(float x); /** - * Report if a character is lower case. + * Compute the floor of `x`. * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * 'a' through 'z' as true. + * The floor of `x` is the largest integer `y` such that `y > x`, i.e `x` + * rounded down to the nearest integer. * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Domain: `-INF <= x <= INF` + * + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on double-precision floating point values, use + * SDL_floorf for single-precision floats. + * + * \param x floating point value. + * \returns the floor of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_floorf + * \sa SDL_ceil + * \sa SDL_trunc + * \sa SDL_round + * \sa SDL_lround */ -extern DECLSPEC int SDLCALL SDL_islower(int x); +extern SDL_DECLSPEC double SDLCALL SDL_floor(double x); /** - * Report if a character is "printable". + * Compute the floor of `x`. * - * Be advised that "printable" has a definition that goes back to text - * terminals from the dawn of computing, making this a sort of special case - * function that is not suitable for Unicode (or most any) text management. + * The floor of `x` is the largest integer `y` such that `y > x`, i.e `x` + * rounded down to the nearest integer. * - * **WARNING**: Regardless of system locale, this will only treat ASCII values - * ' ' (0x20) through '~' (0x7E) as true. + * Domain: `-INF <= x <= INF` * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on single-precision floating point values, use + * SDL_floorf for double-precision floats. + * + * \param x floating point value. + * \returns the floor of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_floor + * \sa SDL_ceilf + * \sa SDL_truncf + * \sa SDL_roundf + * \sa SDL_lroundf */ -extern DECLSPEC int SDLCALL SDL_isprint(int x); +extern SDL_DECLSPEC float SDLCALL SDL_floorf(float x); /** - * Report if a character is any "printable" except space. + * Truncate `x` to an integer. * - * Be advised that "printable" has a definition that goes back to text - * terminals from the dawn of computing, making this a sort of special case - * function that is not suitable for Unicode (or most any) text management. + * Rounds `x` to the next closest integer to 0. This is equivalent to removing + * the fractional part of `x`, leaving only the integer part. * - * **WARNING**: Regardless of system locale, this is equivalent to - * `(SDL_isprint(x)) && ((x) != ' ')`. + * Domain: `-INF <= x <= INF` * - * \param x character value to check. - * \returns non-zero if x falls within the character class, zero otherwise. + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on double-precision floating point values, use + * SDL_truncf for single-precision floats. + * + * \param x floating point value. + * \returns `x` truncated to an integer. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_isprint + * \sa SDL_truncf + * \sa SDL_fmod + * \sa SDL_ceil + * \sa SDL_floor + * \sa SDL_round + * \sa SDL_lround */ -extern DECLSPEC int SDLCALL SDL_isgraph(int x); +extern SDL_DECLSPEC double SDLCALL SDL_trunc(double x); /** - * Convert low-ASCII English letters to uppercase. + * Truncate `x` to an integer. * - * **WARNING**: Regardless of system locale, this will only convert ASCII - * values 'a' through 'z' to uppercase. + * Rounds `x` to the next closest integer to 0. This is equivalent to removing + * the fractional part of `x`, leaving only the integer part. * - * This function returns the uppercase equivalent of `x`. If a character - * cannot be converted, or is already uppercase, this function returns `x`. + * Domain: `-INF <= x <= INF` * - * \param x character value to check. - * \returns Capitalized version of x, or x if no conversion available. + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on single-precision floating point values, use + * SDL_truncf for double-precision floats. + * + * \param x floating point value. + * \returns `x` truncated to an integer. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_trunc + * \sa SDL_fmodf + * \sa SDL_ceilf + * \sa SDL_floorf + * \sa SDL_roundf + * \sa SDL_lroundf */ -extern DECLSPEC int SDLCALL SDL_toupper(int x); +extern SDL_DECLSPEC float SDLCALL SDL_truncf(float x); /** - * Convert low-ASCII English letters to lowercase. + * Return the floating-point remainder of `x / y` * - * **WARNING**: Regardless of system locale, this will only convert ASCII - * values 'A' through 'Z' to lowercase. + * Divides `x` by `y`, and returns the remainder. * - * This function returns the lowercase equivalent of `x`. If a character - * cannot be converted, or is already lowercase, this function returns `x`. + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF`, `y != 0` * - * \param x character value to check. - * \returns Lowercase version of x, or x if no conversion available. + * Range: `-y <= z <= y` + * + * This function operates on double-precision floating point values, use + * SDL_fmodf for single-precision floats. + * + * \param x the numerator. + * \param y the denominator. Must not be 0. + * \returns the remainder of `x / y`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_fmodf + * \sa SDL_modf + * \sa SDL_trunc + * \sa SDL_ceil + * \sa SDL_floor + * \sa SDL_round + * \sa SDL_lround */ -extern DECLSPEC int SDLCALL SDL_tolower(int x); +extern SDL_DECLSPEC double SDLCALL SDL_fmod(double x, double y); -extern DECLSPEC Uint16 SDLCALL SDL_crc16(Uint16 crc, const void *data, size_t len); -extern DECLSPEC Uint32 SDLCALL SDL_crc32(Uint32 crc, const void *data, size_t len); +/** + * Return the floating-point remainder of `x / y` + * + * Divides `x` by `y`, and returns the remainder. + * + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF`, `y != 0` + * + * Range: `-y <= z <= y` + * + * This function operates on single-precision floating point values, use + * SDL_fmod for single-precision floats. + * + * \param x the numerator. + * \param y the denominator. Must not be 0. + * \returns the remainder of `x / y`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_fmod + * \sa SDL_truncf + * \sa SDL_modff + * \sa SDL_ceilf + * \sa SDL_floorf + * \sa SDL_roundf + * \sa SDL_lroundf + */ +extern SDL_DECLSPEC float SDLCALL SDL_fmodf(float x, float y); -extern DECLSPEC void *SDLCALL SDL_memcpy(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); +/** + * Return whether the value is infinity. + * + * \param x double-precision floating point value. + * \returns non-zero if the value is infinity, 0 otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isinff + */ +extern SDL_DECLSPEC int SDLCALL SDL_isinf(double x); -/* Take advantage of compiler optimizations for memcpy */ -#ifndef SDL_SLOW_MEMCPY -#ifdef SDL_memcpy -#undef SDL_memcpy -#endif -#define SDL_memcpy memcpy -#endif +/** + * Return whether the value is infinity. + * + * \param x floating point value. + * \returns non-zero if the value is infinity, 0 otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isinf + */ +extern SDL_DECLSPEC int SDLCALL SDL_isinff(float x); -#define SDL_copyp(dst, src) \ - { SDL_COMPILE_TIME_ASSERT(SDL_copyp, sizeof (*(dst)) == sizeof (*(src))); } \ - SDL_memcpy((dst), (src), sizeof(*(src))) +/** + * Return whether the value is NaN. + * + * \param x double-precision floating point value. + * \returns non-zero if the value is NaN, 0 otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isnanf + */ +extern SDL_DECLSPEC int SDLCALL SDL_isnan(double x); -extern DECLSPEC void *SDLCALL SDL_memmove(SDL_OUT_BYTECAP(len) void *dst, SDL_IN_BYTECAP(len) const void *src, size_t len); +/** + * Return whether the value is NaN. + * + * \param x floating point value. + * \returns non-zero if the value is NaN, 0 otherwise. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_isnan + */ +extern SDL_DECLSPEC int SDLCALL SDL_isnanf(float x); -/* Take advantage of compiler optimizations for memmove */ -#ifndef SDL_SLOW_MEMMOVE -#ifdef SDL_memmove -#undef SDL_memmove -#endif -#define SDL_memmove memmove -#endif +/** + * Compute the natural logarithm of `x`. + * + * Domain: `0 < x <= INF` + * + * Range: `-INF <= y <= INF` + * + * It is an error for `x` to be less than or equal to 0. + * + * This function operates on double-precision floating point values, use + * SDL_logf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. Must be greater than 0. + * \returns the natural logarithm of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_logf + * \sa SDL_log10 + * \sa SDL_exp + */ +extern SDL_DECLSPEC double SDLCALL SDL_log(double x); -extern DECLSPEC void *SDLCALL SDL_memset(SDL_OUT_BYTECAP(len) void *dst, int c, size_t len); -extern DECLSPEC void *SDLCALL SDL_memset4(void *dst, Uint32 val, size_t dwords); +/** + * Compute the natural logarithm of `x`. + * + * Domain: `0 < x <= INF` + * + * Range: `-INF <= y <= INF` + * + * It is an error for `x` to be less than or equal to 0. + * + * This function operates on single-precision floating point values, use + * SDL_log for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. Must be greater than 0. + * \returns the natural logarithm of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_log + * \sa SDL_expf + */ +extern SDL_DECLSPEC float SDLCALL SDL_logf(float x); -/* Take advantage of compiler optimizations for memset */ -#ifndef SDL_SLOW_MEMSET -#ifdef SDL_memset -#undef SDL_memset -#endif -#define SDL_memset memset -#endif +/** + * Compute the base-10 logarithm of `x`. + * + * Domain: `0 < x <= INF` + * + * Range: `-INF <= y <= INF` + * + * It is an error for `x` to be less than or equal to 0. + * + * This function operates on double-precision floating point values, use + * SDL_log10f for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. Must be greater than 0. + * \returns the logarithm of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_log10f + * \sa SDL_log + * \sa SDL_pow + */ +extern SDL_DECLSPEC double SDLCALL SDL_log10(double x); -#define SDL_zero(x) SDL_memset(&(x), 0, sizeof((x))) -#define SDL_zerop(x) SDL_memset((x), 0, sizeof(*(x))) -#define SDL_zeroa(x) SDL_memset((x), 0, sizeof((x))) +/** + * Compute the base-10 logarithm of `x`. + * + * Domain: `0 < x <= INF` + * + * Range: `-INF <= y <= INF` + * + * It is an error for `x` to be less than or equal to 0. + * + * This function operates on single-precision floating point values, use + * SDL_log10 for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. Must be greater than 0. + * \returns the logarithm of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_log10 + * \sa SDL_logf + * \sa SDL_powf + */ +extern SDL_DECLSPEC float SDLCALL SDL_log10f(float x); + +/** + * Split `x` into integer and fractional parts + * + * This function operates on double-precision floating point values, use + * SDL_modff for single-precision floats. + * + * \param x floating point value. + * \param y output pointer to store the integer part of `x`. + * \returns the fractional part of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_modff + * \sa SDL_trunc + * \sa SDL_fmod + */ +extern SDL_DECLSPEC double SDLCALL SDL_modf(double x, double *y); + +/** + * Split `x` into integer and fractional parts + * + * This function operates on single-precision floating point values, use + * SDL_modf for double-precision floats. + * + * \param x floating point value. + * \param y output pointer to store the integer part of `x`. + * \returns the fractional part of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_modf + * \sa SDL_truncf + * \sa SDL_fmodf + */ +extern SDL_DECLSPEC float SDLCALL SDL_modff(float x, float *y); -extern DECLSPEC int SDLCALL SDL_memcmp(const void *s1, const void *s2, size_t len); +/** + * Raise `x` to the power `y` + * + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` + * + * Range: `-INF <= z <= INF` + * + * If `y` is the base of the natural logarithm (e), consider using SDL_exp + * instead. + * + * This function operates on double-precision floating point values, use + * SDL_powf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x the base. + * \param y the exponent. + * \returns `x` raised to the power `y`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_powf + * \sa SDL_exp + * \sa SDL_log + */ +extern SDL_DECLSPEC double SDLCALL SDL_pow(double x, double y); -extern DECLSPEC size_t SDLCALL SDL_wcslen(const wchar_t *wstr); -extern DECLSPEC size_t SDLCALL SDL_wcsnlen(const wchar_t *wstr, size_t maxlen); -extern DECLSPEC size_t SDLCALL SDL_wcslcpy(SDL_OUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); -extern DECLSPEC size_t SDLCALL SDL_wcslcat(SDL_INOUT_Z_CAP(maxlen) wchar_t *dst, const wchar_t *src, size_t maxlen); -extern DECLSPEC wchar_t *SDLCALL SDL_wcsdup(const wchar_t *wstr); -extern DECLSPEC wchar_t *SDLCALL SDL_wcsstr(const wchar_t *haystack, const wchar_t *needle); -extern DECLSPEC wchar_t *SDLCALL SDL_wcsnstr(const wchar_t *haystack, const wchar_t *needle, size_t maxlen); +/** + * Raise `x` to the power `y` + * + * Domain: `-INF <= x <= INF`, `-INF <= y <= INF` + * + * Range: `-INF <= z <= INF` + * + * If `y` is the base of the natural logarithm (e), consider using SDL_exp + * instead. + * + * This function operates on single-precision floating point values, use + * SDL_powf for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x the base. + * \param y the exponent. + * \returns `x` raised to the power `y`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_pow + * \sa SDL_expf + * \sa SDL_logf + */ +extern SDL_DECLSPEC float SDLCALL SDL_powf(float x, float y); /** - * Compare two null-terminated wide strings. + * Round `x` to the nearest integer. * - * This only compares wchar_t values until it hits a null-terminating - * character; it does not care if the string is well-formed UTF-16 (or UTF-32, - * depending on your platform's wchar_t size), or uses valid Unicode values. + * Rounds `x` to the nearest integer. Values halfway between integers will be + * rounded away from zero. * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * Domain: `-INF <= x <= INF` + * + * Range: `-INF <= y <= INF`, y integer + * + * This function operates on double-precision floating point values, use + * SDL_roundf for single-precision floats. To get the result as an integer + * type, use SDL_lround. + * + * \param x floating point value. + * \returns the nearest integer to `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_roundf + * \sa SDL_lround + * \sa SDL_floor + * \sa SDL_ceil + * \sa SDL_trunc */ -extern DECLSPEC int SDLCALL SDL_wcscmp(const wchar_t *str1, const wchar_t *str2); +extern SDL_DECLSPEC double SDLCALL SDL_round(double x); /** - * Compare two wide strings up to a number of wchar_t values. + * Round `x` to the nearest integer. * - * This only compares wchar_t values; it does not care if the string is - * well-formed UTF-16 (or UTF-32, depending on your platform's wchar_t size), - * or uses valid Unicode values. + * Rounds `x` to the nearest integer. Values halfway between integers will be + * rounded away from zero. * - * Note that while this function is intended to be used with UTF-16 (or - * UTF-32, depending on your platform's definition of wchar_t), it is - * comparing raw wchar_t values and not Unicode codepoints: `maxlen` specifies - * a wchar_t limit! If the limit lands in the middle of a multi-wchar UTF-16 - * sequence, it will only compare a portion of the final character. + * Domain: `-INF <= x <= INF` * - * `maxlen` specifies a maximum number of wchar_t to compare; if the strings - * match to this number of wide chars (or both have matched to a - * null-terminator character before this count), they will be considered - * equal. + * Range: `-INF <= y <= INF`, y integer * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \param maxlen The maximum number of wchar_t to compare. - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * This function operates on double-precision floating point values, use + * SDL_roundf for single-precision floats. To get the result as an integer + * type, use SDL_lroundf. + * + * \param x floating point value. + * \returns the nearest integer to `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_round + * \sa SDL_lroundf + * \sa SDL_floorf + * \sa SDL_ceilf + * \sa SDL_truncf */ -extern DECLSPEC int SDLCALL SDL_wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); +extern SDL_DECLSPEC float SDLCALL SDL_roundf(float x); /** - * Compare two null-terminated wide strings, case-insensitively. + * Round `x` to the nearest integer representable as a long * - * This will work with Unicode strings, using a technique called - * "case-folding" to handle the vast majority of case-sensitive human - * languages regardless of system locale. It can deal with expanding values: a - * German Eszett character can compare against two ASCII 's' chars and be - * considered a match, for example. A notable exception: it does not handle - * the Turkish 'i' character; human language is complicated! + * Rounds `x` to the nearest integer. Values halfway between integers will be + * rounded away from zero. * - * Depending on your platform, "wchar_t" might be 2 bytes, and expected to be - * UTF-16 encoded (like Windows), or 4 bytes in UTF-32 format. Since this - * handles Unicode, it expects the string to be well-formed and not a - * null-terminated string of arbitrary bytes. Characters that are not valid - * UTF-16 (or UTF-32) are treated as Unicode character U+FFFD (REPLACEMENT - * CHARACTER), which is to say two strings of random bits may turn out to - * match if they convert to the same amount of replacement characters. + * Domain: `-INF <= x <= INF` * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * Range: `MIN_LONG <= y <= MAX_LONG` + * + * This function operates on double-precision floating point values, use + * SDL_lround for single-precision floats. To get the result as a + * floating-point type, use SDL_round. + * + * \param x floating point value. + * \returns the nearest integer to `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_lroundf + * \sa SDL_round + * \sa SDL_floor + * \sa SDL_ceil + * \sa SDL_trunc */ -extern DECLSPEC int SDLCALL SDL_wcscasecmp(const wchar_t *str1, const wchar_t *str2); +extern SDL_DECLSPEC long SDLCALL SDL_lround(double x); /** - * Compare two wide strings, case-insensitively, up to a number of wchar_t. + * Round `x` to the nearest integer representable as a long * - * This will work with Unicode strings, using a technique called - * "case-folding" to handle the vast majority of case-sensitive human - * languages regardless of system locale. It can deal with expanding values: a - * German Eszett character can compare against two ASCII 's' chars and be - * considered a match, for example. A notable exception: it does not handle - * the Turkish 'i' character; human language is complicated! + * Rounds `x` to the nearest integer. Values halfway between integers will be + * rounded away from zero. * - * Depending on your platform, "wchar_t" might be 2 bytes, and expected to be - * UTF-16 encoded (like Windows), or 4 bytes in UTF-32 format. Since this - * handles Unicode, it expects the string to be well-formed and not a - * null-terminated string of arbitrary bytes. Characters that are not valid - * UTF-16 (or UTF-32) are treated as Unicode character U+FFFD (REPLACEMENT - * CHARACTER), which is to say two strings of random bits may turn out to - * match if they convert to the same amount of replacement characters. + * Domain: `-INF <= x <= INF` * - * Note that while this function might deal with variable-sized characters, - * `maxlen` specifies a _wchar_ limit! If the limit lands in the middle of a - * multi-byte UTF-16 sequence, it may convert a portion of the final character - * to one or more Unicode character U+FFFD (REPLACEMENT CHARACTER) so as not - * to overflow a buffer. + * Range: `MIN_LONG <= y <= MAX_LONG` * - * `maxlen` specifies a maximum number of wchar_t values to compare; if the - * strings match to this number of wchar_t (or both have matched to a - * null-terminator character before this number of bytes), they will be - * considered equal. + * This function operates on single-precision floating point values, use + * SDL_lroundf for double-precision floats. To get the result as a + * floating-point type, use SDL_roundf, * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \param maxlen The maximum number of wchar_t values to compare. - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * \param x floating point value. + * \returns the nearest integer to `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_lround + * \sa SDL_roundf + * \sa SDL_floorf + * \sa SDL_ceilf + * \sa SDL_truncf */ -extern DECLSPEC int SDLCALL SDL_wcsncasecmp(const wchar_t *str1, const wchar_t *str2, size_t maxlen); - -extern DECLSPEC long SDLCALL SDL_wcstol(const wchar_t *str, wchar_t **endp, int base); - -extern DECLSPEC size_t SDLCALL SDL_strlen(const char *str); -extern DECLSPEC size_t SDLCALL SDL_strnlen(const char *str, size_t maxlen); -extern DECLSPEC size_t SDLCALL SDL_strlcpy(SDL_OUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); -extern DECLSPEC size_t SDLCALL SDL_utf8strlcpy(SDL_OUT_Z_CAP(dst_bytes) char *dst, const char *src, size_t dst_bytes); -extern DECLSPEC size_t SDLCALL SDL_strlcat(SDL_INOUT_Z_CAP(maxlen) char *dst, const char *src, size_t maxlen); -extern DECLSPEC SDL_MALLOC char *SDLCALL SDL_strdup(const char *str); -extern DECLSPEC SDL_MALLOC char *SDLCALL SDL_strndup(const char *str, size_t maxlen); -extern DECLSPEC char *SDLCALL SDL_strrev(char *str); +extern SDL_DECLSPEC long SDLCALL SDL_lroundf(float x); /** - * Convert a string to uppercase. + * Scale `x` by an integer power of two. * - * **WARNING**: Regardless of system locale, this will only convert ASCII - * values 'A' through 'Z' to uppercase. + * Multiplies `x` by the `n`th power of the floating point radix (always 2). * - * This function operates on a null-terminated string of bytes--even if it is - * malformed UTF-8!--and converts ASCII characters 'a' through 'z' to their - * uppercase equivalents in-place, returning the original `str` pointer. + * Domain: `-INF <= x <= INF`, `n` integer + * + * Range: `-INF <= y <= INF` + * + * This function operates on double-precision floating point values, use + * SDL_scalbnf for single-precision floats. + * + * \param x floating point value to be scaled. + * \param n integer exponent. + * \returns `x * 2^n`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_strlwr + * \sa SDL_scalbnf + * \sa SDL_pow */ -extern DECLSPEC char *SDLCALL SDL_strupr(char *str); +extern SDL_DECLSPEC double SDLCALL SDL_scalbn(double x, int n); /** - * Convert a string to lowercase. + * Scale `x` by an integer power of two. * - * **WARNING**: Regardless of system locale, this will only convert ASCII - * values 'A' through 'Z' to lowercase. + * Multiplies `x` by the `n`th power of the floating point radix (always 2). * - * This function operates on a null-terminated string of bytes--even if it is - * malformed UTF-8!--and converts ASCII characters 'A' through 'Z' to their - * lowercase equivalents in-place, returning the original `str` pointer. + * Domain: `-INF <= x <= INF`, `n` integer * - * \param str The string to convert in-place. - * \returns The `str` pointer passed into this function. + * Range: `-INF <= y <= INF` + * + * This function operates on single-precision floating point values, use + * SDL_scalbn for double-precision floats. + * + * \param x floating point value to be scaled. + * \param n integer exponent. + * \returns `x * 2^n`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_strupr + * \sa SDL_scalbn + * \sa SDL_powf */ -extern DECLSPEC char *SDLCALL SDL_strlwr(char *str); - -extern DECLSPEC char *SDLCALL SDL_strchr(const char *str, int c); -extern DECLSPEC char *SDLCALL SDL_strrchr(const char *str, int c); -extern DECLSPEC char *SDLCALL SDL_strstr(const char *haystack, const char *needle); -extern DECLSPEC char *SDLCALL SDL_strnstr(const char *haystack, const char *needle, size_t maxlen); -extern DECLSPEC char *SDLCALL SDL_strcasestr(const char *haystack, const char *needle); -extern DECLSPEC char *SDLCALL SDL_strtok_r(char *s1, const char *s2, char **saveptr); -extern DECLSPEC size_t SDLCALL SDL_utf8strlen(const char *str); -extern DECLSPEC size_t SDLCALL SDL_utf8strnlen(const char *str, size_t bytes); - -extern DECLSPEC char *SDLCALL SDL_itoa(int value, char *str, int radix); -extern DECLSPEC char *SDLCALL SDL_uitoa(unsigned int value, char *str, int radix); -extern DECLSPEC char *SDLCALL SDL_ltoa(long value, char *str, int radix); -extern DECLSPEC char *SDLCALL SDL_ultoa(unsigned long value, char *str, int radix); -extern DECLSPEC char *SDLCALL SDL_lltoa(Sint64 value, char *str, int radix); -extern DECLSPEC char *SDLCALL SDL_ulltoa(Uint64 value, char *str, int radix); - -extern DECLSPEC int SDLCALL SDL_atoi(const char *str); -extern DECLSPEC double SDLCALL SDL_atof(const char *str); -extern DECLSPEC long SDLCALL SDL_strtol(const char *str, char **endp, int base); -extern DECLSPEC unsigned long SDLCALL SDL_strtoul(const char *str, char **endp, int base); -extern DECLSPEC Sint64 SDLCALL SDL_strtoll(const char *str, char **endp, int base); -extern DECLSPEC Uint64 SDLCALL SDL_strtoull(const char *str, char **endp, int base); -extern DECLSPEC double SDLCALL SDL_strtod(const char *str, char **endp); +extern SDL_DECLSPEC float SDLCALL SDL_scalbnf(float x, int n); /** - * Compare two null-terminated UTF-8 strings. + * Compute the sine of `x`. * - * Due to the nature of UTF-8 encoding, this will work with Unicode strings, - * since effectively this function just compares bytes until it hits a - * null-terminating character. Also due to the nature of UTF-8, this can be - * used with SDL_qsort() to put strings in (roughly) alphabetical order. + * Domain: `-INF <= x <= INF` * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * Range: `-1 <= y <= 1` + * + * This function operates on double-precision floating point values, use + * SDL_sinf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value, in radians. + * \returns sine of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_sinf + * \sa SDL_asin + * \sa SDL_cos */ -extern DECLSPEC int SDLCALL SDL_strcmp(const char *str1, const char *str2); +extern SDL_DECLSPEC double SDLCALL SDL_sin(double x); /** - * Compare two UTF-8 strings up to a number of bytes. + * Compute the sine of `x`. * - * Due to the nature of UTF-8 encoding, this will work with Unicode strings, - * since effectively this function just compares bytes until it hits a - * null-terminating character. Also due to the nature of UTF-8, this can be - * used with SDL_qsort() to put strings in (roughly) alphabetical order. + * Domain: `-INF <= x <= INF` * - * Note that while this function is intended to be used with UTF-8, it is - * doing a bytewise comparison, and `maxlen` specifies a _byte_ limit! If the - * limit lands in the middle of a multi-byte UTF-8 sequence, it will only - * compare a portion of the final character. + * Range: `-1 <= y <= 1` * - * `maxlen` specifies a maximum number of bytes to compare; if the strings - * match to this number of bytes (or both have matched to a null-terminator - * character before this number of bytes), they will be considered equal. + * This function operates on single-precision floating point values, use + * SDL_sinf for double-precision floats. * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \param maxlen The maximum number of _bytes_ to compare. - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value, in radians. + * \returns sine of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_sin + * \sa SDL_asinf + * \sa SDL_cosf */ -extern DECLSPEC int SDLCALL SDL_strncmp(const char *str1, const char *str2, size_t maxlen); +extern SDL_DECLSPEC float SDLCALL SDL_sinf(float x); /** - * Compare two null-terminated UTF-8 strings, case-insensitively. + * Compute the square root of `x`. * - * This will work with Unicode strings, using a technique called - * "case-folding" to handle the vast majority of case-sensitive human - * languages regardless of system locale. It can deal with expanding values: a - * German Eszett character can compare against two ASCII 's' chars and be - * considered a match, for example. A notable exception: it does not handle - * the Turkish 'i' character; human language is complicated! + * Domain: `0 <= x <= INF` * - * Since this handles Unicode, it expects the string to be well-formed UTF-8 - * and not a null-terminated string of arbitrary bytes. Bytes that are not - * valid UTF-8 are treated as Unicode character U+FFFD (REPLACEMENT - * CHARACTER), which is to say two strings of random bits may turn out to - * match if they convert to the same amount of replacement characters. + * Range: `0 <= y <= INF` * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * This function operates on double-precision floating point values, use + * SDL_sqrtf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value. Must be greater than or equal to 0. + * \returns square root of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_sqrtf */ -extern DECLSPEC int SDLCALL SDL_strcasecmp(const char *str1, const char *str2); - +extern SDL_DECLSPEC double SDLCALL SDL_sqrt(double x); /** - * Compare two UTF-8 strings, case-insensitively, up to a number of bytes. + * Compute the square root of `x`. * - * This will work with Unicode strings, using a technique called - * "case-folding" to handle the vast majority of case-sensitive human - * languages regardless of system locale. It can deal with expanding values: a - * German Eszett character can compare against two ASCII 's' chars and be - * considered a match, for example. A notable exception: it does not handle - * the Turkish 'i' character; human language is complicated! + * Domain: `0 <= x <= INF` * - * Since this handles Unicode, it expects the string to be well-formed UTF-8 - * and not a null-terminated string of arbitrary bytes. Bytes that are not - * valid UTF-8 are treated as Unicode character U+FFFD (REPLACEMENT - * CHARACTER), which is to say two strings of random bits may turn out to - * match if they convert to the same amount of replacement characters. + * Range: `0 <= y <= INF` * - * Note that while this function is intended to be used with UTF-8, `maxlen` - * specifies a _byte_ limit! If the limit lands in the middle of a multi-byte - * UTF-8 sequence, it may convert a portion of the final character to one or - * more Unicode character U+FFFD (REPLACEMENT CHARACTER) so as not to overflow - * a buffer. + * This function operates on single-precision floating point values, use + * SDL_sqrt for double-precision floats. * - * `maxlen` specifies a maximum number of bytes to compare; if the strings - * match to this number of bytes (or both have matched to a null-terminator - * character before this number of bytes), they will be considered equal. + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. * - * \param str1 The first string to compare. NULL is not permitted! - * \param str2 The second string to compare. NULL is not permitted! - * \param maxlen The maximum number of bytes to compare. - * \returns less than zero if str1 is "less than" str2, greater than zero if - * str1 is "greater than" str2, and zero if the strings match - * exactly. + * \param x floating point value. Must be greater than or equal to 0. + * \returns square root of `x`. * * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_sqrt */ -extern DECLSPEC int SDLCALL SDL_strncasecmp(const char *str1, const char *str2, size_t maxlen); - -extern DECLSPEC int SDLCALL SDL_sscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, ...) SDL_SCANF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vsscanf(const char *text, SDL_SCANF_FORMAT_STRING const char *fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); -extern DECLSPEC int SDLCALL SDL_snprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ... ) SDL_PRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_swprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ... ) SDL_WPRINTF_VARARG_FUNC(3); -extern DECLSPEC int SDLCALL SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3); -extern DECLSPEC int SDLCALL SDL_vswprintf(SDL_OUT_Z_CAP(maxlen) wchar_t *text, size_t maxlen, const wchar_t *fmt, va_list ap); -extern DECLSPEC int SDLCALL SDL_asprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -extern DECLSPEC int SDLCALL SDL_vasprintf(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2); +extern SDL_DECLSPEC float SDLCALL SDL_sqrtf(float x); -#ifndef SDL_PI_D -#define SDL_PI_D 3.141592653589793238462643383279502884 /**< pi (double) */ -#endif -#ifndef SDL_PI_F -#define SDL_PI_F 3.141592653589793238462643383279502884F /**< pi (float) */ -#endif +/** + * Compute the tangent of `x`. + * + * Domain: `-INF <= x <= INF` + * + * Range: `-INF <= y <= INF` + * + * This function operates on double-precision floating point values, use + * SDL_tanf for single-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. + * + * \param x floating point value, in radians. + * \returns tangent of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_tanf + * \sa SDL_sin + * \sa SDL_cos + * \sa SDL_atan + * \sa SDL_atan2 + */ +extern SDL_DECLSPEC double SDLCALL SDL_tan(double x); /** - * Use this function to compute arc cosine of `x`. + * Compute the tangent of `x`. * - * The definition of `y = acos(x)` is `x = cos(y)`. + * Domain: `-INF <= x <= INF` * - * Domain: `-1 <= x <= 1` + * Range: `-INF <= y <= INF` * - * Range: `0 <= y <= Pi` + * This function operates on single-precision floating point values, use + * SDL_tanf for double-precision floats. + * + * This function may use a different approximation across different versions, + * platforms and configurations. i.e, it can return a different value given + * the same input on different machines or operating systems, or if SDL is + * updated. * * \param x floating point value, in radians. - * \returns arc cosine of `x`. - * - * \threadsafety It is safe to call this function from any thread. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC double SDLCALL SDL_acos(double x); -extern DECLSPEC float SDLCALL SDL_acosf(float x); -extern DECLSPEC double SDLCALL SDL_asin(double x); -extern DECLSPEC float SDLCALL SDL_asinf(float x); -extern DECLSPEC double SDLCALL SDL_atan(double x); -extern DECLSPEC float SDLCALL SDL_atanf(float x); -extern DECLSPEC double SDLCALL SDL_atan2(double y, double x); -extern DECLSPEC float SDLCALL SDL_atan2f(float y, float x); -extern DECLSPEC double SDLCALL SDL_ceil(double x); -extern DECLSPEC float SDLCALL SDL_ceilf(float x); -extern DECLSPEC double SDLCALL SDL_copysign(double x, double y); -extern DECLSPEC float SDLCALL SDL_copysignf(float x, float y); -extern DECLSPEC double SDLCALL SDL_cos(double x); -extern DECLSPEC float SDLCALL SDL_cosf(float x); -extern DECLSPEC double SDLCALL SDL_exp(double x); -extern DECLSPEC float SDLCALL SDL_expf(float x); -extern DECLSPEC double SDLCALL SDL_fabs(double x); -extern DECLSPEC float SDLCALL SDL_fabsf(float x); -extern DECLSPEC double SDLCALL SDL_floor(double x); -extern DECLSPEC float SDLCALL SDL_floorf(float x); -extern DECLSPEC double SDLCALL SDL_trunc(double x); -extern DECLSPEC float SDLCALL SDL_truncf(float x); -extern DECLSPEC double SDLCALL SDL_fmod(double x, double y); -extern DECLSPEC float SDLCALL SDL_fmodf(float x, float y); -extern DECLSPEC double SDLCALL SDL_log(double x); -extern DECLSPEC float SDLCALL SDL_logf(float x); -extern DECLSPEC double SDLCALL SDL_log10(double x); -extern DECLSPEC float SDLCALL SDL_log10f(float x); -extern DECLSPEC double SDLCALL SDL_modf(double x, double *y); -extern DECLSPEC float SDLCALL SDL_modff(float x, float *y); -extern DECLSPEC double SDLCALL SDL_pow(double x, double y); -extern DECLSPEC float SDLCALL SDL_powf(float x, float y); -extern DECLSPEC double SDLCALL SDL_round(double x); -extern DECLSPEC float SDLCALL SDL_roundf(float x); -extern DECLSPEC long SDLCALL SDL_lround(double x); -extern DECLSPEC long SDLCALL SDL_lroundf(float x); -extern DECLSPEC double SDLCALL SDL_scalbn(double x, int n); -extern DECLSPEC float SDLCALL SDL_scalbnf(float x, int n); -extern DECLSPEC double SDLCALL SDL_sin(double x); -extern DECLSPEC float SDLCALL SDL_sinf(float x); -extern DECLSPEC double SDLCALL SDL_sqrt(double x); -extern DECLSPEC float SDLCALL SDL_sqrtf(float x); -extern DECLSPEC double SDLCALL SDL_tan(double x); -extern DECLSPEC float SDLCALL SDL_tanf(float x); + * \returns tangent of `x`. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_tan + * \sa SDL_sinf + * \sa SDL_cosf + * \sa SDL_atanf + * \sa SDL_atan2f + */ +extern SDL_DECLSPEC float SDLCALL SDL_tanf(float x); /* The SDL implementation of iconv() returns these error codes */ #define SDL_ICONV_ERROR (size_t)-1 @@ -1203,25 +4081,110 @@ extern DECLSPEC float SDLCALL SDL_tanf(float x); #define SDL_ICONV_EILSEQ (size_t)-3 #define SDL_ICONV_EINVAL (size_t)-4 -/* SDL_iconv_* are now always real symbols/types, not macros or inlined. */ typedef struct SDL_iconv_data_t *SDL_iconv_t; -extern DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, + +/** + * This function allocates a context for the specified character set + * conversion. + * + * \param tocode The target character encoding, must not be NULL. + * \param fromcode The source character encoding, must not be NULL. + * \returns a handle that must be freed with SDL_iconv_close, or + * SDL_ICONV_ERROR on failure. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_iconv + * \sa SDL_iconv_close + * \sa SDL_iconv_string + */ +extern SDL_DECLSPEC SDL_iconv_t SDLCALL SDL_iconv_open(const char *tocode, const char *fromcode); -extern DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); -extern DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, - size_t * inbytesleft, char **outbuf, - size_t * outbytesleft); /** - * This function converts a buffer or string between encodings in one pass, - * returning a string that must be freed with SDL_free() or NULL on error. + * This function frees a context used for character set conversion. + * + * \param cd The character set conversion handle. + * \returns 0 on success, or -1 on failure. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_iconv + * \sa SDL_iconv_open + * \sa SDL_iconv_string + */ +extern SDL_DECLSPEC int SDLCALL SDL_iconv_close(SDL_iconv_t cd); + +/** + * This function converts text between encodings, reading from and writing to + * a buffer. + * + * It returns the number of succesful conversions. + * + * \param cd The character set conversion context, created in + * SDL_iconv_open(). + * \param inbuf Address of variable that points to the first character of the + * input sequence. + * \param inbytesleft The number of bytes in the input buffer. + * \param outbuf Address of variable that points to the output buffer. + * \param outbytesleft The number of bytes in the output buffer. + * \returns the number of conversions on success, else SDL_ICONV_E2BIG is + * returned when the output buffer is too small, or SDL_ICONV_EILSEQ + * is returned when an invalid input sequence is encountered, or + * SDL_ICONV_EINVAL is returned when an incomplete input sequence is + * encountered. + * + * On exit: + * + * - inbuf will point to the beginning of the next multibyte + * sequence. On error, this is the location of the problematic + * input sequence. On success, this is the end of the input + * sequence. - inbytesleft will be set to the number of bytes left + * to convert, which will be 0 on success. - outbuf will point to + * the location where to store the next output byte. - outbytesleft + * will be set to the number of bytes left in the output buffer. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_iconv_open + * \sa SDL_iconv_close + * \sa SDL_iconv_string + */ +extern SDL_DECLSPEC size_t SDLCALL SDL_iconv(SDL_iconv_t cd, const char **inbuf, + size_t *inbytesleft, char **outbuf, + size_t *outbytesleft); + +/** + * Helper function to convert a string's encoding in one call. + * + * This function converts a buffer or string between encodings in one pass. + * + * The string does not need to be NULL-terminated; this function operates on + * the number of bytes specified in `inbytesleft` whether there is a NULL + * character anywhere in the buffer. + * + * The returned string is owned by the caller, and should be passed to + * SDL_free when no longer needed. + * + * \param tocode the character encoding of the output string. Examples are + * "UTF-8", "UCS-4", etc. + * \param fromcode the character encoding of data in `inbuf`. + * \param inbuf the string to convert to a different encoding. + * \param inbytesleft the size of the input string _in bytes_. + * \returns a new string, converted to the new encoding, or NULL on error. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_iconv_open + * \sa SDL_iconv_close + * \sa SDL_iconv */ -extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, +extern SDL_DECLSPEC char * SDLCALL SDL_iconv_string(const char *tocode, const char *fromcode, const char *inbuf, size_t inbytesleft); + +/* Some helper macros for common cases... */ #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) #define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) @@ -1233,12 +4196,12 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, /* The analyzer knows about strlcpy even when the system doesn't provide it */ #if !defined(HAVE_STRLCPY) && !defined(strlcpy) -size_t strlcpy(char* dst, const char* src, size_t size); +size_t strlcpy(char *dst, const char *src, size_t size); #endif /* The analyzer knows about strlcat even when the system doesn't provide it */ #if !defined(HAVE_STRLCAT) && !defined(strlcat) -size_t strlcat(char* dst, const char* src, size_t size); +size_t strlcat(char *dst, const char *src, size_t size); #endif #if !defined(HAVE_WCSLCPY) && !defined(wcslcpy) @@ -1251,8 +4214,9 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); /* Starting LLVM 16, the analyser errors out if these functions do not have their prototype defined (clang-diagnostic-implicit-function-declaration) */ -#include #include +#include +#include #define SDL_malloc malloc #define SDL_calloc calloc @@ -1287,6 +4251,7 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #define SDL_wcsncmp wcsncmp #define SDL_strcasecmp strcasecmp #define SDL_strncasecmp strncasecmp +#define SDL_strpbrk strpbrk #define SDL_sscanf sscanf #define SDL_vsscanf vsscanf #define SDL_snprintf snprintf @@ -1294,66 +4259,102 @@ size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t size); #endif /** - * If a * b would overflow, return -1. Otherwise store a * b via ret - * and return 0. + * Multiply two integers, checking for overflow. + * + * If `a * b` would overflow, return false. + * + * Otherwise store `a * b` via ret and return true. + * + * \param a the multiplicand. + * \param b the multiplier. + * \param ret on non-overflow output, stores the multiplication result, may + * not be NULL. + * \returns false on overflow, true if result is multiplied without overflow. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE int SDL_size_mul_overflow (size_t a, - size_t b, - size_t *ret) +SDL_FORCE_INLINE bool SDL_size_mul_check_overflow(size_t a, size_t b, size_t *ret) { if (a != 0 && b > SDL_SIZE_MAX / a) { - return -1; + return false; } *ret = a * b; - return 0; + return true; } +#ifndef SDL_WIKI_DOCUMENTATION_SECTION #if SDL_HAS_BUILTIN(__builtin_mul_overflow) /* This needs to be wrapped in an inline rather than being a direct #define, * because __builtin_mul_overflow() is type-generic, but we want to be * consistent about interpreting a and b as size_t. */ -SDL_FORCE_INLINE int SDL_size_mul_overflow_builtin (size_t a, - size_t b, - size_t *ret) +SDL_FORCE_INLINE bool SDL_size_mul_check_overflow_builtin(size_t a, size_t b, size_t *ret) { - return __builtin_mul_overflow(a, b, ret) == 0 ? 0 : -1; + return (__builtin_mul_overflow(a, b, ret) == 0); } -#define SDL_size_mul_overflow(a, b, ret) (SDL_size_mul_overflow_builtin(a, b, ret)) +#define SDL_size_mul_check_overflow(a, b, ret) SDL_size_mul_check_overflow_builtin(a, b, ret) +#endif #endif /** - * If a + b would overflow, return -1. Otherwise store a + b via ret - * and return 0. + * Add two integers, checking for overflow. + * + * If `a + b` would overflow, return -1. + * + * Otherwise store `a + b` via ret and return 0. + * + * \param a the first addend. + * \param b the second addend. + * \param ret on non-overflow output, stores the addition result, may not be + * NULL. + * \returns false on overflow, true if result is added without overflow. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -SDL_FORCE_INLINE int SDL_size_add_overflow (size_t a, - size_t b, - size_t *ret) +SDL_FORCE_INLINE bool SDL_size_add_check_overflow(size_t a, size_t b, size_t *ret) { if (b > SDL_SIZE_MAX - a) { - return -1; + return false; } *ret = a + b; - return 0; + return true; } +#ifndef SDL_WIKI_DOCUMENTATION_SECTION #if SDL_HAS_BUILTIN(__builtin_add_overflow) /* This needs to be wrapped in an inline rather than being a direct #define, * the same as the call to __builtin_mul_overflow() above. */ -SDL_FORCE_INLINE int SDL_size_add_overflow_builtin (size_t a, - size_t b, - size_t *ret) +SDL_FORCE_INLINE bool SDL_size_add_check_overflow_builtin(size_t a, size_t b, size_t *ret) { - return __builtin_add_overflow(a, b, ret) == 0 ? 0 : -1; + return (__builtin_add_overflow(a, b, ret) == 0); } -#define SDL_size_add_overflow(a, b, ret) (SDL_size_add_overflow_builtin(a, b, ret)) +#define SDL_size_add_check_overflow(a, b, ret) SDL_size_add_check_overflow_builtin(a, b, ret) +#endif #endif /* This is a generic function pointer which should be cast to the type you expect */ -#ifdef SDL_FUNCTION_POINTER_IS_VOID_POINTER +#ifdef SDL_WIKI_DOCUMENTATION_SECTION + +/** + * A generic function pointer. + * + * In theory, generic function pointers should use this, instead of `void *`, + * since some platforms could treat code addresses differently than data + * addresses. Although in current times no popular platforms make this + * distinction, it is more correct and portable to use the correct type for a + * generic pointer. + * + * If for some reason you need to force this typedef to be an actual `void *`, + * perhaps to work around a compiler or existing code, you can define + * `SDL_FUNCTION_POINTER_IS_VOID_POINTER` before including any SDL headers. + * + * \since This datatype is available since SDL 3.0.0. + */ +typedef void (*SDL_FunctionPointer)(void); +#elif defined(SDL_FUNCTION_POINTER_IS_VOID_POINTER) typedef void *SDL_FunctionPointer; #else typedef void (*SDL_FunctionPointer)(void); diff --git a/libs/SDL3/include/SDL3/SDL_storage.h b/libs/SDL3/include/SDL3/SDL_storage.h index 61a75c389..9edbcf8e4 100644 --- a/libs/SDL3/include/SDL3/SDL_storage.h +++ b/libs/SDL3/include/SDL3/SDL_storage.h @@ -20,15 +20,16 @@ */ /** - * \file SDL_storage.h + * # CategoryStorage * - * Include file for storage container SDL API functions + * SDL storage container management. */ #ifndef SDL_storage_h_ #define SDL_storage_h_ #include +#include #include #include @@ -41,47 +42,87 @@ extern "C" { /* !!! FIXME: Don't let this ship without async R/W support!!! */ +/** + * Function interface for SDL_Storage. + * + * Apps that want to supply a custom implementation of SDL_Storage will fill + * in all the functions in this struct, and then pass it to SDL_OpenStorage to + * create a custom SDL_Storage object. + * + * It is not usually necessary to do this; SDL provides standard + * implementations for many things you might expect to do with an SDL_Storage. + * + * This structure should be initialized using SDL_INIT_INTERFACE() + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_INIT_INTERFACE + */ typedef struct SDL_StorageInterface { + /* The version of this interface */ + Uint32 version; + /* Called when the storage is closed */ - int (SDLCALL *close)(void *userdata); + bool (SDLCALL *close)(void *userdata); /* Optional, returns whether the storage is currently ready for access */ - SDL_bool (SDLCALL *ready)(void *userdata); + bool (SDLCALL *ready)(void *userdata); /* Enumerate a directory, optional for write-only storage */ - int (SDLCALL *enumerate)(void *userdata, const char *path, SDL_EnumerateDirectoryCallback callback, void *callback_userdata); + bool (SDLCALL *enumerate)(void *userdata, const char *path, SDL_EnumerateDirectoryCallback callback, void *callback_userdata); /* Get path information, optional for write-only storage */ - int (SDLCALL *info)(void *userdata, const char *path, SDL_PathInfo *info); + bool (SDLCALL *info)(void *userdata, const char *path, SDL_PathInfo *info); /* Read a file from storage, optional for write-only storage */ - int (SDLCALL *read_file)(void *userdata, const char *path, void *destination, Uint64 length); + bool (SDLCALL *read_file)(void *userdata, const char *path, void *destination, Uint64 length); /* Write a file to storage, optional for read-only storage */ - int (SDLCALL *write_file)(void *userdata, const char *path, const void *source, Uint64 length); + bool (SDLCALL *write_file)(void *userdata, const char *path, const void *source, Uint64 length); /* Create a directory, optional for read-only storage */ - int (SDLCALL *mkdir)(void *userdata, const char *path); + bool (SDLCALL *mkdir)(void *userdata, const char *path); /* Remove a file or empty directory, optional for read-only storage */ - int (SDLCALL *remove)(void *userdata, const char *path); + bool (SDLCALL *remove)(void *userdata, const char *path); /* Rename a path, optional for read-only storage */ - int (SDLCALL *rename)(void *userdata, const char *oldpath, const char *newpath); + bool (SDLCALL *rename)(void *userdata, const char *oldpath, const char *newpath); + + /* Copy a file, optional for read-only storage */ + bool (SDLCALL *copy)(void *userdata, const char *oldpath, const char *newpath); /* Get the space remaining, optional for read-only storage */ Uint64 (SDLCALL *space_remaining)(void *userdata); - } SDL_StorageInterface; +/* Check the size of SDL_StorageInterface + * + * If this assert fails, either the compiler is padding to an unexpected size, + * or the interface has been updated and this should be updated to match and + * the code using this interface should be updated to handle the old version. + */ +SDL_COMPILE_TIME_ASSERT(SDL_StorageInterface_SIZE, + (sizeof(void *) == 4 && sizeof(SDL_StorageInterface) == 48) || + (sizeof(void *) == 8 && sizeof(SDL_StorageInterface) == 96)); + +/** + * An abstract interface for filesystem access. + * + * This is an opaque datatype. One can create this object using standard SDL + * functions like SDL_OpenTitleStorage or SDL_OpenUserStorage, etc, or create + * an object with a custom implementation using SDL_OpenStorage. + * + * \since This struct is available since SDL 3.0.0. + */ typedef struct SDL_Storage SDL_Storage; /** * Opens up a read-only container for the application's filesystem. * - * \param override a path to override the backend's default title root - * \param props a property list that may contain backend-specific information + * \param override a path to override the backend's default title root. + * \param props a property list that may contain backend-specific information. * \returns a title storage container on success or NULL on failure; call * SDL_GetError() for more information. * @@ -92,7 +133,7 @@ typedef struct SDL_Storage SDL_Storage; * \sa SDL_OpenUserStorage * \sa SDL_ReadStorageFile */ -extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props); +extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenTitleStorage(const char *override, SDL_PropertiesID props); /** * Opens up a container for a user's unique read/write filesystem. @@ -102,9 +143,9 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override, * This allows the backend to properly batch file operations and flush them * when the container has been closed; ensuring safe and optimal save I/O. * - * \param org the name of your organization - * \param app the name of your application - * \param props a property list that may contain backend-specific information + * \param org the name of your organization. + * \param app the name of your application. + * \param props a property list that may contain backend-specific information. * \returns a user storage container on success or NULL on failure; call * SDL_GetError() for more information. * @@ -118,7 +159,7 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenTitleStorage(const char *override, * \sa SDL_StorageReady * \sa SDL_WriteStorageFile */ -extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props); +extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenUserStorage(const char *org, const char *app, SDL_PropertiesID props); /** * Opens up a container for local filesystem storage. @@ -128,7 +169,7 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const * SDL_OpenUserStorage() for access to user data. * * \param path the base path prepended to all storage paths, or NULL for no - * base path + * base path. * \returns a filesystem storage container on success or NULL on failure; call * SDL_GetError() for more information. * @@ -142,7 +183,7 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenUserStorage(const char *org, const * \sa SDL_ReadStorageFile * \sa SDL_WriteStorageFile */ -extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenFileStorage(const char *path); +extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenFileStorage(const char *path); /** * Opens up a container using a client-provided storage interface. @@ -152,8 +193,12 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenFileStorage(const char *path); * should use the built-in implementations in SDL, like SDL_OpenTitleStorage() * or SDL_OpenUserStorage(). * - * \param iface the function table to be used by this container - * \param userdata the pointer that will be passed to the store interface + * This function makes a copy of `iface` and the caller does not need to keep + * it around after this call. + * + * \param iface the interface that implements this storage, initialized using + * SDL_INIT_INTERFACE(). + * \param userdata the pointer that will be passed to the interface functions. * \returns a storage container on success or NULL on failure; call * SDL_GetError() for more information. * @@ -162,20 +207,21 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenFileStorage(const char *path); * \sa SDL_CloseStorage * \sa SDL_GetStorageFileSize * \sa SDL_GetStorageSpaceRemaining + * \sa SDL_INIT_INTERFACE * \sa SDL_ReadStorageFile * \sa SDL_StorageReady * \sa SDL_WriteStorageFile */ -extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata); +extern SDL_DECLSPEC SDL_Storage * SDLCALL SDL_OpenStorage(const SDL_StorageInterface *iface, void *userdata); /** * Closes and frees a storage container. * - * \param storage a storage container to close - * \returns 0 if the container was freed with no errors, a negative value - * otherwise; call SDL_GetError() for more information. Even if the - * function returns an error, the container data will be freed; the - * error is only for informational purposes. + * \param storage a storage container to close. + * \returns true if the container was freed with no errors, false otherwise; + * call SDL_GetError() for more information. Even if the function + * returns an error, the container data will be freed; the error is + * only for informational purposes. * * \since This function is available since SDL 3.0.0. * @@ -184,29 +230,29 @@ extern DECLSPEC SDL_Storage *SDLCALL SDL_OpenStorage(const SDL_StorageInterface * \sa SDL_OpenTitleStorage * \sa SDL_OpenUserStorage */ -extern DECLSPEC int SDLCALL SDL_CloseStorage(SDL_Storage *storage); +extern SDL_DECLSPEC bool SDLCALL SDL_CloseStorage(SDL_Storage *storage); /** * Checks if the storage container is ready to use. * - * This function should be called in regular intervals until it returns - * SDL_TRUE - however, it is not recommended to spinwait on this call, as the - * backend may depend on a synchronous message loop. + * This function should be called in regular intervals until it returns true - + * however, it is not recommended to spinwait on this call, as the backend may + * depend on a synchronous message loop. * - * \param storage a storage container to query - * \returns SDL_TRUE if the container is ready, SDL_FALSE otherwise + * \param storage a storage container to query. + * \returns true if the container is ready, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_StorageReady(SDL_Storage *storage); +extern SDL_DECLSPEC bool SDLCALL SDL_StorageReady(SDL_Storage *storage); /** * Query the size of a file within a storage container. * - * \param storage a storage container to query - * \param path the relative path of the file to query - * \param length a pointer to be filled with the file's length - * \returns 0 if the file could be queried, a negative value otherwise; call + * \param storage a storage container to query. + * \param path the relative path of the file to query. + * \param length a pointer to be filled with the file's length. + * \returns true if the file could be queried or false on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -214,18 +260,18 @@ extern DECLSPEC SDL_bool SDLCALL SDL_StorageReady(SDL_Storage *storage); * \sa SDL_ReadStorageFile * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_GetStorageFileSize(SDL_Storage *storage, const char *path, Uint64 *length); +extern SDL_DECLSPEC bool SDLCALL SDL_GetStorageFileSize(SDL_Storage *storage, const char *path, Uint64 *length); /** * Synchronously read a file from a storage container into a client-provided * buffer. * - * \param storage a storage container to read from - * \param path the relative path of the file to read - * \param destination a client-provided buffer to read the file into - * \param length the length of the destination buffer - * \returns 0 if the file was read, a negative value otherwise; call - * SDL_GetError() for more information. + * \param storage a storage container to read from. + * \param path the relative path of the file to read. + * \param destination a client-provided buffer to read the file into. + * \param length the length of the destination buffer. + * \returns true if the file was read or false on failure; call SDL_GetError() + * for more information. * * \since This function is available since SDL 3.0.0. * @@ -233,16 +279,16 @@ extern DECLSPEC int SDLCALL SDL_GetStorageFileSize(SDL_Storage *storage, const c * \sa SDL_StorageReady * \sa SDL_WriteStorageFile */ -extern DECLSPEC int SDLCALL SDL_ReadStorageFile(SDL_Storage *storage, const char *path, void *destination, Uint64 length); +extern SDL_DECLSPEC bool SDLCALL SDL_ReadStorageFile(SDL_Storage *storage, const char *path, void *destination, Uint64 length); /** * Synchronously write a file from client memory into a storage container. * - * \param storage a storage container to write to - * \param path the relative path of the file to write - * \param source a client-provided buffer to write from - * \param length the length of the source buffer - * \returns 0 if the file was written, a negative value otherwise; call + * \param storage a storage container to write to. + * \param path the relative path of the file to write. + * \param source a client-provided buffer to write from. + * \param length the length of the source buffer. + * \returns true if the file was written or false on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -251,95 +297,155 @@ extern DECLSPEC int SDLCALL SDL_ReadStorageFile(SDL_Storage *storage, const char * \sa SDL_ReadStorageFile * \sa SDL_StorageReady */ -extern DECLSPEC int SDL_WriteStorageFile(SDL_Storage *storage, const char *path, const void *source, Uint64 length); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteStorageFile(SDL_Storage *storage, const char *path, const void *source, Uint64 length); /** * Create a directory in a writable storage container. * - * \param storage a storage container - * \param path the path of the directory to create - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param storage a storage container. + * \param path the path of the directory to create. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_CreateStorageDirectory(SDL_Storage *storage, const char *path); +extern SDL_DECLSPEC bool SDLCALL SDL_CreateStorageDirectory(SDL_Storage *storage, const char *path); /** - * Enumerate a directory in a storage container. + * Enumerate a directory in a storage container through a callback function. * - * \param storage a storage container - * \param path the path of the directory to enumerate - * \param callback a function that is called for each entry in the directory - * \param userdata a pointer that is passed to `callback` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * This function provides every directory entry through an app-provided + * callback, called once for each directory entry, until all results have been + * provided or the callback returns <= 0. + * + * This will return false if there was a system problem in general, or if a + * callback returns -1. A successful return means a callback returned 1 to + * halt enumeration, or all directory entries were enumerated. + * + * \param storage a storage container. + * \param path the path of the directory to enumerate. + * \param callback a function that is called for each entry in the directory. + * \param userdata a pointer that is passed to `callback`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_EnumerateStorageDirectory(SDL_Storage *storage, const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata); +extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateStorageDirectory(SDL_Storage *storage, const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata); /** * Remove a file or an empty directory in a writable storage container. * - * \param storage a storage container - * \param path the path of the directory to enumerate - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param storage a storage container. + * \param path the path of the directory to enumerate. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_RemoveStoragePath(SDL_Storage *storage, const char *path); +extern SDL_DECLSPEC bool SDLCALL SDL_RemoveStoragePath(SDL_Storage *storage, const char *path); /** * Rename a file or directory in a writable storage container. * - * \param storage a storage container - * \param oldpath the old path - * \param newpath the new path - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param storage a storage container. + * \param oldpath the old path. + * \param newpath the new path. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_RenameStoragePath(SDL_Storage *storage, const char *oldpath, const char *newpath); +extern SDL_DECLSPEC bool SDLCALL SDL_RenameStoragePath(SDL_Storage *storage, const char *oldpath, const char *newpath); + +/** + * Copy a file in a writable storage container. + * + * \param storage a storage container. + * \param oldpath the old path. + * \param newpath the new path. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_StorageReady + */ +extern SDL_DECLSPEC bool SDLCALL SDL_CopyStorageFile(SDL_Storage *storage, const char *oldpath, const char *newpath); /** * Get information about a filesystem path in a storage container. * - * \param storage a storage container - * \param path the path to query + * \param storage a storage container. + * \param path the path to query. * \param info a pointer filled in with information about the path, or NULL to - * check for the existence of a file - * \returns 0 on success or a negative error code if the file doesn't exist, - * or another failure; call SDL_GetError() for more information. + * check for the existence of a file. + * \returns true on success or false if the file doesn't exist, or another + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady */ -extern DECLSPEC int SDLCALL SDL_GetStoragePathInfo(SDL_Storage *storage, const char *path, SDL_PathInfo *info); +extern SDL_DECLSPEC bool SDLCALL SDL_GetStoragePathInfo(SDL_Storage *storage, const char *path, SDL_PathInfo *info); /** * Queries the remaining space in a storage container. * - * \param storage a storage container to query - * \returns the amount of remaining space, in bytes + * \param storage a storage container to query. + * \returns the amount of remaining space, in bytes. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StorageReady * \sa SDL_WriteStorageFile */ -extern DECLSPEC Uint64 SDLCALL SDL_GetStorageSpaceRemaining(SDL_Storage *storage); +extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetStorageSpaceRemaining(SDL_Storage *storage); + +/** + * Enumerate a directory tree, filtered by pattern, and return a list. + * + * Files are filtered out if they don't match the string in `pattern`, which + * may contain wildcard characters '*' (match everything) and '?' (match one + * character). If pattern is NULL, no filtering is done and all results are + * returned. Subdirectories are permitted, and are specified with a path + * separator of '/'. Wildcard characters '*' and '?' never match a path + * separator. + * + * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching + * case-insensitive. + * + * The returned array is always NULL-terminated, for your iterating + * convenience, but if `count` is non-NULL, on return it will contain the + * number of items in the array, not counting the NULL terminator. + * + * \param storage a storage container. + * \param path the path of the directory to enumerate. + * \param pattern the pattern that files in the directory must match. Can be + * NULL. + * \param flags `SDL_GLOB_*` bitflags that affect this search. + * \param count on return, will be set to the number of items in the returned + * array. Can be NULL. + * \returns an array of strings on success or NULL on failure; call + * SDL_GetError() for more information. The caller should pass the + * returned pointer to SDL_free when done with it. This is a single + * allocation that should be freed with SDL_free() when it is no + * longer needed. + * + * \threadsafety It is safe to call this function from any thread, assuming + * the `storage` object is thread-safe. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC char ** SDLCALL SDL_GlobStorageDirectory(SDL_Storage *storage, const char *path, const char *pattern, SDL_GlobFlags flags, int *count); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_surface.h b/libs/SDL3/include/SDL3/SDL_surface.h index 19f77e9ff..f50c5fc1e 100644 --- a/libs/SDL3/include/SDL3/SDL_surface.h +++ b/libs/SDL3/include/SDL3/SDL_surface.h @@ -20,15 +20,28 @@ */ /** - * \file SDL_surface.h + * # CategorySurface * - * Header file for ::SDL_Surface definition and management functions. + * SDL surfaces are buffers of pixels in system RAM. These are useful for + * passing around and manipulating images that are not stored in GPU memory. + * + * SDL_Surface makes serious efforts to manage images in various formats, and + * provides a reasonable toolbox for transforming the data, including copying + * between surfaces, filling rectangles in the image data, etc. + * + * There is also a simple .bmp loader, SDL_LoadBMP(). SDL itself does not + * provide loaders for various other file formats, but there are several + * excellent external libraries that do, including it's own satellite library, + * SDL_image: + * + * https://github.com/libsdl-org/SDL_image */ #ifndef SDL_surface_h_ #define SDL_surface_h_ #include +#include #include #include #include @@ -42,108 +55,97 @@ extern "C" { #endif /** - * \name Surface flags + * The flags on an SDL_Surface. * - * These are the currently supported flags for the ::SDL_Surface. + * These are generally considered read-only. * - * \internal - * Used internally (read-only). + * \since This datatype is available since SDL 3.0.0. */ -/* @{ */ -#define SDL_SWSURFACE 0 /**< Just here for compatibility */ -#define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ -#define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ -#define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ -#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ -#define SDL_SURFACE_USES_PROPERTIES 0x00000010 /**< Surface uses properties */ -/* @} *//* Surface flags */ +typedef Uint32 SDL_SurfaceFlags; + +#define SDL_SURFACE_PREALLOCATED 0x00000001u /**< Surface uses preallocated pixel memory */ +#define SDL_SURFACE_LOCK_NEEDED 0x00000002u /**< Surface needs to be locked to access pixels */ +#define SDL_SURFACE_LOCKED 0x00000004u /**< Surface is currently locked */ +#define SDL_SURFACE_SIMD_ALIGNED 0x00000008u /**< Surface uses pixel memory allocated with SDL_aligned_alloc() */ /** - * Evaluates to true if the surface needs to be locked before access. + * Evaluates to true if the surface needs to be locked before access. + * + * \since This macro is available since SDL 3.0.0. */ -#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) - -typedef struct SDL_BlitMap SDL_BlitMap; /* this is an opaque type. */ +#define SDL_MUSTLOCK(S) ((((S)->flags & SDL_SURFACE_LOCK_NEEDED)) == SDL_SURFACE_LOCK_NEEDED) /** - * The scaling mode + * The scaling mode. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_ScaleMode { SDL_SCALEMODE_NEAREST, /**< nearest pixel sampling */ - SDL_SCALEMODE_LINEAR, /**< linear filtering */ - SDL_SCALEMODE_BEST /**< anisotropic filtering */ + SDL_SCALEMODE_LINEAR /**< linear filtering */ } SDL_ScaleMode; /** - * The flip mode + * The flip mode. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_FlipMode { SDL_FLIP_NONE, /**< Do not flip */ SDL_FLIP_HORIZONTAL, /**< flip horizontally */ SDL_FLIP_VERTICAL /**< flip vertically */ } SDL_FlipMode; +#ifndef SDL_INTERNAL + /** * A collection of pixels used in software blitting. * - * Pixels are arranged in memory in rows, with the top row first. - * Each row occupies an amount of memory given by the pitch (sometimes - * known as the row stride in non-SDL APIs). - * - * Within each row, pixels are arranged from left to right until the - * width is reached. - * Each pixel occupies a number of bits appropriate for its format, with - * most formats representing each pixel as one or more whole bytes - * (in some indexed formats, instead multiple pixels are packed into - * each byte), and a byte order given by the format. - * After encoding all pixels, any remaining bytes to reach the pitch are - * used as padding to reach a desired alignment, and have undefined contents. - * - * \note This structure should be treated as read-only, except for \c pixels, - * which, if not NULL, contains the raw pixel data for the surface. + * Pixels are arranged in memory in rows, with the top row first. Each row + * occupies an amount of memory given by the pitch (sometimes known as the row + * stride in non-SDL APIs). + * + * Within each row, pixels are arranged from left to right until the width is + * reached. Each pixel occupies a number of bits appropriate for its format, + * with most formats representing each pixel as one or more whole bytes (in + * some indexed formats, instead multiple pixels are packed into each byte), + * and a byte order given by the format. After encoding all pixels, any + * remaining bytes to reach the pitch are used as padding to reach a desired + * alignment, and have undefined contents. + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_CreateSurface + * \sa SDL_DestroySurface */ -typedef struct SDL_Surface +struct SDL_Surface { - Uint32 flags; /**< Read-only */ - SDL_PixelFormat *format; /**< Read-only */ - int w, h; /**< Read-only */ - int pitch; /**< Read-only */ - void *pixels; /**< Read-write */ - - void *reserved; /**< Private */ + SDL_SurfaceFlags flags; /**< The flags of the surface, read-only */ + SDL_PixelFormat format; /**< The format of the surface, read-only */ + int w; /**< The width of the surface, read-only. */ + int h; /**< The height of the surface, read-only. */ + int pitch; /**< The distance in bytes between rows of pixels, read-only */ + void *pixels; /**< A pointer to the pixels of the surface, the pixels are writeable if non-NULL */ - /** information needed for surfaces requiring locks */ - int locked; /**< Read-only */ + int refcount; /**< Application reference count, used when freeing surface */ - /** list of BlitMap that hold a reference to this surface */ - void *list_blitmap; /**< Private */ - - /** clipping information */ - SDL_Rect clip_rect; /**< Read-only */ - - /** info for fast blit mapping to other surfaces */ - SDL_BlitMap *map; /**< Private */ - - /** Reference count -- used when freeing surface */ - int refcount; /**< Read-mostly */ -} SDL_Surface; - -/** - * The type of function used for surface blitting functions. - */ -typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrect, - struct SDL_Surface *dst, const SDL_Rect *dstrect); + void *reserved; /**< Reserved for internal use */ +}; +#endif /* !SDL_INTERNAL */ +typedef struct SDL_Surface SDL_Surface; /** - * Allocate a new RGB surface with a specific pixel format. + * Allocate a new surface with a specific pixel format. * - * \param width the width of the surface - * \param height the height of the surface - * \param format the SDL_PixelFormatEnum for the new surface's pixel format. - * \returns the new SDL_Surface structure that is created or NULL if it fails; + * The pixels of the new surface are initialized to zero. + * + * \param width the width of the surface. + * \param height the height of the surface. + * \param format the SDL_PixelFormat for the new surface's pixel format. + * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -151,10 +153,10 @@ typedef int (SDLCALL *SDL_blit) (struct SDL_Surface *src, const SDL_Rect *srcrec * \sa SDL_CreateSurfaceFrom * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface(int width, int height, SDL_PixelFormatEnum format); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurface(int width, int height, SDL_PixelFormat format); /** - * Allocate a new RGB surface with a specific pixel format and existing pixel + * Allocate a new surface with a specific pixel format and existing pixel * data. * * No copy is made of the pixel data. Pixel data is not managed automatically; @@ -166,12 +168,12 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface(int width, int height, SD * You may pass NULL for pixels and 0 for pitch to create a surface that you * will fill in with valid values later. * - * \param pixels a pointer to existing pixel data - * \param width the width of the surface - * \param height the height of the surface - * \param pitch the number of bytes between each row, including padding - * \param format the SDL_PixelFormatEnum for the new surface's pixel format. - * \returns the new SDL_Surface structure that is created or NULL if it fails; + * \param width the width of the surface. + * \param height the height of the surface. + * \param format the SDL_PixelFormat for the new surface's pixel format. + * \param pixels a pointer to existing pixel data. + * \param pitch the number of bytes between each row, including padding. + * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -179,10 +181,10 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurface(int width, int height, SD * \sa SDL_CreateSurface * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom(void *pixels, int width, int height, int pitch, SDL_PixelFormatEnum format); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_CreateSurfaceFrom(int width, int height, SDL_PixelFormat format, void *pixels, int pitch); /** - * Free an RGB surface. + * Free a surface. * * It is safe to pass NULL to this function. * @@ -190,21 +192,17 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateSurfaceFrom(void *pixels, int wid * * \since This function is available since SDL 3.0.0. * + * \sa SDL_CreateStackSurface * \sa SDL_CreateSurface * \sa SDL_CreateSurfaceFrom */ -extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); +extern SDL_DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); /** * Get the properties associated with a surface. * * The following properties are understood by SDL: * - * - `SDL_PROP_SURFACE_COLORSPACE_NUMBER`: an SDL_ColorSpace value describing - * the surface colorspace, defaults to SDL_COLORSPACE_SRGB_LINEAR for - * floating point formats, SDL_COLORSPACE_HDR10 for 10-bit formats, - * SDL_COLORSPACE_SRGB for other RGB surfaces and SDL_COLORSPACE_BT709_FULL - * for YUV surfaces. * - `SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT`: for HDR10 and floating point * surfaces, this defines the value of 100% diffuse white, with higher * values being displayed in the High Dynamic Range headroom. This defaults @@ -220,18 +218,14 @@ extern DECLSPEC void SDLCALL SDL_DestroySurface(SDL_Surface *surface); * where N is a floating point scale factor applied in linear space, and * "none", which disables tone mapping. This defaults to "chrome". * - * \param surface the SDL_Surface structure to query + * \param surface the SDL_Surface structure to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *surface); -#define SDL_PROP_SURFACE_COLORSPACE_NUMBER "SDL.surface.colorspace" #define SDL_PROP_SURFACE_SDR_WHITE_POINT_FLOAT "SDL.surface.SDR_white_point" #define SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT "SDL.surface.HDR_headroom" #define SDL_PROP_SURFACE_TONEMAP_OPERATOR_STRING "SDL.surface.tonemap" @@ -242,14 +236,17 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetSurfaceProperties(SDL_Surface *s * Setting the colorspace doesn't change the pixels, only how they are * interpreted in color operations. * - * \param surface the SDL_Surface structure to update - * \param colorspace an SDL_ColorSpace value describing the surface colorspace - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param colorspace an SDL_ColorSpace value describing the surface + * colorspace. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetSurfaceColorspace */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace colorspace); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace colorspace); /** * Get the colorspace used by a surface. @@ -258,29 +255,153 @@ extern DECLSPEC int SDLCALL SDL_SetSurfaceColorspace(SDL_Surface *surface, SDL_C * formats, SDL_COLORSPACE_HDR10 for 10-bit formats, SDL_COLORSPACE_SRGB for * other RGB surfaces and SDL_COLORSPACE_BT709_FULL for YUV textures. * - * \param surface the SDL_Surface structure to query - * \param colorspace a pointer filled in with an SDL_ColorSpace value - * describing the surface colorspace - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to query. + * \returns the colorspace used by the surface, or SDL_COLORSPACE_UNKNOWN if + * the surface is NULL. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetSurfaceColorspace + */ +extern SDL_DECLSPEC SDL_Colorspace SDLCALL SDL_GetSurfaceColorspace(SDL_Surface *surface); + +/** + * Create a palette and associate it with a surface. + * + * This function creates a palette compatible with the provided surface. The + * palette is then returned for you to modify, and the surface will + * automatically use the new palette in future operations. You do not need to + * destroy the returned palette, it will be freed when the reference count + * reaches 0, usually when the surface is destroyed. + * + * Bitmap surfaces (with format SDL_PIXELFORMAT_INDEX1LSB or + * SDL_PIXELFORMAT_INDEX1MSB) will have the palette initialized with 0 as + * white and 1 as black. Other surfaces will get a palette initialized with + * white in every entry. + * + * If this function is called for a surface that already has a palette, a new + * palette will be created to replace it. + * + * \param surface the SDL_Surface structure to update. + * \returns a new SDL_Palette structure on success or NULL on failure (e.g. if + * the surface didn't have an index format); call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetPaletteColors */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceColorspace(SDL_Surface *surface, SDL_Colorspace *colorspace); +extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_CreateSurfacePalette(SDL_Surface *surface); /** * Set the palette used by a surface. * * A single palette can be shared with many surfaces. * - * \param surface the SDL_Surface structure to update - * \param palette the SDL_Palette structure to use - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param palette the SDL_Palette structure to use. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_CreatePalette + * \sa SDL_GetSurfacePalette + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette); + +/** + * Get the palette used by a surface. + * + * \param surface the SDL_Surface structure to query. + * \returns a pointer to the palette used by the surface, or NULL if there is + * no palette used. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetSurfacePalette */ -extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Palette *palette); +extern SDL_DECLSPEC SDL_Palette * SDLCALL SDL_GetSurfacePalette(SDL_Surface *surface); + +/** + * Add an alternate version of a surface. + * + * This function adds an alternate version of this surface, usually used for + * content with high DPI representations like cursors or icons. The size, + * format, and content do not need to match the original surface, and these + * alternate versions will not be updated when the original surface changes. + * + * This function adds a reference to the alternate version, so you should call + * SDL_DestroySurface() on the image after this call. + * + * \param surface the SDL_Surface structure to update. + * \param image a pointer to an alternate SDL_Surface to associate with this + * surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_RemoveSurfaceAlternateImages + * \sa SDL_GetSurfaceImages + * \sa SDL_SurfaceHasAlternateImages + */ +extern SDL_DECLSPEC bool SDLCALL SDL_AddSurfaceAlternateImage(SDL_Surface *surface, SDL_Surface *image); + +/** + * Return whether a surface has alternate versions available. + * + * \param surface the SDL_Surface structure to query. + * \returns true if alternate versions are available or true otherwise. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AddSurfaceAlternateImage + * \sa SDL_RemoveSurfaceAlternateImages + * \sa SDL_GetSurfaceImages + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasAlternateImages(SDL_Surface *surface); + +/** + * Get an array including all versions of a surface. + * + * This returns all versions of a surface, with the surface being queried as + * the first element in the returned array. + * + * Freeing the array of surfaces does not affect the surfaces in the array. + * They are still referenced by the surface being queried and will be cleaned + * up normally. + * + * \param surface the SDL_Surface structure to query. + * \param count a pointer filled in with the number of surface pointers + * returned, may be NULL. + * \returns a NULL terminated array of SDL_Surface pointers or NULL on + * failure; call SDL_GetError() for more information. This should be + * freed with SDL_free() when it is no longer needed. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AddSurfaceAlternateImage + * \sa SDL_RemoveSurfaceAlternateImages + * \sa SDL_SurfaceHasAlternateImages + */ +extern SDL_DECLSPEC SDL_Surface ** SDLCALL SDL_GetSurfaceImages(SDL_Surface *surface, int *count); + +/** + * Remove all alternate versions of a surface. + * + * This function removes a reference from all the alternative versions, + * destroying them if this is the last reference to them. + * + * \param surface the SDL_Surface structure to update. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AddSurfaceAlternateImage + * \sa SDL_GetSurfaceImages + * \sa SDL_SurfaceHasAlternateImages + */ +extern SDL_DECLSPEC void SDLCALL SDL_RemoveSurfaceAlternateImages(SDL_Surface *surface); /** * Set up a surface for directly accessing the pixels. @@ -294,27 +415,27 @@ extern DECLSPEC int SDLCALL SDL_SetSurfacePalette(SDL_Surface *surface, SDL_Pale * 0, then you can read and write to the surface at any time, and the pixel * format of the surface will not change. * - * \param surface the SDL_Surface structure to be locked - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to be locked. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_MUSTLOCK * \sa SDL_UnlockSurface */ -extern DECLSPEC int SDLCALL SDL_LockSurface(SDL_Surface *surface); +extern SDL_DECLSPEC bool SDLCALL SDL_LockSurface(SDL_Surface *surface); /** * Release a surface after directly accessing the pixels. * - * \param surface the SDL_Surface structure to be unlocked + * \param surface the SDL_Surface structure to be unlocked. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LockSurface */ -extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); +extern SDL_DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); /** * Load a BMP image from a seekable SDL data stream. @@ -322,11 +443,11 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); * The new surface should be freed with SDL_DestroySurface(). Not doing so * will result in a memory leak. * - * \param src the data stream for the surface - * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `src` before returning, - * even in the case of an error - * \returns a pointer to a new SDL_Surface structure or NULL if there was an - * error; call SDL_GetError() for more information. + * \param src the data stream for the surface. + * \param closeio if true, calls SDL_CloseIO() on `src` before returning, even + * in the case of an error. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -334,7 +455,7 @@ extern DECLSPEC void SDLCALL SDL_UnlockSurface(SDL_Surface *surface); * \sa SDL_LoadBMP * \sa SDL_SaveBMP_IO */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool closeio); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio); /** * Load a BMP image from a file. @@ -342,9 +463,9 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool * The new surface should be freed with SDL_DestroySurface(). Not doing so * will result in a memory leak. * - * \param file the BMP file to load - * \returns a pointer to a new SDL_Surface structure or NULL if there was an - * error; call SDL_GetError() for more information. + * \param file the BMP file to load. + * \returns a pointer to a new SDL_Surface structure or NULL on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * @@ -352,7 +473,7 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_IO(SDL_IOStream *src, SDL_bool * \sa SDL_LoadBMP_IO * \sa SDL_SaveBMP */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_LoadBMP(const char *file); /** * Save a surface to a seekable SDL data stream in BMP format. @@ -363,19 +484,19 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP(const char *file); * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are * not supported. * - * \param surface the SDL_Surface structure containing the image to be saved - * \param dst a data stream to save to - * \param closeio if SDL_TRUE, calls SDL_CloseIO() on `dst` before returning, - * even in the case of an error - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure containing the image to be saved. + * \param dst a data stream to save to. + * \param closeio if true, calls SDL_CloseIO() on `dst` before returning, even + * in the case of an error. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadBMP_IO * \sa SDL_SaveBMP */ -extern DECLSPEC int SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, SDL_bool closeio); +extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *dst, bool closeio); /** * Save a surface to a file. @@ -386,17 +507,17 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP_IO(SDL_Surface *surface, SDL_IOStream *d * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are * not supported. * - * \param surface the SDL_Surface structure containing the image to be saved - * \param file a file to save to - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure containing the image to be saved. + * \param file a file to save to. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_LoadBMP * \sa SDL_SaveBMP_IO */ -extern DECLSPEC int SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); +extern SDL_DECLSPEC bool SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); /** * Set the RLE acceleration hint for a surface. @@ -404,10 +525,10 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); * If RLE is enabled, color key and alpha blending blits are much faster, but * the surface must be locked before directly accessing the pixels. * - * \param surface the SDL_Surface structure to optimize - * \param flag 0 to disable, non-zero to enable RLE acceleration - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to optimize. + * \param enabled true to enable RLE acceleration, false to disable it. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -415,21 +536,21 @@ extern DECLSPEC int SDLCALL SDL_SaveBMP(SDL_Surface *surface, const char *file); * \sa SDL_LockSurface * \sa SDL_UnlockSurface */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, int flag); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceRLE(SDL_Surface *surface, bool enabled); /** - * Returns whether the surface is RLE enabled + * Returns whether the surface is RLE enabled. * - * It is safe to pass a NULL `surface` here; it will return SDL_FALSE. + * It is safe to pass a NULL `surface` here; it will return false. * - * \param surface the SDL_Surface structure to query - * \returns SDL_TRUE if the surface is RLE enabled, SDL_FALSE otherwise. + * \param surface the SDL_Surface structure to query. + * \returns true if the surface is RLE enabled, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetSurfaceRLE */ -extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); +extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); /** * Set the color key (transparent pixel) in a surface. @@ -441,36 +562,34 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasRLE(SDL_Surface *surface); * It is a pixel of the format used by the surface, as generated by * SDL_MapRGB(). * - * RLE acceleration can substantially speed up blitting of images with large - * horizontal runs of transparent pixels. See SDL_SetSurfaceRLE() for details. - * - * \param surface the SDL_Surface structure to update - * \param flag SDL_TRUE to enable color key, SDL_FALSE to disable color key - * \param key the transparent pixel - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param enabled true to enable color key, false to disable color key. + * \param key the transparent pixel. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceColorKey + * \sa SDL_SetSurfaceRLE * \sa SDL_SurfaceHasColorKey */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, int flag, Uint32 key); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorKey(SDL_Surface *surface, bool enabled, Uint32 key); /** - * Returns whether the surface has a color key + * Returns whether the surface has a color key. * - * It is safe to pass a NULL `surface` here; it will return SDL_FALSE. + * It is safe to pass a NULL `surface` here; it will return false. * - * \param surface the SDL_Surface structure to query - * \returns SDL_TRUE if the surface has a color key, SDL_FALSE otherwise. + * \param surface the SDL_Surface structure to query. + * \returns true if the surface has a color key, false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetSurfaceColorKey * \sa SDL_GetSurfaceColorKey */ -extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface); +extern SDL_DECLSPEC bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface); /** * Get the color key (transparent pixel) for a surface. @@ -478,19 +597,19 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SurfaceHasColorKey(SDL_Surface *surface); * The color key is a pixel of the format used by the surface, as generated by * SDL_MapRGB(). * - * If the surface doesn't have color key enabled this function returns -1. + * If the surface doesn't have color key enabled this function returns false. * - * \param surface the SDL_Surface structure to query - * \param key a pointer filled in with the transparent pixel - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to query. + * \param key a pointer filled in with the transparent pixel. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetSurfaceColorKey * \sa SDL_SurfaceHasColorKey */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 *key); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 *key); /** * Set an additional color value multiplied into blit operations. @@ -501,37 +620,37 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceColorKey(SDL_Surface *surface, Uint32 * * `srcC = srcC * (color / 255)` * - * \param surface the SDL_Surface structure to update - * \param r the red color value multiplied into blit operations - * \param g the green color value multiplied into blit operations - * \param b the blue color value multiplied into blit operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param r the red color value multiplied into blit operations. + * \param g the green color value multiplied into blit operations. + * \param b the blue color value multiplied into blit operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceColorMod * \sa SDL_SetSurfaceAlphaMod */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceColorMod(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b); /** * Get the additional color value multiplied into blit operations. * - * \param surface the SDL_Surface structure to query - * \param r a pointer filled in with the current red color value - * \param g a pointer filled in with the current green color value - * \param b a pointer filled in with the current blue color value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to query. + * \param r a pointer filled in with the current red color value. + * \param g a pointer filled in with the current green color value. + * \param b a pointer filled in with the current blue color value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceAlphaMod * \sa SDL_SetSurfaceColorMod */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 *r, Uint8 *g, Uint8 *b); /** * Set an additional alpha value used in blit operations. @@ -541,32 +660,32 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceColorMod(SDL_Surface *surface, Uint8 * * * `srcA = srcA * (alpha / 255)` * - * \param surface the SDL_Surface structure to update - * \param alpha the alpha value multiplied into blit operations - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param alpha the alpha value multiplied into blit operations. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceAlphaMod * \sa SDL_SetSurfaceColorMod */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceAlphaMod(SDL_Surface *surface, Uint8 alpha); /** * Get the additional alpha value used in blit operations. * - * \param surface the SDL_Surface structure to query - * \param alpha a pointer filled in with the current alpha value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to query. + * \param alpha a pointer filled in with the current alpha value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceColorMod * \sa SDL_SetSurfaceAlphaMod */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 *alpha); /** * Set the blend mode used for blit operations. @@ -575,30 +694,30 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceAlphaMod(SDL_Surface *surface, Uint8 * * existing data, the blendmode of the SOURCE surface should be set to * `SDL_BLENDMODE_NONE`. * - * \param surface the SDL_Surface structure to update - * \param blendMode the SDL_BlendMode to use for blit blending - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to update. + * \param blendMode the SDL_BlendMode to use for blit blending. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceBlendMode */ -extern DECLSPEC int SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode blendMode); /** * Get the blend mode used for blit operations. * - * \param surface the SDL_Surface structure to query - * \param blendMode a pointer filled in with the current SDL_BlendMode - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the SDL_Surface structure to query. + * \param blendMode a pointer filled in with the current SDL_BlendMode. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetSurfaceBlendMode */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_BlendMode *blendMode); /** * Set the clipping rectangle for a surface. @@ -609,17 +728,17 @@ extern DECLSPEC int SDLCALL SDL_GetSurfaceBlendMode(SDL_Surface *surface, SDL_Bl * Note that blits are automatically clipped to the edges of the source and * destination surfaces. * - * \param surface the SDL_Surface structure to be clipped + * \param surface the SDL_Surface structure to be clipped. * \param rect the SDL_Rect structure representing the clipping rectangle, or - * NULL to disable clipping - * \returns SDL_TRUE if the rectangle intersects the surface, otherwise - * SDL_FALSE and blits will be completely clipped. + * NULL to disable clipping. + * \returns true if the rectangle intersects the surface, otherwise false and + * blits will be completely clipped. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetSurfaceClipRect */ -extern DECLSPEC SDL_bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, const SDL_Rect *rect); /** * Get the clipping rectangle for a surface. @@ -628,88 +747,92 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetSurfaceClipRect(SDL_Surface *surface, co * rectangle is drawn into. * * \param surface the SDL_Surface structure representing the surface to be - * clipped + * clipped. * \param rect an SDL_Rect structure filled in with the clipping rectangle for - * the surface - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetSurfaceClipRect */ -extern DECLSPEC int SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetSurfaceClipRect(SDL_Surface *surface, SDL_Rect *rect); -/* +/** * Flip a surface vertically or horizontally. * - * \param surface the surface to flip - * \param flip the direction to flip - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param surface the surface to flip. + * \param flip the direction to flip. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip); +extern SDL_DECLSPEC bool SDLCALL SDL_FlipSurface(SDL_Surface *surface, SDL_FlipMode flip); -/* +/** * Creates a new surface identical to the existing surface. * + * If the original surface has alternate images, the new surface will have a + * reference to them as well. + * * The returned surface should be freed with SDL_DestroySurface(). * * \param surface the surface to duplicate. - * \returns a copy of the surface, or NULL on failure; call SDL_GetError() for + * \returns a copy of the surface or NULL on failure; call SDL_GetError() for * more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_DuplicateSurface(SDL_Surface *surface); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_DuplicateSurface(SDL_Surface *surface); /** - * Copy an existing surface to a new surface of the specified format. + * Creates a new surface identical to the existing surface, scaled to the + * desired size. * - * This function is used to optimize images for faster *repeat* blitting. This - * is accomplished by converting the original and storing the result as a new - * surface. The new, optimized surface can then be used as the source for - * future blits, making them faster. + * The returned surface should be freed with SDL_DestroySurface(). * - * \param surface the existing SDL_Surface structure to convert - * \param format the SDL_PixelFormat structure that the new surface is - * optimized for - * \returns the new SDL_Surface structure that is created or NULL if it fails; - * call SDL_GetError() for more information. + * \param surface the surface to duplicate and scale. + * \param width the width of the new surface. + * \param height the height of the new surface. + * \param scaleMode the SDL_ScaleMode to be used. + * \returns a copy of the surface or NULL on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_ConvertSurfaceFormat - * \sa SDL_ConvertSurfaceFormatAndColorspace - * \sa SDL_CreatePixelFormat * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface(SDL_Surface *surface, const SDL_PixelFormat *format); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ScaleSurface(SDL_Surface *surface, int width, int height, SDL_ScaleMode scaleMode); /** * Copy an existing surface to a new surface of the specified format. * - * This function operates just like SDL_ConvertSurface(), but accepts an - * SDL_PixelFormatEnum value instead of an SDL_PixelFormat structure. As such, - * it might be easier to call but it doesn't have access to palette - * information for the destination surface, in case that would be important. + * This function is used to optimize images for faster *repeat* blitting. This + * is accomplished by converting the original and storing the result as a new + * surface. The new, optimized surface can then be used as the source for + * future blits, making them faster. + * + * If you are converting to an indexed surface and want to map colors to a + * palette, you can use SDL_ConvertSurfaceAndColorspace() instead. * - * \param surface the existing SDL_Surface structure to convert - * \param pixel_format the new pixel format - * \returns the new SDL_Surface structure that is created or NULL if it fails; + * If the original surface has alternate images, the new surface will have a + * reference to them as well. + * + * \param surface the existing SDL_Surface structure to convert. + * \param format the new pixel format. + * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_ConvertSurface - * \sa SDL_ConvertSurfaceFormatAndColorspace + * \sa SDL_ConvertSurfaceAndColorspace * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surface, SDL_PixelFormatEnum pixel_format); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurface(SDL_Surface *surface, SDL_PixelFormat format); /** * Copy an existing surface to a new surface of the specified format and @@ -719,91 +842,130 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat(SDL_Surface *surfa * and returns the new surface. This will perform any pixel format and * colorspace conversion needed. * - * \param surface the existing SDL_Surface structure to convert - * \param pixel_format the new pixel format - * \param colorspace the new colorspace - * \param props an SDL_PropertiesID with additional color properties, or 0 - * \returns the new SDL_Surface structure that is created or NULL if it fails; + * If the original surface has alternate images, the new surface will have a + * reference to them as well. + * + * \param surface the existing SDL_Surface structure to convert. + * \param format the new pixel format. + * \param palette an optional palette to use for indexed formats, may be NULL. + * \param colorspace the new colorspace. + * \param props an SDL_PropertiesID with additional color properties, or 0. + * \returns the new SDL_Surface structure that is created or NULL on failure; * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ConvertSurface - * \sa SDL_ConvertSurfaceFormat + * \sa SDL_ConvertSurface * \sa SDL_DestroySurface */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormatAndColorspace(SDL_Surface *surface, SDL_PixelFormatEnum pixel_format, SDL_Colorspace colorspace, SDL_PropertiesID props); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_ConvertSurfaceAndColorspace(SDL_Surface *surface, SDL_PixelFormat format, SDL_Palette *palette, SDL_Colorspace colorspace, SDL_PropertiesID props); /** * Copy a block of pixels of one format to another format. * - * \param width the width of the block to copy, in pixels - * \param height the height of the block to copy, in pixels - * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format - * \param src a pointer to the source pixels - * \param src_pitch the pitch of the source pixels, in bytes - * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format - * \param dst a pointer to be filled in with new pixel data - * \param dst_pitch the pitch of the destination pixels, in bytes - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param width the width of the block to copy, in pixels. + * \param height the height of the block to copy, in pixels. + * \param src_format an SDL_PixelFormat value of the `src` pixels format. + * \param src a pointer to the source pixels. + * \param src_pitch the pitch of the source pixels, in bytes. + * \param dst_format an SDL_PixelFormat value of the `dst` pixels format. + * \param dst a pointer to be filled in with new pixel data. + * \param dst_pitch the pitch of the destination pixels, in bytes. + * \returns false on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ConvertPixelsAndColorspace */ -extern DECLSPEC int SDLCALL SDL_ConvertPixels(int width, int height, SDL_PixelFormatEnum src_format, const void *src, int src_pitch, SDL_PixelFormatEnum dst_format, void *dst, int dst_pitch); +extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixels(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch); /** * Copy a block of pixels of one format and colorspace to another format and * colorspace. * - * \param width the width of the block to copy, in pixels - * \param height the height of the block to copy, in pixels - * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format + * \param width the width of the block to copy, in pixels. + * \param height the height of the block to copy, in pixels. + * \param src_format an SDL_PixelFormat value of the `src` pixels format. * \param src_colorspace an SDL_ColorSpace value describing the colorspace of - * the `src` pixels + * the `src` pixels. * \param src_properties an SDL_PropertiesID with additional source color - * properties, or 0 - * \param src a pointer to the source pixels - * \param src_pitch the pitch of the source pixels, in bytes - * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format + * properties, or 0. + * \param src a pointer to the source pixels. + * \param src_pitch the pitch of the source pixels, in bytes. + * \param dst_format an SDL_PixelFormat value of the `dst` pixels format. * \param dst_colorspace an SDL_ColorSpace value describing the colorspace of - * the `dst` pixels + * the `dst` pixels. * \param dst_properties an SDL_PropertiesID with additional destination color - * properties, or 0 - * \param dst a pointer to be filled in with new pixel data - * \param dst_pitch the pitch of the destination pixels, in bytes - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * properties, or 0. + * \param dst a pointer to be filled in with new pixel data. + * \param dst_pitch the pitch of the destination pixels, in bytes. + * \returns false on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ConvertPixels */ -extern DECLSPEC int SDLCALL SDL_ConvertPixelsAndColorspace(int width, int height, SDL_PixelFormatEnum src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormatEnum dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch); +extern SDL_DECLSPEC bool SDLCALL SDL_ConvertPixelsAndColorspace(int width, int height, SDL_PixelFormat src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch, SDL_PixelFormat dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch); /** * Premultiply the alpha on a block of pixels. * * This is safe to use with src == dst, but not for other overlapping areas. * - * This function is currently only implemented for SDL_PIXELFORMAT_ARGB8888. - * - * \param width the width of the block to convert, in pixels - * \param height the height of the block to convert, in pixels - * \param src_format an SDL_PixelFormatEnum value of the `src` pixels format - * \param src a pointer to the source pixels - * \param src_pitch the pitch of the source pixels, in bytes - * \param dst_format an SDL_PixelFormatEnum value of the `dst` pixels format - * \param dst a pointer to be filled in with premultiplied pixel data - * \param dst_pitch the pitch of the destination pixels, in bytes - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param width the width of the block to convert, in pixels. + * \param height the height of the block to convert, in pixels. + * \param src_format an SDL_PixelFormat value of the `src` pixels format. + * \param src a pointer to the source pixels. + * \param src_pitch the pitch of the source pixels, in bytes. + * \param dst_format an SDL_PixelFormat value of the `dst` pixels format. + * \param dst a pointer to be filled in with premultiplied pixel data. + * \param dst_pitch the pitch of the destination pixels, in bytes. + * \param linear true to convert from sRGB to linear space for the alpha + * multiplication, false to do multiplication in sRGB space. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormat src_format, const void *src, int src_pitch, SDL_PixelFormat dst_format, void *dst, int dst_pitch, bool linear); + +/** + * Premultiply the alpha in a surface. + * + * This is safe to use with src == dst, but not for other overlapping areas. + * + * \param surface the surface to modify. + * \param linear true to convert from sRGB to linear space for the alpha + * multiplication, false to do multiplication in sRGB space. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_PremultiplySurfaceAlpha(SDL_Surface *surface, bool linear); + +/** + * Clear a surface with a specific color, with floating point precision. + * + * This function handles all surface formats, and ignores any clip rectangle. + * + * If the surface is YUV, the color is assumed to be in the sRGB colorspace, + * otherwise the color is assumed to be in the colorspace of the suface. + * + * \param surface the SDL_Surface to clear. + * \param r the red component of the pixel, normally in the range 0-1. + * \param g the green component of the pixel, normally in the range 0-1. + * \param b the blue component of the pixel, normally in the range 0-1. + * \param a the alpha component of the pixel, normally in the range 0-1. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_PixelFormatEnum src_format, const void *src, int src_pitch, SDL_PixelFormatEnum dst_format, void *dst, int dst_pitch); +extern SDL_DECLSPEC bool SDLCALL SDL_ClearSurface(SDL_Surface *surface, float r, float g, float b, float a); /** * Perform a fast fill of a rectangle with a specific color. @@ -817,18 +979,18 @@ extern DECLSPEC int SDLCALL SDL_PremultiplyAlpha(int width, int height, SDL_Pixe * SDL_SetSurfaceClipRect()), then this function will fill based on the * intersection of the clip rectangle and `rect`. * - * \param dst the SDL_Surface structure that is the drawing target + * \param dst the SDL_Surface structure that is the drawing target. * \param rect the SDL_Rect structure representing the rectangle to fill, or - * NULL to fill the entire surface - * \param color the color to fill with - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * NULL to fill the entire surface. + * \param color the color to fill with. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_FillSurfaceRects */ -extern DECLSPEC int SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color); +extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect *rect, Uint32 color); /** * Perform a fast fill of a set of rectangles with a specific color. @@ -842,18 +1004,18 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRect(SDL_Surface *dst, const SDL_Rect * SDL_SetSurfaceClipRect()), then this function will fill based on the * intersection of the clip rectangle and `rect`. * - * \param dst the SDL_Surface structure that is the drawing target + * \param dst the SDL_Surface structure that is the drawing target. * \param rects an array of SDL_Rects representing the rectangles to fill. - * \param count the number of rectangles in the array - * \param color the color to fill with - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param count the number of rectangles in the array. + * \param color the color to fill with. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_FillSurfaceRect */ -extern DECLSPEC int SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color); +extern SDL_DECLSPEC bool SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rect *rects, int count, Uint32 color); /** * Performs a fast blit from the source surface to the destination surface. @@ -868,14 +1030,14 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rec * The blit semantics for surfaces with and without blending and colorkey are * defined as follows: * - * ```c + * ``` * RGBA->RGB: * Source surface blend mode set to SDL_BLENDMODE_BLEND: * alpha-blend (using the source alpha-channel and per-surface alpha) * SDL_SRCCOLORKEY ignored. * Source surface blend mode set to SDL_BLENDMODE_NONE: * copy RGB. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * if SDL_SRCCOLORKEY set, only copy the pixels that do not match the * RGB values of the source color key, ignoring alpha in the * comparison. * @@ -885,7 +1047,7 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rec * Source surface blend mode set to SDL_BLENDMODE_NONE: * copy RGB, set destination alpha to source per-surface alpha value. * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * if SDL_SRCCOLORKEY set, only copy the pixels that do not match the * source color key. * * RGBA->RGBA: @@ -894,7 +1056,7 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rec * SDL_SRCCOLORKEY ignored. * Source surface blend mode set to SDL_BLENDMODE_NONE: * copy all of RGBA to the destination. - * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * if SDL_SRCCOLORKEY set, only copy the pixels that do not match the * RGB values of the source color key, ignoring alpha in the * comparison. * @@ -904,26 +1066,31 @@ extern DECLSPEC int SDLCALL SDL_FillSurfaceRects(SDL_Surface *dst, const SDL_Rec * Source surface blend mode set to SDL_BLENDMODE_NONE: * copy RGB. * both: - * if SDL_SRCCOLORKEY set, only copy the pixels matching the + * if SDL_SRCCOLORKEY set, only copy the pixels that do not match the * source color key. * ``` * - * \param src the SDL_Surface structure to be copied from + * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied, or NULL to copy the entire surface - * \param dst the SDL_Surface structure that is the blit target + * copied, or NULL to copy the entire surface. + * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the x and y position in - * the destination surface. On input the width and height are - * ignored (taken from srcrect), and on output this is filled - * in with the actual rectangle used after clipping. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the destination surface, or NULL for (0,0). The width and + * height are ignored, and are copied from `srcrect`. If you + * want a specific width and height, you should use + * SDL_BlitSurfaceScaled(). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); /** * Perform low-level surface blitting only. @@ -931,85 +1098,229 @@ extern DECLSPEC int SDLCALL SDL_BlitSurface(SDL_Surface *src, const SDL_Rect *sr * This is a semi-private blit function and it performs low-level surface * blitting, assuming the input rectangles have already been clipped. * - * \param src the SDL_Surface structure to be copied from + * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied, or NULL to copy the entire surface - * \param dst the SDL_Surface structure that is the blit target + * copied, may not be NULL. + * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the destination surface, may not be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurface */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceUnchecked(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUnchecked(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); /** - * Perform stretch blit between two surfaces of the same format. + * Perform a scaled blit to a destination surface, which may be of a different + * format. * - * Using SDL_SCALEMODE_NEAREST: fast, low quality. Using SDL_SCALEMODE_LINEAR: - * bilinear scaling, slower, better quality, only 32BPP. + * \param src the SDL_Surface structure to be copied from. + * \param srcrect the SDL_Rect structure representing the rectangle to be + * copied, or NULL to copy the entire surface. + * \param dst the SDL_Surface structure that is the blit target. + * \param dstrect the SDL_Rect structure representing the target rectangle in + * the destination surface, or NULL to fill the entire + * destination surface. + * \param scaleMode the SDL_ScaleMode to be used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. + * + * \since This function is available since SDL 3.0.0. * - * \param src the SDL_Surface structure to be copied from + * \sa SDL_BlitSurface + */ +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); + +/** + * Perform low-level surface scaled blitting only. + * + * This is a semi-private function and it performs low-level surface blitting, + * assuming the input rectangles have already been clipped. + * + * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied - * \param dst the SDL_Surface structure that is the blit target + * copied, may not be NULL. + * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface - * \param scaleMode scale algorithm to be used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the destination surface, may not be NULL. + * \param scaleMode the SDL_ScaleMode to be used. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurfaceScaled */ -extern DECLSPEC int SDLCALL SDL_SoftStretch(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); /** - * Perform a scaled blit to a destination surface, which may be of a different + * Perform a tiled blit to a destination surface, which may be of a different * format. * - * \param src the SDL_Surface structure to be copied from + * The pixels in `srcrect` will be repeated as many times as needed to + * completely fill `dstrect`. + * + * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied - * \param dst the SDL_Surface structure that is the blit target + * copied, or NULL to copy the entire surface. + * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface, filled with the actual rectangle - * used after clipping - * \param scaleMode scale algorithm to be used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the destination surface, or NULL to fill the entire surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. * * \since This function is available since SDL 3.0.0. * * \sa SDL_BlitSurface */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, SDL_ScaleMode scaleMode); +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); /** - * Perform low-level surface scaled blitting only. + * Perform a scaled and tiled blit to a destination surface, which may be of a + * different format. * - * This is a semi-private function and it performs low-level surface blitting, - * assuming the input rectangles have already been clipped. + * The pixels in `srcrect` will be scaled and repeated as many times as needed + * to completely fill `dstrect`. * - * \param src the SDL_Surface structure to be copied from + * \param src the SDL_Surface structure to be copied from. * \param srcrect the SDL_Rect structure representing the rectangle to be - * copied - * \param dst the SDL_Surface structure that is the blit target + * copied, or NULL to copy the entire surface. + * \param scale the scale used to transform srcrect into the destination + * rectangle, e.g. a 32x32 texture with a scale of 2 would fill + * 64x64 tiles. + * \param scaleMode scale algorithm to be used. + * \param dst the SDL_Surface structure that is the blit target. * \param dstrect the SDL_Rect structure representing the target rectangle in - * the destination surface - * \param scaleMode scale algorithm to be used - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the destination surface, or NULL to fill the entire surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_BlitSurfaceScaled + * \sa SDL_BlitSurface + */ +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurfaceTiledWithScale(SDL_Surface *src, const SDL_Rect *srcrect, float scale, SDL_ScaleMode scaleMode, SDL_Surface *dst, const SDL_Rect *dstrect); + +/** + * Perform a scaled blit using the 9-grid algorithm to a destination surface, + * which may be of a different format. + * + * The pixels in the source surface are split into a 3x3 grid, using the + * different corner sizes for each corner, and the sides and center making up + * the remaining pixels. The corners are then scaled using `scale` and fit + * into the corners of the destination rectangle. The sides and center are + * then stretched into place to cover the remaining destination rectangle. + * + * \param src the SDL_Surface structure to be copied from. + * \param srcrect the SDL_Rect structure representing the rectangle to be used + * for the 9-grid, or NULL to use the entire surface. + * \param left_width the width, in pixels, of the left corners in `srcrect`. + * \param right_width the width, in pixels, of the right corners in `srcrect`. + * \param top_height the height, in pixels, of the top corners in `srcrect`. + * \param bottom_height the height, in pixels, of the bottom corners in + * `srcrect`. + * \param scale the scale used to transform the corner of `srcrect` into the + * corner of `dstrect`, or 0.0f for an unscaled blit. + * \param scaleMode scale algorithm to be used. + * \param dst the SDL_Surface structure that is the blit target. + * \param dstrect the SDL_Rect structure representing the target rectangle in + * the destination surface, or NULL to fill the entire surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety The same destination surface should not be used from two + * threads at once. It is safe to use the same source surface + * from multiple threads. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_BlitSurface + */ +extern SDL_DECLSPEC bool SDLCALL SDL_BlitSurface9Grid(SDL_Surface *src, const SDL_Rect *srcrect, int left_width, int right_width, int top_height, int bottom_height, float scale, SDL_ScaleMode scaleMode, SDL_Surface *dst, const SDL_Rect *dstrect); + +/** + * Map an RGB triple to an opaque pixel value for a surface. + * + * This function maps the RGB color value to the specified pixel format and + * returns the pixel value best approximating the given RGB color value for + * the given pixel format. + * + * If the surface has a palette, the index of the closest matching color in + * the palette will be returned. + * + * If the surface pixel format has an alpha component it will be returned as + * all 1 bits (fully opaque). + * + * If the pixel format bpp (color depth) is less than 32-bpp then the unused + * upper bits of the return value can safely be ignored (e.g., with a 16-bpp + * format the return value can be assigned to a Uint16, and similarly a Uint8 + * for an 8-bpp format). + * + * \param surface the surface to use for the pixel format and palette. + * \param r the red component of the pixel in the range 0-255. + * \param g the green component of the pixel in the range 0-255. + * \param b the blue component of the pixel in the range 0-255. + * \returns a pixel value. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_MapSurfaceRGBA */ -extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect, SDL_ScaleMode scaleMode); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGB(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b); + +/** + * Map an RGBA quadruple to a pixel value for a surface. + * + * This function maps the RGBA color value to the specified pixel format and + * returns the pixel value best approximating the given RGBA color value for + * the given pixel format. + * + * If the surface pixel format has no alpha component the alpha value will be + * ignored (as it will be in formats with a palette). + * + * If the surface has a palette, the index of the closest matching color in + * the palette will be returned. + * + * If the pixel format bpp (color depth) is less than 32-bpp then the unused + * upper bits of the return value can safely be ignored (e.g., with a 16-bpp + * format the return value can be assigned to a Uint16, and similarly a Uint8 + * for an 8-bpp format). + * + * \param surface the surface to use for the pixel format and palette. + * \param r the red component of the pixel in the range 0-255. + * \param g the green component of the pixel in the range 0-255. + * \param b the blue component of the pixel in the range 0-255. + * \param a the alpha component of the pixel in the range 0-255. + * \returns a pixel value. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_MapSurfaceRGB + */ +extern SDL_DECLSPEC Uint32 SDLCALL SDL_MapSurfaceRGBA(SDL_Surface *surface, Uint8 r, Uint8 g, Uint8 b, Uint8 a); /** * Retrieves a single pixel from a surface. @@ -1020,23 +1331,90 @@ extern DECLSPEC int SDLCALL SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, con * Like SDL_GetRGBA, this uses the entire 0..255 range when converting color * components from pixel formats with less than 8 bits per RGB component. * - * \param surface the surface to read - * \param x the horizontal coordinate, 0 <= x < width - * \param y the vertical coordinate, 0 <= y < height + * \param surface the surface to read. + * \param x the horizontal coordinate, 0 <= x < width. + * \param y the vertical coordinate, 0 <= y < height. * \param r a pointer filled in with the red channel, 0-255, or NULL to ignore - * this channel + * this channel. * \param g a pointer filled in with the green channel, 0-255, or NULL to - * ignore this channel + * ignore this channel. * \param b a pointer filled in with the blue channel, 0-255, or NULL to - * ignore this channel + * ignore this channel. * \param a a pointer filled in with the alpha channel, 0-255, or NULL to - * ignore this channel - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * ignore this channel. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + +/** + * Retrieves a single pixel from a surface. + * + * This function prioritizes correctness over speed: it is suitable for unit + * tests, but is not intended for use in a game engine. + * + * \param surface the surface to read. + * \param x the horizontal coordinate, 0 <= x < width. + * \param y the vertical coordinate, 0 <= y < height. + * \param r a pointer filled in with the red channel, normally in the range + * 0-1, or NULL to ignore this channel. + * \param g a pointer filled in with the green channel, normally in the range + * 0-1, or NULL to ignore this channel. + * \param b a pointer filled in with the blue channel, normally in the range + * 0-1, or NULL to ignore this channel. + * \param a a pointer filled in with the alpha channel, normally in the range + * 0-1, or NULL to ignore this channel. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_ReadSurfacePixelFloat(SDL_Surface *surface, int x, int y, float *r, float *g, float *b, float *a); + +/** + * Writes a single pixel to a surface. + * + * This function prioritizes correctness over speed: it is suitable for unit + * tests, but is not intended for use in a game engine. + * + * Like SDL_MapRGBA, this uses the entire 0..255 range when converting color + * components from pixel formats with less than 8 bits per RGB component. + * + * \param surface the surface to write. + * \param x the horizontal coordinate, 0 <= x < width. + * \param y the vertical coordinate, 0 <= y < height. + * \param r the red channel value, 0-255. + * \param g the green channel value, 0-255. + * \param b the blue channel value, 0-255. + * \param a the alpha channel value, 0-255. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/** + * Writes a single pixel to a surface. + * + * This function prioritizes correctness over speed: it is suitable for unit + * tests, but is not intended for use in a game engine. + * + * \param surface the surface to write. + * \param x the horizontal coordinate, 0 <= x < width. + * \param y the vertical coordinate, 0 <= y < height. + * \param r the red channel value, normally in the range 0-1. + * \param g the green channel value, normally in the range 0-1. + * \param b the blue channel value, normally in the range 0-1. + * \param a the alpha channel value, normally in the range 0-1. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_ReadSurfacePixel(SDL_Surface *surface, int x, int y, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); +extern SDL_DECLSPEC bool SDLCALL SDL_WriteSurfacePixelFloat(SDL_Surface *surface, int x, int y, float r, float g, float b, float a); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_system.h b/libs/SDL3/include/SDL3/SDL_system.h index 25964ba35..88e318ddf 100644 --- a/libs/SDL3/include/SDL3/SDL_system.h +++ b/libs/SDL3/include/SDL3/SDL_system.h @@ -20,17 +20,17 @@ */ /** - * \file SDL_system.h + * # CategorySystem * - * Include file for platform specific SDL API functions + * Platform-specific SDL API functions. */ #ifndef SDL_system_h_ #define SDL_system_h_ #include +#include #include -#include #include #include @@ -43,26 +43,51 @@ extern "C" { /* * Platform specific functions for Windows */ -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) typedef struct tagMSG MSG; -typedef SDL_bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); + +/** + * A callback to be used with SDL_SetWindowsMessageHook. + * + * This callback may modify the message, and should return true if the message + * should continue to be processed, or false to prevent further processing. + * + * As this is processing a message directly from the Windows event loop, this + * callback should do the minimum required work and return quickly. + * + * \param userdata the app-defined pointer provided to + * SDL_SetWindowsMessageHook. + * \param msg a pointer to a Win32 event structure to process. + * \returns true to let event continue on, false to drop it. + * + * \threadsafety This may only be called (by SDL) from the thread handling the + * Windows event loop. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_SetWindowsMessageHook + * \sa SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP + */ +typedef bool (SDLCALL *SDL_WindowsMessageHook)(void *userdata, MSG *msg); /** * Set a callback for every Windows message, run before TranslateMessage(). * - * The callback may modify the message, and should return SDL_TRUE if the - * message should continue to be processed, or SDL_FALSE to prevent further - * processing. + * The callback may modify the message, and should return true if the message + * should continue to be processed, or false to prevent further processing. * - * \param callback The SDL_WindowsMessageHook function to call. - * \param userdata a pointer to pass to every iteration of `callback` + * \param callback the SDL_WindowsMessageHook function to call. + * \param userdata a pointer to pass to every iteration of `callback`. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_WindowsMessageHook + * \sa SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP */ -extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata); +extern SDL_DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata); -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ +#endif /* defined(SDL_PLATFORM_WINDOWS) */ #if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) @@ -72,17 +97,13 @@ extern DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(SDL_WindowsMessageHook ca * The returned adapter index can be passed to `IDirect3D9::CreateDevice` and * controls on which monitor a full screen application will appear. * - * \param displayID the instance of the display to query - * \returns the D3D9 adapter index on success or a negative error code on - * failure; call SDL_GetError() for more information. + * \param displayID the instance of the display to query. + * \returns the D3D9 adapter index on success or -1 on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID); - -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ - -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) +extern SDL_DECLSPEC int SDLCALL SDL_GetDirect3D9AdapterIndex(SDL_DisplayID displayID); /** * Get the DXGI Adapter and Output indices for the specified display. @@ -91,42 +112,40 @@ extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex(SDL_DisplayID displayID * `EnumOutputs` respectively to get the objects required to create a DX10 or * DX11 device and swap chain. * - * \param displayID the instance of the display to query - * \param adapterIndex a pointer to be filled in with the adapter index - * \param outputIndex a pointer to be filled in with the output index - * \returns SDL_TRUE on success or SDL_FALSE on failure; call SDL_GetError() - * for more information. + * \param displayID the instance of the display to query. + * \param adapterIndex a pointer to be filled in with the adapter index. + * \param outputIndex a pointer to be filled in with the output index. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_DXGIGetOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex); +extern SDL_DECLSPEC bool SDLCALL SDL_GetDXGIOutputInfo(SDL_DisplayID displayID, int *adapterIndex, int *outputIndex); #endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ + /* * Platform specific functions for UNIX */ typedef union _XEvent XEvent; -typedef SDL_bool (SDLCALL *SDL_X11EventHook)(void *userdata, XEvent *xevent); +typedef bool (SDLCALL *SDL_X11EventHook)(void *userdata, XEvent *xevent); /** - * Set a callback for every X11 event + * Set a callback for every X11 event. * - * The callback may modify the event, and should return SDL_TRUE if the event - * should continue to be processed, or SDL_FALSE to prevent further - * processing. + * The callback may modify the event, and should return true if the event + * should continue to be processed, or false to prevent further processing. * - * \param callback The SDL_X11EventHook function to call. - * \param userdata a pointer to pass to every iteration of `callback` + * \param callback the SDL_X11EventHook function to call. + * \param userdata a pointer to pass to every iteration of `callback`. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata); +extern SDL_DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata); -/* - * Platform specific functions for Linux - */ +/* Platform specific functions for Linux*/ #ifdef SDL_PLATFORM_LINUX /** @@ -135,28 +154,29 @@ extern DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void * This uses setpriority() if possible, and RealtimeKit if available. * * \param threadID the Unix thread ID to change priority of. - * \param priority The new, Unix-specific, priority value. - * \returns 0 on success, or -1 on error. + * \param priority the new, Unix-specific, priority value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); +extern SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriority(Sint64 threadID, int priority); /** * Sets the priority (not nice level) and scheduling policy for a thread. * * This uses setpriority() if possible, and RealtimeKit if available. * - * \param threadID The Unix thread ID to change priority of. - * \param sdlPriority The new SDL_ThreadPriority value. - * \param schedPolicy The new scheduling policy (SCHED_FIFO, SCHED_RR, - * SCHED_OTHER, etc...) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param threadID the Unix thread ID to change priority of. + * \param sdlPriority the new SDL_ThreadPriority value. + * \param schedPolicy the new scheduling policy (SCHED_FIFO, SCHED_RR, + * SCHED_OTHER, etc...). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); +extern SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); #endif /* SDL_PLATFORM_LINUX */ @@ -165,7 +185,23 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, */ #ifdef SDL_PLATFORM_IOS -#define SDL_iOSSetAnimationCallback(window, interval, callback, callbackParam) SDL_iPhoneSetAnimationCallback(window, interval, callback, callbackParam) +/** + * The prototype for an Apple iOS animation callback. + * + * This datatype is only useful on Apple iOS. + * + * After passing a function pointer of this type to + * SDL_SetiOSAnimationCallback, the system will call that function pointer at + * a regular interval. + * + * \param userdata what was passed as `callbackParam` to + * SDL_SetiOSAnimationCallback as `callbackParam`. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_SetiOSAnimationCallback + */ +typedef void (SDLCALL *SDL_iOSAnimationCallback)(void *userdata); /** * Use this function to set the animation callback on Apple iOS. @@ -173,51 +209,51 @@ extern DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, * The function prototype for `callback` is: * * ```c - * void callback(void* callbackParam); + * void callback(void *callbackParam); * ``` * * Where its parameter, `callbackParam`, is what was passed as `callbackParam` - * to SDL_iPhoneSetAnimationCallback(). + * to SDL_SetiOSAnimationCallback(). * * This function is only available on Apple iOS. * * For more information see: - * https://github.com/libsdl-org/SDL/blob/main/docs/README-ios.md * - * This functions is also accessible using the macro - * SDL_iOSSetAnimationCallback() since SDL 2.0.4. + * https://wiki.libsdl.org/SDL3/README/ios + * + * Note that if you use the "main callbacks" instead of a standard C `main` + * function, you don't have to use this API, as SDL will manage this for you. + * + * Details on main callbacks are here: + * + * https://wiki.libsdl.org/SDL3/README/main-functions * - * \param window the window for which the animation callback should be set + * \param window the window for which the animation callback should be set. * \param interval the number of frames after which **callback** will be - * called + * called. * \param callback the function to call for every frame. * \param callbackParam a pointer that is passed to `callback`. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_iPhoneSetEventPump + * \sa SDL_SetiOSEventPump */ -extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (SDLCALL *callback)(void*), void *callbackParam); - -#define SDL_iOSSetEventPump(enabled) SDL_iPhoneSetEventPump(enabled) +extern SDL_DECLSPEC bool SDLCALL SDL_SetiOSAnimationCallback(SDL_Window *window, int interval, SDL_iOSAnimationCallback callback, void *callbackParam); /** * Use this function to enable or disable the SDL event pump on Apple iOS. * * This function is only available on Apple iOS. * - * This functions is also accessible using the macro SDL_iOSSetEventPump() - * since SDL 2.0.4. - * - * \param enabled SDL_TRUE to enable the event pump, SDL_FALSE to disable it + * \param enabled true to enable the event pump, false to disable it. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_iPhoneSetAnimationCallback + * \sa SDL_SetiOSAnimationCallback */ -extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); +extern SDL_DECLSPEC void SDLCALL SDL_SetiOSEventPump(bool enabled); #endif /* SDL_PLATFORM_IOS */ @@ -238,13 +274,16 @@ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); * rationale being that the SDL headers can avoid including jni.h. * * \returns a pointer to Java native interface object (JNIEnv) to which the - * current thread is attached, or 0 on error. + * current thread is attached, or NULL on failure; call + * SDL_GetError() for more information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AndroidGetActivity + * \sa SDL_GetAndroidActivity */ -extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(void); +extern SDL_DECLSPEC void * SDLCALL SDL_GetAndroidJNIEnv(void); /** * Retrieve the Java instance of the Android activity class. @@ -260,17 +299,21 @@ extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(void); * https://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html * * \returns the jobject representing the instance of the Activity class of the - * Android application, or NULL on error. + * Android application, or NULL on failure; call SDL_GetError() for + * more information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AndroidGetJNIEnv + * \sa SDL_GetAndroidJNIEnv */ -extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void); +extern SDL_DECLSPEC void * SDLCALL SDL_GetAndroidActivity(void); /** * Query Android API level of the current device. * + * - API level 35: Android 15 (VANILLA_ICE_CREAM) * - API level 34: Android 14 (UPSIDE_DOWN_CAKE) * - API level 33: Android 13 (TIRAMISU) * - API level 32: Android 12L (S_V2) @@ -301,51 +344,46 @@ extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); - -/** - * Query if the application is running on Android TV. - * - * \returns SDL_TRUE if this is Android TV, SDL_FALSE otherwise. - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void); +extern SDL_DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); /** * Query if the application is running on a Chromebook. * - * \returns SDL_TRUE if this is a Chromebook, SDL_FALSE otherwise. + * \returns true if this is a Chromebook, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void); +extern SDL_DECLSPEC bool SDLCALL SDL_IsChromebook(void); /** * Query if the application is running on a Samsung DeX docking station. * - * \returns SDL_TRUE if this is a DeX docking station, SDL_FALSE otherwise. + * \returns true if this is a DeX docking station, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void); +extern SDL_DECLSPEC bool SDLCALL SDL_IsDeXMode(void); /** * Trigger the Android system back button behavior. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void); +extern SDL_DECLSPEC void SDLCALL SDL_SendAndroidBackButton(void); /** - See the official Android developer guide for more information: - http://developer.android.com/guide/topics/data/data-storage.html -*/ + * See the official Android developer guide for more information: + * http://developer.android.com/guide/topics/data/data-storage.html + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01 #define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02 /** - * Get the path used for internal storage for this application. + * Get the path used for internal storage for this Android application. * * This path is unique to your application and cannot be written to by other * applications. @@ -353,36 +391,38 @@ extern DECLSPEC void SDLCALL SDL_AndroidBackButton(void); * Your internal storage path is typically: * `/data/data/your.app.package/files`. * + * This is a C wrapper over `android.content.Context.getFilesDir()`: + * + * https://developer.android.com/reference/android/content/Context#getFilesDir() + * * \returns the path used for internal storage or NULL on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AndroidGetExternalStorageState + * \sa SDL_GetAndroidExternalStorageState */ -extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(void); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetAndroidInternalStoragePath(void); /** - * Get the current state of external storage. + * Get the current state of external storage for this Android application. * * The current state of external storage, a bitmask of these values: * `SDL_ANDROID_EXTERNAL_STORAGE_READ`, `SDL_ANDROID_EXTERNAL_STORAGE_WRITE`. * * If external storage is currently unavailable, this will return 0. * - * \param state filled with the current state of external storage. 0 if - * external storage is currently unavailable. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns the current state of external storage, or 0 if external storage is + * currently unavailable. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AndroidGetExternalStoragePath + * \sa SDL_GetAndroidExternalStoragePath */ -extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state); +extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetAndroidExternalStorageState(void); /** - * Get the path used for external storage for this application. + * Get the path used for external storage for this Android application. * * This path is unique to your application, but is public and can be written * to by other applications. @@ -390,17 +430,40 @@ extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state); * Your external storage path is typically: * `/storage/sdcard0/Android/data/your.app.package/files`. * + * This is a C wrapper over `android.content.Context.getExternalFilesDir()`: + * + * https://developer.android.com/reference/android/content/Context#getExternalFilesDir() + * * \returns the path used for external storage for this application on success * or NULL on failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_AndroidGetExternalStorageState + * \sa SDL_GetAndroidExternalStorageState */ -extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(void); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetAndroidExternalStoragePath(void); + +/** + * Get the path used for caching data for this Android application. + * + * This path is unique to your application, but is public and can be written + * to by other applications. + * + * Your cache path is typically: `/data/data/your.app.package/cache/`. + * + * This is a C wrapper over `android.content.Context.getCacheDir()`: + * + * https://developer.android.com/reference/android/content/Context#getCacheDir() + * + * \returns the path used for caches for this application on success or NULL + * on failure; call SDL_GetError() for more information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC const char * SDLCALL SDL_GetAndroidCachePath(void); -typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, const char *permission, SDL_bool granted); +typedef void (SDLCALL *SDL_RequestAndroidPermissionCallback)(void *userdata, const char *permission, bool granted); /** * Request permissions at runtime, asynchronously. @@ -421,16 +484,18 @@ typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, con * like memory running out. Normally there will be a yes or no to the request * through the callback. * - * \param permission The permission to request. - * \param cb The callback to trigger when the request has a response. - * \param userdata An app-controlled pointer that is passed to the callback. - * \returns zero if the request was submitted, -1 if there was an error + * \param permission the permission to request. + * \param cb the callback to trigger when the request has a response. + * \param userdata an app-controlled pointer that is passed to the callback. + * \returns true if the request was submitted, false if there was an error * submitting. The result of the request is only ever reported * through the callback, not this return value. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata); +extern SDL_DECLSPEC bool SDLCALL SDL_RequestAndroidPermission(const char *permission, SDL_RequestAndroidPermissionCallback cb, void *userdata); /** * Shows an Android toast notification. @@ -446,196 +511,182 @@ extern DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, * * https://developer.android.com/reference/android/view/Gravity * - * \param message text message to be shown - * \param duration 0=short, 1=long + * \param message text message to be shown. + * \param duration 0=short, 1=long. * \param gravity where the notification should appear on the screen. - * \param xoffset set this parameter only when gravity >=0 - * \param yoffset set this parameter only when gravity >=0 - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param xoffset set this parameter only when gravity >=0. + * \param yoffset set this parameter only when gravity >=0. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowAndroidToast(const char *message, int duration, int gravity, int xoffset, int yoffset); /** * Send a user command to SDLActivity. * * Override "boolean onUnhandledMessage(Message msg)" to handle the message. * - * \param command user command that must be greater or equal to 0x8000 - * \param param user parameter - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param command user command that must be greater or equal to 0x8000. + * \param param user parameter. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); +extern SDL_DECLSPEC bool SDLCALL SDL_SendAndroidMessage(Uint32 command, int param); #endif /* SDL_PLATFORM_ANDROID */ -/* - * Platform specific functions for WinRT - */ -#ifdef SDL_PLATFORM_WINRT - /** - * WinRT / Windows Phone path types + * Query if the current device is a tablet. + * + * If SDL can't determine this, it will return false. + * + * \returns true if the device is a tablet, false otherwise. + * + * \since This function is available since SDL 3.0.0. */ -typedef enum -{ - /** The installed app's root directory. - Files here are likely to be read-only. */ - SDL_WINRT_PATH_INSTALLED_LOCATION, - - /** The app's local data store. Files may be written here */ - SDL_WINRT_PATH_LOCAL_FOLDER, - - /** The app's roaming data store. Unsupported on Windows Phone. - Files written here may be copied to other machines via a network - connection. - */ - SDL_WINRT_PATH_ROAMING_FOLDER, - - /** The app's temporary data store. Unsupported on Windows Phone. - Files written here may be deleted at any time. */ - SDL_WINRT_PATH_TEMP_FOLDER -} SDL_WinRT_Path; - +extern SDL_DECLSPEC bool SDLCALL SDL_IsTablet(void); /** - * WinRT Device Family + * Query if the current device is a TV. + * + * If SDL can't determine this, it will return false. + * + * \returns true if the device is a TV, false otherwise. + * + * \since This function is available since SDL 3.0.0. */ -typedef enum -{ - /** Unknown family */ - SDL_WINRT_DEVICEFAMILY_UNKNOWN, - - /** Desktop family*/ - SDL_WINRT_DEVICEFAMILY_DESKTOP, - - /** Mobile family (for example smartphone) */ - SDL_WINRT_DEVICEFAMILY_MOBILE, - - /** XBox family */ - SDL_WINRT_DEVICEFAMILY_XBOX, -} SDL_WinRT_DeviceFamily; +extern SDL_DECLSPEC bool SDLCALL SDL_IsTV(void); +/* Functions used by iOS app delegates to notify SDL about state changes. */ /** - * Retrieve a WinRT defined path on the local file system. + * Let iOS apps with external event handling report + * onApplicationWillTerminate. * - * Not all paths are available on all versions of Windows. This is especially - * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path - * for more information on which path types are supported where. + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! * - * Documentation on most app-specific path types on WinRT can be found on - * MSDN, at the URL: + * \threadsafety It is safe to call this function from any thread. * - * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx - * - * \param pathType the type of path to retrieve, one of SDL_WinRT_Path - * \returns a UCS-2 string (16-bit, wide-char) containing the path, or NULL if - * the path is not available for any reason; call SDL_GetError() for - * more information. - * - * \since This function is available since SDL 2.0.3. - * - * \sa SDL_WinRTGetFSPathUTF8 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const wchar_t * SDLCALL SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationWillTerminate(void); /** - * Retrieve a WinRT defined path on the local file system. - * - * Not all paths are available on all versions of Windows. This is especially - * true on Windows Phone. Check the documentation for the given SDL_WinRT_Path - * for more information on which path types are supported where. + * Let iOS apps with external event handling report + * onApplicationDidReceiveMemoryWarning. * - * Documentation on most app-specific path types on WinRT can be found on - * MSDN, at the URL: + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! * - * https://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx + * \threadsafety It is safe to call this function from any thread. * - * \param pathType the type of path to retrieve, one of SDL_WinRT_Path - * \returns a UTF-8 string (8-bit, multi-byte) containing the path, or NULL if - * the path is not available for any reason; call SDL_GetError() for - * more information. - * - * \since This function is available since SDL 2.0.3. - * - * \sa SDL_WinRTGetFSPathUNICODE + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char * SDLCALL SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationDidReceiveMemoryWarning(void); /** - * Detects the device family of WinRT platform at runtime. + * Let iOS apps with external event handling report + * onApplicationWillResignActive. * - * \returns a value from the SDL_WinRT_DeviceFamily enum. + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_WinRT_DeviceFamily SDLCALL SDL_WinRTGetDeviceFamily(); - -#endif /* SDL_PLATFORM_WINRT */ +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationWillEnterBackground(void); /** - * Query if the current device is a tablet. + * Let iOS apps with external event handling report + * onApplicationDidEnterBackground. * - * If SDL can't determine this, it will return SDL_FALSE. + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! * - * \returns SDL_TRUE if the device is a tablet, SDL_FALSE otherwise. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_IsTablet(void); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationDidEnterBackground(void); -/* Functions used by iOS app delegates to notify SDL about state changes. +/** + * Let iOS apps with external event handling report + * onApplicationWillEnterForeground. + * + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! + * + * \threadsafety It is safe to call this function from any thread. * - * These functions allow iOS apps that have their own event handling to hook - * into SDL to generate SDL events. These map directly to iOS-specific - * events, but since they don't do anything iOS-specific internally, they - * are available on all platforms, in case they might be useful for some - * specific paradigm. Most apps do not need to use these directly; SDL's - * internal event code will handle all this for windows created by - * SDL_CreateWindow! - */ - -/* - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_OnApplicationWillTerminate(void); - -/* - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_OnApplicationDidReceiveMemoryWarning(void); - -/* - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_OnApplicationWillResignActive(void); - -/* - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC void SDLCALL SDL_OnApplicationDidEnterBackground(void); - -/* * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationWillEnterForeground(void); -/* +/** + * Let iOS apps with external event handling report + * onApplicationDidBecomeActive. + * + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! + * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_OnApplicationDidBecomeActive(void); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationDidEnterForeground(void); #ifdef SDL_PLATFORM_IOS -/* + +/** + * Let iOS apps with external event handling report + * onApplicationDidChangeStatusBarOrientation. + * + * This functions allows iOS apps that have their own event handling to hook + * into SDL to generate SDL events. This maps directly to an iOS-specific + * event, but since it doesn't do anything iOS-specific internally, it is + * available on all platforms, in case it might be useful for some specific + * paradigm. Most apps do not need to use this directly; SDL's internal event + * code will handle all this for windows created by SDL_CreateWindow! + * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void); +extern SDL_DECLSPEC void SDLCALL SDL_OnApplicationDidChangeStatusBarOrientation(void); #endif /* @@ -654,12 +705,12 @@ typedef struct XUser *XUserHandle; * leak. * * \param outTaskQueue a pointer to be filled in with task queue handle. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue); +extern SDL_DECLSPEC bool SDLCALL SDL_GetGDKTaskQueue(XTaskQueueHandle *outTaskQueue); /** * Gets a reference to the default user handle for GDK. @@ -669,11 +720,12 @@ extern DECLSPEC int SDLCALL SDL_GDKGetTaskQueue(XTaskQueueHandle * outTaskQueue) * * \param outUserHandle a pointer to be filled in with the default user * handle. - * \returns 0 if success, -1 if any error occurs. + * \returns true if success or false on failure; call SDL_GetError() for more + * information. * - * \since This function is available since SDL 2.28.0. + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(XUserHandle * outUserHandle); +extern SDL_DECLSPEC bool SDLCALL SDL_GetGDKDefaultUser(XUserHandle *outUserHandle); #endif diff --git a/libs/SDL3/include/SDL3/SDL_test.h b/libs/SDL3/include/SDL3/SDL_test.h index 634382cf4..e84687391 100644 --- a/libs/SDL3/include/SDL3/SDL_test.h +++ b/libs/SDL3/include/SDL3/SDL_test.h @@ -41,7 +41,6 @@ #include #include #include -#include #include /* Set up for C function definitions, even when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_test_assert.h b/libs/SDL3/include/SDL3/SDL_test_assert.h index 122c355bd..4d857b2ab 100644 --- a/libs/SDL3/include/SDL3/SDL_test_assert.h +++ b/libs/SDL3/include/SDL3/SDL_test_assert.h @@ -20,8 +20,6 @@ */ /** - * \file SDL_test_assert.h - * * Assertion functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. @@ -36,31 +34,29 @@ #ifndef SDL_test_assert_h_ #define SDL_test_assert_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif -/** - * Fails the assert. - */ +/* Fails the assert. */ #define ASSERT_FAIL 0 -/** - * Passes the assert. - */ +/* Passes the assert. */ #define ASSERT_PASS 1 -/** +/* * Assert that logs and break execution flow on failures. * * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). * \param assertDescription Message to log with the assert describing it. */ -void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); +void SDLCALL SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); -/** +/* * Assert for test cases that logs but does not break execution flow on failures. Updates assertion counters. * * \param assertCondition Evaluated condition or variable to assert; fail (==0) or pass (!=0). @@ -68,32 +64,31 @@ void SDLTest_Assert(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *as * * \returns the assertCondition so it can be used to externally to break execution flow if desired. */ -int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); +int SDLCALL SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(2); -/** +/* * Explicitly pass without checking an assertion condition. Updates assertion counter. * * \param assertDescription Message to log with the assert describing it. */ -void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1); +void SDLCALL SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription, ...) SDL_PRINTF_VARARG_FUNC(1); -/** +/* * Resets the assert summary counters to zero. */ -void SDLTest_ResetAssertSummary(void); +void SDLCALL SDLTest_ResetAssertSummary(void); -/** +/* * Logs summary of all assertions (total, pass, fail) since last reset as INFO or ERROR. */ -void SDLTest_LogAssertSummary(void); - +void SDLCALL SDLTest_LogAssertSummary(void); -/** +/* * Converts the current assert summary state to a test result. * * \returns TEST_RESULT_PASSED, TEST_RESULT_FAILED, or TEST_RESULT_NO_ASSERT */ -int SDLTest_AssertSummaryToTestResult(void); +int SDLCALL SDLTest_AssertSummaryToTestResult(void); #ifdef __cplusplus } diff --git a/libs/SDL3/include/SDL3/SDL_test_common.h b/libs/SDL3/include/SDL3/SDL_test_common.h index 5697c5648..aeffeb93b 100644 --- a/libs/SDL3/include/SDL3/SDL_test_common.h +++ b/libs/SDL3/include/SDL3/SDL_test_common.h @@ -27,7 +27,7 @@ * This code is a part of the SDL test library, not the main SDL library. */ -/* Ported from original test\common.h file. */ +/* Ported from original test/common.h file. */ #ifndef SDL_test_common_h_ #define SDL_test_common_h_ @@ -45,6 +45,7 @@ #define DEFAULT_WINDOW_HEIGHT 480 #endif +typedef Uint32 SDLTest_VerboseFlags; #define VERBOSE_VIDEO 0x00000001 #define VERBOSE_MODES 0x00000002 #define VERBOSE_RENDER 0x00000004 @@ -52,12 +53,33 @@ #define VERBOSE_AUDIO 0x00000010 #define VERBOSE_MOTION 0x00000020 +/* !< Function pointer parsing one argument at argv[index], returning the number of parsed arguments, + * or a negative value when the argument is invalid */ +typedef int (SDLCALL *SDLTest_ParseArgumentsFp)(void *data, char **argv, int index); + +/* !< Finalize the argument parser. */ +typedef void (SDLCALL *SDLTest_FinalizeArgumentParserFp)(void *arg); + +typedef struct SDLTest_ArgumentParser +{ + /* !< Parse an argument. */ + SDLTest_ParseArgumentsFp parse_arguments; + /* !< Finalize this argument parser. Called once before parsing the first argument. */ + SDLTest_FinalizeArgumentParserFp finalize; + /* !< Null-terminated array of arguments. Printed when running with --help. */ + const char **usage; + /* !< User data, passed to all callbacks. */ + void *data; + /* !< Next argument parser. */ + struct SDLTest_ArgumentParser *next; +} SDLTest_ArgumentParser; + typedef struct { /* SDL init flags */ char **argv; - Uint32 flags; - Uint32 verbose; + SDL_InitFlags flags; + SDLTest_VerboseFlags verbose; /* Video info */ const char *videodriver; @@ -66,7 +88,7 @@ typedef struct const char *window_title; const char *window_icon; SDL_WindowFlags window_flags; - SDL_bool flash_on_focus_loss; + bool flash_on_focus_loss; int window_x; int window_y; int window_w; @@ -75,23 +97,26 @@ typedef struct int window_minH; int window_maxW; int window_maxH; + float window_min_aspect; + float window_max_aspect; int logical_w; int logical_h; - SDL_bool auto_scale_content; + bool auto_scale_content; SDL_RendererLogicalPresentation logical_presentation; - SDL_ScaleMode logical_scale_mode; float scale; int depth; float refresh_rate; - SDL_bool fullscreen_exclusive; + bool fill_usable_bounds; + bool fullscreen_exclusive; SDL_DisplayMode fullscreen_mode; int num_windows; SDL_Window **windows; + const char *gpudriver; /* Renderer info */ const char *renderdriver; - Uint32 render_flags; - SDL_bool skip_renderer; + int render_vsync; + bool skip_renderer; SDL_Renderer **renderers; SDL_Texture **targets; @@ -127,7 +152,14 @@ typedef struct /* Mouse info */ SDL_Rect confine; + bool hide_cursor; + + /* Options info */ + SDLTest_ArgumentParser common_argparser; + SDLTest_ArgumentParser video_argparser; + SDLTest_ArgumentParser audio_argparser; + SDLTest_ArgumentParser *argparser; } SDLTest_CommonState; #include @@ -146,14 +178,16 @@ extern "C" { * * \returns a newly allocated common state object. */ -SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); +SDLTest_CommonState *SDLCALL SDLTest_CommonCreateState(char **argv, SDL_InitFlags flags); /** * Free the common state object. * + * You should call SDL_Quit() before calling this function. + * * \param state The common state object to destroy */ -void SDLTest_CommonDestroyState(SDLTest_CommonState *state); +void SDLCALL SDLTest_CommonDestroyState(SDLTest_CommonState *state); /** * Process one common argument. @@ -163,7 +197,7 @@ void SDLTest_CommonDestroyState(SDLTest_CommonState *state); * * \returns the number of arguments processed (i.e. 1 for --fullscreen, 2 for --video [videodriver], or -1 on error. */ -int SDLTest_CommonArg(SDLTest_CommonState *state, int index); +int SDLCALL SDLTest_CommonArg(SDLTest_CommonState *state, int index); /** @@ -178,16 +212,16 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index); * \param argv0 argv[0], as passed to main/SDL_main. * \param options an array of strings for application specific options. The last element of the array should be NULL. */ -void SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options); +void SDLCALL SDLTest_CommonLogUsage(SDLTest_CommonState *state, const char *argv0, const char **options); /** * Open test window. * * \param state The common state describing the test window to create. * - * \returns SDL_TRUE if initialization succeeded, false otherwise + * \returns true if initialization succeeded, false otherwise */ -SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state); +bool SDLCALL SDLTest_CommonInit(SDLTest_CommonState *state); /** * Easy argument handling when test app doesn't need any custom args. @@ -196,20 +230,27 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state); * \param argc argc, as supplied to SDL_main * \param argv argv, as supplied to SDL_main * - * \returns SDL_FALSE if app should quit, true otherwise. + * \returns false if app should quit, true otherwise. */ -SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **argv); +bool SDLCALL SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, int argc, char **argv); /** - * Common event handler for test windows if you use a standard SDL_main. + * Print the details of an event. + * + * This is automatically called by SDLTest_CommonEvent() as needed. * - * This will free data from the event, like the string in a drop event! + * \param event The event to print. + */ +void SDLCALL SDLTest_PrintEvent(const SDL_Event *event); + +/** + * Common event handler for test windows if you use a standard SDL_main. * * \param state The common state used to create test window. * \param event The event to handle. * \param done Flag indicating we are done. */ -void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done); +void SDLCALL SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done); /** * Common event handler for test windows if you use SDL_AppEvent. @@ -220,7 +261,7 @@ void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done * \param event The event to handle. * \returns Value suitable for returning from SDL_AppEvent(). */ -int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event); +SDL_AppResult SDLCALL SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event *event); /** * Close test window. @@ -228,7 +269,7 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event * \param state The common state used to create test window. * */ -void SDLTest_CommonQuit(SDLTest_CommonState *state); +void SDLCALL SDLTest_CommonQuit(SDLTest_CommonState *state); /** * Draws various window information (position, size, etc.) to the renderer. @@ -238,7 +279,7 @@ void SDLTest_CommonQuit(SDLTest_CommonState *state); * \param usedHeight Returns the height used, so the caller can draw more below. * */ -void SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, float *usedHeight); +void SDLCALL SDLTest_CommonDrawWindowInfo(SDL_Renderer *renderer, SDL_Window *window, float *usedHeight); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_compare.h b/libs/SDL3/include/SDL3/SDL_test_compare.h index 82de5d249..a7e18e3c7 100644 --- a/libs/SDL3/include/SDL3/SDL_test_compare.h +++ b/libs/SDL3/include/SDL3/SDL_test_compare.h @@ -53,8 +53,21 @@ extern "C" { * * \returns 0 if comparison succeeded, >0 (=number of pixels for which the comparison failed) if comparison failed, -1 if any of the surfaces were NULL, -2 if the surface sizes differ. */ -int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); +int SDLCALL SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface, int allowable_error); +/** + * Compares 2 memory blocks for equality + * + * \param actual Memory used in comparison, displayed on the left + * \param size_actual Size of actual in bytes + * \param reference Reference memory, displayed on the right + * \param size_reference Size of reference in bytes + * + * \returns 0 if the left and right memory block are equal, non-zero if they are non-equal. + * + * \since This function is available since SDL 3.0.0. + */ +int SDLCALL SDLTest_CompareMemory(const void *actual, size_t size_actual, const void *reference, size_t size_reference); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_crc32.h b/libs/SDL3/include/SDL3/SDL_test_crc32.h index 07f89aba2..62ece2afa 100644 --- a/libs/SDL3/include/SDL3/SDL_test_crc32.h +++ b/libs/SDL3/include/SDL3/SDL_test_crc32.h @@ -20,8 +20,6 @@ */ /** - * \file SDL_test_crc32.h - * * CRC32 functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. @@ -36,13 +34,14 @@ #ifndef SDL_test_crc32_h_ #define SDL_test_crc32_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif - /* ------------ Definitions --------- */ /* Definition shared by all CRC routines */ @@ -60,7 +59,7 @@ extern "C" { #define CRC32_POLY 0xEDB88320 /* Perl String::CRC32 compatible */ #endif -/** +/* * Data structure for CRC32 (checksum) computation */ typedef struct SDLTest_Crc32Context { @@ -69,20 +68,20 @@ extern "C" { /* ---------- Function Prototypes ------------- */ -/** +/* * Initialize the CRC context * * Note: The function initializes the crc table required for all crc calculations. * * \param crcContext pointer to context variable * - * \returns 0 for OK, -1 on error + * \returns true on success or false on failure; call SDL_GetError() + * for more information. * */ - int SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext); +bool SDLCALL SDLTest_Crc32Init(SDLTest_Crc32Context *crcContext); - -/** +/* * calculate a crc32 from a data block * * \param crcContext pointer to context variable @@ -90,28 +89,28 @@ extern "C" { * \param inLen length of input buffer * \param crc32 pointer to Uint32 to store the final CRC into * - * \returns 0 for OK, -1 on error + * \returns true on success or false on failure; call SDL_GetError() + * for more information. * */ -int SDLTest_Crc32Calc(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); +bool SDLCALL SDLTest_Crc32Calc(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); /* Same routine broken down into three steps */ -int SDLTest_Crc32CalcStart(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32); -int SDLTest_Crc32CalcEnd(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32); -int SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); - +bool SDLCALL SDLTest_Crc32CalcStart(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32); +bool SDLCALL SDLTest_Crc32CalcEnd(SDLTest_Crc32Context *crcContext, CrcUint32 *crc32); +bool SDLCALL SDLTest_Crc32CalcBuffer(SDLTest_Crc32Context *crcContext, CrcUint8 *inBuf, CrcUint32 inLen, CrcUint32 *crc32); -/** +/* * clean up CRC context * * \param crcContext pointer to context variable * - * \returns 0 for OK, -1 on error + * \returns true on success or false on failure; call SDL_GetError() + * for more information. * */ -int SDLTest_Crc32Done(SDLTest_Crc32Context *crcContext); - +bool SDLCALL SDLTest_Crc32Done(SDLTest_Crc32Context *crcContext); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_font.h b/libs/SDL3/include/SDL3/SDL_test_font.h index 824f97c25..99308abbf 100644 --- a/libs/SDL3/include/SDL3/SDL_test_font.h +++ b/libs/SDL3/include/SDL3/SDL_test_font.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -/** +/* * \file SDL_test_font.h * * Font related functions of SDL test framework. @@ -30,6 +30,10 @@ #ifndef SDL_test_font_h_ #define SDL_test_font_h_ +#include +#include +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -42,7 +46,7 @@ extern int FONT_CHARACTER_SIZE; #define FONT_LINE_HEIGHT (FONT_CHARACTER_SIZE + 2) -/** +/* * Draw a string in the currently set font. * * \param renderer The renderer to draw on. @@ -50,11 +54,11 @@ extern int FONT_CHARACTER_SIZE; * \param y The Y coordinate of the upper left corner of the character. * \param c The character to draw. * - * \returns 0 on success, -1 on failure. + * \returns true on success, false on failure. */ -int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c); +bool SDLCALL SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c); -/** +/* * Draw a UTF-8 string in the currently set font. * * The font currently only supports characters in the Basic Latin and Latin-1 Supplement sets. @@ -64,11 +68,11 @@ int SDLTest_DrawCharacter(SDL_Renderer *renderer, float x, float y, Uint32 c); * \param y The Y coordinate of the upper left corner of the string. * \param s The string to draw. * - * \returns 0 on success, -1 on failure. + * \returns true on success, false on failure. */ -int SDLTest_DrawString(SDL_Renderer *renderer, float x, float y, const char *s); +bool SDLCALL SDLTest_DrawString(SDL_Renderer *renderer, float x, float y, const char *s); -/** +/* * Data used for multi-line text output */ typedef struct SDLTest_TextWindow @@ -79,7 +83,7 @@ typedef struct SDLTest_TextWindow char **lines; } SDLTest_TextWindow; -/** +/* * Create a multi-line text output window * * \param x The X coordinate of the upper left corner of the window. @@ -91,9 +95,9 @@ typedef struct SDLTest_TextWindow * * \since This function is available since SDL 3.0.0. */ -SDLTest_TextWindow *SDLTest_TextWindowCreate(float x, float y, float w, float h); +SDLTest_TextWindow * SDLCALL SDLTest_TextWindowCreate(float x, float y, float w, float h); -/** +/* * Display a multi-line text output window * * This function should be called every frame to display the text @@ -103,9 +107,9 @@ SDLTest_TextWindow *SDLTest_TextWindowCreate(float x, float y, float w, float h) * * \since This function is available since SDL 3.0.0. */ -void SDLTest_TextWindowDisplay(SDLTest_TextWindow *textwin, SDL_Renderer *renderer); +void SDLCALL SDLTest_TextWindowDisplay(SDLTest_TextWindow *textwin, SDL_Renderer *renderer); -/** +/* * Add text to a multi-line text output window * * Adds UTF-8 text to the end of the current text. The newline character starts a @@ -118,9 +122,9 @@ void SDLTest_TextWindowDisplay(SDLTest_TextWindow *textwin, SDL_Renderer *render * * \since This function is available since SDL 3.0.0. */ -void SDLTest_TextWindowAddText(SDLTest_TextWindow *textwin, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); +void SDLCALL SDLTest_TextWindowAddText(SDLTest_TextWindow *textwin, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2); -/** +/* * Add text to a multi-line text output window * * Adds UTF-8 text to the end of the current text. The newline character starts a @@ -133,30 +137,30 @@ void SDLTest_TextWindowAddText(SDLTest_TextWindow *textwin, SDL_PRINTF_FORMAT_ST * * \since This function is available since SDL 3.0.0. */ -void SDLTest_TextWindowAddTextWithLength(SDLTest_TextWindow *textwin, const char *text, size_t len); +void SDLCALL SDLTest_TextWindowAddTextWithLength(SDLTest_TextWindow *textwin, const char *text, size_t len); -/** +/* * Clear the text in a multi-line text output window * * \param textwin The text output window * * \since This function is available since SDL 3.0.0. */ -void SDLTest_TextWindowClear(SDLTest_TextWindow *textwin); +void SDLCALL SDLTest_TextWindowClear(SDLTest_TextWindow *textwin); -/** +/* * Free the storage associated with a multi-line text output window * * \param textwin The text output window * * \since This function is available since SDL 3.0.0. */ -void SDLTest_TextWindowDestroy(SDLTest_TextWindow *textwin); +void SDLCALL SDLTest_TextWindowDestroy(SDLTest_TextWindow *textwin); -/** +/* * Cleanup textures used by font drawing functions. */ -void SDLTest_CleanupTextDrawing(void); +void SDLCALL SDLTest_CleanupTextDrawing(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_fuzzer.h b/libs/SDL3/include/SDL3/SDL_test_fuzzer.h index 14c5dc9b9..4fdfd4989 100644 --- a/libs/SDL3/include/SDL3/SDL_test_fuzzer.h +++ b/libs/SDL3/include/SDL3/SDL_test_fuzzer.h @@ -20,8 +20,6 @@ */ /** - * \file SDL_test_fuzzer.h - * * Fuzzer functions of SDL test framework. * * This code is a part of the SDL test library, not the main SDL library. @@ -36,20 +34,19 @@ #ifndef SDL_test_fuzzer_h_ #define SDL_test_fuzzer_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif - /* Based on GSOC code by Markus Kauppila */ - /** - * \file * Note: The fuzzer implementation uses a static instance of random context * internally which makes it thread-UNsafe. */ @@ -60,53 +57,49 @@ extern "C" { * \param execKey Execution "Key" that initializes the random number generator uniquely for the test. * */ -void SDLTest_FuzzerInit(Uint64 execKey); - +void SDLCALL SDLTest_FuzzerInit(Uint64 execKey); /** * Returns a random Uint8 * * \returns a generated integer */ -Uint8 SDLTest_RandomUint8(void); +Uint8 SDLCALL SDLTest_RandomUint8(void); /** * Returns a random Sint8 * * \returns a generated signed integer */ -Sint8 SDLTest_RandomSint8(void); - +Sint8 SDLCALL SDLTest_RandomSint8(void); /** * Returns a random Uint16 * * \returns a generated integer */ -Uint16 SDLTest_RandomUint16(void); +Uint16 SDLCALL SDLTest_RandomUint16(void); /** * Returns a random Sint16 * * \returns a generated signed integer */ -Sint16 SDLTest_RandomSint16(void); - +Sint16 SDLCALL SDLTest_RandomSint16(void); /** * Returns a random integer * * \returns a generated integer */ -Sint32 SDLTest_RandomSint32(void); - +Sint32 SDLCALL SDLTest_RandomSint32(void); /** * Returns a random positive integer * * \returns a generated integer */ -Uint32 SDLTest_RandomUint32(void); +Uint32 SDLCALL SDLTest_RandomUint32(void); /** * Returns random Uint64. @@ -115,35 +108,34 @@ Uint32 SDLTest_RandomUint32(void); */ Uint64 SDLTest_RandomUint64(void); - /** * Returns random Sint64. * * \returns a generated signed integer */ -Sint64 SDLTest_RandomSint64(void); +Sint64 SDLCALL SDLTest_RandomSint64(void); /** * \returns a random float in range [0.0 - 1.0] */ -float SDLTest_RandomUnitFloat(void); +float SDLCALL SDLTest_RandomUnitFloat(void); /** * \returns a random double in range [0.0 - 1.0] */ -double SDLTest_RandomUnitDouble(void); +double SDLCALL SDLTest_RandomUnitDouble(void); /** * \returns a random float. * */ -float SDLTest_RandomFloat(void); +float SDLCALL SDLTest_RandomFloat(void); /** * \returns a random double. * */ -double SDLTest_RandomDouble(void); +double SDLCALL SDLTest_RandomDouble(void); /** * Returns a random boundary value for Uint8 within the given boundaries. @@ -153,10 +145,10 @@ double SDLTest_RandomDouble(void); * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomUint8BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 - * RandomUint8BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 - * RandomUint8BoundaryValue(0, 99, SDL_FALSE) returns 100 - * RandomUint8BoundaryValue(0, 255, SDL_FALSE) returns 0 (error set) + * RandomUint8BoundaryValue(10, 20, true) returns 10, 11, 19 or 20 + * RandomUint8BoundaryValue(1, 20, false) returns 0 or 21 + * RandomUint8BoundaryValue(0, 99, false) returns 100 + * RandomUint8BoundaryValue(0, 255, false) returns 0 (error set) * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -164,7 +156,7 @@ double SDLTest_RandomDouble(void); * * \returns a random boundary value for the given range and domain or 0 with error set */ -Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_bool validDomain); +Uint8 SDLCALL SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, bool validDomain); /** * Returns a random boundary value for Uint16 within the given boundaries. @@ -174,10 +166,10 @@ Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_boo * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomUint16BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 - * RandomUint16BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 - * RandomUint16BoundaryValue(0, 99, SDL_FALSE) returns 100 - * RandomUint16BoundaryValue(0, 0xFFFF, SDL_FALSE) returns 0 (error set) + * RandomUint16BoundaryValue(10, 20, true) returns 10, 11, 19 or 20 + * RandomUint16BoundaryValue(1, 20, false) returns 0 or 21 + * RandomUint16BoundaryValue(0, 99, false) returns 100 + * RandomUint16BoundaryValue(0, 0xFFFF, false) returns 0 (error set) * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -185,7 +177,7 @@ Uint8 SDLTest_RandomUint8BoundaryValue(Uint8 boundary1, Uint8 boundary2, SDL_boo * * \returns a random boundary value for the given range and domain or 0 with error set */ -Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL_bool validDomain); +Uint16 SDLCALL SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, bool validDomain); /** * Returns a random boundary value for Uint32 within the given boundaries. @@ -195,10 +187,10 @@ Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomUint32BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 - * RandomUint32BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 - * RandomUint32BoundaryValue(0, 99, SDL_FALSE) returns 100 - * RandomUint32BoundaryValue(0, 0xFFFFFFFF, SDL_FALSE) returns 0 (with error set) + * RandomUint32BoundaryValue(10, 20, true) returns 10, 11, 19 or 20 + * RandomUint32BoundaryValue(1, 20, false) returns 0 or 21 + * RandomUint32BoundaryValue(0, 99, false) returns 100 + * RandomUint32BoundaryValue(0, 0xFFFFFFFF, false) returns 0 (with error set) * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -206,7 +198,7 @@ Uint16 SDLTest_RandomUint16BoundaryValue(Uint16 boundary1, Uint16 boundary2, SDL * * \returns a random boundary value for the given range and domain or 0 with error set */ -Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL_bool validDomain); +Uint32 SDLCALL SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, bool validDomain); /** * Returns a random boundary value for Uint64 within the given boundaries. @@ -216,10 +208,10 @@ Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomUint64BoundaryValue(10, 20, SDL_TRUE) returns 10, 11, 19 or 20 - * RandomUint64BoundaryValue(1, 20, SDL_FALSE) returns 0 or 21 - * RandomUint64BoundaryValue(0, 99, SDL_FALSE) returns 100 - * RandomUint64BoundaryValue(0, 0xFFFFFFFFFFFFFFFF, SDL_FALSE) returns 0 (with error set) + * RandomUint64BoundaryValue(10, 20, true) returns 10, 11, 19 or 20 + * RandomUint64BoundaryValue(1, 20, false) returns 0 or 21 + * RandomUint64BoundaryValue(0, 99, false) returns 100 + * RandomUint64BoundaryValue(0, 0xFFFFFFFFFFFFFFFF, false) returns 0 (with error set) * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -227,7 +219,7 @@ Uint32 SDLTest_RandomUint32BoundaryValue(Uint32 boundary1, Uint32 boundary2, SDL * * \returns a random boundary value for the given range and domain or 0 with error set */ -Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL_bool validDomain); +Uint64 SDLCALL SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, bool validDomain); /** * Returns a random boundary value for Sint8 within the given boundaries. @@ -237,10 +229,10 @@ Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomSint8BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 - * RandomSint8BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 - * RandomSint8BoundaryValue(SINT8_MIN, 99, SDL_FALSE) returns 100 - * RandomSint8BoundaryValue(SINT8_MIN, SINT8_MAX, SDL_FALSE) returns SINT8_MIN (== error value) with error set + * RandomSint8BoundaryValue(-10, 20, true) returns -11, -10, 19 or 20 + * RandomSint8BoundaryValue(-100, -10, false) returns -101 or -9 + * RandomSint8BoundaryValue(SINT8_MIN, 99, false) returns 100 + * RandomSint8BoundaryValue(SINT8_MIN, SINT8_MAX, false) returns SINT8_MIN (== error value) with error set * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -248,8 +240,7 @@ Uint64 SDLTest_RandomUint64BoundaryValue(Uint64 boundary1, Uint64 boundary2, SDL * * \returns a random boundary value for the given range and domain or SINT8_MIN with error set */ -Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_bool validDomain); - +Sint8 SDLCALL SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, bool validDomain); /** * Returns a random boundary value for Sint16 within the given boundaries. @@ -259,10 +250,10 @@ Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_boo * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomSint16BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 - * RandomSint16BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 - * RandomSint16BoundaryValue(SINT16_MIN, 99, SDL_FALSE) returns 100 - * RandomSint16BoundaryValue(SINT16_MIN, SINT16_MAX, SDL_FALSE) returns SINT16_MIN (== error value) with error set + * RandomSint16BoundaryValue(-10, 20, true) returns -11, -10, 19 or 20 + * RandomSint16BoundaryValue(-100, -10, false) returns -101 or -9 + * RandomSint16BoundaryValue(SINT16_MIN, 99, false) returns 100 + * RandomSint16BoundaryValue(SINT16_MIN, SINT16_MAX, false) returns SINT16_MIN (== error value) with error set * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -270,7 +261,7 @@ Sint8 SDLTest_RandomSint8BoundaryValue(Sint8 boundary1, Sint8 boundary2, SDL_boo * * \returns a random boundary value for the given range and domain or SINT16_MIN with error set */ -Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL_bool validDomain); +Sint16 SDLCALL SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, bool validDomain); /** * Returns a random boundary value for Sint32 within the given boundaries. @@ -280,10 +271,10 @@ Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomSint32BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 - * RandomSint32BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 - * RandomSint32BoundaryValue(SINT32_MIN, 99, SDL_FALSE) returns 100 - * RandomSint32BoundaryValue(SINT32_MIN, SINT32_MAX, SDL_FALSE) returns SINT32_MIN (== error value) + * RandomSint32BoundaryValue(-10, 20, true) returns -11, -10, 19 or 20 + * RandomSint32BoundaryValue(-100, -10, false) returns -101 or -9 + * RandomSint32BoundaryValue(SINT32_MIN, 99, false) returns 100 + * RandomSint32BoundaryValue(SINT32_MIN, SINT32_MAX, false) returns SINT32_MIN (== error value) * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -291,7 +282,7 @@ Sint16 SDLTest_RandomSint16BoundaryValue(Sint16 boundary1, Sint16 boundary2, SDL * * \returns a random boundary value for the given range and domain or SINT32_MIN with error set */ -Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL_bool validDomain); +Sint32 SDLCALL SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, bool validDomain); /** * Returns a random boundary value for Sint64 within the given boundaries. @@ -301,10 +292,10 @@ Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL * If boundary1 > boundary2, the values are swapped * * Usage examples: - * RandomSint64BoundaryValue(-10, 20, SDL_TRUE) returns -11, -10, 19 or 20 - * RandomSint64BoundaryValue(-100, -10, SDL_FALSE) returns -101 or -9 - * RandomSint64BoundaryValue(SINT64_MIN, 99, SDL_FALSE) returns 100 - * RandomSint64BoundaryValue(SINT64_MIN, SINT64_MAX, SDL_FALSE) returns SINT64_MIN (== error value) and error set + * RandomSint64BoundaryValue(-10, 20, true) returns -11, -10, 19 or 20 + * RandomSint64BoundaryValue(-100, -10, false) returns -101 or -9 + * RandomSint64BoundaryValue(SINT64_MIN, 99, false) returns 100 + * RandomSint64BoundaryValue(SINT64_MIN, SINT64_MAX, false) returns SINT64_MIN (== error value) and error set * * \param boundary1 Lower boundary limit * \param boundary2 Upper boundary limit @@ -312,8 +303,7 @@ Sint32 SDLTest_RandomSint32BoundaryValue(Sint32 boundary1, Sint32 boundary2, SDL * * \returns a random boundary value for the given range and domain or SINT64_MIN with error set */ -Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL_bool validDomain); - +Sint64 SDLCALL SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, bool validDomain); /** * Returns integer in range [min, max] (inclusive). @@ -326,8 +316,7 @@ Sint64 SDLTest_RandomSint64BoundaryValue(Sint64 boundary1, Sint64 boundary2, SDL * * \returns a generated random integer in range */ -Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max); - +Sint32 SDLCALL SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max); /** * Generates random null-terminated string. The minimum length for @@ -338,8 +327,7 @@ Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max); * * \returns a newly allocated random string; or NULL if length was invalid or string could not be allocated. */ -char *SDLTest_RandomAsciiString(void); - +char * SDLCALL SDLTest_RandomAsciiString(void); /** * Generates random null-terminated string. The maximum length for @@ -352,8 +340,7 @@ char *SDLTest_RandomAsciiString(void); * * \returns a newly allocated random string; or NULL if maxLength was invalid or string could not be allocated. */ -char *SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); - +char * SDLCALL SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); /** * Generates random null-terminated string. The length for @@ -366,14 +353,14 @@ char *SDLTest_RandomAsciiStringWithMaximumLength(int maxLength); * * \returns a newly allocated random string; or NULL if size was invalid or string could not be allocated. */ -char *SDLTest_RandomAsciiStringOfSize(int size); +char * SDLCALL SDLTest_RandomAsciiStringOfSize(int size); /** * Get the invocation count for the fuzzer since last ...FuzzerInit. * * \returns the invocation count. */ -int SDLTest_GetFuzzerInvocationCount(void); +int SDLCALL SDLTest_GetFuzzerInvocationCount(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_harness.h b/libs/SDL3/include/SDL3/SDL_test_harness.h index b17e0b30a..cea0db465 100644 --- a/libs/SDL3/include/SDL3/SDL_test_harness.h +++ b/libs/SDL3/include/SDL3/SDL_test_harness.h @@ -36,13 +36,15 @@ #ifndef SDL_test_h_arness_h #define SDL_test_h_arness_h +#include +#include /* SDLTest_CommonState */ + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif - /* ! Definitions for test case structures */ #define TEST_ENABLED 1 #define TEST_DISABLED 0 @@ -61,15 +63,15 @@ extern "C" { #define TEST_RESULT_SETUP_FAILURE 4 /* !< Function pointer to a test case setup function (run before every test) */ -typedef void (*SDLTest_TestCaseSetUpFp)(void *arg); +typedef void (SDLCALL *SDLTest_TestCaseSetUpFp)(void **arg); /* !< Function pointer to a test case function */ -typedef int (*SDLTest_TestCaseFp)(void *arg); +typedef int (SDLCALL *SDLTest_TestCaseFp)(void *arg); /* !< Function pointer to a test case teardown function (run after every test) */ -typedef void (*SDLTest_TestCaseTearDownFp)(void *arg); +typedef void (SDLCALL *SDLTest_TestCaseTearDownFp)(void *arg); -/** +/* * Holds information about a single test case. */ typedef struct SDLTest_TestCaseReference { @@ -83,7 +85,7 @@ typedef struct SDLTest_TestCaseReference { int enabled; } SDLTest_TestCaseReference; -/** +/* * Holds information about a test suite (multiple test cases). */ typedef struct SDLTest_TestSuiteReference { @@ -98,30 +100,49 @@ typedef struct SDLTest_TestSuiteReference { } SDLTest_TestSuiteReference; -/** - * Generates a random run seed string for the harness. The generated seed will contain alphanumeric characters (0-9A-Z). - * - * Note: The returned string needs to be deallocated by the caller. +/* + * Generates a random run seed string for the harness. The generated seed + * will contain alphanumeric characters (0-9A-Z). * - * \param length The length of the seed string to generate + * \param buffer Buffer in which to generate the random seed. Must have a capacity of at least length + 1 characters. + * \param length Number of alphanumeric characters to write to buffer, must be >0 * - * \returns the generated seed string + * \returns A null-terminated seed string and equal to the in put buffer on success, NULL on failure */ -char *SDLTest_GenerateRunSeed(const int length); +char * SDLCALL SDLTest_GenerateRunSeed(char *buffer, int length); -/** - * Execute a test suite using the given run seed and execution key. +/* + * Holds information about the execution of test suites. + * */ +typedef struct SDLTest_TestSuiteRunner SDLTest_TestSuiteRunner; + +/* + * Create a new test suite runner, that will execute the given test suites. + * It will register the harness cli arguments to the common SDL state. * - * \param testSuites Suites containing the test case. - * \param userRunSeed Custom run seed provided by user, or NULL to autogenerate one. - * \param userExecKey Custom execution key provided by user, or 0 to autogenerate one. - * \param filter Filter specification. NULL disables. Case sensitive. - * \param testIterations Number of iterations to run each test case. + * \param state Common SDL state on which to register CLI arguments. + * \param testSuites NULL-terminated test suites containing test cases. * * \returns the test run result: 0 when all tests passed, 1 if any tests failed. */ -int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *userRunSeed, Uint64 userExecKey, const char *filter, int testIterations); +SDLTest_TestSuiteRunner * SDLCALL SDLTest_CreateTestSuiteRunner(SDLTest_CommonState *state, SDLTest_TestSuiteReference *testSuites[]); + +/* + * Destroy a test suite runner. + * It will unregister the harness cli arguments to the common SDL state. + * + * \param runner The runner that should be destroyed. + */ +void SDLCALL SDLTest_DestroyTestSuiteRunner(SDLTest_TestSuiteRunner *runner); +/* + * Execute a test suite, using the configured run seed, execution key, filter, etc. + * + * \param runner The runner that should be executed. + * + * \returns the test run result: 0 when all tests passed, 1 if any tests failed. + */ +int SDLCALL SDLTest_ExecuteTestSuiteRunner(SDLTest_TestSuiteRunner *runner); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_log.h b/libs/SDL3/include/SDL3/SDL_test_log.h index 315d0ae0e..ff798d633 100644 --- a/libs/SDL3/include/SDL3/SDL_test_log.h +++ b/libs/SDL3/include/SDL3/SDL_test_log.h @@ -36,6 +36,8 @@ #ifndef SDL_test_log_h_ #define SDL_test_log_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -47,14 +49,24 @@ extern "C" { * * \param fmt Message to be logged */ -void SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); +void SDLCALL SDLTest_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); + +/** + * Prints given prefix and buffer. + * Non-printible characters in the raw data are substituted by printible alternatives. + * + * \param prefix Prefix message. + * \param buffer Raw data to be escaped. + * \param size Number of bytes in buffer. + */ +void SDLCALL SDLTest_LogEscapedString(const char *prefix, const void *buffer, size_t size); /** * Prints given message with a timestamp in the TEST category and the ERROR priority. * * \param fmt Message to be logged */ -void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); +void SDLCALL SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_md5.h b/libs/SDL3/include/SDL3/SDL_test_md5.h index 06a6272bd..d751aab96 100644 --- a/libs/SDL3/include/SDL3/SDL_test_md5.h +++ b/libs/SDL3/include/SDL3/SDL_test_md5.h @@ -56,6 +56,8 @@ #ifndef SDL_test_md5_h_ #define SDL_test_md5_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -65,15 +67,15 @@ extern "C" { /* ------------ Definitions --------- */ /* typedef a 32-bit type */ - typedef Uint32 MD5UINT4; +typedef Uint32 MD5UINT4; /* Data structure for MD5 (Message-Digest) computation */ - typedef struct SDLTest_Md5Context { - MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ - MD5UINT4 buf[4]; /* scratch buffer */ - unsigned char in[64]; /* input buffer */ +typedef struct SDLTest_Md5Context { + MD5UINT4 i[2]; /* number of _bits_ handled mod 2^64 */ + MD5UINT4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ unsigned char digest[16]; /* actual digest after Md5Final call */ - } SDLTest_Md5Context; +} SDLTest_Md5Context; /* ---------- Function Prototypes ------------- */ @@ -86,8 +88,7 @@ extern "C" { * mdContext. Call before each new use of the context - * all fields are set to zero. */ - void SDLTest_Md5Init(SDLTest_Md5Context *mdContext); - +void SDLCALL SDLTest_Md5Init(SDLTest_Md5Context *mdContext); /** * update digest from variable length data @@ -99,12 +100,10 @@ extern "C" { * Note: The function updates the message-digest context to account * for the presence of each of the characters inBuf[0..inLen-1] * in the message whose digest is being computed. -*/ - - void SDLTest_Md5Update(SDLTest_Md5Context *mdContext, unsigned char *inBuf, + */ +void SDLCALL SDLTest_Md5Update(SDLTest_Md5Context *mdContext, unsigned char *inBuf, unsigned int inLen); - /** * complete digest computation * @@ -113,10 +112,8 @@ extern "C" { * Note: The function terminates the message-digest computation and * ends with the desired message digest in mdContext.digest[0..15]. * Always call before using the digest[] variable. -*/ - - void SDLTest_Md5Final(SDLTest_Md5Context *mdContext); - + */ +void SDLCALL SDLTest_Md5Final(SDLTest_Md5Context *mdContext); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_memory.h b/libs/SDL3/include/SDL3/SDL_test_memory.h index 6d858efdf..16b2f6330 100644 --- a/libs/SDL3/include/SDL3/SDL_test_memory.h +++ b/libs/SDL3/include/SDL3/SDL_test_memory.h @@ -30,34 +30,34 @@ #ifndef SDL_test_memory_h_ #define SDL_test_memory_h_ +#include + #include /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus extern "C" { #endif - /** * Start tracking SDL memory allocations * * \note This should be called before any other SDL functions for complete tracking coverage */ -void SDLTest_TrackAllocations(void); +void SDLCALL SDLTest_TrackAllocations(void); /** * Fill allocations with random data * * \note This implicitly calls SDLTest_TrackAllocations() */ -void SDLTest_RandFillAllocations(); +void SDLCALL SDLTest_RandFillAllocations(void); /** * Print a log of any outstanding allocations * * \note This can be called after SDL_Quit() */ -void SDLTest_LogAllocations(void); - +void SDLCALL SDLTest_LogAllocations(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_test_random.h b/libs/SDL3/include/SDL3/SDL_test_random.h deleted file mode 100644 index 73088e138..000000000 --- a/libs/SDL3/include/SDL3/SDL_test_random.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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. -*/ - -/** - * \file SDL_test_random.h - * - * Random number generator related function of SDL test framework. - * - * This code is a part of the SDL test library, not the main SDL library. - */ - -/* - - A "32-bit Multiply with carry random number generator. Very fast. - Includes a list of recommended multipliers. - - multiply-with-carry generator: x(n) = a*x(n-1) + carry mod 2^32. - period: (a*2^31)-1 - -*/ - -#ifndef SDL_test_random_h_ -#define SDL_test_random_h_ - -#include -/* Set up for C function definitions, even when using C++ */ -#ifdef __cplusplus -extern "C" { -#endif - -/* --- Definitions */ - -/* - * Macros that return a random number in a specific format. - */ -#define SDLTest_RandomInt(c) ((int)SDLTest_Random(c)) - -/* - * Context structure for the random number generator state. - */ - typedef struct SDLTest_RandomContext { - unsigned int a; - unsigned int x; - unsigned int c; - unsigned int ah; - unsigned int al; - } SDLTest_RandomContext; - - -/* --- Function prototypes */ - -/** - * Initialize random number generator with two integers. - * - * Note: The random sequence of numbers returned by ...Random() is the - * same for the same two integers and has a period of 2^31. - * - * \param rndContext pointer to context structure - * \param xi integer that defines the random sequence - * \param ci integer that defines the random sequence - * - */ - void SDLTest_RandomInit(SDLTest_RandomContext *rndContext, unsigned int xi, unsigned int ci); - -/** - * Initialize random number generator based on current system time. - * - * \param rndContext pointer to context structure - * - */ - void SDLTest_RandomInitTime(SDLTest_RandomContext *rndContext); - - -/** - * Initialize random number generator based on current system time. - * - * Note: ...RandomInit() or ...RandomInitTime() must have been called - * before using this function. - * - * \param rndContext pointer to context structure - * - * \returns a random number (32bit unsigned integer) - * - */ - unsigned int SDLTest_Random(SDLTest_RandomContext *rndContext); - - -/* Ends C function definitions when using C++ */ -#ifdef __cplusplus -} -#endif -#include - -#endif /* SDL_test_random_h_ */ diff --git a/libs/SDL3/include/SDL3/SDL_thread.h b/libs/SDL3/include/SDL3/SDL_thread.h index ad16fc25c..f21356544 100644 --- a/libs/SDL3/include/SDL3/SDL_thread.h +++ b/libs/SDL3/include/SDL3/SDL_thread.h @@ -23,19 +23,19 @@ #define SDL_thread_h_ /** - * \file SDL_thread.h + * # CategoryThread * - * Header for the SDL thread management routines. + * SDL thread management routines. */ #include #include +#include /* Thread synchronization primitives */ #include -#include -#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_WINRT) +#if defined(SDL_PLATFORM_WINDOWS) #include /* _beginthreadex() and _endthreadex() */ #endif @@ -45,27 +45,57 @@ extern "C" { #endif -/* The SDL thread structure, defined in SDL_thread.c */ -struct SDL_Thread; +/** + * The SDL thread object. + * + * These are opaque data. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_CreateThread + * \sa SDL_WaitThread + */ typedef struct SDL_Thread SDL_Thread; -/* The SDL thread ID */ +/** + * A unique numeric ID that identifies a thread. + * + * These are different from SDL_Thread objects, which are generally what an + * application will operate on, but having a way to uniquely identify a thread + * can be useful at times. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_GetThreadID + * \sa SDL_GetCurrentThreadID + */ typedef Uint64 SDL_ThreadID; -/* Thread local storage ID, 0 is the invalid ID */ -typedef Uint32 SDL_TLSID; +/** + * Thread local storage ID. + * + * 0 is the invalid ID. An app can create these and then set data for these + * IDs that is unique to each thread. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_GetTLS + * \sa SDL_SetTLS + */ +typedef SDL_AtomicInt SDL_TLSID; /** - * The SDL thread priority. + * The SDL thread priority. * - * SDL will make system changes as necessary in order to apply the thread priority. - * Code which attempts to control thread state related to priority should be aware - * that calling SDL_SetThreadPriority may alter such state. - * SDL_HINT_THREAD_PRIORITY_POLICY can be used to control aspects of this behavior. + * SDL will make system changes as necessary in order to apply the thread + * priority. Code which attempts to control thread state related to priority + * should be aware that calling SDL_SetCurrentThreadPriority may alter such + * state. SDL_HINT_THREAD_PRIORITY_POLICY can be used to control aspects of + * this behavior. * - * \note On many systems you require special privileges to set high or time critical priority. + * \since This enum is available since SDL 3.0.0. */ -typedef enum { +typedef enum SDL_ThreadPriority { SDL_THREAD_PRIORITY_LOW, SDL_THREAD_PRIORITY_NORMAL, SDL_THREAD_PRIORITY_HIGH, @@ -73,130 +103,106 @@ typedef enum { } SDL_ThreadPriority; /** - * The function passed to SDL_CreateThread(). + * The function passed to SDL_CreateThread() as the new thread's entry point. * - * \param data what was passed as `data` to SDL_CreateThread() + * \param data what was passed as `data` to SDL_CreateThread(). * \returns a value that can be reported through SDL_WaitThread(). - */ -typedef int (SDLCALL * SDL_ThreadFunction) (void *data); - - -#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_WINRT) -/** - * \file SDL_thread.h - * - * We compile SDL into a DLL. This means, that it's the DLL which - * creates a new thread for the calling process with the SDL_CreateThread() - * API. There is a problem with this, that only the RTL of the SDL3.DLL will - * be initialized for those threads, and not the RTL of the calling - * application! * - * To solve this, we make a little hack here. - * - * We'll always use the caller's _beginthread() and _endthread() APIs to - * start a new thread. This way, if it's the SDL3.DLL which uses this API, - * then the RTL of SDL3.DLL will be used to create the new thread, and if it's - * the application, then the RTL of the application will be used. - * - * So, in short: - * Always use the _beginthread() and _endthread() of the calling runtime - * library! + * \since This datatype is available since SDL 3.0.0. */ -#define SDL_PASSED_BEGINTHREAD_ENDTHREAD - -typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread) - (void *, unsigned, unsigned (__stdcall *func)(void *), - void * /*arg*/, unsigned, unsigned * /* threadID */); -typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code); - -#ifndef SDL_beginthread -#define SDL_beginthread _beginthreadex -#endif -#ifndef SDL_endthread -#define SDL_endthread _endthreadex -#endif +typedef int (SDLCALL * SDL_ThreadFunction) (void *data); -/* - * Create a SDL Thread - * - * \param fn Thread function - * \param name name - * \param data some data - * \param pfnBeginThread begin function - * \param pfnEndThread end function - * - * \returns SDL_Thread pointer - * - * \since This function is available since SDL 3.0.0. - */ -extern DECLSPEC SDL_Thread *SDLCALL -SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data, - pfnSDL_CurrentBeginThread pfnBeginThread, - pfnSDL_CurrentEndThread pfnEndThread); +#ifdef SDL_WIKI_DOCUMENTATION_SECTION /* - * Create a SDL Thread, with explicit stack size - * - * \param fn Thread function - * \param name name - * \param stacksize stack size - * \param data some data - * \param pfnBeginThread begin function - * \param pfnEndThread end function - * - * \returns SDL_Thread pointer - * - * \since This function is available since SDL 3.0.0. + * Note that these aren't the correct function signatures in this block, but + * this is what the API reference manual should look like for all intents and + * purposes. + * + * Technical details, not for the wiki (hello, header readers!)... + * + * On Windows (and maybe other platforms), a program might use a different + * C runtime than its libraries. Or, in SDL's case, it might use a C runtime + * while SDL uses none at all. + * + * C runtimes expect to initialize thread-specific details when a new thread + * is created, but to do this in SDL_CreateThread would require SDL to know + * intimate details about the caller's C runtime, which is not possible. + * + * So SDL_CreateThread has two extra parameters, which are + * hidden at compile time by macros: the C runtime's `_beginthreadex` and + * `_endthreadex` entry points. If these are not NULL, they are used to spin + * and terminate the new thread; otherwise the standard Win32 `CreateThread` + * function is used. When `SDL_CreateThread` is called from a compiler that + * needs this C runtime thread init function, macros insert the appropriate + * function pointers for SDL_CreateThread's caller (which might be a different + * compiler with a different runtime in different calls to SDL_CreateThread!). + * + * SDL_BeginThreadFunction defaults to `_beginthreadex` on Windows (and NULL + * everywhere else), but apps that have extremely specific special needs can + * define this to something else and the SDL headers will use it, passing the + * app-defined value to SDL_CreateThread calls. Redefine this with caution! + * + * Platforms that don't need _beginthread stuff (most everything) will fail + * SDL_CreateThread with an error if these pointers _aren't_ NULL. + * + * Unless you are doing something extremely complicated, like perhaps a + * language binding, **you should never deal with this directly**. Let SDL's + * macros handle this platform-specific detail transparently! */ -extern DECLSPEC SDL_Thread *SDLCALL -SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, - const char *name, const size_t stacksize, void *data, - pfnSDL_CurrentBeginThread pfnBeginThread, - pfnSDL_CurrentEndThread pfnEndThread); - -#if !defined(__BUILDING_SDL2_COMPAT__) /* do not conflict with sdl2-compat::sdl3_include_wrapper.h */ -#if defined(SDL_CreateThread) && SDL_DYNAMIC_API -#undef SDL_CreateThread -#define SDL_CreateThread(fn, name, data) SDL_CreateThread_REAL(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) -#undef SDL_CreateThreadWithStackSize -#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize_REAL(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) -#else -#define SDL_CreateThread(fn, name, data) SDL_CreateThread(fn, name, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) -#define SDL_CreateThreadWithStackSize(fn, name, stacksize, data) SDL_CreateThreadWithStackSize(fn, name, stacksize, data, (pfnSDL_CurrentBeginThread)SDL_beginthread, (pfnSDL_CurrentEndThread)SDL_endthread) -#endif -#endif /* !__BUILDING_SDL2_COMPAT__ */ - -#else /** * Create a new thread with a default stack size. * - * This is equivalent to calling: + * This is a convenience function, equivalent to calling + * SDL_CreateThreadWithProperties with the following properties set: * - * ```c - * SDL_CreateThreadWithStackSize(fn, name, 0, data); - * ``` + * - `SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER`: `fn` + * - `SDL_PROP_THREAD_CREATE_NAME_STRING`: `name` + * - `SDL_PROP_THREAD_CREATE_USERDATA_POINTER`: `data` * - * \param fn the SDL_ThreadFunction function to call in the new thread - * \param name the name of the thread - * \param data a pointer that is passed to `fn` + * Note that this "function" is actually a macro that calls an internal + * function with two extra parameters not listed here; they are hidden through + * preprocessor macros and are needed to support various C runtimes at the + * point of the function call. Language bindings that aren't using the C + * headers will need to deal with this. + * + * Usually, apps should just call this function the same way on every platform + * and let the macros hide the details. + * + * \param fn the SDL_ThreadFunction function to call in the new thread. + * \param name the name of the thread. + * \param data a pointer that is passed to `fn`. * \returns an opaque pointer to the new thread object on success, NULL if the * new thread could not be created; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_CreateThreadWithStackSize + * \sa SDL_CreateThreadWithProperties * \sa SDL_WaitThread */ -extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); +extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, const char *name, void *data); /** - * Create a new thread with a specific stack size. + * Create a new thread with with the specified properties. + * + * These are the supported properties: + * + * - `SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER`: an SDL_ThreadFunction + * value that will be called at the start of the new thread's life. + * Required. + * - `SDL_PROP_THREAD_CREATE_NAME_STRING`: the name of the new thread, which + * might be available to debuggers. Optional, defaults to NULL. + * - `SDL_PROP_THREAD_CREATE_USERDATA_POINTER`: an arbitrary app-defined + * pointer, which is passed to the entry function on the new thread, as its + * only parameter. Optional, defaults to NULL. + * - `SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER`: the size, in bytes, of the new + * thread's stack. Optional, defaults to 0 (system-defined default). * - * SDL makes an attempt to report `name` to the system, so that debuggers can - * display it. Not all platforms support this. + * SDL makes an attempt to report `SDL_PROP_THREAD_CREATE_NAME_STRING` to the + * system, so that debuggers can display it. Not all platforms support this. * * Thread naming is a little complicated: Most systems have very small limits * for the string length (Haiku has 32 bytes, Linux currently has 16, Visual @@ -212,17 +218,28 @@ extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, con * (truncate, etc), but the original string contents will be available from * SDL_GetThreadName(). * - * The size (in bytes) of the new stack can be specified. Zero means "use the - * system default" which might be wildly different between platforms. x86 - * Linux generally defaults to eight megabytes, an embedded device might be a - * few kilobytes instead. You generally need to specify a stack that is a - * multiple of the system's page size (in many cases, this is 4 kilobytes, but - * check your system documentation). + * The size (in bytes) of the new stack can be specified with + * `SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER`. Zero means "use the system + * default" which might be wildly different between platforms. x86 Linux + * generally defaults to eight megabytes, an embedded device might be a few + * kilobytes instead. You generally need to specify a stack that is a multiple + * of the system's page size (in many cases, this is 4 kilobytes, but check + * your system documentation). * - * \param fn the SDL_ThreadFunction function to call in the new thread - * \param name the name of the thread - * \param stacksize the size, in bytes, to allocate for the new thread stack. - * \param data a pointer that is passed to `fn` + * Note that this "function" is actually a macro that calls an internal + * function with two extra parameters not listed here; they are hidden through + * preprocessor macros and are needed to support various C runtimes at the + * point of the function call. Language bindings that aren't using the C + * headers will need to deal with this. + * + * The actual symbol in SDL is `SDL_CreateThreadWithPropertiesRuntime`, so + * there is no symbol clash, but trying to load an SDL shared library and look + * for "SDL_CreateThreadWithProperties" will fail. + * + * Usually, apps should just call this function the same way on every platform + * and let the macros hide the details. + * + * \param props the properties to use. * \returns an opaque pointer to the new thread object on success, NULL if the * new thread could not be created; call SDL_GetError() for more * information. @@ -232,23 +249,93 @@ extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThread(SDL_ThreadFunction fn, con * \sa SDL_CreateThread * \sa SDL_WaitThread */ -extern DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithStackSize(SDL_ThreadFunction fn, const char *name, const size_t stacksize, void *data); +extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithProperties(SDL_PropertiesID props); + +#define SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER "SDL.thread.create.entry_function" +#define SDL_PROP_THREAD_CREATE_NAME_STRING "SDL.thread.create.name" +#define SDL_PROP_THREAD_CREATE_USERDATA_POINTER "SDL.thread.create.userdata" +#define SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER "SDL.thread.create.stacksize" + +/* end wiki documentation for macros that are meant to look like functions. */ +#endif + + +/* The real implementation, hidden from the wiki, so it can show this as real functions that don't have macro magic. */ +#ifndef SDL_WIKI_DOCUMENTATION_SECTION +# if defined(SDL_PLATFORM_WINDOWS) +# ifndef SDL_BeginThreadFunction +# define SDL_BeginThreadFunction _beginthreadex +# endif +# ifndef SDL_EndThreadFunction +# define SDL_EndThreadFunction _endthreadex +# endif +# endif +#endif + +/* currently no other platforms than Windows use _beginthreadex/_endthreadex things. */ +#ifndef SDL_WIKI_DOCUMENTATION_SECTION +# ifndef SDL_BeginThreadFunction +# define SDL_BeginThreadFunction NULL +# endif +#endif +#ifndef SDL_WIKI_DOCUMENTATION_SECTION +# ifndef SDL_EndThreadFunction +# define SDL_EndThreadFunction NULL +# endif #endif +#ifndef SDL_WIKI_DOCUMENTATION_SECTION +/* These are the actual functions exported from SDL! Don't use them directly! Use the SDL_CreateThread and SDL_CreateThreadWithProperties macros! */ /** - * Get the thread name as it was specified in SDL_CreateThread(). + * The actual entry point for SDL_CreateThread. + * + * \param fn the SDL_ThreadFunction function to call in the new thread + * \param name the name of the thread + * \param data a pointer that is passed to `fn` + * \param pfnBeginThread the C runtime's _beginthreadex (or whatnot). Can be NULL. + * \param pfnEndThread the C runtime's _endthreadex (or whatnot). Can be NULL. + * \returns an opaque pointer to the new thread object on success, NULL if the + * new thread could not be created; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadRuntime(SDL_ThreadFunction fn, const char *name, void *data, SDL_FunctionPointer pfnBeginThread, SDL_FunctionPointer pfnEndThread); + +/** + * The actual entry point for SDL_CreateThreadWithProperties. * - * This is internal memory, not to be freed by the caller, and remains valid - * until the specified thread is cleaned up by SDL_WaitThread(). + * \param props the properties to use + * \param pfnBeginThread the C runtime's _beginthreadex (or whatnot). Can be NULL. + * \param pfnEndThread the C runtime's _endthreadex (or whatnot). Can be NULL. + * \returns an opaque pointer to the new thread object on success, NULL if the + * new thread could not be created; call SDL_GetError() for more + * information. * - * \param thread the thread to query + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC SDL_Thread * SDLCALL SDL_CreateThreadWithPropertiesRuntime(SDL_PropertiesID props, SDL_FunctionPointer pfnBeginThread, SDL_FunctionPointer pfnEndThread); + +#define SDL_CreateThread(fn, name, data) SDL_CreateThreadRuntime((fn), (name), (data), (SDL_FunctionPointer) (SDL_BeginThreadFunction), (SDL_FunctionPointer) (SDL_EndThreadFunction)) +#define SDL_CreateThreadWithProperties(props) SDL_CreateThreadWithPropertiesRuntime((props), (SDL_FunctionPointer) (SDL_BeginThreadFunction), (SDL_FunctionPointer) (SDL_EndThreadFunction)) +#define SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER "SDL.thread.create.entry_function" +#define SDL_PROP_THREAD_CREATE_NAME_STRING "SDL.thread.create.name" +#define SDL_PROP_THREAD_CREATE_USERDATA_POINTER "SDL.thread.create.userdata" +#define SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER "SDL.thread.create.stacksize" +#endif + + +/** + * Get the thread name as it was specified in SDL_CreateThread(). + * + * \param thread the thread to query. * \returns a pointer to a UTF-8 string that names the specified thread, or * NULL if it doesn't have a name. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetThreadName(SDL_Thread *thread); /** * Get the thread identifier for the current thread. @@ -266,7 +353,7 @@ extern DECLSPEC const char *SDLCALL SDL_GetThreadName(SDL_Thread *thread); * * \sa SDL_GetThreadID */ -extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); +extern SDL_DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); /** * Get the thread identifier for the specified thread. @@ -275,7 +362,7 @@ extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); * If SDL is running on a platform that does not support threads the return * value will always be zero. * - * \param thread the thread to query + * \param thread the thread to query. * \returns the ID of the specified thread, or the ID of the current thread if * `thread` is NULL. * @@ -283,7 +370,7 @@ extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetCurrentThreadID(void); * * \sa SDL_GetCurrentThreadID */ -extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); +extern SDL_DECLSPEC SDL_ThreadID SDLCALL SDL_GetThreadID(SDL_Thread *thread); /** * Set the priority for the current thread. @@ -292,13 +379,13 @@ extern DECLSPEC SDL_ThreadID SDLCALL SDL_GetThreadID(SDL_Thread * thread); * promote the thread to a higher priority) at all, and some require you to be * an administrator account. Be prepared for this to fail. * - * \param priority the SDL_ThreadPriority to set - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param priority the SDL_ThreadPriority to set. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); +extern SDL_DECLSPEC bool SDLCALL SDL_SetCurrentThreadPriority(SDL_ThreadPriority priority); /** * Wait for a thread to finish. @@ -323,7 +410,7 @@ extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); * afterward. * * \param thread the SDL_Thread pointer that was returned from the - * SDL_CreateThread() call that started this thread + * SDL_CreateThread() call that started this thread. * \param status pointer to an integer that will receive the value returned * from the thread function by its 'return', or NULL to not * receive such value back. @@ -333,7 +420,7 @@ extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority); * \sa SDL_CreateThread * \sa SDL_DetachThread */ -extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status); +extern SDL_DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread *thread, int *status); /** * Let a thread clean up on exit without intervention. @@ -362,73 +449,83 @@ extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status); * It is safe to pass NULL to this function; it is a no-op. * * \param thread the SDL_Thread pointer that was returned from the - * SDL_CreateThread() call that started this thread + * SDL_CreateThread() call that started this thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateThread * \sa SDL_WaitThread */ -extern DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread * thread); +extern SDL_DECLSPEC void SDLCALL SDL_DetachThread(SDL_Thread *thread); /** - * Create a piece of thread-local storage. + * Get the current thread's value associated with a thread local storage ID. * - * This creates an identifier that is globally visible to all threads but - * refers to data that is thread-specific. + * \param id a pointer to the thread local storage ID, may not be NULL. + * \returns the value associated with the ID for the current thread or NULL if + * no value has been set; call SDL_GetError() for more information. * - * \returns the newly created thread local storage identifier or 0 on error. + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GetTLS * \sa SDL_SetTLS */ -extern DECLSPEC SDL_TLSID SDLCALL SDL_CreateTLS(void); +extern SDL_DECLSPEC void * SDLCALL SDL_GetTLS(SDL_TLSID *id); /** - * Get the current thread's value associated with a thread local storage ID. + * The callback used to cleanup data passed to SDL_SetTLS. * - * \param id the thread local storage ID - * \returns the value associated with the ID for the current thread or NULL if - * no value has been set; call SDL_GetError() for more information. + * This is called when a thread exits, to allow an app to free any resources. * - * \since This function is available since SDL 3.0.0. + * \param value a pointer previously handed to SDL_SetTLS. + * + * \since This datatype is available since SDL 3.0.0. * * \sa SDL_SetTLS */ -extern DECLSPEC void * SDLCALL SDL_GetTLS(SDL_TLSID id); +typedef void (SDLCALL *SDL_TLSDestructorCallback)(void *value); /** * Set the current thread's value associated with a thread local storage ID. * - * The function prototype for `destructor` is: + * If the thread local storage ID is not initialized (the value is 0), a new + * ID will be created in a thread-safe way, so all calls using a pointer to + * the same ID will refer to the same local storage. * - * ```c - * void destructor(void *value) - * ``` + * Note that replacing a value from a previous call to this function on the + * same thread does _not_ call the previous value's destructor! * - * where its parameter `value` is what was passed as `value` to SDL_SetTLS(). + * `destructor` can be NULL; it is assumed that `value` does not need to be + * cleaned up if so. * - * \param id the thread local storage ID - * \param value the value to associate with the ID for the current thread + * \param id a pointer to the thread local storage ID, may not be NULL. + * \param value the value to associate with the ID for the current thread. * \param destructor a function called when the thread exits, to free the - * value - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * value, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetTLS */ -extern DECLSPEC int SDLCALL SDL_SetTLS(SDL_TLSID id, const void *value, void (SDLCALL *destructor)(void*)); +extern SDL_DECLSPEC bool SDLCALL SDL_SetTLS(SDL_TLSID *id, const void *value, SDL_TLSDestructorCallback destructor); /** * Cleanup all TLS data for this thread. * + * If you are creating your threads outside of SDL and then calling SDL + * functions, you should call this function before your thread exits, to + * properly clean up SDL memory. + * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_CleanupTLS(void); +extern SDL_DECLSPEC void SDLCALL SDL_CleanupTLS(void); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_time.h b/libs/SDL3/include/SDL3/SDL_time.h index d69d4be7b..eb73f7a7f 100644 --- a/libs/SDL3/include/SDL3/SDL_time.h +++ b/libs/SDL3/include/SDL3/SDL_time.h @@ -23,9 +23,9 @@ freely, subject to the following restrictions: #define SDL_time_h_ /** - * \file SDL_time.h + * # CategoryTime * - * Header for the SDL realtime clock and date/time routines. + * SDL realtime clock and date/time routines. */ #include @@ -38,7 +38,10 @@ extern "C" { #endif /** - * A structure holding a calendar date and time broken down into its components. + * A structure holding a calendar date and time broken down into its + * components. + * + * \since This struct is available since SDL 3.0.0. */ typedef struct SDL_DateTime { @@ -56,64 +59,76 @@ typedef struct SDL_DateTime /** * The preferred date format of the current system locale. * - * \sa SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_GetDateTimeLocalePreferences */ -typedef enum SDL_DATE_FORMAT +typedef enum SDL_DateFormat { SDL_DATE_FORMAT_YYYYMMDD = 0, /**< Year/Month/Day */ SDL_DATE_FORMAT_DDMMYYYY = 1, /**< Day/Month/Year */ - SDL_DATE_FORMAT_MMDDYYYY = 2, /**< Month/Day/Year */ -} SDL_DATE_FORMAT; + SDL_DATE_FORMAT_MMDDYYYY = 2 /**< Month/Day/Year */ +} SDL_DateFormat; /** * The preferred time format of the current system locale. * - * \sa SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER + * \since This enum is available since SDL 3.0.0. + * + * \sa SDL_GetDateTimeLocalePreferences */ -typedef enum SDL_TIME_FORMAT +typedef enum SDL_TimeFormat { SDL_TIME_FORMAT_24HR = 0, /**< 24 hour time */ - SDL_TIME_FORMAT_12HR = 1, /**< 12 hour time */ -} SDL_TIME_FORMAT; + SDL_TIME_FORMAT_12HR = 1 /**< 12 hour time */ +} SDL_TimeFormat; /** - * Global date/time properties + * Gets the current preferred date and time format for the system locale. + * + * This might be a "slow" call that has to query the operating system. It's + * best to ask for this once and save the results. However, the preferred + * formats can change, usually because the user has changed a system + * preference outside of your program. + * + * \param dateFormat a pointer to the SDL_DateFormat to hold the returned date + * format, may be NULL. + * \param timeFormat a pointer to the SDL_TimeFormat to hold the returned time + * format, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * - * - `SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER`: the SDL_DATE_FORMAT to use as the preferred date display format - * for the current system locale. - * - `SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER`: the SDL_TIME_FORMAT to use as the preferred time display format - * for the current system locale. + * \since This function is available since SDL 3.0.0. */ -#define SDL_PROP_GLOBAL_SYSTEM_DATE_FORMAT_NUMBER "SDL.time.date_format" -#define SDL_PROP_GLOBAL_SYSTEM_TIME_FORMAT_NUMBER "SDL.time.time_format" +extern SDL_DECLSPEC bool SDLCALL SDL_GetDateTimeLocalePreferences(SDL_DateFormat *dateFormat, SDL_TimeFormat *timeFormat); /** * Gets the current value of the system realtime clock in nanoseconds since * Jan 1, 1970 in Universal Coordinated Time (UTC). * - * \param ticks the SDL_Time to hold the returned tick count - * \returns 0 on success or -1 on error; call SDL_GetError() for more + * \param ticks the SDL_Time to hold the returned tick count. + * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetCurrentTime(SDL_Time *ticks); +extern SDL_DECLSPEC bool SDLCALL SDL_GetCurrentTime(SDL_Time *ticks); /** * Converts an SDL_Time in nanoseconds since the epoch to a calendar time in * the SDL_DateTime format. * - * \param ticks the SDL_Time to be converted - * \param dt the resulting SDL_DateTime + * \param ticks the SDL_Time to be converted. + * \param dt the resulting SDL_DateTime. * \param localTime the resulting SDL_DateTime will be expressed in local time * if true, otherwise it will be in Universal Coordinated - * Time (UTC) - * \returns 0 on success or -1 on error; call SDL_GetError() for more + * Time (UTC). + * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, SDL_bool localTime); +extern SDL_DECLSPEC bool SDLCALL SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, bool localTime); /** * Converts a calendar time to an SDL_Time in nanoseconds since the epoch. @@ -121,14 +136,14 @@ extern DECLSPEC int SDLCALL SDL_TimeToDateTime(SDL_Time ticks, SDL_DateTime *dt, * This function ignores the day_of_week member of the SDL_DateTime struct, so * it may remain unset. * - * \param dt the source SDL_DateTime - * \param ticks the resulting SDL_Time - * \returns 0 on success or -1 on error; call SDL_GetError() for more + * \param dt the source SDL_DateTime. + * \param ticks the resulting SDL_Time. + * \returns true on success or false on failure; call SDL_GetError() for more * information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_Time *ticks); +extern SDL_DECLSPEC bool SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_Time *ticks); /** * Converts an SDL time into a Windows FILETIME (100-nanosecond intervals @@ -136,68 +151,68 @@ extern DECLSPEC int SDLCALL SDL_DateTimeToTime(const SDL_DateTime *dt, SDL_Time * * This function fills in the two 32-bit values of the FILETIME structure. * - * \param ticks the time to convert + * \param ticks the time to convert. * \param dwLowDateTime a pointer filled in with the low portion of the - * Windows FILETIME value + * Windows FILETIME value. * \param dwHighDateTime a pointer filled in with the high portion of the - * Windows FILETIME value + * Windows FILETIME value. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_TimeToWindows(SDL_Time ticks, Uint32 *dwLowDateTime, Uint32 *dwHighDateTime); +extern SDL_DECLSPEC void SDLCALL SDL_TimeToWindows(SDL_Time ticks, Uint32 *dwLowDateTime, Uint32 *dwHighDateTime); /** * Converts a Windows FILETIME (100-nanosecond intervals since January 1, - * 1601) to an SDL time + * 1601) to an SDL time. * * This function takes the two 32-bit values of the FILETIME structure as * parameters. * - * \param dwLowDateTime the low portion of the Windows FILETIME value - * \param dwHighDateTime the high portion of the Windows FILETIME value - * \returns the converted SDL time + * \param dwLowDateTime the low portion of the Windows FILETIME value. + * \param dwHighDateTime the high portion of the Windows FILETIME value. + * \returns the converted SDL time. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Time SDLCALL SDL_TimeFromWindows(Uint32 dwLowDateTime, Uint32 dwHighDateTime); +extern SDL_DECLSPEC SDL_Time SDLCALL SDL_TimeFromWindows(Uint32 dwLowDateTime, Uint32 dwHighDateTime); /** * Get the number of days in a month for a given year. * - * \param year the year - * \param month the month [1-12] - * \returns the number of days in the requested month, otherwise -1; call + * \param year the year. + * \param month the month [1-12]. + * \returns the number of days in the requested month or -1 on failure; call * SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetDaysInMonth(int year, int month); +extern SDL_DECLSPEC int SDLCALL SDL_GetDaysInMonth(int year, int month); /** * Get the day of year for a calendar date. * - * \param year the year component of the date - * \param month the month component of the date - * \param day the day component of the date - * \returns the day of year [0-365] if the date is valid, otherwise -1; call - * SDL_GetError() for more information. + * \param year the year component of the date. + * \param month the month component of the date. + * \param day the day component of the date. + * \returns the day of year [0-365] if the date is valid or -1 on failure; + * call SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetDayOfYear(int year, int month, int day); +extern SDL_DECLSPEC int SDLCALL SDL_GetDayOfYear(int year, int month, int day); /** * Get the day of week for a calendar date. * - * \param year the year component of the date - * \param month the month component of the date - * \param day the day component of the date - * \returns a value between 0 and 6 (0 being Sunday) if the date is valid, - * otherwise -1; call SDL_GetError() for more information. + * \param year the year component of the date. + * \param month the month component of the date. + * \param day the day component of the date. + * \returns a value between 0 and 6 (0 being Sunday) if the date is valid or + * -1 on failure; call SDL_GetError() for more information. * - * \since This function is available since SDL 3.0.0 + * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GetDayOfWeek(int year, int month, int day); +extern SDL_DECLSPEC int SDLCALL SDL_GetDayOfWeek(int year, int month, int day); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_timer.h b/libs/SDL3/include/SDL3/SDL_timer.h index d317bd81f..fa8b2bb22 100644 --- a/libs/SDL3/include/SDL3/SDL_timer.h +++ b/libs/SDL3/include/SDL3/SDL_timer.h @@ -23,9 +23,9 @@ #define SDL_timer_h_ /** - * \file SDL_timer.h + * # CategoryTimer * - * Header for the SDL time management routines. + * SDL time management routines. */ #include @@ -37,9 +37,7 @@ extern "C" { #endif -/** - * SDL time constants - */ +/* SDL time constants */ #define SDL_MS_PER_SECOND 1000 #define SDL_US_PER_SECOND 1000000 #define SDL_NS_PER_SECOND 1000000000LL @@ -60,7 +58,7 @@ extern "C" { * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Uint64 SDLCALL SDL_GetTicks(void); +extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetTicks(void); /** * Get the number of nanoseconds since SDL library initialization. @@ -70,7 +68,7 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetTicks(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Uint64 SDLCALL SDL_GetTicksNS(void); +extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetTicksNS(void); /** * Get the current value of the high resolution counter. @@ -87,7 +85,7 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetTicksNS(void); * * \sa SDL_GetPerformanceFrequency */ -extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void); +extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void); /** * Get the count per second of the high resolution counter. @@ -98,7 +96,7 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceCounter(void); * * \sa SDL_GetPerformanceCounter */ -extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); +extern SDL_DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); /** * Wait a specified number of milliseconds before returning. @@ -107,51 +105,68 @@ extern DECLSPEC Uint64 SDLCALL SDL_GetPerformanceFrequency(void); * waits at least the specified time, but possibly longer due to OS * scheduling. * - * \param ms the number of milliseconds to delay + * \param ms the number of milliseconds to delay. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_Delay(Uint32 ms); +extern SDL_DECLSPEC void SDLCALL SDL_Delay(Uint32 ms); /** * Wait a specified number of nanoseconds before returning. * * This function waits a specified number of nanoseconds before returning. It - * waits at least the specified time, but possibly longer due to OS - * scheduling. + * will attempt to wait as close to the requested time as possible, busy + * waiting if necessary, but could return later due to OS scheduling. * - * \param ns the number of nanoseconds to delay + * \param ns the number of nanoseconds to delay. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_DelayNS(Uint64 ns); +extern SDL_DECLSPEC void SDLCALL SDL_DelayNS(Uint64 ns); /** - * Function prototype for the timer callback function. + * Definition of the timer ID type. * - * The callback function is passed the current timer interval and returns - * the next timer interval, in milliseconds. If the returned value is the same as the one - * passed in, the periodic alarm continues, otherwise a new alarm is - * scheduled. If the callback returns 0, the periodic alarm is cancelled. + * \since This datatype is available since SDL 3.0.0. */ -typedef Uint32 (SDLCALL *SDL_TimerCallback)(Uint32 interval, void *param); +typedef Uint32 SDL_TimerID; /** - * Definition of the timer ID type. + * Function prototype for the millisecond timer callback function. + * + * The callback function is passed the current timer interval and returns the + * next timer interval, in milliseconds. If the returned value is the same as + * the one passed in, the periodic alarm continues, otherwise a new alarm is + * scheduled. If the callback returns 0, the periodic alarm is canceled and + * will be removed. + * + * \param userdata an arbitrary pointer provided by the app through + * SDL_AddTimer, for its own use. + * \param timerID the current timer being processed. + * \param interval the current callback time interval. + * \returns the new callback time interval, or 0 to disable further runs of + * the callback. + * + * \threadsafety SDL may call this callback at any time from a background + * thread; the application is responsible for locking resources + * the callback touches that need to be protected. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_AddTimer */ -typedef Uint32 SDL_TimerID; +typedef Uint32 (SDLCALL *SDL_TimerCallback)(void *userdata, SDL_TimerID timerID, Uint32 interval); /** * Call a callback function at a future time. * - * If you use this function, you must pass `SDL_INIT_TIMER` to SDL_Init(). - * * The callback function is passed the current timer interval and the user * supplied parameter from the SDL_AddTimer() call and should return the next * timer interval. If the value returned from the callback is 0, the timer is - * canceled. + * canceled and will be removed. * - * The callback is run on a separate thread. + * The callback is run on a separate thread, and for short timeouts can + * potentially be called before this function returns. * * Timers take into account the amount of time it took to execute the * callback. For example, if the callback took 250 ms to execute and returned @@ -162,33 +177,96 @@ typedef Uint32 SDL_TimerID; * time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your * callback needs to adjust for variances. * - * \param interval the timer delay, in milliseconds, passed to `callback` + * \param interval the timer delay, in milliseconds, passed to `callback`. + * \param callback the SDL_TimerCallback function to call when the specified + * `interval` elapses. + * \param userdata a pointer that is passed to `callback`. + * \returns a timer ID or 0 on failure; call SDL_GetError() for more + * information. + * + * \threadsafety It is safe to call this function from any thread. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_AddTimerNS + * \sa SDL_RemoveTimer + */ +extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *userdata); + +/** + * Function prototype for the nanosecond timer callback function. + * + * The callback function is passed the current timer interval and returns the + * next timer interval, in nanoseconds. If the returned value is the same as + * the one passed in, the periodic alarm continues, otherwise a new alarm is + * scheduled. If the callback returns 0, the periodic alarm is canceled and + * will be removed. + * + * \param userdata an arbitrary pointer provided by the app through + * SDL_AddTimer, for its own use. + * \param timerID the current timer being processed. + * \param interval the current callback time interval. + * \returns the new callback time interval, or 0 to disable further runs of + * the callback. + * + * \threadsafety SDL may call this callback at any time from a background + * thread; the application is responsible for locking resources + * the callback touches that need to be protected. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_AddTimerNS + */ +typedef Uint64 (SDLCALL *SDL_NSTimerCallback)(void *userdata, SDL_TimerID timerID, Uint64 interval); + +/** + * Call a callback function at a future time. + * + * The callback function is passed the current timer interval and the user + * supplied parameter from the SDL_AddTimerNS() call and should return the + * next timer interval. If the value returned from the callback is 0, the + * timer is canceled and will be removed. + * + * The callback is run on a separate thread, and for short timeouts can + * potentially be called before this function returns. + * + * Timers take into account the amount of time it took to execute the + * callback. For example, if the callback took 250 ns to execute and returned + * 1000 (ns), the timer would only wait another 750 ns before its next + * iteration. + * + * Timing may be inexact due to OS scheduling. Be sure to note the current + * time with SDL_GetTicksNS() or SDL_GetPerformanceCounter() in case your + * callback needs to adjust for variances. + * + * \param interval the timer delay, in nanoseconds, passed to `callback`. * \param callback the SDL_TimerCallback function to call when the specified - * `interval` elapses - * \param param a pointer that is passed to `callback` - * \returns a timer ID or 0 if an error occurs; call SDL_GetError() for more + * `interval` elapses. + * \param userdata a pointer that is passed to `callback`. + * \returns a timer ID or 0 on failure; call SDL_GetError() for more * information. * + * \threadsafety It is safe to call this function from any thread. + * * \since This function is available since SDL 3.0.0. * + * \sa SDL_AddTimer * \sa SDL_RemoveTimer */ -extern DECLSPEC SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, - SDL_TimerCallback callback, - void *param); +extern SDL_DECLSPEC SDL_TimerID SDLCALL SDL_AddTimerNS(Uint64 interval, SDL_NSTimerCallback callback, void *userdata); /** * Remove a timer created with SDL_AddTimer(). * - * \param id the ID of the timer to remove - * \returns SDL_TRUE if the timer is removed or SDL_FALSE if the timer wasn't - * found. + * \param id the ID of the timer to remove. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_AddTimer */ -extern DECLSPEC SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID id); +extern SDL_DECLSPEC bool SDLCALL SDL_RemoveTimer(SDL_TimerID id); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_touch.h b/libs/SDL3/include/SDL3/SDL_touch.h index 0e679cb0d..2b07d2d32 100644 --- a/libs/SDL3/include/SDL3/SDL_touch.h +++ b/libs/SDL3/include/SDL3/SDL_touch.h @@ -20,9 +20,9 @@ */ /** - * \file SDL_touch.h + * # CategoryTouch * - * Include file for SDL touch event handling. + * SDL touch management. */ #ifndef SDL_touch_h_ @@ -31,7 +31,6 @@ #include #include #include -#include #include /* Set up for C function definitions, even when using C++ */ @@ -42,7 +41,7 @@ extern "C" { typedef Uint64 SDL_TouchID; typedef Uint64 SDL_FingerID; -typedef enum +typedef enum SDL_TouchDeviceType { SDL_TOUCH_DEVICE_INVALID = -1, SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */ @@ -50,12 +49,23 @@ typedef enum SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */ } SDL_TouchDeviceType; +/** + * Data about a single finger in a multitouch event. + * + * Each touch even is a collection of fingers that are simultaneously in + * contact with the touch device (so a "touch" can be a "multitouch," in + * reality), and this struct reports details of the specific fingers. + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_GetTouchFingers + */ typedef struct SDL_Finger { - SDL_FingerID id; - float x; - float y; - float pressure; + SDL_FingerID id; /**< the finger ID */ + float x; /**< the x-axis location of the touch event, normalized (0...1) */ + float y; /**< the y-axis location of the touch event, normalized (0...1) */ + float pressure; /**< the quantity of pressure applied, normalized (0...1) */ } SDL_Finger; /* Used as the device ID for mouse events simulated with touch input */ @@ -72,70 +82,51 @@ typedef struct SDL_Finger * Therefore the returned list might be empty, although devices are available. * After using all devices at least once the number will be correct. * - * This was fixed for Android in SDL 2.0.1. - * - * \param count a pointer filled in with the number of devices returned, can + * \param count a pointer filled in with the number of devices returned, may * be NULL. - * \returns a 0 terminated array of touch device IDs which should be freed - * with SDL_free(), or NULL on error; call SDL_GetError() for more - * details. + * \returns a 0 terminated array of touch device IDs or NULL on failure; call + * SDL_GetError() for more information. This should be freed with + * SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_TouchID *SDLCALL SDL_GetTouchDevices(int *count); +extern SDL_DECLSPEC SDL_TouchID * SDLCALL SDL_GetTouchDevices(int *count); /** * Get the touch device name as reported from the driver. * - * You do not own the returned string, do not modify or free it. - * * \param touchID the touch device instance ID. - * \returns touch device name, or NULL on error; call SDL_GetError() for more - * details. + * \returns touch device name, or NULL on failure; call SDL_GetError() for + * more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC const char* SDLCALL SDL_GetTouchDeviceName(SDL_TouchID touchID); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetTouchDeviceName(SDL_TouchID touchID); /** * Get the type of the given touch device. * - * \param touchID the ID of a touch device - * \returns touch device type + * \param touchID the ID of a touch device. + * \returns touch device type. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); +extern SDL_DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); /** - * Get the number of active fingers for a given touch device. + * Get a list of active fingers for a given touch device. * - * \param touchID the ID of a touch device - * \returns the number of active fingers for a given touch device on success - * or a negative error code on failure; call SDL_GetError() for more - * information. - * - * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetTouchFinger - */ -extern DECLSPEC int SDLCALL SDL_GetNumTouchFingers(SDL_TouchID touchID); - -/** - * Get the finger object for specified touch device ID and finger index. - * - * The returned resource is owned by SDL and should not be deallocated. - * - * \param touchID the ID of the requested touch device - * \param index the index of the requested finger - * \returns a pointer to the SDL_Finger object or NULL if no object at the - * given ID and index could be found. + * \param touchID the ID of a touch device. + * \param count a pointer filled in with the number of fingers returned, can + * be NULL. + * \returns a NULL terminated array of SDL_Finger pointers or NULL on failure; + * call SDL_GetError() for more information. This is a single + * allocation that should be freed with SDL_free() when it is no + * longer needed. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetNumTouchFingers */ -extern DECLSPEC SDL_Finger * SDLCALL SDL_GetTouchFinger(SDL_TouchID touchID, int index); +extern SDL_DECLSPEC SDL_Finger ** SDLCALL SDL_GetTouchFingers(SDL_TouchID touchID, int *count); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/libs/SDL3/include/SDL3/SDL_version.h b/libs/SDL3/include/SDL3/SDL_version.h index 492898a1b..09b010dc0 100644 --- a/libs/SDL3/include/SDL3/SDL_version.h +++ b/libs/SDL3/include/SDL3/SDL_version.h @@ -20,9 +20,10 @@ */ /** - * \file SDL_version.h + * # CategoryVersion * - * This header defines the current SDL version. + * Functionality to query the current SDL version, both as headers the app was + * compiled against, and a library the app is linked to. */ #ifndef SDL_version_h_ @@ -37,92 +38,112 @@ extern "C" { #endif /** - * Information about the version of SDL in use. + * The current major version of SDL headers. * - * Represents the library's version as three levels: major revision - * (increments with massive changes, additions, and enhancements), - * minor revision (increments with backwards-compatible changes to the - * major revision), and patchlevel (increments with fixes to the minor - * revision). + * If this were SDL version 3.2.1, this value would be 3. * - * \sa SDL_VERSION - * \sa SDL_GetVersion + * \since This macro is available since SDL 3.0.0. */ -typedef struct SDL_Version -{ - Uint8 major; /**< major version */ - Uint8 minor; /**< minor version */ - Uint8 patch; /**< update version */ -} SDL_Version; - -/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL -*/ #define SDL_MAJOR_VERSION 3 + +/** + * The current minor version of the SDL headers. + * + * If this were SDL version 3.2.1, this value would be 2. + * + * \since This macro is available since SDL 3.0.0. + */ #define SDL_MINOR_VERSION 1 -#define SDL_PATCHLEVEL 1 /** - * Macro to determine SDL version program was compiled against. + * The current micro (or patchlevel) version of the SDL headers. + * + * If this were SDL version 3.2.1, this value would be 1. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_MICRO_VERSION 3 + +/** + * This macro turns the version numbers into a numeric value. * - * This macro fills in an SDL_Version structure with the version of the - * library you compiled against. This is determined by what header the - * compiler uses. Note that if you dynamically linked the library, you might - * have a slightly newer or older version at runtime. That version can be - * determined with SDL_GetVersion(), which, unlike SDL_VERSION(), - * is not a macro. + * (1,2,3) becomes 1002003. * - * \param x A pointer to an SDL_Version struct to initialize. + * \param major the major version number. + * \param minor the minorversion number. + * \param patch the patch version number. * - * \sa SDL_Version - * \sa SDL_GetVersion + * \since This macro is available since SDL 3.0.0. */ -#define SDL_VERSION(x) \ -{ \ - (x)->major = SDL_MAJOR_VERSION; \ - (x)->minor = SDL_MINOR_VERSION; \ - (x)->patch = SDL_PATCHLEVEL; \ -} +#define SDL_VERSIONNUM(major, minor, patch) \ + ((major) * 1000000 + (minor) * 1000 + (patch)) + +/** + * This macro extracts the major version from a version number + * + * 1002003 becomes 1. + * + * \param version the version number. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_VERSIONNUM_MAJOR(version) ((version) / 1000000) + +/** + * This macro extracts the minor version from a version number + * + * 1002003 becomes 2. + * + * \param version the version number. + * + * \since This macro is available since SDL 3.0.0. + */ +#define SDL_VERSIONNUM_MINOR(version) (((version) / 1000) % 1000) /** - * This macro turns the version numbers into a numeric value: - * \verbatim - (1,2,3) -> (0x1000203) - \endverbatim + * This macro extracts the micro version from a version number + * + * 1002003 becomes 3. + * + * \param version the version number. + * + * \since This macro is available since SDL 3.0.0. */ -#define SDL_VERSIONNUM(X, Y, Z) \ - ((X) << 24 | (Y) << 8 | (Z) << 0) +#define SDL_VERSIONNUM_MICRO(version) ((version) % 1000) /** - * This is the version number macro for the current SDL version. + * This is the version number macro for the current SDL version. + * + * \since This macro is available since SDL 3.0.0. */ -#define SDL_COMPILEDVERSION \ - SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) +#define SDL_VERSION \ + SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION) /** - * This macro will evaluate to true if compiled with SDL at least X.Y.Z. + * This macro will evaluate to true if compiled with SDL at least X.Y.Z. + * + * \since This macro is available since SDL 3.0.0. */ #define SDL_VERSION_ATLEAST(X, Y, Z) \ - (SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) + (SDL_VERSION >= SDL_VERSIONNUM(X, Y, Z)) /** * Get the version of SDL that is linked against your program. * * If you are linking to SDL dynamically, then it is possible that the current * version will be different than the version you compiled against. This - * function returns the current version, while SDL_VERSION() is a macro that - * tells you what version you compiled with. + * function returns the current version, while SDL_VERSION is the version you + * compiled with. * * This function may be called safely at any time, even before SDL_Init(). * - * \param ver the SDL_Version structure that contains the version information - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns the version of the linked library. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetRevision */ -extern DECLSPEC int SDLCALL SDL_GetVersion(SDL_Version * ver); +extern SDL_DECLSPEC int SDLCALL SDL_GetVersion(void); /** * Get the code revision of SDL that is linked against your program. @@ -138,9 +159,6 @@ extern DECLSPEC int SDLCALL SDL_GetVersion(SDL_Version * ver); * If SDL wasn't built from a git repository with the appropriate tools, this * will return an empty string. * - * Prior to SDL 2.0.16, before development moved to GitHub, this returned a - * hash for a Mercurial repository. - * * You shouldn't use this function for anything but logging it for debugging * purposes. The string is not intended to be reliable in any way. * @@ -151,7 +169,7 @@ extern DECLSPEC int SDLCALL SDL_GetVersion(SDL_Version * ver); * * \sa SDL_GetVersion */ -extern DECLSPEC const char *SDLCALL SDL_GetRevision(void); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetRevision(void); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL3/include/SDL3/SDL_video.h b/libs/SDL3/include/SDL3/SDL_video.h index fff4e8fa8..4310f03e3 100644 --- a/libs/SDL3/include/SDL3/SDL_video.h +++ b/libs/SDL3/include/SDL3/SDL_video.h @@ -20,15 +20,37 @@ */ /** - * \file SDL_video.h - * - * Header file for SDL video functions. + * # CategoryVideo + * + * SDL's video subsystem is largely interested in abstracting window + * management from the underlying operating system. You can create windows, + * manage them in various ways, set them fullscreen, and get events when + * interesting things happen with them, such as the mouse or keyboard + * interacting with a window. + * + * The video subsystem is also interested in abstracting away some + * platform-specific differences in OpenGL: context creation, swapping + * buffers, etc. This may be crucial to your app, but also you are not + * required to use OpenGL at all. In fact, SDL can provide rendering to those + * windows as well, either with an easy-to-use + * [2D API](https://wiki.libsdl.org/SDL3/CategoryRender) + * or with a more-powerful + * [GPU API](https://wiki.libsdl.org/SDL3/CategoryGPU) + * . Of course, it can simply get out of your way and give you the window + * handles you need to use Vulkan, Direct3D, Metal, or whatever else you like + * directly, too. + * + * The video subsystem covers a lot of functionality, out of necessity, so it + * is worth perusing the list of functions just to see what's available, but + * most apps can get by with simply creating a window and listening for + * events, so start with SDL_CreateWindow() and SDL_PollEvent(). */ #ifndef SDL_video_h_ #define SDL_video_h_ #include +#include #include #include #include @@ -40,60 +62,91 @@ extern "C" { #endif - +/** + * This is a unique ID for a display for the time it is connected to the + * system, and is never reused for the lifetime of the application. + * + * If the display is disconnected and reconnected, it will get a new ID. + * + * The value 0 is an invalid ID. + * + * \since This datatype is available since SDL 3.0.0. + */ typedef Uint32 SDL_DisplayID; + +/** + * This is a unique ID for a window. + * + * The value 0 is an invalid ID. + * + * \since This datatype is available since SDL 3.0.0. + */ typedef Uint32 SDL_WindowID; +/* Global video properties... */ + /** - * Global video properties + * The pointer to the global `wl_display` object used by the Wayland video + * backend. * - * - `SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER`: the pointer to - * the global `wl_display` object used by the Wayland video backend. Can be - * set before the video subsystem is initialized to import an external - * `wl_display` object from an application or toolkit for use in SDL, or - * read after initialization to export the `wl_display` used by the - * Wayland video backend. Setting this property after the video subsystem - * has been initialized has no effect, and reading it when the video - * subsystem is uninitialized will either return the user provided value, - * if one was set prior to initialization, or NULL. See - * docs/README-wayland.md for more information. + * Can be set before the video subsystem is initialized to import an external + * `wl_display` object from an application or toolkit for use in SDL, or read + * after initialization to export the `wl_display` used by the Wayland video + * backend. Setting this property after the video subsystem has been + * initialized has no effect, and reading it when the video subsystem is + * uninitialized will either return the user provided value, if one was set + * prior to initialization, or NULL. See docs/README-wayland.md for more + * information. */ #define SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER "SDL.video.wayland.wl_display" /** - * System theme + * System theme. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_SystemTheme { SDL_SYSTEM_THEME_UNKNOWN, /**< Unknown system theme */ SDL_SYSTEM_THEME_LIGHT, /**< Light colored system theme */ SDL_SYSTEM_THEME_DARK /**< Dark colored system theme */ } SDL_SystemTheme; +/* Internal display mode data */ +typedef struct SDL_DisplayModeData SDL_DisplayModeData; + /** - * The structure that defines a display mode + * The structure that defines a display mode. * - * \sa SDL_GetFullscreenDisplayModes() - * \sa SDL_GetDesktopDisplayMode() - * \sa SDL_GetCurrentDisplayMode() - * \sa SDL_SetWindowFullscreenMode() - * \sa SDL_GetWindowFullscreenMode() + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_GetFullscreenDisplayModes + * \sa SDL_GetDesktopDisplayMode + * \sa SDL_GetCurrentDisplayMode + * \sa SDL_SetWindowFullscreenMode + * \sa SDL_GetWindowFullscreenMode */ -typedef struct +typedef struct SDL_DisplayMode { - SDL_DisplayID displayID; /**< the display this mode is associated with */ - SDL_PixelFormatEnum format; /**< pixel format */ - int w; /**< width */ - int h; /**< height */ - float pixel_density; /**< scale converting size to pixels (e.g. a 1920x1080 mode with 2.0 scale would have 3840x2160 pixels) */ - float refresh_rate; /**< refresh rate (or zero for unspecified) */ - void *driverdata; /**< driver-specific data, initialize to 0 */ + SDL_DisplayID displayID; /**< the display this mode is associated with */ + SDL_PixelFormat format; /**< pixel format */ + int w; /**< width */ + int h; /**< height */ + float pixel_density; /**< scale converting size to pixels (e.g. a 1920x1080 mode with 2.0 scale would have 3840x2160 pixels) */ + float refresh_rate; /**< refresh rate (or 0.0f for unspecified) */ + int refresh_rate_numerator; /**< precise refresh rate numerator (or 0 for unspecified) */ + int refresh_rate_denominator; /**< precise refresh rate denominator */ + + SDL_DisplayModeData *internal; /**< Private */ + } SDL_DisplayMode; /** - * Display orientation + * Display orientation values; the way a display is rotated. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_DisplayOrientation { SDL_ORIENTATION_UNKNOWN, /**< The display orientation can't be determined */ SDL_ORIENTATION_LANDSCAPE, /**< The display is in landscape mode, with the right side up, relative to portrait mode */ @@ -103,43 +156,59 @@ typedef enum } SDL_DisplayOrientation; /** - * The type used to identify a window + * The struct used as an opaque handle to a window. + * + * \since This struct is available since SDL 3.0.0. + * + * \sa SDL_CreateWindow */ typedef struct SDL_Window SDL_Window; /** - * The flags on a window + * The flags on a window. + * + * These cover a lot of true/false, or on/off, window state. Some of it is + * immutable after being set through SDL_CreateWindow(), some of it can be + * changed on existing windows by the app, and some of it might be altered by + * the user or system outside of the app's control. * - * \sa SDL_GetWindowFlags + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_GetWindowFlags */ -typedef Uint32 SDL_WindowFlags; - -#define SDL_WINDOW_FULLSCREEN 0x00000001U /**< window is in fullscreen mode */ -#define SDL_WINDOW_OPENGL 0x00000002U /**< window usable with OpenGL context */ -#define SDL_WINDOW_OCCLUDED 0x00000004U /**< window is occluded */ -#define SDL_WINDOW_HIDDEN 0x00000008U /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible */ -#define SDL_WINDOW_BORDERLESS 0x00000010U /**< no window decoration */ -#define SDL_WINDOW_RESIZABLE 0x00000020U /**< window can be resized */ -#define SDL_WINDOW_MINIMIZED 0x00000040U /**< window is minimized */ -#define SDL_WINDOW_MAXIMIZED 0x00000080U /**< window is maximized */ -#define SDL_WINDOW_MOUSE_GRABBED 0x00000100U /**< window has grabbed mouse input */ -#define SDL_WINDOW_INPUT_FOCUS 0x00000200U /**< window has input focus */ -#define SDL_WINDOW_MOUSE_FOCUS 0x00000400U /**< window has mouse focus */ -#define SDL_WINDOW_EXTERNAL 0x00000800U /**< window not created by SDL */ -#define SDL_WINDOW_HIGH_PIXEL_DENSITY 0x00002000U /**< window uses high pixel density back buffer if possible */ -#define SDL_WINDOW_MOUSE_CAPTURE 0x00004000U /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ -#define SDL_WINDOW_ALWAYS_ON_TOP 0x00008000U /**< window should always be above others */ -#define SDL_WINDOW_UTILITY 0x00020000U /**< window should be treated as a utility window, not showing in the task bar and window list */ -#define SDL_WINDOW_TOOLTIP 0x00040000U /**< window should be treated as a tooltip */ -#define SDL_WINDOW_POPUP_MENU 0x00080000U /**< window should be treated as a popup menu */ -#define SDL_WINDOW_KEYBOARD_GRABBED 0x00100000U /**< window has grabbed keyboard input */ -#define SDL_WINDOW_VULKAN 0x10000000U /**< window usable for Vulkan surface */ -#define SDL_WINDOW_METAL 0x20000000U /**< window usable for Metal view */ -#define SDL_WINDOW_TRANSPARENT 0x40000000U /**< window with transparent buffer */ -#define SDL_WINDOW_NOT_FOCUSABLE 0x80000000U /**< window should not be focusable */ - -/** - * Used to indicate that you don't care what the window position is. +typedef Uint64 SDL_WindowFlags; + +#define SDL_WINDOW_FULLSCREEN SDL_UINT64_C(0x0000000000000001) /**< window is in fullscreen mode */ +#define SDL_WINDOW_OPENGL SDL_UINT64_C(0x0000000000000002) /**< window usable with OpenGL context */ +#define SDL_WINDOW_OCCLUDED SDL_UINT64_C(0x0000000000000004) /**< window is occluded */ +#define SDL_WINDOW_HIDDEN SDL_UINT64_C(0x0000000000000008) /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow() is required for it to become visible */ +#define SDL_WINDOW_BORDERLESS SDL_UINT64_C(0x0000000000000010) /**< no window decoration */ +#define SDL_WINDOW_RESIZABLE SDL_UINT64_C(0x0000000000000020) /**< window can be resized */ +#define SDL_WINDOW_MINIMIZED SDL_UINT64_C(0x0000000000000040) /**< window is minimized */ +#define SDL_WINDOW_MAXIMIZED SDL_UINT64_C(0x0000000000000080) /**< window is maximized */ +#define SDL_WINDOW_MOUSE_GRABBED SDL_UINT64_C(0x0000000000000100) /**< window has grabbed mouse input */ +#define SDL_WINDOW_INPUT_FOCUS SDL_UINT64_C(0x0000000000000200) /**< window has input focus */ +#define SDL_WINDOW_MOUSE_FOCUS SDL_UINT64_C(0x0000000000000400) /**< window has mouse focus */ +#define SDL_WINDOW_EXTERNAL SDL_UINT64_C(0x0000000000000800) /**< window not created by SDL */ +#define SDL_WINDOW_MODAL SDL_UINT64_C(0x0000000000001000) /**< window is modal */ +#define SDL_WINDOW_HIGH_PIXEL_DENSITY SDL_UINT64_C(0x0000000000002000) /**< window uses high pixel density back buffer if possible */ +#define SDL_WINDOW_MOUSE_CAPTURE SDL_UINT64_C(0x0000000000004000) /**< window has mouse captured (unrelated to MOUSE_GRABBED) */ +#define SDL_WINDOW_MOUSE_RELATIVE_MODE SDL_UINT64_C(0x0000000000008000) /**< window has relative mode enabled */ +#define SDL_WINDOW_ALWAYS_ON_TOP SDL_UINT64_C(0x0000000000010000) /**< window should always be above others */ +#define SDL_WINDOW_UTILITY SDL_UINT64_C(0x0000000000020000) /**< window should be treated as a utility window, not showing in the task bar and window list */ +#define SDL_WINDOW_TOOLTIP SDL_UINT64_C(0x0000000000040000) /**< window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window */ +#define SDL_WINDOW_POPUP_MENU SDL_UINT64_C(0x0000000000080000) /**< window should be treated as a popup menu, requires a parent window */ +#define SDL_WINDOW_KEYBOARD_GRABBED SDL_UINT64_C(0x0000000000100000) /**< window has grabbed keyboard input */ +#define SDL_WINDOW_VULKAN SDL_UINT64_C(0x0000000010000000) /**< window usable for Vulkan surface */ +#define SDL_WINDOW_METAL SDL_UINT64_C(0x0000000020000000) /**< window usable for Metal view */ +#define SDL_WINDOW_TRANSPARENT SDL_UINT64_C(0x0000000040000000) /**< window with transparent buffer */ +#define SDL_WINDOW_NOT_FOCUSABLE SDL_UINT64_C(0x0000000080000000) /**< window should not be focusable */ + + +/** + * Used to indicate that you don't care what the window position is. + * + * \since This macro is available since SDL 3.0.0. */ #define SDL_WINDOWPOS_UNDEFINED_MASK 0x1FFF0000u #define SDL_WINDOWPOS_UNDEFINED_DISPLAY(X) (SDL_WINDOWPOS_UNDEFINED_MASK|(X)) @@ -148,7 +217,9 @@ typedef Uint32 SDL_WindowFlags; (((X)&0xFFFF0000) == SDL_WINDOWPOS_UNDEFINED_MASK) /** - * Used to indicate that the window position should be centered. + * Used to indicate that the window position should be centered. + * + * \since This macro is available since SDL 3.0.0. */ #define SDL_WINDOWPOS_CENTERED_MASK 0x2FFF0000u #define SDL_WINDOWPOS_CENTERED_DISPLAY(X) (SDL_WINDOWPOS_CENTERED_MASK|(X)) @@ -157,9 +228,11 @@ typedef Uint32 SDL_WindowFlags; (((X)&0xFFFF0000) == SDL_WINDOWPOS_CENTERED_MASK) /** - * Window flash operation + * Window flash operation. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_FlashOperation { SDL_FLASH_CANCEL, /**< Cancel any window flash state */ SDL_FLASH_BRIEFLY, /**< Flash the window briefly to get attention */ @@ -167,12 +240,18 @@ typedef enum } SDL_FlashOperation; /** - * An opaque handle to an OpenGL context. + * An opaque handle to an OpenGL context. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_GL_CreateContext */ -typedef void *SDL_GLContext; +typedef struct SDL_GLContextState *SDL_GLContext; /** - * Opaque EGL types. + * Opaque EGL types. + * + * \since This datatype is available since SDL 3.0.0. */ typedef void *SDL_EGLDisplay; typedef void *SDL_EGLConfig; @@ -181,54 +260,128 @@ typedef intptr_t SDL_EGLAttrib; typedef int SDL_EGLint; /** - * EGL attribute initialization callback types. + * EGL platform attribute initialization callback. + * + * This is called when SDL is attempting to create an EGL context, to let the + * app add extra attributes to its eglGetPlatformDisplay() call. + * + * The callback should return a pointer to an EGL attribute array terminated + * with `EGL_NONE`. If this function returns NULL, the SDL_CreateWindow + * process will fail gracefully. + * + * The returned pointer should be allocated with SDL_malloc() and will be + * passed to SDL_free(). + * + * The arrays returned by each callback will be appended to the existing + * attribute arrays defined by SDL. + * + * \param userdata an app-controlled pointer that is passed to the callback. + * \returns a newly-allocated array of attributes, terminated with `EGL_NONE`. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_EGL_SetAttributeCallbacks + */ +typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void *userdata); + +/** + * EGL surface/context attribute initialization callback types. + * + * This is called when SDL is attempting to create an EGL surface, to let the + * app add extra attributes to its eglCreateWindowSurface() or + * eglCreateContext calls. + * + * For convenience, the EGLDisplay and EGLConfig to use are provided to the + * callback. + * + * The callback should return a pointer to an EGL attribute array terminated + * with `EGL_NONE`. If this function returns NULL, the SDL_CreateWindow + * process will fail gracefully. + * + * The returned pointer should be allocated with SDL_malloc() and will be + * passed to SDL_free(). + * + * The arrays returned by each callback will be appended to the existing + * attribute arrays defined by SDL. + * + * \param userdata an app-controlled pointer that is passed to the callback. + * \param display the EGL display to be used. + * \param config the EGL config to be used. + * \returns a newly-allocated array of attributes, terminated with `EGL_NONE`. + * + * \since This datatype is available since SDL 3.0.0. + * + * \sa SDL_EGL_SetAttributeCallbacks */ -typedef SDL_EGLAttrib *(SDLCALL *SDL_EGLAttribArrayCallback)(void); -typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void); +typedef SDL_EGLint *(SDLCALL *SDL_EGLIntArrayCallback)(void *userdata, SDL_EGLDisplay display, SDL_EGLConfig config); /** - * OpenGL configuration attributes + * An enumeration of OpenGL configuration attributes. + * + * While you can set most OpenGL attributes normally, the attributes listed + * above must be known before SDL creates the window that will be used with + * the OpenGL context. These attributes are set and read with + * SDL_GL_SetAttribute() and SDL_GL_GetAttribute(). + * + * In some cases, these attributes are minimum requests; the GL does not + * promise to give you exactly what you asked for. It's possible to ask for a + * 16-bit depth buffer and get a 24-bit one instead, for example, or to ask + * for no stencil buffer and still have one available. Context creation should + * fail if the GL can't provide your requested attributes at a minimum, but + * you should check to see exactly what you got. + * + * \since This enum is available since SDL 3.0.0. */ -typedef enum +typedef enum SDL_GLattr { - SDL_GL_RED_SIZE, - SDL_GL_GREEN_SIZE, - SDL_GL_BLUE_SIZE, - SDL_GL_ALPHA_SIZE, - SDL_GL_BUFFER_SIZE, - SDL_GL_DOUBLEBUFFER, - SDL_GL_DEPTH_SIZE, - SDL_GL_STENCIL_SIZE, - SDL_GL_ACCUM_RED_SIZE, - SDL_GL_ACCUM_GREEN_SIZE, - SDL_GL_ACCUM_BLUE_SIZE, - SDL_GL_ACCUM_ALPHA_SIZE, - SDL_GL_STEREO, - SDL_GL_MULTISAMPLEBUFFERS, - SDL_GL_MULTISAMPLESAMPLES, - SDL_GL_ACCELERATED_VISUAL, - SDL_GL_RETAINED_BACKING, - SDL_GL_CONTEXT_MAJOR_VERSION, - SDL_GL_CONTEXT_MINOR_VERSION, - SDL_GL_CONTEXT_FLAGS, - SDL_GL_CONTEXT_PROFILE_MASK, - SDL_GL_SHARE_WITH_CURRENT_CONTEXT, - SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, - SDL_GL_CONTEXT_RELEASE_BEHAVIOR, - SDL_GL_CONTEXT_RESET_NOTIFICATION, + SDL_GL_RED_SIZE, /**< the minimum number of bits for the red channel of the color buffer; defaults to 3. */ + SDL_GL_GREEN_SIZE, /**< the minimum number of bits for the green channel of the color buffer; defaults to 3. */ + SDL_GL_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the color buffer; defaults to 2. */ + SDL_GL_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the color buffer; defaults to 0. */ + SDL_GL_BUFFER_SIZE, /**< the minimum number of bits for frame buffer size; defaults to 0. */ + SDL_GL_DOUBLEBUFFER, /**< whether the output is single or double buffered; defaults to double buffering on. */ + SDL_GL_DEPTH_SIZE, /**< the minimum number of bits in the depth buffer; defaults to 16. */ + SDL_GL_STENCIL_SIZE, /**< the minimum number of bits in the stencil buffer; defaults to 0. */ + SDL_GL_ACCUM_RED_SIZE, /**< the minimum number of bits for the red channel of the accumulation buffer; defaults to 0. */ + SDL_GL_ACCUM_GREEN_SIZE, /**< the minimum number of bits for the green channel of the accumulation buffer; defaults to 0. */ + SDL_GL_ACCUM_BLUE_SIZE, /**< the minimum number of bits for the blue channel of the accumulation buffer; defaults to 0. */ + SDL_GL_ACCUM_ALPHA_SIZE, /**< the minimum number of bits for the alpha channel of the accumulation buffer; defaults to 0. */ + SDL_GL_STEREO, /**< whether the output is stereo 3D; defaults to off. */ + SDL_GL_MULTISAMPLEBUFFERS, /**< the number of buffers used for multisample anti-aliasing; defaults to 0. */ + SDL_GL_MULTISAMPLESAMPLES, /**< the number of samples used around the current pixel used for multisample anti-aliasing. */ + SDL_GL_ACCELERATED_VISUAL, /**< set to 1 to require hardware acceleration, set to 0 to force software rendering; defaults to allow either. */ + SDL_GL_RETAINED_BACKING, /**< not used (deprecated). */ + SDL_GL_CONTEXT_MAJOR_VERSION, /**< OpenGL context major version. */ + SDL_GL_CONTEXT_MINOR_VERSION, /**< OpenGL context minor version. */ + SDL_GL_CONTEXT_FLAGS, /**< some combination of 0 or more of elements of the SDL_GLcontextFlag enumeration; defaults to 0. */ + SDL_GL_CONTEXT_PROFILE_MASK, /**< type of GL context (Core, Compatibility, ES). See SDL_GLprofile; default value depends on platform. */ + SDL_GL_SHARE_WITH_CURRENT_CONTEXT, /**< OpenGL context sharing; defaults to 0. */ + SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, /**< requests sRGB capable visual; defaults to 0. */ + SDL_GL_CONTEXT_RELEASE_BEHAVIOR, /**< sets context the release behavior. See SDL_GLcontextReleaseFlag; defaults to FLUSH. */ + SDL_GL_CONTEXT_RESET_NOTIFICATION, /**< set context reset notification. See SDL_GLContextResetNotification; defaults to NO_NOTIFICATION. */ SDL_GL_CONTEXT_NO_ERROR, SDL_GL_FLOATBUFFERS, SDL_GL_EGL_PLATFORM } SDL_GLattr; -typedef enum +/** + * Possible values to be set for the SDL_GL_CONTEXT_PROFILE_MASK attribute. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_GLprofile { SDL_GL_CONTEXT_PROFILE_CORE = 0x0001, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002, SDL_GL_CONTEXT_PROFILE_ES = 0x0004 /**< GLX_CONTEXT_ES2_PROFILE_BIT_EXT */ } SDL_GLprofile; -typedef enum +/** + * Possible values to be set for the SDL_GL_CONTEXT_FLAGS attribute. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_GLcontextFlag { SDL_GL_CONTEXT_DEBUG_FLAG = 0x0001, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002, @@ -236,13 +389,24 @@ typedef enum SDL_GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008 } SDL_GLcontextFlag; -typedef enum +/** + * Possible values to be set for the SDL_GL_CONTEXT_RELEASE_BEHAVIOR + * attribute. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_GLcontextReleaseFlag { SDL_GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000, SDL_GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001 } SDL_GLcontextReleaseFlag; -typedef enum +/** + * Possible values to be set SDL_GL_CONTEXT_RESET_NOTIFICATION attribute. + * + * \since This enum is available since SDL 3.0.0. + */ +typedef enum SDL_GLContextResetNotification { SDL_GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000, SDL_GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001 @@ -253,14 +417,13 @@ typedef enum /** * Get the number of video drivers compiled into SDL. * - * \returns a number >= 1 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns the number of built in video drivers. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetVideoDriver */ -extern DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); +extern SDL_DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); /** * Get the name of a built in video driver. @@ -268,18 +431,26 @@ extern DECLSPEC int SDLCALL SDL_GetNumVideoDrivers(void); * The video drivers are presented in the order in which they are normally * checked during initialization. * - * \param index the index of a video driver + * The names of drivers are all simple, low-ASCII identifiers, like "cocoa", + * "x11" or "windows". These never have Unicode characters, and are not meant + * to be proper names. + * + * \param index the index of a video driver. * \returns the name of the video driver with the given **index**. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetNumVideoDrivers */ -extern DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetVideoDriver(int index); /** * Get the name of the currently initialized video driver. * + * The names of drivers are all simple, low-ASCII identifiers, like "cocoa", + * "x11" or "windows". These never have Unicode characters, and are not meant + * to be proper names. + * * \returns the name of the current video driver or NULL if no driver has been * initialized. * @@ -288,28 +459,29 @@ extern DECLSPEC const char *SDLCALL SDL_GetVideoDriver(int index); * \sa SDL_GetNumVideoDrivers * \sa SDL_GetVideoDriver */ -extern DECLSPEC const char *SDLCALL SDL_GetCurrentVideoDriver(void); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetCurrentVideoDriver(void); /** - * Get the current system theme + * Get the current system theme. * - * \returns the current system theme, light, dark, or unknown + * \returns the current system theme, light, dark, or unknown. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_SystemTheme SDLCALL SDL_GetSystemTheme(void); +extern SDL_DECLSPEC SDL_SystemTheme SDLCALL SDL_GetSystemTheme(void); /** * Get a list of currently connected displays. * - * \param count a pointer filled in with the number of displays returned - * \returns a 0 terminated array of display instance IDs which should be freed - * with SDL_free(), or NULL on error; call SDL_GetError() for more - * details. + * \param count a pointer filled in with the number of displays returned, may + * be NULL. + * \returns a 0 terminated array of display instance IDs or NULL on failure; + * call SDL_GetError() for more information. This should be freed + * with SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_DisplayID *SDLCALL SDL_GetDisplays(int *count); +extern SDL_DECLSPEC SDL_DisplayID * SDLCALL SDL_GetDisplays(int *count); /** * Return the primary display. @@ -321,7 +493,7 @@ extern DECLSPEC SDL_DisplayID *SDLCALL SDL_GetDisplays(int *count); * * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); +extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); /** * Get the properties associated with a display. @@ -329,37 +501,33 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetPrimaryDisplay(void); * The following read-only properties are provided by SDL: * * - `SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN`: true if the display has HDR - * headroom above the SDR white point. This property can change dynamically - * when SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. - * - `SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT`: the value of SDR white in the - * SDL_COLORSPACE_SRGB_LINEAR colorspace. On Windows this corresponds to the - * SDR white level in scRGB colorspace, and on Apple platforms this is - * always 1.0 for EDR content. This property can change dynamically when - * SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. - * - `SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT`: the additional high dynamic range - * that can be displayed, in terms of the SDR white point. When HDR is not - * enabled, this will be 1.0. This property can change dynamically when - * SDL_EVENT_DISPLAY_HDR_STATE_CHANGED is sent. + * headroom above the SDR white point. This is for informational and + * diagnostic purposes only, as not all platforms provide this information + * at the display level. + * + * On KMS/DRM: + * + * - `SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER`: the "panel + * orientation" property for the display in degrees of clockwise rotation. + * Note that this is provided only as a hint, and the application is + * responsible for any coordinate transformations needed to conform to the + * requested display orientation. * - * \param displayID the instance ID of the display to query + * \param displayID the instance ID of the display to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID); +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID displayID); -#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled" -#define SDL_PROP_DISPLAY_SDR_WHITE_POINT_FLOAT "SDL.display.SDR_white_point" -#define SDL_PROP_DISPLAY_HDR_HEADROOM_FLOAT "SDL.display.HDR_headroom" +#define SDL_PROP_DISPLAY_HDR_ENABLED_BOOLEAN "SDL.display.HDR_enabled" +#define SDL_PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER "SDL.display.KMSDRM.panel_orientation" /** * Get the name of a display in UTF-8 encoding. * - * \param displayID the instance ID of the display to query + * \param displayID the instance ID of the display to query. * \returns the name of a display or NULL on failure; call SDL_GetError() for * more information. * @@ -367,24 +535,24 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetDisplayProperties(SDL_DisplayID * * \sa SDL_GetDisplays */ -extern DECLSPEC const char *SDLCALL SDL_GetDisplayName(SDL_DisplayID displayID); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetDisplayName(SDL_DisplayID displayID); /** * Get the desktop area represented by a display. * * The primary display is always located at (0,0). * - * \param displayID the instance ID of the display to query - * \param rect the SDL_Rect structure filled in with the display bounds - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param displayID the instance ID of the display to query. + * \param rect the SDL_Rect structure filled in with the display bounds. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplayUsableBounds * \sa SDL_GetDisplays */ -extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Rect *rect); /** * Get the usable desktop area represented by a display, in screen @@ -398,43 +566,43 @@ extern DECLSPEC int SDLCALL SDL_GetDisplayBounds(SDL_DisplayID displayID, SDL_Re * so these are good guidelines for the maximum space available to a * non-fullscreen window. * - * \param displayID the instance ID of the display to query - * \param rect the SDL_Rect structure filled in with the display bounds - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param displayID the instance ID of the display to query. + * \param rect the SDL_Rect structure filled in with the display bounds. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplayBounds * \sa SDL_GetDisplays */ -extern DECLSPEC int SDLCALL SDL_GetDisplayUsableBounds(SDL_DisplayID displayID, SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_GetDisplayUsableBounds(SDL_DisplayID displayID, SDL_Rect *rect); /** * Get the orientation of a display when it is unrotated. * - * \param displayID the instance ID of the display to query - * \returns The SDL_DisplayOrientation enum value of the display, or + * \param displayID the instance ID of the display to query. + * \returns the SDL_DisplayOrientation enum value of the display, or * `SDL_ORIENTATION_UNKNOWN` if it isn't available. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetNaturalDisplayOrientation(SDL_DisplayID displayID); +extern SDL_DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetNaturalDisplayOrientation(SDL_DisplayID displayID); /** * Get the orientation of a display. * - * \param displayID the instance ID of the display to query - * \returns The SDL_DisplayOrientation enum value of the display, or + * \param displayID the instance ID of the display to query. + * \returns the SDL_DisplayOrientation enum value of the display, or * `SDL_ORIENTATION_UNKNOWN` if it isn't available. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetCurrentDisplayOrientation(SDL_DisplayID displayID); +extern SDL_DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetCurrentDisplayOrientation(SDL_DisplayID displayID); /** * Get the content scale of a display. @@ -444,15 +612,15 @@ extern DECLSPEC SDL_DisplayOrientation SDLCALL SDL_GetCurrentDisplayOrientation( * display scale, which means that the user expects UI elements to be twice as * big on this display, to aid in readability. * - * \param displayID the instance ID of the display to query - * \returns The content scale of the display, or 0.0f on error; call - * SDL_GetError() for more details. + * \param displayID the instance ID of the display to query. + * \returns the content scale of the display, or 0.0f on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplays */ -extern DECLSPEC float SDLCALL SDL_GetDisplayContentScale(SDL_DisplayID displayID); +extern SDL_DECLSPEC float SDLCALL SDL_GetDisplayContentScale(SDL_DisplayID displayID); /** * Get a list of fullscreen display modes available on a display. @@ -466,17 +634,19 @@ extern DECLSPEC float SDLCALL SDL_GetDisplayContentScale(SDL_DisplayID displayID * - refresh rate -> highest to lowest * - pixel density -> lowest to highest * - * \param displayID the instance ID of the display to query - * \param count a pointer filled in with the number of displays returned - * \returns a NULL terminated array of display mode pointers which should be - * freed with SDL_free(), or NULL on error; call SDL_GetError() for - * more details. + * \param displayID the instance ID of the display to query. + * \param count a pointer filled in with the number of display modes returned, + * may be NULL. + * \returns a NULL terminated array of display mode pointers or NULL on + * failure; call SDL_GetError() for more information. This is a + * single allocation that should be freed with SDL_free() when it is + * no longer needed. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetDisplays */ -extern DECLSPEC const SDL_DisplayMode **SDLCALL SDL_GetFullscreenDisplayModes(SDL_DisplayID displayID, int *count); +extern SDL_DECLSPEC SDL_DisplayMode ** SDLCALL SDL_GetFullscreenDisplayModes(SDL_DisplayID displayID, int *count); /** * Get the closest match to the requested display mode. @@ -488,15 +658,16 @@ extern DECLSPEC const SDL_DisplayMode **SDLCALL SDL_GetFullscreenDisplayModes(SD * and finally checking the refresh rate. If all the available modes are too * small, then NULL is returned. * - * \param displayID the instance ID of the display to query - * \param w the width in pixels of the desired display mode - * \param h the height in pixels of the desired display mode + * \param displayID the instance ID of the display to query. + * \param w the width in pixels of the desired display mode. + * \param h the height in pixels of the desired display mode. * \param refresh_rate the refresh rate of the desired display mode, or 0.0f - * for the desktop refresh rate - * \param include_high_density_modes Boolean to include high density modes in - * the search - * \returns a pointer to the closest display mode equal to or larger than the - * desired mode, or NULL on error; call SDL_GetError() for more + * for the desktop refresh rate. + * \param include_high_density_modes boolean to include high density modes in + * the search. + * \param mode a pointer filled in with the closest display mode equal to or + * larger than the desired mode. + * \returns true on success or false on failure; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. @@ -504,7 +675,7 @@ extern DECLSPEC const SDL_DisplayMode **SDLCALL SDL_GetFullscreenDisplayModes(SD * \sa SDL_GetDisplays * \sa SDL_GetFullscreenDisplayModes */ -extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetClosestFullscreenDisplayMode(SDL_DisplayID displayID, int w, int h, float refresh_rate, SDL_bool include_high_density_modes); +extern SDL_DECLSPEC bool SDLCALL SDL_GetClosestFullscreenDisplayMode(SDL_DisplayID displayID, int w, int h, float refresh_rate, bool include_high_density_modes, SDL_DisplayMode *mode); /** * Get information about the desktop's display mode. @@ -514,8 +685,8 @@ extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetClosestFullscreenDisplayMo * function will return the previous native display mode, and not the current * display mode. * - * \param displayID the instance ID of the display to query - * \returns a pointer to the desktop display mode or NULL on error; call + * \param displayID the instance ID of the display to query. + * \returns a pointer to the desktop display mode or NULL on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -523,7 +694,7 @@ extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetClosestFullscreenDisplayMo * \sa SDL_GetCurrentDisplayMode * \sa SDL_GetDisplays */ -extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetDesktopDisplayMode(SDL_DisplayID displayID); +extern SDL_DECLSPEC const SDL_DisplayMode * SDLCALL SDL_GetDesktopDisplayMode(SDL_DisplayID displayID); /** * Get information about the current display mode. @@ -533,8 +704,8 @@ extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetDesktopDisplayMode(SDL_Dis * function will return the current display mode, and not the previous native * display mode. * - * \param displayID the instance ID of the display to query - * \returns a pointer to the desktop display mode or NULL on error; call + * \param displayID the instance ID of the display to query. + * \returns a pointer to the desktop display mode or NULL on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. @@ -542,12 +713,12 @@ extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetDesktopDisplayMode(SDL_Dis * \sa SDL_GetDesktopDisplayMode * \sa SDL_GetDisplays */ -extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetCurrentDisplayMode(SDL_DisplayID displayID); +extern SDL_DECLSPEC const SDL_DisplayMode * SDLCALL SDL_GetCurrentDisplayMode(SDL_DisplayID displayID); /** * Get the display containing a point. * - * \param point the point to query + * \param point the point to query. * \returns the instance ID of the display containing the point or 0 on * failure; call SDL_GetError() for more information. * @@ -556,12 +727,12 @@ extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetCurrentDisplayMode(SDL_Dis * \sa SDL_GetDisplayBounds * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForPoint(const SDL_Point *point); +extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForPoint(const SDL_Point *point); /** * Get the display primarily containing a rect. * - * \param rect the rect to query + * \param rect the rect to query. * \returns the instance ID of the display entirely containing the rect or * closest to the center of the rect on success or 0 on failure; call * SDL_GetError() for more information. @@ -571,12 +742,12 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForPoint(const SDL_Point *po * \sa SDL_GetDisplayBounds * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForRect(const SDL_Rect *rect); +extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForRect(const SDL_Rect *rect); /** * Get the display associated with a window. * - * \param window the window to query + * \param window the window to query. * \returns the instance ID of the display containing the center of the window * on success or 0 on failure; call SDL_GetError() for more * information. @@ -586,7 +757,7 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForRect(const SDL_Rect *rect * \sa SDL_GetDisplayBounds * \sa SDL_GetDisplays */ -extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForWindow(SDL_Window *window); +extern SDL_DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForWindow(SDL_Window *window); /** * Get the pixel density of a window. @@ -595,7 +766,7 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForWindow(SDL_Window *window * 1920x1080 and it has a high density back buffer of 3840x2160 pixels, it * would have a pixel density of 2.0. * - * \param window the window to query + * \param window the window to query. * \returns the pixel density or 0.0f on failure; call SDL_GetError() for more * information. * @@ -603,7 +774,7 @@ extern DECLSPEC SDL_DisplayID SDLCALL SDL_GetDisplayForWindow(SDL_Window *window * * \sa SDL_GetWindowDisplayScale */ -extern DECLSPEC float SDLCALL SDL_GetWindowPixelDensity(SDL_Window *window); +extern SDL_DECLSPEC float SDLCALL SDL_GetWindowPixelDensity(SDL_Window *window); /** * Get the content display scale relative to a window's pixel size. @@ -619,13 +790,13 @@ extern DECLSPEC float SDLCALL SDL_GetWindowPixelDensity(SDL_Window *window); * updated when that setting is changed, or the window moves to a display with * a different scale setting. * - * \param window the window to query + * \param window the window to query. * \returns the display scale, or 0.0f on failure; call SDL_GetError() for * more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); +extern SDL_DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); /** * Set the display mode to use when a window is visible and fullscreen. @@ -641,16 +812,16 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * taken effect. * * When the new mode takes effect, an SDL_EVENT_WINDOW_RESIZED and/or an - * SDL_EVENT_WINDOOW_PIXEL_SIZE_CHANGED event will be emitted with the new - * mode dimensions. + * SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event will be emitted with the new mode + * dimensions. * - * \param window the window to affect + * \param window the window to affect. * \param mode a pointer to the display mode to use, which can be NULL for * borderless fullscreen desktop mode, or one of the fullscreen * modes returned by SDL_GetFullscreenDisplayModes() to set an * exclusive fullscreen mode. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -658,47 +829,60 @@ extern DECLSPEC float SDLCALL SDL_GetWindowDisplayScale(SDL_Window *window); * \sa SDL_SetWindowFullscreen * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_SetWindowFullscreenMode(SDL_Window *window, const SDL_DisplayMode *mode); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowFullscreenMode(SDL_Window *window, const SDL_DisplayMode *mode); /** * Query the display mode to use when a window is visible at fullscreen. * - * \param window the window to query + * \param window the window to query. * \returns a pointer to the exclusive fullscreen mode to use or NULL for - * borderless fullscreen desktop mode + * borderless fullscreen desktop mode. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowFullscreenMode * \sa SDL_SetWindowFullscreen */ -extern DECLSPEC const SDL_DisplayMode *SDLCALL SDL_GetWindowFullscreenMode(SDL_Window *window); +extern SDL_DECLSPEC const SDL_DisplayMode * SDLCALL SDL_GetWindowFullscreenMode(SDL_Window *window); /** * Get the raw ICC profile data for the screen the window is currently on. * - * Data returned should be freed with SDL_free. - * - * \param window the window to query - * \param size the size of the ICC profile + * \param window the window to query. + * \param size the size of the ICC profile. * \returns the raw ICC profile data on success or NULL on failure; call - * SDL_GetError() for more information. + * SDL_GetError() for more information. This should be freed with + * SDL_free() when it is no longer needed. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void *SDLCALL SDL_GetWindowICCProfile(SDL_Window *window, size_t *size); +extern SDL_DECLSPEC void * SDLCALL SDL_GetWindowICCProfile(SDL_Window *window, size_t *size); /** * Get the pixel format associated with the window. * - * \param window the window to query + * \param window the window to query. * \returns the pixel format of the window on success or * SDL_PIXELFORMAT_UNKNOWN on failure; call SDL_GetError() for more * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); +extern SDL_DECLSPEC SDL_PixelFormat SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); + +/** + * Get a list of valid windows. + * + * \param count a pointer filled in with the number of windows returned, may + * be NULL. + * \returns a NULL terminated array of SDL_Window pointers or NULL on failure; + * call SDL_GetError() for more information. This is a single + * allocation that should be freed with SDL_free() when it is no + * longer needed. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC SDL_Window ** SDLCALL SDL_GetWindows(int *count); /** * Create a window with the specified dimensions and flags. @@ -707,14 +891,34 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * * - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution * - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context - * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance - * - `SDL_WINDOW_METAL`: window usable with a Metal instance + * - `SDL_WINDOW_OCCLUDED`: window partially or completely obscured by another + * window * - `SDL_WINDOW_HIDDEN`: window is not visible * - `SDL_WINDOW_BORDERLESS`: no window decoration * - `SDL_WINDOW_RESIZABLE`: window can be resized * - `SDL_WINDOW_MINIMIZED`: window is minimized * - `SDL_WINDOW_MAXIMIZED`: window is maximized * - `SDL_WINDOW_MOUSE_GRABBED`: window has grabbed mouse focus + * - `SDL_WINDOW_INPUT_FOCUS`: window has input focus + * - `SDL_WINDOW_MOUSE_FOCUS`: window has mouse focus + * - `SDL_WINDOW_EXTERNAL`: window not created by SDL + * - `SDL_WINDOW_MODAL`: window is modal + * - `SDL_WINDOW_HIGH_PIXEL_DENSITY`: window uses high pixel density back + * buffer if possible + * - `SDL_WINDOW_MOUSE_CAPTURE`: window has mouse captured (unrelated to + * MOUSE_GRABBED) + * - `SDL_WINDOW_ALWAYS_ON_TOP`: window should always be above others + * - `SDL_WINDOW_UTILITY`: window should be treated as a utility window, not + * showing in the task bar and window list + * - `SDL_WINDOW_TOOLTIP`: window should be treated as a tooltip and does not + * get mouse or keyboard focus, requires a parent window + * - `SDL_WINDOW_POPUP_MENU`: window should be treated as a popup menu, + * requires a parent window + * - `SDL_WINDOW_KEYBOARD_GRABBED`: window has grabbed keyboard input + * - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance + * - `SDL_WINDOW_METAL`: window usable with a Metal instance + * - `SDL_WINDOW_TRANSPARENT`: window with transparent buffer + * - `SDL_WINDOW_NOT_FOCUSABLE`: window should not be focusable * * The SDL_Window is implicitly shown if SDL_WINDOW_HIDDEN is not set. * @@ -740,14 +944,18 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * If SDL_WINDOW_METAL is specified on an OS that does not support Metal, * SDL_CreateWindow() will fail. * + * If you intend to use this window with an SDL_Renderer, you should use + * SDL_CreateWindowAndRenderer() instead of this function, to avoid window + * flicker. + * * On non-Apple devices, SDL requires you to either not link to the Vulkan * loader or link to a dynamic library version. This limitation may be removed * in a future version of SDL. * - * \param title the title of the window, in UTF-8 encoding - * \param w the width of the window - * \param h the height of the window - * \param flags 0, or one or more SDL_WindowFlags OR'd together + * \param title the title of the window, in UTF-8 encoding. + * \param w the width of the window. + * \param h the height of the window. + * \param flags 0, or one or more SDL_WindowFlags OR'd together. * \returns the window that was created or NULL on failure; call * SDL_GetError() for more information. * @@ -757,7 +965,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); * \sa SDL_CreateWindowWithProperties * \sa SDL_DestroyWindow */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, int h, SDL_WindowFlags flags); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindow(const char *title, int w, int h, SDL_WindowFlags flags); /** * Create a child popup window of the specified parent window. @@ -793,14 +1001,14 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, i * If the parent window is destroyed, any child popup windows will be * recursively destroyed as well. * - * \param parent the parent of the window, must not be NULL + * \param parent the parent of the window, must not be NULL. * \param offset_x the x position of the popup window relative to the origin - * of the parent + * of the parent. * \param offset_y the y position of the popup window relative to the origin - * of the parent window - * \param w the width of the window - * \param h the height of the window - * \param flags SDL_WINDOW_TOOLTIP or SDL_WINDOW_POPUP MENU, and zero or more + * of the parent window. + * \param w the width of the window. + * \param h the height of the window. + * \param flags SDL_WINDOW_TOOLTIP or SDL_WINDOW_POPUP_MENU, and zero or more * additional SDL_WindowFlags OR'd together. * \returns the window that was created or NULL on failure; call * SDL_GetError() for more information. @@ -812,7 +1020,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, i * \sa SDL_DestroyWindow * \sa SDL_GetWindowParent */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, SDL_WindowFlags flags); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, SDL_WindowFlags flags); /** * Create a window with the specified properties. @@ -841,13 +1049,15 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * with Metal rendering * - `SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN`: true if the window should * start minimized + * - `SDL_PROP_WINDOW_CREATE_MODAL_BOOLEAN`: true if the window is modal to + * its parent * - `SDL_PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN`: true if the window starts * with grabbed mouse focus * - `SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN`: true if the window will be used * with OpenGL rendering * - `SDL_PROP_WINDOW_CREATE_PARENT_POINTER`: an SDL_Window that will be the - * parent of this window, required for windows with the "toolip" and "menu" - * properties + * parent of this window, required for windows with the "toolip", "menu", + * and "modal" properties * - `SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN`: true if the window should be * resizable * - `SDL_PROP_WINDOW_CREATE_TITLE_STRING`: the title of the window, in UTF-8 @@ -877,28 +1087,17 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * * These are additional supported properties on Wayland: * - * - `SDL_PROP_WINDOW_CREATE_WAYLAND_SCALE_TO_DISPLAY_BOOLEAN` - true if the - * window should use forced scaling designed to produce 1:1 pixel mapping if - * not flagged as being DPI-aware. This is intended to allow legacy - * applications to be displayed without desktop scaling being applied, and - * has issues with certain display configurations, as this forces the window - * to behave in a way that Wayland desktops were not designed to - * accommodate. Potential issues include, but are not limited to: rounding - * errors can result when odd window sizes/scales are used, the window may - * be unusably small, the window may jump in visible size at times, the - * window may appear to be larger than the desktop space, and possible loss - * of cursor precision can occur. New applications should be designed with - * proper DPI awareness and handling instead of enabling this. * - `SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN` - true if * the application wants to use the Wayland surface for a custom role and * does not want it attached to an XDG toplevel window. See - * docs/README-wayland.md for more information on using custom surfaces. - * - `SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN - true if the + * [README/wayland](README/wayland) for more information on using custom + * surfaces. + * - `SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN` - true if the * application wants an associated `wl_egl_window` object to be created, * even if the window does not have the OpenGL property or flag set. * - `SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER` - the wl_surface * associated with the window, if you want to wrap an existing window. See - * docs/README-wayland.md for more information. + * [README/wayland](README/wayland) for more information. * * These are additional supported properties on Windows: * @@ -915,9 +1114,19 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * The window is implicitly shown if the "hidden" property is not set. * * Windows with the "tooltip" and "menu" properties are popup windows and have - * the behaviors and guidelines outlined in `SDL_CreatePopupWindow()`. - * - * \param props the properties to use + * the behaviors and guidelines outlined in SDL_CreatePopupWindow(). + * + * If this window is being created to be used with an SDL_Renderer, you should + * not add a graphics API specific property + * (`SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN`, etc), as SDL will handle that + * internally when it chooses a renderer. However, SDL might need to recreate + * your window at that point, which may cause the window to appear briefly, + * and then flicker as it is recreated. The correct approach to this is to + * create the window with the `SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN` property + * set to true, then create the renderer, then show the window with + * SDL_ShowWindow(). + * + * \param props the properties to use. * \returns the window that was created or NULL on failure; call * SDL_GetError() for more information. * @@ -927,41 +1136,42 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreatePopupWindow(SDL_Window *parent, in * \sa SDL_CreateWindow * \sa SDL_DestroyWindow */ -extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); - -#define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "always_on_top" -#define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "borderless" -#define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "focusable" -#define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "external_graphics_context" -#define SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN "fullscreen" -#define SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER "height" -#define SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN "hidden" -#define SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "high_pixel_density" -#define SDL_PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN "maximized" -#define SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN "menu" -#define SDL_PROP_WINDOW_CREATE_METAL_BOOLEAN "metal" -#define SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN "minimized" -#define SDL_PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "mouse_grabbed" -#define SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN "opengl" -#define SDL_PROP_WINDOW_CREATE_PARENT_POINTER "parent" -#define SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN "resizable" -#define SDL_PROP_WINDOW_CREATE_TITLE_STRING "title" -#define SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN "transparent" -#define SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN "tooltip" -#define SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN "utility" -#define SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN "vulkan" -#define SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER "width" -#define SDL_PROP_WINDOW_CREATE_X_NUMBER "x" -#define SDL_PROP_WINDOW_CREATE_Y_NUMBER "y" -#define SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER "cocoa.window" -#define SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER "cocoa.view" -#define SDL_PROP_WINDOW_CREATE_WAYLAND_SCALE_TO_DISPLAY_BOOLEAN "wayland.scale_to_display" -#define SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "wayland.surface_role_custom" -#define SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "wayland.create_egl_window" -#define SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER "wayland.wl_surface" -#define SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER "win32.hwnd" -#define SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "win32.pixel_format_hwnd" -#define SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER "x11.window" +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_CreateWindowWithProperties(SDL_PropertiesID props); + +#define SDL_PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN "SDL.window.create.always_on_top" +#define SDL_PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN "SDL.window.create.borderless" +#define SDL_PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN "SDL.window.create.focusable" +#define SDL_PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN "SDL.window.create.external_graphics_context" +#define SDL_PROP_WINDOW_CREATE_FLAGS_NUMBER "SDL.window.create.flags" +#define SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN "SDL.window.create.fullscreen" +#define SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER "SDL.window.create.height" +#define SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN "SDL.window.create.hidden" +#define SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN "SDL.window.create.high_pixel_density" +#define SDL_PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN "SDL.window.create.maximized" +#define SDL_PROP_WINDOW_CREATE_MENU_BOOLEAN "SDL.window.create.menu" +#define SDL_PROP_WINDOW_CREATE_METAL_BOOLEAN "SDL.window.create.metal" +#define SDL_PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN "SDL.window.create.minimized" +#define SDL_PROP_WINDOW_CREATE_MODAL_BOOLEAN "SDL.window.create.modal" +#define SDL_PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN "SDL.window.create.mouse_grabbed" +#define SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN "SDL.window.create.opengl" +#define SDL_PROP_WINDOW_CREATE_PARENT_POINTER "SDL.window.create.parent" +#define SDL_PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN "SDL.window.create.resizable" +#define SDL_PROP_WINDOW_CREATE_TITLE_STRING "SDL.window.create.title" +#define SDL_PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN "SDL.window.create.transparent" +#define SDL_PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN "SDL.window.create.tooltip" +#define SDL_PROP_WINDOW_CREATE_UTILITY_BOOLEAN "SDL.window.create.utility" +#define SDL_PROP_WINDOW_CREATE_VULKAN_BOOLEAN "SDL.window.create.vulkan" +#define SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER "SDL.window.create.width" +#define SDL_PROP_WINDOW_CREATE_X_NUMBER "SDL.window.create.x" +#define SDL_PROP_WINDOW_CREATE_Y_NUMBER "SDL.window.create.y" +#define SDL_PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER "SDL.window.create.cocoa.window" +#define SDL_PROP_WINDOW_CREATE_COCOA_VIEW_POINTER "SDL.window.create.cocoa.view" +#define SDL_PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN "SDL.window.create.wayland.surface_role_custom" +#define SDL_PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN "SDL.window.create.wayland.create_egl_window" +#define SDL_PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER "SDL.window.create.wayland.wl_surface" +#define SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER "SDL.window.create.win32.hwnd" +#define SDL_PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER "SDL.window.create.win32.pixel_format_hwnd" +#define SDL_PROP_WINDOW_CREATE_X11_WINDOW_NUMBER "SDL.window.create.x11.window" /** * Get the numeric ID of a window. @@ -969,7 +1179,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_Propertie * The numeric ID is what SDL_WindowEvent references, and is necessary to map * these events to specific SDL_Window objects. * - * \param window the window to query + * \param window the window to query. * \returns the ID of the window on success or 0 on failure; call * SDL_GetError() for more information. * @@ -977,7 +1187,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithProperties(SDL_Propertie * * \sa SDL_GetWindowFromID */ -extern DECLSPEC SDL_WindowID SDLCALL SDL_GetWindowID(SDL_Window *window); +extern SDL_DECLSPEC SDL_WindowID SDLCALL SDL_GetWindowID(SDL_Window *window); /** * Get a window from a stored ID. @@ -985,7 +1195,7 @@ extern DECLSPEC SDL_WindowID SDLCALL SDL_GetWindowID(SDL_Window *window); * The numeric ID is what SDL_WindowEvent references, and is necessary to map * these events to specific SDL_Window objects. * - * \param id the ID of the window + * \param id the ID of the window. * \returns the window associated with `id` or NULL if it doesn't exist; call * SDL_GetError() for more information. * @@ -993,12 +1203,12 @@ extern DECLSPEC SDL_WindowID SDLCALL SDL_GetWindowID(SDL_Window *window); * * \sa SDL_GetWindowID */ -extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowFromID(SDL_WindowID id); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowFromID(SDL_WindowID id); /** * Get parent of a window. * - * \param window the window to query + * \param window the window to query. * \returns the parent of the window on success or NULL if the window has no * parent. * @@ -1006,7 +1216,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowFromID(SDL_WindowID id); * * \sa SDL_CreatePopupWindow */ -extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetWindowParent(SDL_Window *window); /** * Get the properties associated with a window. @@ -1015,6 +1225,18 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * * - `SDL_PROP_WINDOW_SHAPE_POINTER`: the surface associated with a shaped * window + * - `SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN`: true if the window has HDR + * headroom above the SDR white point. This property can change dynamically + * when SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent. + * - `SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT`: the value of SDR white in the + * SDL_COLORSPACE_SRGB_LINEAR colorspace. On Windows this corresponds to the + * SDR white level in scRGB colorspace, and on Apple platforms this is + * always 1.0 for EDR content. This property can change dynamically when + * SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent. + * - `SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT`: the additional high dynamic range + * that can be displayed, in terms of the SDR white point. When HDR is not + * enabled, this will be 1.0. This property can change dynamically when + * SDL_EVENT_WINDOW_HDR_STATE_CHANGED is sent. * * On Android: * @@ -1029,6 +1251,13 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * UIWindow associated with the window * - `SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER`: the NSInteger tag * assocated with metal views on the window + * - `SDL_PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER`: the OpenGL view's + * framebuffer object. It must be bound when rendering to the screen using + * OpenGL. + * - `SDL_PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER`: the OpenGL view's + * renderbuffer object. It must be bound when SDL_GL_SwapWindow is called. + * - `SDL_PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER`: the OpenGL + * view's resolve framebuffer, when MSAA is used. * * On KMS/DRM: * @@ -1055,11 +1284,6 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * - `SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER`: the EGLSurface associated with * the window * - * On UWP: - * - * - `SDL_PROP_WINDOW_WINRT_WINDOW_POINTER`: the IInspectable CoreWindow - * associated with the window - * * On Windows: * * - `SDL_PROP_WINDOW_WIN32_HWND_POINTER`: the HWND associated with the window @@ -1099,51 +1323,53 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetWindowParent(SDL_Window *window); * - `SDL_PROP_WINDOW_X11_WINDOW_NUMBER`: the X11 Window associated with the * window * - * \param window the window to query + * \param window the window to query. * \returns a valid property ID on success or 0 on failure; call * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. - * - * \sa SDL_GetProperty - * \sa SDL_SetProperty - */ -extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); - -#define SDL_PROP_WINDOW_SHAPE_POINTER "SDL.window.shape" -#define SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" -#define SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" -#define SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" -#define SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" -#define SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" -#define SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" -#define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" -#define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" -#define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" -#define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" -#define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" -#define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" -#define SDL_PROP_WINDOW_WINRT_WINDOW_POINTER "SDL.window.winrt.window" -#define SDL_PROP_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" -#define SDL_PROP_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" -#define SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" -#define SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" -#define SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" -#define SDL_PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" -#define SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" -#define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" -#define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_STRING "SDL.window.wayland.xdg_toplevel_export_handle" -#define SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" -#define SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" -#define SDL_PROP_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" -#define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" -#define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" + */ +extern SDL_DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *window); + +#define SDL_PROP_WINDOW_SHAPE_POINTER "SDL.window.shape" +#define SDL_PROP_WINDOW_HDR_ENABLED_BOOLEAN "SDL.window.HDR_enabled" +#define SDL_PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT "SDL.window.SDR_white_level" +#define SDL_PROP_WINDOW_HDR_HEADROOM_FLOAT "SDL.window.HDR_headroom" +#define SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER "SDL.window.android.window" +#define SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER "SDL.window.android.surface" +#define SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER "SDL.window.uikit.window" +#define SDL_PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER "SDL.window.uikit.metal_view_tag" +#define SDL_PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER "SDL.window.uikit.opengl.framebuffer" +#define SDL_PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER "SDL.window.uikit.opengl.renderbuffer" +#define SDL_PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER "SDL.window.uikit.opengl.resolve_framebuffer" +#define SDL_PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER "SDL.window.kmsdrm.dev_index" +#define SDL_PROP_WINDOW_KMSDRM_DRM_FD_NUMBER "SDL.window.kmsdrm.drm_fd" +#define SDL_PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER "SDL.window.kmsdrm.gbm_dev" +#define SDL_PROP_WINDOW_COCOA_WINDOW_POINTER "SDL.window.cocoa.window" +#define SDL_PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER "SDL.window.cocoa.metal_view_tag" +#define SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER "SDL.window.vivante.display" +#define SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER "SDL.window.vivante.window" +#define SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER "SDL.window.vivante.surface" +#define SDL_PROP_WINDOW_WIN32_HWND_POINTER "SDL.window.win32.hwnd" +#define SDL_PROP_WINDOW_WIN32_HDC_POINTER "SDL.window.win32.hdc" +#define SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER "SDL.window.win32.instance" +#define SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER "SDL.window.wayland.display" +#define SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER "SDL.window.wayland.surface" +#define SDL_PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER "SDL.window.wayland.egl_window" +#define SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER "SDL.window.wayland.xdg_surface" +#define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER "SDL.window.wayland.xdg_toplevel" +#define SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_STRING "SDL.window.wayland.xdg_toplevel_export_handle" +#define SDL_PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER "SDL.window.wayland.xdg_popup" +#define SDL_PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER "SDL.window.wayland.xdg_positioner" +#define SDL_PROP_WINDOW_X11_DISPLAY_POINTER "SDL.window.x11.display" +#define SDL_PROP_WINDOW_X11_SCREEN_NUMBER "SDL.window.x11.screen" +#define SDL_PROP_WINDOW_X11_WINDOW_NUMBER "SDL.window.x11.window" /** * Get the window flags. * - * \param window the window to query - * \returns a mask of the SDL_WindowFlags associated with `window` + * \param window the window to query. + * \returns a mask of the SDL_WindowFlags associated with `window`. * * \since This function is available since SDL 3.0.0. * @@ -1155,28 +1381,28 @@ extern DECLSPEC SDL_PropertiesID SDLCALL SDL_GetWindowProperties(SDL_Window *win * \sa SDL_SetWindowMouseGrab * \sa SDL_ShowWindow */ -extern DECLSPEC SDL_WindowFlags SDLCALL SDL_GetWindowFlags(SDL_Window *window); +extern SDL_DECLSPEC SDL_WindowFlags SDLCALL SDL_GetWindowFlags(SDL_Window *window); /** * Set the title of a window. * * This string is expected to be in UTF-8 encoding. * - * \param window the window to change - * \param title the desired window title in UTF-8 format - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param title the desired window title in UTF-8 format. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowTitle */ -extern DECLSPEC int SDLCALL SDL_SetWindowTitle(SDL_Window *window, const char *title); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowTitle(SDL_Window *window, const char *title); /** * Get the title of a window. * - * \param window the window to query + * \param window the window to query. * \returns the title of the window in UTF-8 format or "" if there is no * title. * @@ -1184,19 +1410,29 @@ extern DECLSPEC int SDLCALL SDL_SetWindowTitle(SDL_Window *window, const char *t * * \sa SDL_SetWindowTitle */ -extern DECLSPEC const char *SDLCALL SDL_GetWindowTitle(SDL_Window *window); +extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window); /** * Set the icon for a window. * - * \param window the window to change - * \param icon an SDL_Surface structure containing the icon for the window - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * If this function is passed a surface with alternate representations, the + * surface will be interpreted as the content to be used for 100% display + * scale, and the alternate representations will be used for high DPI + * situations. For example, if the original surface is 32x32, then on a 2x + * macOS display or 200% display scale on Windows, a 64x64 version of the + * image will be used, if available. If a matching version of the image isn't + * available, the closest larger size image will be downscaled to the + * appropriate size and be used instead, if available. Otherwise, the closest + * smaller image will be upscaled and be used instead. + * + * \param window the window to change. + * \param icon an SDL_Surface structure containing the icon for the window. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); /** * Request that the window's position be set. @@ -1223,20 +1459,20 @@ extern DECLSPEC int SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *i * Additionally, as this is just a request, it can be denied by the windowing * system. * - * \param window the window to reposition + * \param window the window to reposition. * \param x the x coordinate of the window, or `SDL_WINDOWPOS_CENTERED` or - * `SDL_WINDOWPOS_UNDEFINED` + * `SDL_WINDOWPOS_UNDEFINED`. * \param y the y coordinate of the window, or `SDL_WINDOWPOS_CENTERED` or - * `SDL_WINDOWPOS_UNDEFINED` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * `SDL_WINDOWPOS_UNDEFINED`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowPosition * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int y); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int y); /** * Get the position of a window. @@ -1247,24 +1483,23 @@ extern DECLSPEC int SDLCALL SDL_SetWindowPosition(SDL_Window *window, int x, int * If you do not need the value for one of the positions a NULL may be passed * in the `x` or `y` parameter. * - * \param window the window to query - * \param x a pointer filled in with the x position of the window, may be NULL - * \param y a pointer filled in with the y position of the window, may be NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to query. + * \param x a pointer filled in with the x position of the window, may be + * NULL. + * \param y a pointer filled in with the y position of the window, may be + * NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowPosition */ -extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, int *y); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, int *y); /** * Request that the size of a window's client area be set. * - * NULL can safely be passed as the `w` or `h` parameter if the width or - * height value is not desired. - * * If, at the time of this request, the window in a fixed-size state, such as * maximized or fullscreen, the request will be deferred until the window * exits this state and becomes resizable again. @@ -1284,11 +1519,11 @@ extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, in * content area to remain within the usable desktop bounds). Additionally, as * this is just a request, it can be denied by the windowing system. * - * \param window the window to change - * \param w the width of the window, must be > 0 - * \param h the height of the window, must be > 0 - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param w the width of the window, must be > 0. + * \param h the height of the window, must be > 0. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1296,23 +1531,20 @@ extern DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x, in * \sa SDL_SetWindowFullscreenMode * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h); /** * Get the size of a window's client area. * - * NULL can safely be passed as the `w` or `h` parameter if the width or - * height value is not desired. - * * The window pixel size may differ from its window coordinate size if the * window is on a high pixel density display. Use SDL_GetWindowSizeInPixels() * or SDL_GetRenderOutputSize() to get the real client area size in pixels. * - * \param window the window to query the width and height from - * \param w a pointer filled in with the width of the window, may be NULL - * \param h a pointer filled in with the height of the window, may be NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to query the width and height from. + * \param w a pointer filled in with the width of the window, may be NULL. + * \param h a pointer filled in with the height of the window, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1320,12 +1552,88 @@ extern DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int h); * \sa SDL_GetWindowSizeInPixels * \sa SDL_SetWindowSize */ -extern DECLSPEC int SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h); + +/** + * Get the safe area for this window. + * + * Some devices have portions of the screen which are partially obscured or + * not interactive, possibly due to on-screen controls, curved edges, camera + * notches, TV overscan, etc. This function provides the area of the window + * which is safe to have interactible content. You should continue rendering + * into the rest of the window, but it should not contain visually important + * or interactible content. + * + * \param window the window to query. + * \param rect a pointer filled in with the client area that is safe for + * interactive content. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSafeArea(SDL_Window *window, SDL_Rect *rect); + +/** + * Request that the aspect ratio of a window's client area be set. + * + * The aspect ratio is the ratio of width divided by height, e.g. 2560x1600 + * would be 1.6. Larger aspect ratios are wider and smaller aspect ratios are + * narrower. + * + * If, at the time of this request, the window in a fixed-size state, such as + * maximized or fullscreen, the request will be deferred until the window + * exits this state and becomes resizable again. + * + * On some windowing systems, this request is asynchronous and the new window + * aspect ratio may not have have been applied immediately upon the return of + * this function. If an immediate change is required, call SDL_SyncWindow() to + * block until the changes have taken effect. + * + * When the window size changes, an SDL_EVENT_WINDOW_RESIZED event will be + * emitted with the new window dimensions. Note that the new dimensions may + * not match the exact aspect ratio requested, as some windowing systems can + * restrict the window size in certain scenarios (e.g. constraining the size + * of the content area to remain within the usable desktop bounds). + * Additionally, as this is just a request, it can be denied by the windowing + * system. + * + * \param window the window to change. + * \param min_aspect the minimum aspect ratio of the window, or 0.0f for no + * limit. + * \param max_aspect the maximum aspect ratio of the window, or 0.0f for no + * limit. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetWindowAspectRatio + * \sa SDL_SyncWindow + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAspectRatio(SDL_Window *window, float min_aspect, float max_aspect); + +/** + * Get the size of a window's client area. + * + * \param window the window to query the width and height from. + * \param min_aspect a pointer filled in with the minimum aspect ratio of the + * window, may be NULL. + * \param max_aspect a pointer filled in with the maximum aspect ratio of the + * window, may be NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetWindowAspectRatio + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowAspectRatio(SDL_Window *window, float *min_aspect, float *max_aspect); /** * Get the size of a window's borders (decorations) around the client area. * - * Note: If this function fails (returns -1), the size values will be + * Note: If this function fails (returns false), the size values will be * initialized to 0, 0, 0, 0 (if a non-NULL pointer is provided), as if the * window in question was borderless. * @@ -1335,111 +1643,113 @@ extern DECLSPEC int SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h * window has been presented and composited, so that the window system has a * chance to decorate the window and provide the border dimensions to SDL. * - * This function also returns -1 if getting the information is not supported. + * This function also returns false if getting the information is not + * supported. * * \param window the window to query the size values of the border - * (decorations) from + * (decorations) from. * \param top pointer to variable for storing the size of the top border; NULL - * is permitted + * is permitted. * \param left pointer to variable for storing the size of the left border; - * NULL is permitted + * NULL is permitted. * \param bottom pointer to variable for storing the size of the bottom - * border; NULL is permitted + * border; NULL is permitted. * \param right pointer to variable for storing the size of the right border; - * NULL is permitted - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * NULL is permitted. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSize */ -extern DECLSPEC int SDLCALL SDL_GetWindowBordersSize(SDL_Window *window, int *top, int *left, int *bottom, int *right); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowBordersSize(SDL_Window *window, int *top, int *left, int *bottom, int *right); /** * Get the size of a window's client area, in pixels. * - * \param window the window from which the drawable size should be queried - * \param w a pointer to variable for storing the width in pixels, may be NULL + * \param window the window from which the drawable size should be queried. + * \param w a pointer to variable for storing the width in pixels, may be + * NULL. * \param h a pointer to variable for storing the height in pixels, may be - * NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_CreateWindow * \sa SDL_GetWindowSize */ -extern DECLSPEC int SDLCALL SDL_GetWindowSizeInPixels(SDL_Window *window, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSizeInPixels(SDL_Window *window, int *w, int *h); /** * Set the minimum size of a window's client area. * - * \param window the window to change - * \param min_w the minimum width of the window, or 0 for no limit - * \param min_h the minimum height of the window, or 0 for no limit - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param min_w the minimum width of the window, or 0 for no limit. + * \param min_h the minimum height of the window, or 0 for no limit. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMinimumSize * \sa SDL_SetWindowMaximumSize */ -extern DECLSPEC int SDLCALL SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowMinimumSize(SDL_Window *window, int min_w, int min_h); /** * Get the minimum size of a window's client area. * - * \param window the window to query + * \param window the window to query. * \param w a pointer filled in with the minimum width of the window, may be - * NULL + * NULL. * \param h a pointer filled in with the minimum height of the window, may be - * NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMaximumSize * \sa SDL_SetWindowMinimumSize */ -extern DECLSPEC int SDLCALL SDL_GetWindowMinimumSize(SDL_Window *window, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowMinimumSize(SDL_Window *window, int *w, int *h); /** * Set the maximum size of a window's client area. * - * \param window the window to change - * \param max_w the maximum width of the window, or 0 for no limit - * \param max_h the maximum height of the window, or 0 for no limit - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param max_w the maximum width of the window, or 0 for no limit. + * \param max_h the maximum height of the window, or 0 for no limit. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMaximumSize * \sa SDL_SetWindowMinimumSize */ -extern DECLSPEC int SDLCALL SDL_SetWindowMaximumSize(SDL_Window *window, int max_w, int max_h); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowMaximumSize(SDL_Window *window, int max_w, int max_h); /** * Get the maximum size of a window's client area. * - * \param window the window to query + * \param window the window to query. * \param w a pointer filled in with the maximum width of the window, may be - * NULL + * NULL. * \param h a pointer filled in with the maximum height of the window, may be - * NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMinimumSize * \sa SDL_SetWindowMaximumSize */ -extern DECLSPEC int SDLCALL SDL_GetWindowMaximumSize(SDL_Window *window, int *w, int *h); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowMaximumSize(SDL_Window *window, int *w, int *h); /** * Set the border state of a window. @@ -1450,16 +1760,16 @@ extern DECLSPEC int SDLCALL SDL_GetWindowMaximumSize(SDL_Window *window, int *w, * * You can't change the border state of a fullscreen window. * - * \param window the window of which to change the border state - * \param bordered SDL_FALSE to remove border, SDL_TRUE to add border - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window of which to change the border state. + * \param bordered false to remove border, true to add border. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowFlags */ -extern DECLSPEC int SDLCALL SDL_SetWindowBordered(SDL_Window *window, SDL_bool bordered); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowBordered(SDL_Window *window, bool bordered); /** * Set the user-resizable state of a window. @@ -1470,16 +1780,16 @@ extern DECLSPEC int SDLCALL SDL_SetWindowBordered(SDL_Window *window, SDL_bool b * * You can't change the resizable state of a fullscreen window. * - * \param window the window of which to change the resizable state - * \param resizable SDL_TRUE to allow resizing, SDL_FALSE to disallow - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window of which to change the resizable state. + * \param resizable true to allow resizing, false to disallow. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowFlags */ -extern DECLSPEC int SDLCALL SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowResizable(SDL_Window *window, bool resizable); /** * Set the window to always be above the others. @@ -1487,55 +1797,61 @@ extern DECLSPEC int SDLCALL SDL_SetWindowResizable(SDL_Window *window, SDL_bool * This will add or remove the window's `SDL_WINDOW_ALWAYS_ON_TOP` flag. This * will bring the window to the front and keep the window above the rest. * - * \param window The window of which to change the always on top state - * \param on_top SDL_TRUE to set the window always on top, SDL_FALSE to - * disable - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window of which to change the always on top state. + * \param on_top true to set the window always on top, false to disable. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowFlags */ -extern DECLSPEC int SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window *window, SDL_bool on_top); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowAlwaysOnTop(SDL_Window *window, bool on_top); /** * Show a window. * - * \param window the window to show - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to show. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_HideWindow * \sa SDL_RaiseWindow */ -extern DECLSPEC int SDLCALL SDL_ShowWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowWindow(SDL_Window *window); /** * Hide a window. * - * \param window the window to hide - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to hide. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_ShowWindow */ -extern DECLSPEC int SDLCALL SDL_HideWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_HideWindow(SDL_Window *window); /** - * Raise a window above other windows and set the input focus. + * Request that a window be raised above other windows and gain the input + * focus. * - * \param window the window to raise - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * The result of this request is subject to desktop window manager policy, + * particularly if raising the requested window would result in stealing focus + * from another application. If the window is successfully raised and gains + * input focus, an SDL_EVENT_WINDOW_FOCUS_GAINED event will be emitted, and + * the window will have the SDL_WINDOW_INPUT_FOCUS flag set. + * + * \param window the window to raise. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_RaiseWindow(SDL_Window *window); /** * Request that the window be made as large as possible. @@ -1557,9 +1873,9 @@ extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); * manager. Win32 and macOS enforce the constraints when maximizing, while X11 * and Wayland window managers may vary. * - * \param window the window to maximize - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to maximize. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1567,7 +1883,7 @@ extern DECLSPEC int SDLCALL SDL_RaiseWindow(SDL_Window *window); * \sa SDL_RestoreWindow * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_MaximizeWindow(SDL_Window *window); /** * Request that the window be minimized to an iconic representation. @@ -1581,9 +1897,9 @@ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); * emitted. Note that, as this is just a request, the windowing system can * deny the state change. * - * \param window the window to minimize - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to minimize. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1591,7 +1907,7 @@ extern DECLSPEC int SDLCALL SDL_MaximizeWindow(SDL_Window *window); * \sa SDL_RestoreWindow * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_MinimizeWindow(SDL_Window *window); /** * Request that the size and position of a minimized or maximized window be @@ -1606,9 +1922,9 @@ extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); * emitted. Note that, as this is just a request, the windowing system can * deny the state change. * - * \param window the window to restore - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to restore. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1616,7 +1932,7 @@ extern DECLSPEC int SDLCALL SDL_MinimizeWindow(SDL_Window *window); * \sa SDL_MinimizeWindow * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_RestoreWindow(SDL_Window *window); /** * Request that the window's fullscreen state be changed. @@ -1634,10 +1950,10 @@ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); * SDL_EVENT_WINDOW_LEAVE_FULLSCREEN event will be emitted. Note that, as this * is just a request, it can be denied by the windowing system. * - * \param window the window to change - * \param fullscreen SDL_TRUE for fullscreen mode, SDL_FALSE for windowed mode - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \param fullscreen true for fullscreen mode, false for windowed mode. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * @@ -1645,7 +1961,7 @@ extern DECLSPEC int SDLCALL SDL_RestoreWindow(SDL_Window *window); * \sa SDL_SetWindowFullscreenMode * \sa SDL_SyncWindow */ -extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool fullscreen); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, bool fullscreen); /** * Block until any pending window state is finalized. @@ -1660,10 +1976,9 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool * On windowing systems where changes are immediate, this does nothing. * * \param window the window for which to wait for the pending state to be - * applied - * \returns 0 on success, a positive value if the operation timed out before - * the window was in the requested state, or a negative error code on - * failure; call SDL_GetError() for more information. + * applied. + * \returns true on success or false if the operation timed out before the + * window was in the requested state. * * \since This function is available since SDL 3.0.0. * @@ -1673,21 +1988,22 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFullscreen(SDL_Window *window, SDL_bool * \sa SDL_MinimizeWindow * \sa SDL_MaximizeWindow * \sa SDL_RestoreWindow + * \sa SDL_HINT_VIDEO_SYNC_WINDOW_OPERATIONS */ -extern DECLSPEC int SDLCALL SDL_SyncWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_SyncWindow(SDL_Window *window); /** * Return whether the window has a surface associated with it. * - * \param window the window to query - * \returns SDL_TRUE if there is a surface associated with the window, or - * SDL_FALSE otherwise. + * \param window the window to query. + * \returns true if there is a surface associated with the window, or false + * otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSurface */ -extern DECLSPEC SDL_bool SDLCALL SDL_WindowHasSurface(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_WindowHasSurface(SDL_Window *window); /** * Get the SDL surface associated with the window. @@ -1703,7 +2019,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WindowHasSurface(SDL_Window *window); * * This function is affected by `SDL_HINT_FRAMEBUFFER_ACCELERATION`. * - * \param window the window to query + * \param window the window to query. * \returns the surface associated with the window, or NULL on failure; call * SDL_GetError() for more information. * @@ -1714,7 +2030,49 @@ extern DECLSPEC SDL_bool SDLCALL SDL_WindowHasSurface(SDL_Window *window); * \sa SDL_UpdateWindowSurface * \sa SDL_UpdateWindowSurfaceRects */ -extern DECLSPEC SDL_Surface *SDLCALL SDL_GetWindowSurface(SDL_Window *window); +extern SDL_DECLSPEC SDL_Surface * SDLCALL SDL_GetWindowSurface(SDL_Window *window); + +/** + * Toggle VSync for the window surface. + * + * When a window surface is created, vsync defaults to + * SDL_WINDOW_SURFACE_VSYNC_DISABLED. + * + * The `vsync` parameter can be 1 to synchronize present with every vertical + * refresh, 2 to synchronize present with every second vertical refresh, etc., + * SDL_WINDOW_SURFACE_VSYNC_ADAPTIVE for late swap tearing (adaptive vsync), + * or SDL_WINDOW_SURFACE_VSYNC_DISABLED to disable. Not every value is + * supported by every driver, so you should check the return value to see + * whether the requested setting is supported. + * + * \param window the window. + * \param vsync the vertical refresh sync interval. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_GetWindowSurfaceVSync + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowSurfaceVSync(SDL_Window *window, int vsync); + +#define SDL_WINDOW_SURFACE_VSYNC_DISABLED 0 +#define SDL_WINDOW_SURFACE_VSYNC_ADAPTIVE (-1) + +/** + * Get VSync for the window surface. + * + * \param window the window to query. + * \param vsync an int filled with the current vertical refresh sync interval. + * See SDL_SetWindowSurfaceVSync() for the meaning of the value. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetWindowSurfaceVSync + */ +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowSurfaceVSync(SDL_Window *window, int *vsync); /** * Copy the window surface to the screen. @@ -1724,16 +2082,16 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_GetWindowSurface(SDL_Window *window); * * This function is equivalent to the SDL 1.2 API SDL_Flip(). * - * \param window the window to update - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to update. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSurface * \sa SDL_UpdateWindowSurfaceRects */ -extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateWindowSurface(SDL_Window *window); /** * Copy areas of the window surface to the screen. @@ -1748,33 +2106,33 @@ extern DECLSPEC int SDLCALL SDL_UpdateWindowSurface(SDL_Window *window); * update more of the screen (or all of the screen!), depending on what method * SDL uses to send pixels to the system. * - * \param window the window to update + * \param window the window to update. * \param rects an array of SDL_Rect structures representing areas of the - * surface to copy, in pixels - * \param numrects the number of rectangles - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * surface to copy, in pixels. + * \param numrects the number of rectangles. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSurface * \sa SDL_UpdateWindowSurface */ -extern DECLSPEC int SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window *window, const SDL_Rect *rects, int numrects); +extern SDL_DECLSPEC bool SDLCALL SDL_UpdateWindowSurfaceRects(SDL_Window *window, const SDL_Rect *rects, int numrects); /** * Destroy the surface associated with the window. * - * \param window the window to update - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to update. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowSurface * \sa SDL_WindowHasSurface */ -extern DECLSPEC int SDLCALL SDL_DestroyWindowSurface(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_DestroyWindowSurface(SDL_Window *window); /** * Set a window's keyboard grab mode. @@ -1795,58 +2153,58 @@ extern DECLSPEC int SDLCALL SDL_DestroyWindowSurface(SDL_Window *window); * If the caller enables a grab while another window is currently grabbed, the * other window loses its grab in favor of the caller's window. * - * \param window The window for which the keyboard grab mode should be set. - * \param grabbed This is SDL_TRUE to grab keyboard, and SDL_FALSE to release. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window for which the keyboard grab mode should be set. + * \param grabbed this is true to grab keyboard, and false to release. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowKeyboardGrab * \sa SDL_SetWindowMouseGrab */ -extern DECLSPEC int SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window *window, SDL_bool grabbed); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowKeyboardGrab(SDL_Window *window, bool grabbed); /** * Set a window's mouse grab mode. * * Mouse grab confines the mouse cursor to the window. * - * \param window The window for which the mouse grab mode should be set. - * \param grabbed This is SDL_TRUE to grab mouse, and SDL_FALSE to release. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window for which the mouse grab mode should be set. + * \param grabbed this is true to grab mouse, and false to release. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMouseGrab * \sa SDL_SetWindowKeyboardGrab */ -extern DECLSPEC int SDLCALL SDL_SetWindowMouseGrab(SDL_Window *window, SDL_bool grabbed); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowMouseGrab(SDL_Window *window, bool grabbed); /** * Get a window's keyboard grab mode. * - * \param window the window to query - * \returns SDL_TRUE if keyboard is grabbed, and SDL_FALSE otherwise. + * \param window the window to query. + * \returns true if keyboard is grabbed, and false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowKeyboardGrab */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowKeyboardGrab(SDL_Window *window); /** * Get a window's mouse grab mode. * - * \param window the window to query - * \returns SDL_TRUE if mouse is grabbed, and SDL_FALSE otherwise. + * \param window the window to query. + * \returns true if mouse is grabbed, and false otherwise. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowKeyboardGrab */ -extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window *window); /** * Get the window that currently has an input grab enabled. @@ -1858,7 +2216,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GetWindowMouseGrab(SDL_Window *window); * \sa SDL_SetWindowMouseGrab * \sa SDL_SetWindowKeyboardGrab */ -extern DECLSPEC SDL_Window *SDLCALL SDL_GetGrabbedWindow(void); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetGrabbedWindow(void); /** * Confines the cursor to the specified area of a window. @@ -1866,31 +2224,31 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GetGrabbedWindow(void); * Note that this does NOT grab the cursor, it only defines the area a cursor * is restricted to when the window has mouse focus. * - * \param window The window that will be associated with the barrier. - * \param rect A rectangle area in window-relative coordinates. If NULL the + * \param window the window that will be associated with the barrier. + * \param rect a rectangle area in window-relative coordinates. If NULL the * barrier for the specified window will be destroyed. - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowMouseRect * \sa SDL_SetWindowMouseGrab */ -extern DECLSPEC int SDLCALL SDL_SetWindowMouseRect(SDL_Window *window, const SDL_Rect *rect); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowMouseRect(SDL_Window *window, const SDL_Rect *rect); /** * Get the mouse confinement rectangle of a window. * - * \param window The window to query - * \returns A pointer to the mouse confinement rectangle of a window, or NULL + * \param window the window to query. + * \returns a pointer to the mouse confinement rectangle of a window, or NULL * if there isn't one. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowMouseRect */ -extern DECLSPEC const SDL_Rect *SDLCALL SDL_GetWindowMouseRect(SDL_Window *window); +extern SDL_DECLSPEC const SDL_Rect * SDLCALL SDL_GetWindowMouseRect(SDL_Window *window); /** * Set the opacity for a window. @@ -1898,81 +2256,88 @@ extern DECLSPEC const SDL_Rect *SDLCALL SDL_GetWindowMouseRect(SDL_Window *windo * The parameter `opacity` will be clamped internally between 0.0f * (transparent) and 1.0f (opaque). * - * This function also returns -1 if setting the opacity isn't supported. + * This function also returns false if setting the opacity isn't supported. * - * \param window the window which will be made transparent or opaque - * \param opacity the opacity value (0.0f - transparent, 1.0f - opaque) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window which will be made transparent or opaque. + * \param opacity the opacity value (0.0f - transparent, 1.0f - opaque). + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GetWindowOpacity */ -extern DECLSPEC int SDLCALL SDL_SetWindowOpacity(SDL_Window *window, float opacity); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowOpacity(SDL_Window *window, float opacity); /** * Get the opacity of a window. * - * If transparency isn't supported on this platform, opacity will be reported + * If transparency isn't supported on this platform, opacity will be returned * as 1.0f without error. * - * The parameter `opacity` is ignored if it is NULL. - * - * This function also returns -1 if an invalid window was provided. - * - * \param window the window to get the current opacity value from - * \param out_opacity the float filled in (0.0f - transparent, 1.0f - opaque) - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to get the current opacity value from. + * \returns the opacity, (0.0f - transparent, 1.0f - opaque), or -1.0f on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetWindowOpacity */ -extern DECLSPEC int SDLCALL SDL_GetWindowOpacity(SDL_Window *window, float *out_opacity); +extern SDL_DECLSPEC float SDLCALL SDL_GetWindowOpacity(SDL_Window *window); /** - * Set the window as a modal for another window. + * Set the window as a child of a parent window. * - * \param modal_window the window that should be set modal - * \param parent_window the parent window for the modal window - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * If the window is already the child of an existing window, it will be + * reparented to the new owner. Setting the parent window to NULL unparents + * the window and removes child window status. + * + * Attempting to set the parent of a window that is currently in the modal + * state will fail. Use SDL_SetWindowModalFor() to cancel the modal status + * before attempting to change the parent. + * + * Setting a parent window that is currently the sibling or descendent of the + * child window results in undefined behavior. + * + * \param window the window that should become the child of a parent. + * \param parent the new parent window for the child window. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. + * + * \sa SDL_SetWindowModal */ -extern DECLSPEC int SDLCALL SDL_SetWindowModalFor(SDL_Window *modal_window, SDL_Window *parent_window); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowParent(SDL_Window *window, SDL_Window *parent); /** - * Explicitly set input focus to the window. + * Toggle the state of the window as modal. * - * You almost certainly want SDL_RaiseWindow() instead of this function. Use - * this with caution, as you might give focus to a window that is completely - * obscured by other windows. + * To enable modal status on a window, the window must currently be the child + * window of a parent, or toggling modal status on will fail. * - * \param window the window that should get the input focus - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window on which to set the modal state. + * \param modal true to toggle modal status on, false to toggle it off. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_RaiseWindow + * \sa SDL_SetWindowParent */ -extern DECLSPEC int SDLCALL SDL_SetWindowInputFocus(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowModal(SDL_Window *window, bool modal); /** * Set whether the window may have input focus. * - * \param window the window to set focusable state - * \param focusable SDL_TRUE to allow input focus, SDL_FALSE to not allow - * input focus - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to set focusable state. + * \param focusable true to allow input focus, false to not allow input focus. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetWindowFocusable(SDL_Window *window, SDL_bool focusable); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowFocusable(SDL_Window *window, bool focusable); /** @@ -1986,43 +2351,45 @@ extern DECLSPEC int SDLCALL SDL_SetWindowFocusable(SDL_Window *window, SDL_bool * On platforms or desktops where this is unsupported, this function does * nothing. * - * \param window the window for which the menu will be displayed + * \param window the window for which the menu will be displayed. * \param x the x coordinate of the menu, relative to the origin (top-left) of - * the client area + * the client area. * \param y the y coordinate of the menu, relative to the origin (top-left) of - * the client area - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the client area. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_ShowWindowSystemMenu(SDL_Window *window, int x, int y); +extern SDL_DECLSPEC bool SDLCALL SDL_ShowWindowSystemMenu(SDL_Window *window, int x, int y); /** * Possible return values from the SDL_HitTest callback. * + * \since This enum is available since SDL 3.0.0. + * * \sa SDL_HitTest */ -typedef enum +typedef enum SDL_HitTestResult { - SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */ - SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */ - SDL_HITTEST_RESIZE_TOPLEFT, - SDL_HITTEST_RESIZE_TOP, - SDL_HITTEST_RESIZE_TOPRIGHT, - SDL_HITTEST_RESIZE_RIGHT, - SDL_HITTEST_RESIZE_BOTTOMRIGHT, - SDL_HITTEST_RESIZE_BOTTOM, - SDL_HITTEST_RESIZE_BOTTOMLEFT, - SDL_HITTEST_RESIZE_LEFT + SDL_HITTEST_NORMAL, /**< Region is normal. No special properties. */ + SDL_HITTEST_DRAGGABLE, /**< Region can drag entire window. */ + SDL_HITTEST_RESIZE_TOPLEFT, /**< Region is the resizable top-left corner border. */ + SDL_HITTEST_RESIZE_TOP, /**< Region is the resizable top border. */ + SDL_HITTEST_RESIZE_TOPRIGHT, /**< Region is the resizable top-right corner border. */ + SDL_HITTEST_RESIZE_RIGHT, /**< Region is the resizable right border. */ + SDL_HITTEST_RESIZE_BOTTOMRIGHT, /**< Region is the resizable bottom-right corner border. */ + SDL_HITTEST_RESIZE_BOTTOM, /**< Region is the resizable bottom border. */ + SDL_HITTEST_RESIZE_BOTTOMLEFT, /**< Region is the resizable bottom-left corner border. */ + SDL_HITTEST_RESIZE_LEFT /**< Region is the resizable left border. */ } SDL_HitTestResult; /** * Callback used for hit-testing. * - * \param win the SDL_Window where hit-testing was set on - * \param area an SDL_Point which should be hit-tested - * \param data what was passed as `callback_data` to SDL_SetWindowHitTest() + * \param win the SDL_Window where hit-testing was set on. + * \param area an SDL_Point which should be hit-tested. + * \param data what was passed as `callback_data` to SDL_SetWindowHitTest(). * \returns an SDL_HitTestResult value. * * \sa SDL_SetWindowHitTest @@ -2052,7 +2419,7 @@ typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, * Specifying NULL for a callback disables hit-testing. Hit-testing is * disabled by default. * - * Platforms that don't support this functionality will return -1 + * Platforms that don't support this functionality will return false * unconditionally, even if you're attempting to disable hit-testing. * * Your callback may fire at any time, and its firing does not indicate any @@ -2063,15 +2430,15 @@ typedef SDL_HitTestResult (SDLCALL *SDL_HitTest)(SDL_Window *win, * can fire at any time, you should try to keep your callback efficient, * devoid of allocations, etc. * - * \param window the window to set hit-testing on - * \param callback the function to call when doing a hit-test - * \param callback_data an app-defined void pointer passed to **callback** - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to set hit-testing on. + * \param callback the function to call when doing a hit-test. + * \param callback_data an app-defined void pointer passed to **callback**. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window *window, SDL_HitTest callback, void *callback_data); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowHitTest(SDL_Window *window, SDL_HitTest callback, void *callback_data); /** * Set the shape of a transparent window. @@ -2087,38 +2454,35 @@ extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window *window, SDL_HitTest * * The window must have been created with the SDL_WINDOW_TRANSPARENT flag. * - * \param window the window + * \param window the window. * \param shape the surface representing the shape of the window, or NULL to - * remove any current shape - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * remove any current shape. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape); +extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowShape(SDL_Window *window, SDL_Surface *shape); /** * Request a window to demand attention from the user. * - * \param window the window to be flashed - * \param operation the flash operation - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to be flashed. + * \param operation the operation to perform. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation); +extern SDL_DECLSPEC bool SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperation operation); /** * Destroy a window. * - * If the window has an associated SDL_Renderer, it will be implicitly + * Any popups or modal windows owned by the window will be recursively * destroyed as well. * - * If `window` is NULL, this function will return immediately after setting - * the SDL error message to "Invalid window". See SDL_GetError(). - * - * \param window the window to destroy + * \param window the window to destroy. * * \since This function is available since SDL 3.0.0. * @@ -2126,39 +2490,37 @@ extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window *window, SDL_FlashOperati * \sa SDL_CreateWindow * \sa SDL_CreateWindowWithProperties */ -extern DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window *window); +extern SDL_DECLSPEC void SDLCALL SDL_DestroyWindow(SDL_Window *window); /** * Check whether the screensaver is currently enabled. * - * The screensaver is disabled by default since SDL 2.0.2. Before SDL 2.0.2 - * the screensaver was enabled by default. + * The screensaver is disabled by default. * * The default can also be changed using `SDL_HINT_VIDEO_ALLOW_SCREENSAVER`. * - * \returns SDL_TRUE if the screensaver is enabled, SDL_FALSE if it is - * disabled. + * \returns true if the screensaver is enabled, false if it is disabled. * * \since This function is available since SDL 3.0.0. * * \sa SDL_DisableScreenSaver * \sa SDL_EnableScreenSaver */ -extern DECLSPEC SDL_bool SDLCALL SDL_ScreenSaverEnabled(void); +extern SDL_DECLSPEC bool SDLCALL SDL_ScreenSaverEnabled(void); /** * Allow the screen to be blanked by a screen saver. * - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_DisableScreenSaver * \sa SDL_ScreenSaverEnabled */ -extern DECLSPEC int SDLCALL SDL_EnableScreenSaver(void); +extern SDL_DECLSPEC bool SDLCALL SDL_EnableScreenSaver(void); /** * Prevent the screen from being blanked by a screen saver. @@ -2166,18 +2528,18 @@ extern DECLSPEC int SDLCALL SDL_EnableScreenSaver(void); * If you disable the screensaver, it is automatically re-enabled when SDL * quits. * - * The screensaver is disabled by default since SDL 2.0.2. Before SDL 2.0.2 - * the screensaver was enabled by default. + * The screensaver is disabled by default, but this may by changed by + * SDL_HINT_VIDEO_ALLOW_SCREENSAVER. * - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_EnableScreenSaver * \sa SDL_ScreenSaverEnabled */ -extern DECLSPEC int SDLCALL SDL_DisableScreenSaver(void); +extern SDL_DECLSPEC bool SDLCALL SDL_DisableScreenSaver(void); /** @@ -2196,16 +2558,16 @@ extern DECLSPEC int SDLCALL SDL_DisableScreenSaver(void); * program from the dynamic library using SDL_GL_GetProcAddress(). * * \param path the platform dependent OpenGL library name, or NULL to open the - * default OpenGL library - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * default OpenGL library. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_GetProcAddress * \sa SDL_GL_UnloadLibrary */ -extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_LoadLibrary(const char *path); /** * Get an OpenGL function by name. @@ -2248,7 +2610,7 @@ extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); * code. This will ensure the proper calling convention is followed on * platforms where this matters (Win32) thereby avoiding stack corruption. * - * \param proc the name of an OpenGL function + * \param proc the name of an OpenGL function. * \returns a pointer to the named OpenGL function. The returned pointer * should be cast to the appropriate function signature. * @@ -2258,7 +2620,7 @@ extern DECLSPEC int SDLCALL SDL_GL_LoadLibrary(const char *path); * \sa SDL_GL_LoadLibrary * \sa SDL_GL_UnloadLibrary */ -extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_GL_GetProcAddress(const char *proc); +extern SDL_DECLSPEC SDL_FunctionPointer SDLCALL SDL_GL_GetProcAddress(const char *proc); /** * Get an EGL library function by name. @@ -2267,15 +2629,15 @@ extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_GL_GetProcAddress(const char *pr * points for EGL functions. This is useful to provide to an EGL API and * extension loader. * - * \param proc the name of an EGL function + * \param proc the name of an EGL function. * \returns a pointer to the named EGL function. The returned pointer should * be cast to the appropriate function signature. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GL_GetCurrentEGLDisplay + * \sa SDL_EGL_GetCurrentDisplay */ -extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_EGL_GetProcAddress(const char *proc); +extern SDL_DECLSPEC SDL_FunctionPointer SDLCALL SDL_EGL_GetProcAddress(const char *proc); /** * Unload the OpenGL library previously loaded by SDL_GL_LoadLibrary(). @@ -2284,7 +2646,7 @@ extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_EGL_GetProcAddress(const char *p * * \sa SDL_GL_LoadLibrary */ -extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void); +extern SDL_DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void); /** * Check if an OpenGL extension is supported for the current context. @@ -2300,12 +2662,12 @@ extern DECLSPEC void SDLCALL SDL_GL_UnloadLibrary(void); * context and save that information somewhere instead of calling the function * every time you need to know. * - * \param extension the name of the extension to check - * \returns SDL_TRUE if the extension is supported, SDL_FALSE otherwise. + * \param extension the name of the extension to check. + * \returns true if the extension is supported, false otherwise. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char *extension); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_ExtensionSupported(const char *extension); /** * Reset all previously set OpenGL context attributes to their default values. @@ -2315,7 +2677,7 @@ extern DECLSPEC SDL_bool SDLCALL SDL_GL_ExtensionSupported(const char *extension * \sa SDL_GL_GetAttribute * \sa SDL_GL_SetAttribute */ -extern DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); +extern SDL_DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); /** * Set an OpenGL window attribute before window creation. @@ -2325,32 +2687,34 @@ extern DECLSPEC void SDLCALL SDL_GL_ResetAttributes(void); * SDL_GL_GetAttribute() to check the values after creating the OpenGL * context, since the values obtained can differ from the requested ones. * - * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to set - * \param value the desired value for the attribute - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to + * set. + * \param value the desired value for the attribute. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_GetAttribute * \sa SDL_GL_ResetAttributes */ -extern DECLSPEC int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value); /** * Get the actual value for an attribute from the current context. * - * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to get - * \param value a pointer filled in with the current value of `attr` - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param attr an SDL_GLattr enum value specifying the OpenGL attribute to + * get. + * \param value a pointer filled in with the current value of `attr`. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_ResetAttributes * \sa SDL_GL_SetAttribute */ -extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); /** * Create an OpenGL context for an OpenGL window, and make it current. @@ -2361,34 +2725,34 @@ extern DECLSPEC int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int *value); * extension-handling library or with SDL_GL_GetProcAddress() and its related * functions. * - * SDL_GLContext is an alias for `void *`. It's opaque to the application. + * SDL_GLContext is opaque to the application. * - * \param window the window to associate with the context - * \returns the OpenGL context associated with `window` or NULL on error; call - * SDL_GetError() for more details. + * \param window the window to associate with the context. + * \returns the OpenGL context associated with `window` or NULL on failure; + * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_GL_DeleteContext + * \sa SDL_GL_DestroyContext * \sa SDL_GL_MakeCurrent */ -extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *window); +extern SDL_DECLSPEC SDL_GLContext SDLCALL SDL_GL_CreateContext(SDL_Window *window); /** * Set up an OpenGL context for rendering into an OpenGL window. * * The context must have been created with a compatible window. * - * \param window the window to associate with the context - * \param context the OpenGL context to associate with the window - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to associate with the context. + * \param context the OpenGL context to associate with the window. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_CreateContext */ -extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext context); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext context); /** * Get the currently active OpenGL window. @@ -2398,7 +2762,7 @@ extern DECLSPEC int SDLCALL SDL_GL_MakeCurrent(SDL_Window *window, SDL_GLContext * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_Window *SDLCALL SDL_GL_GetCurrentWindow(void); +extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GL_GetCurrentWindow(void); /** * Get the currently active OpenGL context. @@ -2410,7 +2774,7 @@ extern DECLSPEC SDL_Window *SDLCALL SDL_GL_GetCurrentWindow(void); * * \sa SDL_GL_MakeCurrent */ -extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void); +extern SDL_DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void); /** * Get the currently active EGL display. @@ -2420,7 +2784,7 @@ extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_EGLDisplay SDLCALL SDL_EGL_GetCurrentEGLDisplay(void); +extern SDL_DECLSPEC SDL_EGLDisplay SDLCALL SDL_EGL_GetCurrentDisplay(void); /** * Get the currently active EGL config. @@ -2430,44 +2794,40 @@ extern DECLSPEC SDL_EGLDisplay SDLCALL SDL_EGL_GetCurrentEGLDisplay(void); * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_EGLConfig SDLCALL SDL_EGL_GetCurrentEGLConfig(void); +extern SDL_DECLSPEC SDL_EGLConfig SDLCALL SDL_EGL_GetCurrentConfig(void); /** * Get the EGL surface associated with the window. * - * \param window the window to query + * \param window the window to query. * \returns the EGLSurface pointer associated with the window, or NULL on * failure. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowEGLSurface(SDL_Window *window); +extern SDL_DECLSPEC SDL_EGLSurface SDLCALL SDL_EGL_GetWindowSurface(SDL_Window *window); /** * Sets the callbacks for defining custom EGLAttrib arrays for EGL * initialization. * - * Each callback should return a pointer to an EGL attribute array terminated - * with EGL_NONE. Callbacks may return NULL pointers to signal an error, which - * will cause the SDL_CreateWindow process to fail gracefully. - * - * The arrays returned by each callback will be appended to the existing - * attribute arrays defined by SDL. + * Callbacks that aren't needed can be set to NULL. * * NOTE: These callback pointers will be reset after SDL_GL_ResetAttributes. * - * \param platformAttribCallback Callback for attributes to pass to - * eglGetPlatformDisplay. - * \param surfaceAttribCallback Callback for attributes to pass to - * eglCreateSurface. - * \param contextAttribCallback Callback for attributes to pass to - * eglCreateContext. + * \param platformAttribCallback callback for attributes to pass to + * eglGetPlatformDisplay. May be NULL. + * \param surfaceAttribCallback callback for attributes to pass to + * eglCreateSurface. May be NULL. + * \param contextAttribCallback callback for attributes to pass to + * eglCreateContext. May be NULL. + * \param userdata a pointer that is passed to the callbacks. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC void SDLCALL SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback, - SDL_EGLIntArrayCallback surfaceAttribCallback, - SDL_EGLIntArrayCallback contextAttribCallback); +extern SDL_DECLSPEC void SDLCALL SDL_EGL_SetAttributeCallbacks(SDL_EGLAttribArrayCallback platformAttribCallback, + SDL_EGLIntArrayCallback surfaceAttribCallback, + SDL_EGLIntArrayCallback contextAttribCallback, void *userdata); /** * Set the swap interval for the current OpenGL context. @@ -2477,8 +2837,8 @@ extern DECLSPEC void SDLCALL SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArray * the vertical retrace for a given frame, it swaps buffers immediately, which * might be less jarring for the user during occasional framerate drops. If an * application requests adaptive vsync and the system does not support it, - * this function will fail and return -1. In such a case, you should probably - * retry the call with 1 for the interval. + * this function will fail and return false. In such a case, you should + * probably retry the call with 1 for the interval. * * Adaptive vsync is implemented for some glX drivers with * GLX_EXT_swap_control_tear, and for some Windows drivers with @@ -2488,15 +2848,15 @@ extern DECLSPEC void SDLCALL SDL_EGL_SetEGLAttributeCallbacks(SDL_EGLAttribArray * https://www.khronos.org/opengl/wiki/Swap_Interval#Adaptive_Vsync * * \param interval 0 for immediate updates, 1 for updates synchronized with - * the vertical retrace, -1 for adaptive vsync - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * the vertical retrace, -1 for adaptive vsync. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_GetSwapInterval */ -extern DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_SetSwapInterval(int interval); /** * Get the swap interval for the current OpenGL context. @@ -2504,18 +2864,18 @@ extern DECLSPEC int SDLCALL SDL_GL_SetSwapInterval(int interval); * If the system can't determine the swap interval, or there isn't a valid * current context, this function will set *interval to 0 as a safe default. * - * \param interval Output interval value. 0 if there is no vertical retrace + * \param interval output interval value. 0 if there is no vertical retrace * synchronization, 1 if the buffer swap is synchronized with * the vertical retrace, and -1 if late swaps happen - * immediately instead of waiting for the next retrace - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * immediately instead of waiting for the next retrace. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_SetSwapInterval */ -extern DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(int *interval); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_GetSwapInterval(int *interval); /** * Update a window with OpenGL rendering. @@ -2527,26 +2887,26 @@ extern DECLSPEC int SDLCALL SDL_GL_GetSwapInterval(int *interval); * glBindFramebuffer(), this is the default and you won't have to do anything * extra. * - * \param window the window to change - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param window the window to change. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC int SDLCALL SDL_GL_SwapWindow(SDL_Window *window); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_SwapWindow(SDL_Window *window); /** * Delete an OpenGL context. * - * \param context the OpenGL context to be deleted - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param context the OpenGL context to be deleted. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_GL_CreateContext */ -extern DECLSPEC int SDLCALL SDL_GL_DeleteContext(SDL_GLContext context); +extern SDL_DECLSPEC bool SDLCALL SDL_GL_DestroyContext(SDL_GLContext context); /* @} *//* OpenGL support functions */ diff --git a/libs/SDL3/include/SDL3/SDL_vulkan.h b/libs/SDL3/include/SDL3/SDL_vulkan.h index 64544c8b6..b6b54f859 100644 --- a/libs/SDL3/include/SDL3/SDL_vulkan.h +++ b/libs/SDL3/include/SDL3/SDL_vulkan.h @@ -20,14 +20,29 @@ */ /** - * \file SDL_vulkan.h + * # CategoryVulkan * - * Header file for functions to creating Vulkan surfaces on SDL windows. + * Functions for creating Vulkan surfaces on SDL windows. + * + * For the most part, Vulkan operates independent of SDL, but it benefits from + * a little support during setup. + * + * Use SDL_Vulkan_GetInstanceExtensions() to get platform-specific bits for + * creating a VkInstance, then SDL_Vulkan_GetVkGetInstanceProcAddr() to get + * the appropriate function for querying Vulkan entry points. Then + * SDL_Vulkan_CreateSurface() will get you the final pieces you need to + * prepare for rendering into an SDL_Window with Vulkan. + * + * Unlike OpenGL, most of the details of "context" creation and window buffer + * swapping are handled by the Vulkan API directly, so SDL doesn't provide + * Vulkan equivalents of SDL_GL_SwapWindow(), etc; they aren't necessary. */ #ifndef SDL_vulkan_h_ #define SDL_vulkan_h_ +#include +#include #include #include @@ -50,14 +65,12 @@ extern "C" { #endif VK_DEFINE_HANDLE(VkInstance) +VK_DEFINE_HANDLE(VkPhysicalDevice) VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR) struct VkAllocationCallbacks; #endif /* !NO_SDL_VULKAN_TYPEDEFS */ -typedef VkInstance SDL_vulkanInstance; -typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ - /** * \name Vulkan support functions */ @@ -95,16 +108,16 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ * supported. Either do not link to the Vulkan loader or link to a dynamic * library version. * - * \param path The platform dependent Vulkan loader library name or NULL - * \returns 0 on success or a negative error code on failure; call - * SDL_GetError() for more information. + * \param path the platform dependent Vulkan loader library name or NULL. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. * * \since This function is available since SDL 3.0.0. * - * \sa SDL_Vulkan_GetVkInstanceProcAddr + * \sa SDL_Vulkan_GetVkGetInstanceProcAddr * \sa SDL_Vulkan_UnloadLibrary */ -extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path); +extern SDL_DECLSPEC bool SDLCALL SDL_Vulkan_LoadLibrary(const char *path); /** * Get the address of the `vkGetInstanceProcAddr` function. @@ -120,20 +133,21 @@ extern DECLSPEC int SDLCALL SDL_Vulkan_LoadLibrary(const char *path); * `vkGetInstanceProcAddr = * (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr();` * - * \returns the function pointer for `vkGetInstanceProcAddr` or NULL on error. + * \returns the function pointer for `vkGetInstanceProcAddr` or NULL on + * failure; call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. */ -extern DECLSPEC SDL_FunctionPointer SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void); +extern SDL_DECLSPEC SDL_FunctionPointer SDLCALL SDL_Vulkan_GetVkGetInstanceProcAddr(void); /** - * Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary() + * Unload the Vulkan library previously loaded by SDL_Vulkan_LoadLibrary(). * * \since This function is available since SDL 3.0.0. * * \sa SDL_Vulkan_LoadLibrary */ -extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); +extern SDL_DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); /** * Get the Vulkan instance extensions needed for vkCreateInstance. @@ -150,13 +164,14 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * You should not free the returned array; it is owned by SDL. * * \param count a pointer filled in with the number of extensions returned. - * \returns An array of extension name strings on success, NULL on error. + * \returns an array of extension name strings on success, NULL on failure; + * call SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_Vulkan_CreateSurface */ -extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint32 *count); +extern SDL_DECLSPEC char const * const * SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint32 *count); /** * Create a Vulkan rendering surface for a window. @@ -168,22 +183,72 @@ extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint * If `allocator` is NULL, Vulkan will use the system default allocator. This * argument is passed directly to Vulkan and isn't used by SDL itself. * - * \param window The window to which to attach the Vulkan surface - * \param instance The Vulkan instance handle - * \param allocator A VkAllocationCallbacks struct, which lets the app set the + * \param window the window to which to attach the Vulkan surface. + * \param instance the Vulkan instance handle. + * \param allocator a VkAllocationCallbacks struct, which lets the app set the * allocator that creates the surface. Can be NULL. - * \param surface A pointer to a VkSurfaceKHR handle to output the newly - * created surface - * \returns SDL_TRUE on success, SDL_FALSE on error. + * \param surface a pointer to a VkSurfaceKHR handle to output the newly + * created surface. + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_Vulkan_GetInstanceExtensions + * \sa SDL_Vulkan_DestroySurface + */ +extern SDL_DECLSPEC bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window, + VkInstance instance, + const struct VkAllocationCallbacks *allocator, + VkSurfaceKHR* surface); + +/** + * Destroy the Vulkan rendering surface of a window. + * + * This should be called before SDL_DestroyWindow, if SDL_Vulkan_CreateSurface + * was called after SDL_CreateWindow. + * + * The `instance` must have been created with extensions returned by + * SDL_Vulkan_GetInstanceExtensions() enabled and `surface` must have been + * created successfully by an SDL_Vulkan_CreateSurface() call. + * + * If `allocator` is NULL, Vulkan will use the system default allocator. This + * argument is passed directly to Vulkan and isn't used by SDL itself. + * + * \param instance the Vulkan instance handle. + * \param surface vkSurfaceKHR handle to destroy. + * \param allocator a VkAllocationCallbacks struct, which lets the app set the + * allocator that destroys the surface. Can be NULL. + * + * \since This function is available since SDL 3.0.0. + * + * \sa SDL_Vulkan_GetInstanceExtensions + * \sa SDL_Vulkan_CreateSurface + */ +extern SDL_DECLSPEC void SDLCALL SDL_Vulkan_DestroySurface(VkInstance instance, + VkSurfaceKHR surface, + const struct VkAllocationCallbacks *allocator); + +/** + * Query support for presentation via a given physical device and queue + * family. + * + * The `instance` must have been created with extensions returned by + * SDL_Vulkan_GetInstanceExtensions() enabled. + * + * \param instance the Vulkan instance handle. + * \param physicalDevice a valid Vulkan physical device handle. + * \param queueFamilyIndex a valid queue family index for the given physical + * device. + * \returns true if supported, false if unsupported or an error occurred. * * \since This function is available since SDL 3.0.0. * * \sa SDL_Vulkan_GetInstanceExtensions */ -extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window, - VkInstance instance, - const struct VkAllocationCallbacks *allocator, - VkSurfaceKHR* surface); +extern SDL_DECLSPEC bool SDLCALL SDL_Vulkan_GetPresentationSupport(VkInstance instance, + VkPhysicalDevice physicalDevice, + Uint32 queueFamilyIndex); /* @} *//* Vulkan support functions */ diff --git a/libs/SDL3/include/build_config/SDL_build_config.h b/libs/SDL3/include/build_config/SDL_build_config.h index beaceb584..eca4268cb 100644 --- a/libs/SDL3/include/build_config/SDL_build_config.h +++ b/libs/SDL3/include/build_config/SDL_build_config.h @@ -33,8 +33,6 @@ /* Add any platform that doesn't build using the configure system. */ #if defined(SDL_PLATFORM_WIN32) #include "SDL_build_config_windows.h" -#elif defined(SDL_PLATFORM_WINRT) -#include "SDL_build_config_winrt.h" #elif defined(SDL_PLATFORM_WINGDK) #include "SDL_build_config_wingdk.h" #elif defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) diff --git a/libs/SDL3/include/build_config/SDL_build_config.h.cmake b/libs/SDL3/include/build_config/SDL_build_config.h.cmake index b30699bfa..d0598aea8 100644 --- a/libs/SDL3/include/build_config/SDL_build_config.h.cmake +++ b/libs/SDL3/include/build_config/SDL_build_config.h.cmake @@ -59,6 +59,7 @@ #cmakedefine HAVE_MEMORY_H 1 #cmakedefine HAVE_SIGNAL_H 1 #cmakedefine HAVE_STDARG_H 1 +#cmakedefine HAVE_STDBOOL_H 1 #cmakedefine HAVE_STDDEF_H 1 #cmakedefine HAVE_STDINT_H 1 #cmakedefine HAVE_STDIO_H 1 @@ -75,12 +76,10 @@ #cmakedefine HAVE_CALLOC 1 #cmakedefine HAVE_REALLOC 1 #cmakedefine HAVE_FREE 1 -#ifndef SDL_PLATFORM_WIN32 /* Don't use C runtime versions of these on Windows */ #cmakedefine HAVE_GETENV 1 #cmakedefine HAVE_SETENV 1 #cmakedefine HAVE_PUTENV 1 #cmakedefine HAVE_UNSETENV 1 -#endif #cmakedefine HAVE_ABS 1 #cmakedefine HAVE_BCOPY 1 #cmakedefine HAVE_MEMSET 1 @@ -101,6 +100,7 @@ #cmakedefine HAVE_STRNLEN 1 #cmakedefine HAVE_STRLCPY 1 #cmakedefine HAVE_STRLCAT 1 +#cmakedefine HAVE_STRPBRK 1 #cmakedefine HAVE__STRREV 1 #cmakedefine HAVE__STRUPR 1 #cmakedefine HAVE__STRLWR 1 @@ -152,6 +152,12 @@ #cmakedefine HAVE_FLOORF 1 #cmakedefine HAVE_FMOD 1 #cmakedefine HAVE_FMODF 1 +#cmakedefine HAVE_ISINF 1 +#cmakedefine HAVE_ISINFF 1 +#cmakedefine HAVE_ISINF_FLOAT_MACRO 1 +#cmakedefine HAVE_ISNAN 1 +#cmakedefine HAVE_ISNANF 1 +#cmakedefine HAVE_ISNAN_FLOAT_MACRO 1 #cmakedefine HAVE_LOG 1 #cmakedefine HAVE_LOGF 1 #cmakedefine HAVE_LOG10 1 @@ -222,15 +228,15 @@ #cmakedefine HAVE_LIBUDEV_H 1 #cmakedefine HAVE_LIBDECOR_H 1 -#cmakedefine HAVE_D3D_H @HAVE_D3D_H@ #cmakedefine HAVE_D3D11_H @HAVE_D3D11_H@ -#cmakedefine HAVE_D3D12_H @HAVE_D3D12_H@ #cmakedefine HAVE_DDRAW_H @HAVE_DDRAW_H@ #cmakedefine HAVE_DSOUND_H @HAVE_DSOUND_H@ #cmakedefine HAVE_DINPUT_H @HAVE_DINPUT_H@ #cmakedefine HAVE_XINPUT_H @HAVE_XINPUT_H@ #cmakedefine HAVE_WINDOWS_GAMING_INPUT_H @HAVE_WINDOWS_GAMING_INPUT_H@ +#cmakedefine HAVE_GAMEINPUT_H @HAVE_GAMEINPUT_H@ #cmakedefine HAVE_DXGI_H @HAVE_DXGI_H@ +#cmakedefine HAVE_DXGI1_6_H @HAVE_DXGI1_6_H@ #cmakedefine HAVE_MMDEVICEAPI_H @HAVE_MMDEVICEAPI_H@ #cmakedefine HAVE_AUDIOCLIENT_H @HAVE_AUDIOCLIENT_H@ @@ -257,11 +263,11 @@ #cmakedefine SDL_VIDEO_DISABLED @SDL_VIDEO_DISABLED@ #cmakedefine SDL_POWER_DISABLED @SDL_POWER_DISABLED@ #cmakedefine SDL_CAMERA_DISABLED @SDL_CAMERA_DISABLED@ +#cmakedefine SDL_GPU_DISABLED @SDL_GPU_DISABLED@ /* Enable various audio drivers */ #cmakedefine SDL_AUDIO_DRIVER_ALSA @SDL_AUDIO_DRIVER_ALSA@ #cmakedefine SDL_AUDIO_DRIVER_ALSA_DYNAMIC @SDL_AUDIO_DRIVER_ALSA_DYNAMIC@ -#cmakedefine SDL_AUDIO_DRIVER_ANDROID @SDL_AUDIO_DRIVER_ANDROID@ #cmakedefine SDL_AUDIO_DRIVER_OPENSLES @SDL_AUDIO_DRIVER_OPENSLES@ #cmakedefine SDL_AUDIO_DRIVER_AAUDIO @SDL_AUDIO_DRIVER_AAUDIO@ #cmakedefine SDL_AUDIO_DRIVER_COREAUDIO @SDL_AUDIO_DRIVER_COREAUDIO@ @@ -292,25 +298,26 @@ #cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@ #cmakedefine SDL_INPUT_FBSDKBIO @SDL_INPUT_FBSDKBIO@ #cmakedefine SDL_INPUT_WSCONS @SDL_INPUT_WSCONS@ +#cmakedefine SDL_HAVE_MACHINE_JOYSTICK_H @SDL_HAVE_MACHINE_JOYSTICK_H@ #cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@ -#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@ -#cmakedefine SDL_JOYSTICK_WGI @SDL_JOYSTICK_WGI@ #cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@ -#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@ #cmakedefine SDL_JOYSTICK_DUMMY @SDL_JOYSTICK_DUMMY@ +#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@ +#cmakedefine SDL_JOYSTICK_GAMEINPUT @SDL_JOYSTICK_GAMEINPUT@ +#cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@ +#cmakedefine SDL_JOYSTICK_HIDAPI @SDL_JOYSTICK_HIDAPI@ #cmakedefine SDL_JOYSTICK_IOKIT @SDL_JOYSTICK_IOKIT@ -#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@ #cmakedefine SDL_JOYSTICK_LINUX @SDL_JOYSTICK_LINUX@ -#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@ -#cmakedefine SDL_HAVE_MACHINE_JOYSTICK_H @SDL_HAVE_MACHINE_JOYSTICK_H@ -#cmakedefine SDL_JOYSTICK_HIDAPI @SDL_JOYSTICK_HIDAPI@ +#cmakedefine SDL_JOYSTICK_MFI @SDL_JOYSTICK_MFI@ +#cmakedefine SDL_JOYSTICK_N3DS @SDL_JOYSTICK_N3DS@ +#cmakedefine SDL_JOYSTICK_PS2 @SDL_JOYSTICK_PS2@ +#cmakedefine SDL_JOYSTICK_PSP @SDL_JOYSTICK_PSP@ #cmakedefine SDL_JOYSTICK_RAWINPUT @SDL_JOYSTICK_RAWINPUT@ -#cmakedefine SDL_JOYSTICK_EMSCRIPTEN @SDL_JOYSTICK_EMSCRIPTEN@ +#cmakedefine SDL_JOYSTICK_USBHID @SDL_JOYSTICK_USBHID@ #cmakedefine SDL_JOYSTICK_VIRTUAL @SDL_JOYSTICK_VIRTUAL@ #cmakedefine SDL_JOYSTICK_VITA @SDL_JOYSTICK_VITA@ -#cmakedefine SDL_JOYSTICK_PSP @SDL_JOYSTICK_PSP@ -#cmakedefine SDL_JOYSTICK_PS2 @SDL_JOYSTICK_PS2@ -#cmakedefine SDL_JOYSTICK_N3DS @SDL_JOYSTICK_N3DS@ +#cmakedefine SDL_JOYSTICK_WGI @SDL_JOYSTICK_WGI@ +#cmakedefine SDL_JOYSTICK_XINPUT @SDL_JOYSTICK_XINPUT@ #cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@ #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@ #cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@ @@ -319,6 +326,11 @@ #cmakedefine SDL_LIBUSB_DYNAMIC @SDL_LIBUSB_DYNAMIC@ #cmakedefine SDL_UDEV_DYNAMIC @SDL_UDEV_DYNAMIC@ +/* Enable various process implementations */ +#cmakedefine SDL_PROCESS_DUMMY @SDL_PROCESS_DUMMY@ +#cmakedefine SDL_PROCESS_POSIX @SDL_PROCESS_POSIX@ +#cmakedefine SDL_PROCESS_WINDOWS @SDL_PROCESS_WINDOWS@ + /* Enable various sensor drivers */ #cmakedefine SDL_SENSOR_ANDROID @SDL_SENSOR_ANDROID@ #cmakedefine SDL_SENSOR_COREMOTION @SDL_SENSOR_COREMOTION@ @@ -390,7 +402,6 @@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR@ #cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@ #cmakedefine SDL_VIDEO_DRIVER_WINDOWS @SDL_VIDEO_DRIVER_WINDOWS@ -#cmakedefine SDL_VIDEO_DRIVER_WINRT @SDL_VIDEO_DRIVER_WINRT@ #cmakedefine SDL_VIDEO_DRIVER_X11 @SDL_VIDEO_DRIVER_X11@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XCURSOR@ @@ -399,7 +410,7 @@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 @SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR @SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR@ #cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS @SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS@ -#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM@ +#cmakedefine SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM @SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM@ #cmakedefine SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS @SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS@ #cmakedefine SDL_VIDEO_DRIVER_X11_XCURSOR @SDL_VIDEO_DRIVER_X11_XCURSOR@ #cmakedefine SDL_VIDEO_DRIVER_X11_XDBE @SDL_VIDEO_DRIVER_X11_XDBE@ @@ -414,6 +425,7 @@ #cmakedefine SDL_VIDEO_RENDER_D3D @SDL_VIDEO_RENDER_D3D@ #cmakedefine SDL_VIDEO_RENDER_D3D11 @SDL_VIDEO_RENDER_D3D11@ #cmakedefine SDL_VIDEO_RENDER_D3D12 @SDL_VIDEO_RENDER_D3D12@ +#cmakedefine SDL_VIDEO_RENDER_GPU @SDL_VIDEO_RENDER_GPU@ #cmakedefine SDL_VIDEO_RENDER_METAL @SDL_VIDEO_RENDER_METAL@ #cmakedefine SDL_VIDEO_RENDER_VULKAN @SDL_VIDEO_RENDER_VULKAN@ #cmakedefine SDL_VIDEO_RENDER_OGL @SDL_VIDEO_RENDER_OGL@ @@ -440,11 +452,16 @@ /* Enable Metal support */ #cmakedefine SDL_VIDEO_METAL @SDL_VIDEO_METAL@ +/* Enable GPU support */ +#cmakedefine SDL_GPU_D3D11 @SDL_GPU_D3D11@ +#cmakedefine SDL_GPU_D3D12 @SDL_GPU_D3D12@ +#cmakedefine SDL_GPU_VULKAN @SDL_GPU_VULKAN@ +#cmakedefine SDL_GPU_METAL @SDL_GPU_METAL@ + /* Enable system power support */ #cmakedefine SDL_POWER_ANDROID @SDL_POWER_ANDROID@ #cmakedefine SDL_POWER_LINUX @SDL_POWER_LINUX@ #cmakedefine SDL_POWER_WINDOWS @SDL_POWER_WINDOWS@ -#cmakedefine SDL_POWER_WINRT @SDL_POWER_WINRT@ #cmakedefine SDL_POWER_MACOSX @SDL_POWER_MACOSX@ #cmakedefine SDL_POWER_UIKIT @SDL_POWER_UIKIT@ #cmakedefine SDL_POWER_HAIKU @SDL_POWER_HAIKU@ @@ -485,6 +502,8 @@ #cmakedefine SDL_CAMERA_DRIVER_ANDROID @SDL_CAMERA_DRIVER_ANDROID@ #cmakedefine SDL_CAMERA_DRIVER_EMSCRIPTEN @SDL_CAMERA_DRIVER_EMSCRIPTEN@ #cmakedefine SDL_CAMERA_DRIVER_MEDIAFOUNDATION @SDL_CAMERA_DRIVER_MEDIAFOUNDATION@ +#cmakedefine SDL_CAMERA_DRIVER_PIPEWIRE @SDL_CAMERA_DRIVER_PIPEWIRE@ +#cmakedefine SDL_CAMERA_DRIVER_PIPEWIRE_DYNAMIC @SDL_CAMERA_DRIVER_PIPEWIRE_DYNAMIC@ /* Enable misc subsystem */ #cmakedefine SDL_MISC_DUMMY @SDL_MISC_DUMMY@ diff --git a/libs/SDL3/include/build_config/SDL_build_config_android.h b/libs/SDL3/include/build_config/SDL_build_config_android.h index 61b2035dc..db5e3cebd 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_android.h +++ b/libs/SDL3/include/build_config/SDL_build_config_android.h @@ -42,6 +42,7 @@ #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -58,7 +59,6 @@ #define HAVE_REALLOC 1 #define HAVE_FREE 1 #define HAVE_GETENV 1 -#define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_SETENV 1 #define HAVE_UNSETENV 1 @@ -109,6 +109,10 @@ #define HAVE_FLOORF 1 #define HAVE_FMOD 1 #define HAVE_FMODF 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOGF 1 #define HAVE_LOG10 1 @@ -140,19 +144,28 @@ #define HAVE_CLOCK_GETTIME 1 /* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_ANDROID 1 +#ifndef SDL_AUDIO_DISABLED #define SDL_AUDIO_DRIVER_OPENSLES 1 #define SDL_AUDIO_DRIVER_AAUDIO 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 +#endif /* SDL_AUDIO_DISABLED */ /* Enable various input drivers */ +#ifndef SDL_JOYSTICK_DISABLED #define SDL_JOYSTICK_ANDROID 1 #define SDL_JOYSTICK_HIDAPI 1 #define SDL_JOYSTICK_VIRTUAL 1 +#endif /* SDL_JOYSTICK_DISABLED */ +#ifndef SDL_HAPTIC_DISABLED #define SDL_HAPTIC_ANDROID 1 +#endif /* SDL_HAPTIC_DISABLED */ + +/* Enable the stub process support */ +#define SDL_PROCESS_DUMMY 1 /* Enable sensor driver */ +#ifndef SDL_SENSOR_DISABLED #define SDL_SENSOR_ANDROID 1 +#endif /* SDL_SENSOR_DISABLED */ /* Enable various shared object loading systems */ #define SDL_LOADSO_DLOPEN 1 @@ -177,11 +190,13 @@ #define SDL_VIDEO_RENDER_OGL_ES2 1 /* Enable Vulkan support */ -/* Android does not support Vulkan in native code using the "armeabi" ABI. */ #if defined(__ARM_ARCH) && __ARM_ARCH < 7 -#define SDL_VIDEO_VULKAN 0 +/* Android does not support Vulkan in native code using the "armeabi" ABI. */ #else #define SDL_VIDEO_VULKAN 1 +#define SDL_VIDEO_RENDER_VULKAN 1 +#define SDL_GPU_VULKAN 1 +#define SDL_VIDEO_RENDER_GPU 1 #endif /* Enable system power support */ @@ -192,8 +207,9 @@ #define SDL_FSOPS_POSIX 1 /* Enable the camera driver */ +#ifndef SDL_CAMERA_DISABLED #define SDL_CAMERA_DRIVER_ANDROID 1 -#define SDL_CAMERA_DRIVER_DUMMY 1 +#endif /* SDL_CAMERA_DISABLED */ /* Enable nl_langinfo and high-res file times on version 26 and higher. */ #if __ANDROID_API__ >= 26 diff --git a/libs/SDL3/include/build_config/SDL_build_config_emscripten.h b/libs/SDL3/include/build_config/SDL_build_config_emscripten.h index a5b019e6e..d19cf8856 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_emscripten.h +++ b/libs/SDL3/include/build_config/SDL_build_config_emscripten.h @@ -44,6 +44,7 @@ #define HAVE_MEMORY_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -163,6 +164,10 @@ /* Enable various input drivers */ #define SDL_JOYSTICK_EMSCRIPTEN 1 +#define SDL_JOYSTICK_VIRTUAL 1 + +/* Enable various process implementations */ +#define SDL_PROCESS_DUMMY 1 /* Enable various sensor drivers */ #define SDL_SENSOR_DUMMY 1 diff --git a/libs/SDL3/include/build_config/SDL_build_config_ios.h b/libs/SDL3/include/build_config/SDL_build_config_ios.h index b8349930a..2f40f6641 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_ios.h +++ b/libs/SDL3/include/build_config/SDL_build_config_ios.h @@ -34,6 +34,7 @@ #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -50,7 +51,6 @@ #define HAVE_REALLOC 1 #define HAVE_FREE 1 #define HAVE_GETENV 1 -#define HAVE_SETENV 1 #define HAVE_PUTENV 1 #define HAVE_SETENV 1 #define HAVE_UNSETENV 1 @@ -76,6 +76,7 @@ #define HAVE_ATOF 1 #define HAVE_STRCMP 1 #define HAVE_STRNCMP 1 +#define HAVE_STRPBRK 1 #define HAVE_STRCASESTR 1 #define HAVE_VSSCANF 1 #define HAVE_VSNPRINTF 1 @@ -101,6 +102,10 @@ #define HAVE_FLOORF 1 #define HAVE_FMOD 1 #define HAVE_FMODF 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOGF 1 #define HAVE_LOG10 1 @@ -147,6 +152,9 @@ #define SDL_JOYSTICK_MFI 1 #define SDL_JOYSTICK_VIRTUAL 1 +/* Enable various process implementations */ +#define SDL_PROCESS_DUMMY 1 + #ifdef SDL_PLATFORM_TVOS #define SDL_SENSOR_DUMMY 1 #else @@ -182,9 +190,9 @@ Also supported in simulator from iOS 13.0 and tvOS 13.0 */ #if (TARGET_OS_SIMULATOR && ((__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000) || (__TV_OS_VERSION_MIN_REQUIRED >= 130000))) || (!TARGET_CPU_ARM && ((__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 90000))) -#define SDL_PLATFORM_SUPPORTS_METAL 1 +#define SDL_PLATFORM_SUPPORTS_METAL 1 #else -#define SDL_PLATFORM_SUPPORTS_METAL 0 +#define SDL_PLATFORM_SUPPORTS_METAL 0 #endif #if SDL_PLATFORM_SUPPORTS_METAL diff --git a/libs/SDL3/include/build_config/SDL_build_config_macos.h b/libs/SDL3/include/build_config/SDL_build_config_macos.h index ea7eb56a6..cd041b9e9 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_macos.h +++ b/libs/SDL3/include/build_config/SDL_build_config_macos.h @@ -39,6 +39,7 @@ #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -67,6 +68,7 @@ #define HAVE_STRLEN 1 #define HAVE_STRLCPY 1 #define HAVE_STRLCAT 1 +#define HAVE_STRPBRK 1 #define HAVE_STRCHR 1 #define HAVE_STRRCHR 1 #define HAVE_STRSTR 1 @@ -105,6 +107,10 @@ #define HAVE_FLOORF 1 #define HAVE_FMOD 1 #define HAVE_FMODF 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOGF 1 #define HAVE_LOG10 1 @@ -164,6 +170,9 @@ #define SDL_JOYSTICK_MFI 1 #endif +/* Enable various process implementations */ +#define SDL_PROCESS_POSIX 1 + /* Enable the dummy sensor driver */ #define SDL_SENSOR_DUMMY 1 @@ -183,6 +192,7 @@ /* Enable various video drivers */ #define SDL_VIDEO_DRIVER_COCOA 1 #define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_OFFSCREEN 1 #undef SDL_VIDEO_DRIVER_X11 #define SDL_VIDEO_DRIVER_X11_DYNAMIC "/opt/X11/lib/libX11.6.dylib" #define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/opt/X11/lib/libXext.6.dylib" @@ -193,7 +203,7 @@ #define SDL_VIDEO_DRIVER_X11_XRANDR 1 #define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1 #define SDL_VIDEO_DRIVER_X11_XSHAPE 1 -#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1 +#define SDL_VIDEO_DRIVER_X11_HAS_XKBLOOKUPKEYSYM 1 #ifdef MAC_OS_X_VERSION_10_8 /* @@ -205,61 +215,32 @@ #define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1 #endif -#ifndef SDL_VIDEO_RENDER_OGL #define SDL_VIDEO_RENDER_OGL 1 -#endif - -#ifndef SDL_VIDEO_RENDER_OGL_ES2 #define SDL_VIDEO_RENDER_OGL_ES2 1 -#endif /* Metal only supported on 64-bit architectures with 10.11+ */ #if TARGET_RT_64_BIT && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100) -#define SDL_PLATFORM_SUPPORTS_METAL 1 -#else -#define SDL_PLATFORM_SUPPORTS_METAL 0 +#define SDL_PLATFORM_SUPPORTS_METAL 1 #endif -#ifndef SDL_VIDEO_RENDER_METAL -#if SDL_PLATFORM_SUPPORTS_METAL -#define SDL_VIDEO_RENDER_METAL 1 -#else -#define SDL_VIDEO_RENDER_METAL 0 -#endif +#ifdef SDL_PLATFORM_SUPPORTS_METAL +#define SDL_VIDEO_RENDER_METAL 1 #endif /* Enable OpenGL support */ -#ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_ES2 -#define SDL_VIDEO_OPENGL_ES2 1 -#endif -#ifndef SDL_VIDEO_OPENGL_EGL -#define SDL_VIDEO_OPENGL_EGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_CGL -#define SDL_VIDEO_OPENGL_CGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_GLX -#define SDL_VIDEO_OPENGL_GLX 1 -#endif +#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_EGL 1 +#define SDL_VIDEO_OPENGL_CGL 1 +#define SDL_VIDEO_OPENGL_GLX 1 /* Enable Vulkan and Metal support */ -#ifndef SDL_VIDEO_VULKAN -#if SDL_PLATFORM_SUPPORTS_METAL -#define SDL_VIDEO_VULKAN 1 -#else -#define SDL_VIDEO_VULKAN 0 -#endif -#endif - -#ifndef SDL_VIDEO_METAL -#if SDL_PLATFORM_SUPPORTS_METAL +#ifdef SDL_PLATFORM_SUPPORTS_METAL #define SDL_VIDEO_METAL 1 -#else -#define SDL_VIDEO_METAL 0 -#endif +#define SDL_GPU_METAL 1 +#define SDL_VIDEO_VULKAN 1 +#define SDL_GPU_VULKAN 1 +#define SDL_VIDEO_RENDER_GPU 1 #endif /* Enable system power support */ diff --git a/libs/SDL3/include/build_config/SDL_build_config_minimal.h b/libs/SDL3/include/build_config/SDL_build_config_minimal.h index f949f94f6..5dc4305a9 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_minimal.h +++ b/libs/SDL3/include/build_config/SDL_build_config_minimal.h @@ -74,6 +74,9 @@ typedef unsigned int uintptr_t; /* Enable the stub HIDAPI */ #define SDL_HIDAPI_DISABLED 1 +/* Enable the stub process support */ +#define SDL_PROCESS_DUMMY 1 + /* Enable the stub sensor driver (src/sensor/dummy/\*.c) */ #define SDL_SENSOR_DISABLED 1 diff --git a/libs/SDL3/include/build_config/SDL_build_config_ngage.h b/libs/SDL3/include/build_config/SDL_build_config_ngage.h index 596943703..a834bc09f 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_ngage.h +++ b/libs/SDL3/include/build_config/SDL_build_config_ngage.h @@ -77,6 +77,9 @@ typedef unsigned long uintptr_t; /* Enable the stub HIDAPI */ #define SDL_HIDAPI_DISABLED 1 +/* Enable the stub process support */ +#define SDL_PROCESS_DUMMY 1 + /* Enable the stub sensor driver (src/sensor/dummy/\*.c) */ #define SDL_SENSOR_DISABLED 1 diff --git a/libs/SDL3/include/build_config/SDL_build_config_windows.h b/libs/SDL3/include/build_config/SDL_build_config_windows.h index e6bc73f73..24e21f88f 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_windows.h +++ b/libs/SDL3/include/build_config/SDL_build_config_windows.h @@ -86,15 +86,13 @@ typedef unsigned int uintptr_t; #define HAVE_DXGI_H 1 #define HAVE_XINPUT_H 1 #if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0A00 /* Windows 10 SDK */ +#define HAVE_DXGI1_6_H 1 #define HAVE_WINDOWS_GAMING_INPUT_H 1 #endif #if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0602 /* Windows 8 SDK */ #define HAVE_D3D11_H 1 #define HAVE_ROAPI_H 1 #endif -#if defined(WDK_NTDDI_VERSION) && WDK_NTDDI_VERSION > 0x0A000008 /* 10.0.19041.0 */ -#define HAVE_D3D12_H 1 -#endif #if defined(_WIN32_MAXVER) && _WIN32_MAXVER >= 0x0603 /* Windows 8.1 SDK */ #define HAVE_SHELLSCALINGAPI_H 1 #endif @@ -102,6 +100,9 @@ typedef unsigned int uintptr_t; #define HAVE_AUDIOCLIENT_H 1 #define HAVE_TPCSHRD_H 1 #define HAVE_SENSORSAPI_H 1 +#if defined(__has_include) && __has_include() +#define HAVE_GAMEINPUT_H 1 +#endif #if (defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)) && (defined(_MSC_VER) && _MSC_VER >= 1600) #elif defined(__has_include) && (defined(__i386__) || defined(__x86_64)) # if !__has_include() @@ -123,6 +124,7 @@ typedef unsigned int uintptr_t; #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDIO_H 1 #define HAVE_STDLIB_H 1 @@ -158,6 +160,7 @@ typedef unsigned int uintptr_t; #define HAVE_ATOF 1 #define HAVE_STRCMP 1 #define HAVE_STRNCMP 1 +#define HAVE_STRPBRK 1 #define HAVE__WCSDUP 1 #define HAVE_SSCANF 1 #define HAVE_VSSCANF 1 @@ -172,6 +175,10 @@ typedef unsigned int uintptr_t; #define HAVE_FABS 1 #define HAVE_FLOOR 1 #define HAVE_FMOD 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOG10 1 #define HAVE_POW 1 @@ -195,7 +202,7 @@ typedef unsigned int uintptr_t; #define HAVE_SINF 1 #define HAVE_SQRTF 1 #define HAVE_TANF 1 -#if defined(_MSC_VER) +#ifdef _MSC_VER /* These functions were added with the VC++ 2013 C runtime library */ #if _MSC_VER >= 1800 #define HAVE_STRTOLL 1 @@ -231,11 +238,11 @@ typedef unsigned int uintptr_t; /* Enable various input drivers */ #define SDL_JOYSTICK_DINPUT 1 -/*#define SDL_JOYSTICK_GAMEINPUT 1*/ +#ifdef HAVE_GAMEINPUT_H +#define SDL_JOYSTICK_GAMEINPUT 1 +#endif #define SDL_JOYSTICK_HIDAPI 1 -#ifndef SDL_PLATFORM_WINRT #define SDL_JOYSTICK_RAWINPUT 1 -#endif #define SDL_JOYSTICK_VIRTUAL 1 #ifdef HAVE_WINDOWS_GAMING_INPUT_H #define SDL_JOYSTICK_WGI 1 @@ -243,6 +250,9 @@ typedef unsigned int uintptr_t; #define SDL_JOYSTICK_XINPUT 1 #define SDL_HAPTIC_DINPUT 1 +/* Enable various process implementations */ +#define SDL_PROCESS_WINDOWS 1 + /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H #define SDL_SENSOR_WINDOWS 1 @@ -265,45 +275,34 @@ typedef unsigned int uintptr_t; #define SDL_TIMER_WINDOWS 1 /* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_DUMMY 1 -#define SDL_VIDEO_DRIVER_WINDOWS 1 - -#ifndef SDL_VIDEO_RENDER_D3D -#define SDL_VIDEO_RENDER_D3D 1 -#endif -#if !defined(SDL_VIDEO_RENDER_D3D11) && defined(HAVE_D3D11_H) -#define SDL_VIDEO_RENDER_D3D11 1 -#endif -#if !defined(SDL_VIDEO_RENDER_D3D12) && defined(HAVE_D3D12_H) -#define SDL_VIDEO_RENDER_D3D12 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_OFFSCREEN 1 +#define SDL_VIDEO_DRIVER_WINDOWS 1 +#define SDL_VIDEO_RENDER_D3D 1 +#ifdef HAVE_D3D11_H +#define SDL_VIDEO_RENDER_D3D11 1 #endif +#define SDL_VIDEO_RENDER_D3D12 1 /* Enable OpenGL support */ -#ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_WGL -#define SDL_VIDEO_OPENGL_WGL 1 -#endif -#ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 1 -#endif -#ifndef SDL_VIDEO_RENDER_OGL_ES2 -#define SDL_VIDEO_RENDER_OGL_ES2 1 -#endif -#ifndef SDL_VIDEO_OPENGL_ES2 -#define SDL_VIDEO_OPENGL_ES2 1 -#endif -#ifndef SDL_VIDEO_OPENGL_EGL -#define SDL_VIDEO_OPENGL_EGL 1 -#endif +#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_RENDER_OGL 1 +#define SDL_VIDEO_RENDER_OGL_ES2 1 +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_EGL 1 /* Enable Vulkan support */ #define SDL_VIDEO_VULKAN 1 +#define SDL_VIDEO_RENDER_VULKAN 1 -#ifndef SDL_VIDEO_RENDER_VULKAN -#define SDL_VIDEO_RENDER_VULKAN 1 +/* Enable GPU support */ +#ifdef HAVE_D3D11_H +#define SDL_GPU_D3D11 1 #endif +#define SDL_GPU_D3D12 1 +#define SDL_GPU_VULKAN 1 +#define SDL_VIDEO_RENDER_GPU 1 /* Enable system power support */ #define SDL_POWER_WINDOWS 1 diff --git a/libs/SDL3/include/build_config/SDL_build_config_wingdk.h b/libs/SDL3/include/build_config/SDL_build_config_wingdk.h index 167d661f3..5b7ebf1dd 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_wingdk.h +++ b/libs/SDL3/include/build_config/SDL_build_config_wingdk.h @@ -37,16 +37,17 @@ #define HAVE_DSOUND_H 1 /* No SDK version checks needed for these because the SDK has to be new. */ #define HAVE_DXGI_H 1 +#define HAVE_DXGI1_6_H 1 #define HAVE_XINPUT_H 1 #define HAVE_WINDOWS_GAMING_INPUT_H 1 #define HAVE_D3D11_H 1 #define HAVE_ROAPI_H 1 -#define HAVE_D3D12_H 1 #define HAVE_SHELLSCALINGAPI_H 1 #define HAVE_MMDEVICEAPI_H 1 #define HAVE_AUDIOCLIENT_H 1 #define HAVE_TPCSHRD_H 1 #define HAVE_SENSORSAPI_H 1 +#define HAVE_GAMEINPUT_H 1 #if (defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)) && (defined(_MSC_VER) && _MSC_VER >= 1600) #elif defined(__has_include) && (defined(__i386__) || defined(__x86_64)) # if !__has_include() @@ -62,6 +63,7 @@ #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -110,6 +112,10 @@ #define HAVE_FABS 1 #define HAVE_FLOOR 1 #define HAVE_FMOD 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOG10 1 #define HAVE_POW 1 @@ -133,7 +139,7 @@ #define HAVE_SINF 1 #define HAVE_SQRTF 1 #define HAVE_TANF 1 -#if defined(_MSC_VER) +#ifdef _MSC_VER /* These functions were added with the VC++ 2013 C runtime library */ #define HAVE_STRTOLL 1 #define HAVE_STRTOULL 1 @@ -160,24 +166,16 @@ /* Enable various input drivers */ #define SDL_JOYSTICK_DINPUT 1 +#define SDL_JOYSTICK_GAMEINPUT 1 #define SDL_JOYSTICK_HIDAPI 1 #define SDL_JOYSTICK_RAWINPUT 1 #define SDL_JOYSTICK_VIRTUAL 1 -#ifdef HAVE_WINDOWS_GAMING_INPUT_H #define SDL_JOYSTICK_WGI 1 -#endif #define SDL_JOYSTICK_XINPUT 1 #define SDL_HAPTIC_DINPUT 1 -/* Native GameInput: */ -/*#define SDL_JOYSTICK_GAMEINPUT 1*/ -#if defined(SDL_JOYSTICK_GAMEINPUT) && (defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_DINPUT)) -#error "GameInput cannot co-exist, choose one." -#endif /* defined(SDL_JOYSTICK_GAMEINPUT) && (defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_DINPUT)) */ -#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT -/* TODO: Implement proper haptics for GameInput! */ -#define SDL_HAPTIC_DUMMY 1 -#endif /* defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT */ +/* Enable various process implementations */ +#define SDL_PROCESS_WINDOWS 1 /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H @@ -201,41 +199,33 @@ #define SDL_TIMER_WINDOWS 1 /* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_DUMMY 1 -#define SDL_VIDEO_DRIVER_WINDOWS 1 - -#ifndef SDL_VIDEO_RENDER_D3D -#define SDL_VIDEO_RENDER_D3D 1 -#endif -#if !defined(SDL_VIDEO_RENDER_D3D11) && defined(HAVE_D3D11_H) -#define SDL_VIDEO_RENDER_D3D11 1 -#endif -#if !defined(SDL_VIDEO_RENDER_D3D12) && defined(HAVE_D3D12_H) -#define SDL_VIDEO_RENDER_D3D12 1 +#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_WINDOWS 1 +#define SDL_VIDEO_RENDER_D3D 1 +#ifdef HAVE_D3D11_H +#define SDL_VIDEO_RENDER_D3D11 1 #endif +#define SDL_VIDEO_RENDER_D3D12 1 /* Enable OpenGL support */ -#ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_WGL -#define SDL_VIDEO_OPENGL_WGL 1 -#endif -#ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 1 -#endif -#ifndef SDL_VIDEO_RENDER_OGL_ES2 -#define SDL_VIDEO_RENDER_OGL_ES2 1 -#endif -#ifndef SDL_VIDEO_OPENGL_ES2 -#define SDL_VIDEO_OPENGL_ES2 1 -#endif -#ifndef SDL_VIDEO_OPENGL_EGL -#define SDL_VIDEO_OPENGL_EGL 1 -#endif +#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_RENDER_OGL 1 +#define SDL_VIDEO_RENDER_OGL_ES2 1 +#define SDL_VIDEO_OPENGL_ES2 1 +#define SDL_VIDEO_OPENGL_EGL 1 /* Enable Vulkan support */ #define SDL_VIDEO_VULKAN 1 +#define SDL_VIDEO_RENDER_VULKAN 1 + +/* Enable GPU support */ +#ifdef HAVE_D3D11_H +#define SDL_GPU_D3D11 1 +#endif +#define SDL_GPU_D3D12 1 +#define SDL_GPU_VULKAN 1 +#define SDL_VIDEO_RENDER_GPU 1 /* Enable system power support */ #define SDL_POWER_WINDOWS 1 diff --git a/libs/SDL3/include/build_config/SDL_build_config_winrt.h b/libs/SDL3/include/build_config/SDL_build_config_winrt.h deleted file mode 100644 index 1555962b8..000000000 --- a/libs/SDL3/include/build_config/SDL_build_config_winrt.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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_build_config_winrt_h_ -#define SDL_build_config_winrt_h_ -#define SDL_build_config_h_ - -#include - -/* Make sure the Windows SDK's NTDDI_VERSION macro gets defined. This is used - by SDL to determine which version of the Windows SDK is being used. -*/ -#include - -/* Define possibly-undefined NTDDI values (used when compiling SDL against - older versions of the Windows SDK. -*/ -#ifndef NTDDI_WINBLUE -#define NTDDI_WINBLUE 0x06030000 -#endif -#ifndef NTDDI_WIN10 -#define NTDDI_WIN10 0x0A000000 -#endif - -/* This is a set of defines to configure the SDL features */ - -#ifdef __clang__ -# define HAVE_GCC_ATOMICS 1 -#endif - -/* Useful headers */ -#define HAVE_DXGI_H 1 -#if !SDL_WINAPI_FAMILY_PHONE -#define HAVE_XINPUT_H 1 -#endif - -#define HAVE_MMDEVICEAPI_H 1 -#define HAVE_AUDIOCLIENT_H 1 -#define HAVE_TPCSHRD_H 1 - -#define HAVE_LIBC 1 -#define HAVE_FLOAT_H 1 -#define HAVE_LIMITS_H 1 -#define HAVE_MATH_H 1 -#define HAVE_SIGNAL_H 1 -#define HAVE_STDARG_H 1 -#define HAVE_STDDEF_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDIO_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRING_H 1 -#define HAVE_WCHAR_H 1 - -/* C library functions */ -#define HAVE_LIBC 1 -#define HAVE_MALLOC 1 -#define HAVE_CALLOC 1 -#define HAVE_REALLOC 1 -#define HAVE_FREE 1 -#define HAVE_ABS 1 -#define HAVE_MEMSET 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMMOVE 1 -#define HAVE_MEMCMP 1 -#define HAVE_STRLEN 1 -#define HAVE__STRREV 1 -#define HAVE__STRUPR 1 -#define HAVE_STRCHR 1 -#define HAVE_STRRCHR 1 -#define HAVE_STRSTR 1 -#define HAVE_STRTOL 1 -#define HAVE_STRTOUL 1 -/* #undef HAVE_STRTOLL */ -/* #undef HAVE_STRTOULL */ -#define HAVE_STRTOD 1 -#define HAVE_ATOI 1 -#define HAVE_ATOF 1 -#define HAVE_STRCMP 1 -#define HAVE_STRNCMP 1 -#define HAVE_VSNPRINTF 1 -/* TODO, WinRT: consider using ??_s versions of the following */ -/* #undef HAVE__STRLWR */ -/* #undef HAVE_ITOA */ -/* #undef HAVE__LTOA */ -/* #undef HAVE__ULTOA */ -/* #undef HAVE_SSCANF */ -#define HAVE_ACOS 1 -#define HAVE_ACOSF 1 -#define HAVE_ASIN 1 -#define HAVE_ASINF 1 -#define HAVE_ATAN 1 -#define HAVE_ATANF 1 -#define HAVE_ATAN2 1 -#define HAVE_ATAN2F 1 -#define HAVE_CEIL 1 -#define HAVE_CEILF 1 -#define HAVE__COPYSIGN 1 -#define HAVE_COS 1 -#define HAVE_COSF 1 -#define HAVE_EXP 1 -#define HAVE_EXPF 1 -#define HAVE_FABS 1 -#define HAVE_FABSF 1 -#define HAVE_FLOOR 1 -#define HAVE_FLOORF 1 -#define HAVE_FMOD 1 -#define HAVE_FMODF 1 -#define HAVE_LOG 1 -#define HAVE_LOGF 1 -#define HAVE_LOG10 1 -#define HAVE_LOG10F 1 -#define HAVE_LROUND 1 -#define HAVE_LROUNDF 1 -#define HAVE_MODF 1 -#define HAVE_MODFF 1 -#define HAVE_POW 1 -#define HAVE_POWF 1 -#define HAVE_ROUND 1 -#define HAVE_ROUNDF 1 -#define HAVE__SCALB 1 -#define HAVE_SIN 1 -#define HAVE_SINF 1 -#define HAVE_SQRT 1 -#define HAVE_SQRTF 1 -#define HAVE_TAN 1 -#define HAVE_TANF 1 -#define HAVE_TRUNC 1 -#define HAVE_TRUNCF 1 -#define HAVE__FSEEKI64 1 - -#define HAVE_ROAPI_H 1 - -/* Enable various audio drivers */ -#define SDL_AUDIO_DRIVER_WASAPI 1 -#define SDL_AUDIO_DRIVER_DISK 1 -#define SDL_AUDIO_DRIVER_DUMMY 1 - -/* Enable various input drivers */ -#if SDL_WINAPI_FAMILY_PHONE -#define SDL_JOYSTICK_DISABLED 1 -#define SDL_HAPTIC_DISABLED 1 -#else -#define SDL_JOYSTICK_VIRTUAL 1 -#if (NTDDI_VERSION >= NTDDI_WIN10) -#define SDL_JOYSTICK_WGI 1 -#define SDL_HAPTIC_DISABLED 1 -#else -#define SDL_JOYSTICK_XINPUT 1 -#endif /* WIN10 */ -#endif - -/* WinRT doesn't have HIDAPI available */ -#define SDL_HIDAPI_DISABLED 1 - -/* Enable the dummy sensor driver */ -#define SDL_SENSOR_DUMMY 1 - -/* Enable various shared object loading systems */ -#define SDL_LOADSO_WINDOWS 1 - -/* Enable various threading systems */ -#if (NTDDI_VERSION >= NTDDI_WINBLUE) -#define SDL_THREAD_GENERIC_COND_SUFFIX 1 -#define SDL_THREAD_GENERIC_RWLOCK_SUFFIX 1 -#define SDL_THREAD_WINDOWS 1 -#else -/* WinRT on Windows 8.0 and Windows Phone 8.0 don't support CreateThread() */ -#define SDL_THREAD_STDCPP 1 -#endif - -/* Enable RTC system */ -#define SDL_TIME_WINDOWS 1 - -/* Enable various timer systems */ -#define SDL_TIMER_WINDOWS 1 - -/* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_WINRT 1 -#define SDL_VIDEO_DRIVER_DUMMY 1 - -/* Enable OpenGL ES 2.0 (via a modified ANGLE library) */ -#define SDL_VIDEO_OPENGL_ES2 1 -#define SDL_VIDEO_OPENGL_EGL 1 - -/* Enable appropriate renderer(s) */ -#define SDL_VIDEO_RENDER_D3D11 1 - -/* Disable D3D12 as it's not implemented for WinRT */ -/* #undef SDL_VIDEO_RENDER_D3D12 */ - -#ifdef SDL_VIDEO_OPENGL_ES2 -#define SDL_VIDEO_RENDER_OGL_ES2 1 -#endif - -/* Enable system power support */ -#define SDL_POWER_WINRT 1 - -/* Enable filesystem support */ -#define SDL_FILESYSTEM_WINDOWS 1 -#define SDL_FSOPS_WINDOWS 1 - -/* Enable the camera driver (src/camera/dummy/\*.c) */ /* !!! FIXME */ -#define SDL_CAMERA_DRIVER_DUMMY 1 - -#endif /* SDL_build_config_winrt_h_ */ diff --git a/libs/SDL3/include/build_config/SDL_build_config_xbox.h b/libs/SDL3/include/build_config/SDL_build_config_xbox.h index 0ca413132..02e06799e 100644 --- a/libs/SDL3/include/build_config/SDL_build_config_xbox.h +++ b/libs/SDL3/include/build_config/SDL_build_config_xbox.h @@ -41,12 +41,12 @@ /*#define HAVE_WINDOWS_GAMING_INPUT_H 1*/ /*#define HAVE_D3D11_H 1*/ /*#define HAVE_ROAPI_H 1*/ -#define HAVE_D3D12_H 1 /*#define HAVE_SHELLSCALINGAPI_H 1*/ #define HAVE_MMDEVICEAPI_H 1 #define HAVE_AUDIOCLIENT_H 1 /*#define HAVE_TPCSHRD_H 1*/ /*#define HAVE_SENSORSAPI_H 1*/ +#define HAVE_GAMEINPUT_H 1 #if (defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)) && (defined(_MSC_VER) && _MSC_VER >= 1600) #elif defined(__has_include) && (defined(__i386__) || defined(__x86_64)) # if !__has_include() @@ -62,6 +62,7 @@ #define HAVE_MATH_H 1 #define HAVE_SIGNAL_H 1 #define HAVE_STDARG_H 1 +#define HAVE_STDBOOL_H 1 #define HAVE_STDDEF_H 1 #define HAVE_STDINT_H 1 #define HAVE_STDIO_H 1 @@ -81,6 +82,7 @@ #define HAVE_MEMMOVE 1 #define HAVE_MEMCMP 1 #define HAVE_STRLEN 1 +#define HAVE_STRPBRK 1 #define HAVE__STRREV 1 /* These functions have security warnings, so we won't use them */ /* #undef HAVE__STRUPR */ @@ -110,6 +112,10 @@ #define HAVE_FABS 1 #define HAVE_FLOOR 1 #define HAVE_FMOD 1 +#define HAVE_ISINF 1 +#define HAVE_ISINF_FLOAT_MACRO 1 +#define HAVE_ISNAN 1 +#define HAVE_ISNAN_FLOAT_MACRO 1 #define HAVE_LOG 1 #define HAVE_LOG10 1 #define HAVE_POW 1 @@ -133,7 +139,7 @@ #define HAVE_SINF 1 #define HAVE_SQRTF 1 #define HAVE_TANF 1 -#if defined(_MSC_VER) +#ifdef _MSC_VER /* These functions were added with the VC++ 2013 C runtime library */ #define HAVE_STRTOLL 1 #define HAVE_STRTOULL 1 @@ -159,25 +165,15 @@ #define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various input drivers */ -/*#define SDL_JOYSTICK_DINPUT 1*/ -/*#define SDL_JOYSTICK_HIDAPI 1*/ -/*#define SDL_JOYSTICK_RAWINPUT 1*/ #define SDL_JOYSTICK_VIRTUAL 1 -#ifdef HAVE_WINDOWS_GAMING_INPUT_H -#define SDL_JOYSTICK_WGI 1 -#endif /* This is XInputOnGameInput for GDK platforms: */ /*#define SDL_JOYSTICK_XINPUT 1*/ /* Native GameInput: */ #define SDL_JOYSTICK_GAMEINPUT 1 -#if defined(SDL_JOYSTICK_GAMEINPUT) && (defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_DINPUT)) -#error "GameInput cannot co-exist, choose one." -#endif /* defined(SDL_JOYSTICK_GAMEINPUT) && (defined(SDL_JOYSTICK_XINPUT) || defined(SDL_JOYSTICK_DINPUT)) */ -#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT -/* TODO: Implement proper haptics for GameInput! */ #define SDL_HAPTIC_DUMMY 1 -#endif /* defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT */ -/*#define SDL_HAPTIC_DINPUT 1*/ + +/* Enable various process implementations */ +#define SDL_PROCESS_DUMMY 1 /* Enable the sensor driver */ #ifdef HAVE_SENSORSAPI_H @@ -201,23 +197,18 @@ #define SDL_TIMER_WINDOWS 1 /* Enable various video drivers */ -#define SDL_VIDEO_DRIVER_DUMMY 1 -#define SDL_VIDEO_DRIVER_WINDOWS 1 - -#if !defined(SDL_VIDEO_RENDER_D3D12) && defined(HAVE_D3D12_H) -#define SDL_VIDEO_RENDER_D3D12 1 -#endif +#define SDL_VIDEO_DRIVER_DUMMY 1 +#define SDL_VIDEO_DRIVER_WINDOWS 1 +#define SDL_VIDEO_RENDER_D3D12 1 /* Enable OpenGL support */ -#ifndef SDL_VIDEO_OPENGL -#define SDL_VIDEO_OPENGL 1 -#endif -#ifndef SDL_VIDEO_OPENGL_WGL -#define SDL_VIDEO_OPENGL_WGL 1 -#endif -#ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 1 -#endif +#define SDL_VIDEO_OPENGL 1 +#define SDL_VIDEO_OPENGL_WGL 1 +#define SDL_VIDEO_RENDER_OGL 1 + +/* Enable GPU support */ +#define SDL_GPU_D3D12 1 +#define SDL_VIDEO_RENDER_GPU 1 /* Enable system power support */ /*#define SDL_POWER_WINDOWS 1*/ diff --git a/libs/SDL3/mingw/pkg-support/INSTALL.txt b/libs/SDL3/mingw/pkg-support/INSTALL.txt deleted file mode 100644 index 607dafd0e..000000000 --- a/libs/SDL3/mingw/pkg-support/INSTALL.txt +++ /dev/null @@ -1,18 +0,0 @@ - -The 32-bit files are in i686-w64-mingw32 -The 64-bit files are in x86_64-w64-mingw32 - -To install SDL for native development: - make native - -To install SDL for cross-compiling development: - make cross - -Look at the example programs in ./test, and check out online documentation: - http://wiki.libsdl.org/ - -Join the SDL developer mailing list if you want to join the community: - http://www.libsdl.org/mailing-list.php - -That's it! -Sam Lantinga diff --git a/libs/SDL3/mingw/pkg-support/Makefile b/libs/SDL3/mingw/pkg-support/Makefile deleted file mode 100644 index 19732d7d2..000000000 --- a/libs/SDL3/mingw/pkg-support/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# -# Makefile for installing the mingw32 version of the SDL library - -CROSS_PATH := /usr/local -ARCHITECTURES := i686-w64-mingw32 x86_64-w64-mingw32 - -all install: - @echo "Type \"make native\" to install 32-bit to /usr" - @echo "Type \"make cross\" to install 32-bit and 64-bit to $(CROSS_PATH)" - -native: - make install-package arch=i686-w64-mingw32 prefix=/usr - -cross: - for arch in $(ARCHITECTURES); do \ - make install-package arch=$$arch prefix=$(CROSS_PATH)/$$arch; \ - done - -install-package: - @if test -d $(arch) && test -d $(prefix); then \ - (cd $(arch) && cp -rv bin include lib share $(prefix)/); \ - sed "s|^prefix=.*|prefix=$(prefix)|" <$(arch)/lib/pkgconfig/sdl3.pc >$(prefix)/lib/pkgconfig/sdl3.pc; \ - else \ - echo "*** ERROR: $(arch) or $(prefix) does not exist!"; \ - exit 1; \ - fi diff --git a/libs/SDL3/mingw/pkg-support/cmake/sdl3-config-version.cmake b/libs/SDL3/mingw/pkg-support/cmake/sdl3-config-version.cmake deleted file mode 100644 index 5a78c11ee..000000000 --- a/libs/SDL3/mingw/pkg-support/cmake/sdl3-config-version.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# SDL3 CMake version configuration file: -# This file is meant to be placed in a cmake subfolder of SDL3-devel-3.x.y-mingw - -if(CMAKE_SIZEOF_VOID_P EQUAL 4) - set(sdl3_config_path "${CMAKE_CURRENT_LIST_DIR}/../i686-w64-mingw32/lib/cmake/SDL3/SDL3ConfigVersion.cmake") -elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(sdl3_config_path "${CMAKE_CURRENT_LIST_DIR}/../x86_64-w64-mingw32/lib/cmake/SDL3/SDL3ConfigVersion.cmake") -else() - set(PACKAGE_VERSION_UNSUITABLE TRUE) - return() -endif() - -if(NOT EXISTS "${sdl3_config_path}") - message(WARNING "${sdl3_config_path} does not exist: MinGW development package is corrupted") - set(PACKAGE_VERSION_UNSUITABLE TRUE) - return() -endif() - -include("${sdl3_config_path}") diff --git a/libs/SDL3/src/SDL.c b/libs/SDL3/src/SDL.c index f3faf9d59..c140ef36c 100644 --- a/libs/SDL3/src/SDL.c +++ b/libs/SDL3/src/SDL.c @@ -21,43 +21,48 @@ #include "SDL_internal.h" #include "SDL3/SDL_revision.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "core/windows/SDL_windows.h" -#elif !defined(SDL_PLATFORM_WINRT) -#include /* _exit(), etc. */ +#else +#include // _exit(), etc. #endif -/* this checks for HAVE_DBUS_DBUS_H internally. */ +// this checks for HAVE_DBUS_DBUS_H internally. #include "core/linux/SDL_dbus.h" #ifdef SDL_PLATFORM_EMSCRIPTEN #include #endif -/* Initialization code for SDL */ +// Initialization code for SDL #include "SDL_assert_c.h" #include "SDL_hints_c.h" #include "SDL_log_c.h" #include "SDL_properties_c.h" #include "audio/SDL_sysaudio.h" +#include "camera/SDL_camera_c.h" #include "cpuinfo/SDL_cpuinfo_c.h" -#include "video/SDL_video_c.h" #include "events/SDL_events_c.h" #include "haptic/SDL_haptic_c.h" #include "joystick/SDL_gamepad_c.h" #include "joystick/SDL_joystick_c.h" +#include "render/SDL_sysrender.h" #include "sensor/SDL_sensor_c.h" -#include "camera/SDL_camera_c.h" +#include "stdlib/SDL_getenv_c.h" +#include "thread/SDL_thread_c.h" +#include "video/SDL_pixels_c.h" +#include "video/SDL_surface_c.h" +#include "video/SDL_video_c.h" +#include "filesystem/SDL_filesystem_c.h" #define SDL_INIT_EVERYTHING ~0U -/* Initialization/Cleanup routines */ -#include "time/SDL_time_c.h" +// Initialization/Cleanup routines #include "timer/SDL_timer_c.h" #ifdef SDL_VIDEO_DRIVER_WINDOWS -extern int SDL_HelperWindowCreate(void); -extern int SDL_HelperWindowDestroy(void); +extern bool SDL_HelperWindowCreate(void); +extern void SDL_HelperWindowDestroy(void); #endif #ifdef SDL_BUILD_MAJOR_VERSION @@ -66,20 +71,16 @@ SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MAJOR_VERSION, SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MINOR_VERSION, SDL_MINOR_VERSION == SDL_BUILD_MINOR_VERSION); SDL_COMPILE_TIME_ASSERT(SDL_BUILD_MICRO_VERSION, - SDL_PATCHLEVEL == SDL_BUILD_MICRO_VERSION); + SDL_MICRO_VERSION == SDL_BUILD_MICRO_VERSION); #endif +// Limited by its encoding in SDL_VERSIONNUM SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_min, SDL_MAJOR_VERSION >= 0); -/* Limited only by the need to fit in SDL_Version */ -SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_max, SDL_MAJOR_VERSION <= 255); - +SDL_COMPILE_TIME_ASSERT(SDL_MAJOR_VERSION_max, SDL_MAJOR_VERSION <= 10); SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_min, SDL_MINOR_VERSION >= 0); -/* Limited only by the need to fit in SDL_Version */ -SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_max, SDL_MINOR_VERSION <= 255); - -SDL_COMPILE_TIME_ASSERT(SDL_PATCHLEVEL_min, SDL_PATCHLEVEL >= 0); -/* Limited by its encoding in SDL_VERSIONNUM and in the ABI versions */ -SDL_COMPILE_TIME_ASSERT(SDL_PATCHLEVEL_max, SDL_PATCHLEVEL <= 99); +SDL_COMPILE_TIME_ASSERT(SDL_MINOR_VERSION_max, SDL_MINOR_VERSION <= 999); +SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_min, SDL_MICRO_VERSION >= 0); +SDL_COMPILE_TIME_ASSERT(SDL_MICRO_VERSION_max, SDL_MICRO_VERSION <= 999); /* This is not declared in any header, although it is shared between some parts of SDL, because we don't want anything calling it without an @@ -87,7 +88,7 @@ SDL_COMPILE_TIME_ASSERT(SDL_PATCHLEVEL_max, SDL_PATCHLEVEL <= 99); extern SDL_NORETURN void SDL_ExitProcess(int exitcode); SDL_NORETURN void SDL_ExitProcess(int exitcode) { -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) /* "if you do not know the state of all threads in your process, it is better to call TerminateProcess than ExitProcess" https://msdn.microsoft.com/en-us/library/windows/desktop/ms682658(v=vs.85).aspx */ @@ -96,28 +97,92 @@ SDL_NORETURN void SDL_ExitProcess(int exitcode) ExitProcess here that will never be reached but make MingW happy. */ ExitProcess(exitcode); #elif defined(SDL_PLATFORM_EMSCRIPTEN) - emscripten_cancel_main_loop(); /* this should "kill" the app. */ - emscripten_force_exit(exitcode); /* this should "kill" the app. */ + emscripten_cancel_main_loop(); // this should "kill" the app. + emscripten_force_exit(exitcode); // this should "kill" the app. exit(exitcode); -#elif defined(SDL_PLATFORM_HAIKU) /* Haiku has _Exit, but it's not marked noreturn. */ +#elif defined(SDL_PLATFORM_HAIKU) // Haiku has _Exit, but it's not marked noreturn. _exit(exitcode); -#elif defined(HAVE__EXIT) /* Upper case _Exit() */ +#elif defined(HAVE__EXIT) // Upper case _Exit() _Exit(exitcode); #else _exit(exitcode); #endif } -/* The initialized subsystems */ +// App metadata + +bool SDL_SetAppMetadata(const char *appname, const char *appversion, const char *appidentifier) +{ + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, appname); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, appversion); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, appidentifier); + return true; +} + +static bool SDL_ValidMetadataProperty(const char *name) +{ + if (!name || !*name) { + return false; + } + + if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_VERSION_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_CREATOR_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_COPYRIGHT_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_URL_STRING) == 0 || + SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) { + return true; + } + return false; +} + +bool SDL_SetAppMetadataProperty(const char *name, const char *value) +{ + if (!SDL_ValidMetadataProperty(name)) { + return SDL_InvalidParamError("name"); + } + + return SDL_SetStringProperty(SDL_GetGlobalProperties(), name, value); +} + +const char *SDL_GetAppMetadataProperty(const char *name) +{ + if (!SDL_ValidMetadataProperty(name)) { + SDL_InvalidParamError("name"); + return NULL; + } + + const char *value = NULL; + if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) { + value = SDL_GetHint(SDL_HINT_APP_NAME); + } else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_IDENTIFIER_STRING) == 0) { + value = SDL_GetHint(SDL_HINT_APP_ID); + } + if (!value || !*value) { + value = SDL_GetStringProperty(SDL_GetGlobalProperties(), name, NULL); + } + if (!value || !*value) { + if (SDL_strcmp(name, SDL_PROP_APP_METADATA_NAME_STRING) == 0) { + value = "SDL Application"; + } else if (SDL_strcmp(name, SDL_PROP_APP_METADATA_TYPE_STRING) == 0) { + value = "application"; + } + } + return value; +} + + +// The initialized subsystems #ifdef SDL_MAIN_NEEDED -static SDL_bool SDL_MainIsReady = SDL_FALSE; +static bool SDL_MainIsReady = false; #else -static SDL_bool SDL_MainIsReady = SDL_TRUE; +static bool SDL_MainIsReady = true; #endif -static SDL_bool SDL_bInMainQuit = SDL_FALSE; +static bool SDL_bInMainQuit = false; static Uint8 SDL_SubsystemRefCount[32]; -/* Private helper to increment a subsystem's ref counter. */ +// Private helper to increment a subsystem's ref counter. static void SDL_IncrementSubsystemRefCount(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); @@ -127,7 +192,7 @@ static void SDL_IncrementSubsystemRefCount(Uint32 subsystem) } } -/* Private helper to decrement a subsystem's ref counter. */ +// Private helper to decrement a subsystem's ref counter. static void SDL_DecrementSubsystemRefCount(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); @@ -140,20 +205,20 @@ static void SDL_DecrementSubsystemRefCount(Uint32 subsystem) } } -/* Private helper to check if a system needs init. */ -static SDL_bool SDL_ShouldInitSubsystem(Uint32 subsystem) +// Private helper to check if a system needs init. +static bool SDL_ShouldInitSubsystem(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); return ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)); } -/* Private helper to check if a system needs to be quit. */ -static SDL_bool SDL_ShouldQuitSubsystem(Uint32 subsystem) +// Private helper to check if a system needs to be quit. +static bool SDL_ShouldQuitSubsystem(Uint32 subsystem) { const int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); if ((subsystem_index >= 0) && (SDL_SubsystemRefCount[subsystem_index] == 0)) { - return SDL_FALSE; + return false; } /* If we're in SDL_Quit, we shut down every subsystem, even if refcount @@ -164,26 +229,43 @@ static SDL_bool SDL_ShouldQuitSubsystem(Uint32 subsystem) /* Private helper to either increment's existing ref counter, * or fully init a new subsystem. */ -static SDL_bool SDL_InitOrIncrementSubsystem(Uint32 subsystem) +static bool SDL_InitOrIncrementSubsystem(Uint32 subsystem) { int subsystem_index = SDL_MostSignificantBitIndex32(subsystem); SDL_assert((subsystem_index < 0) || (SDL_SubsystemRefCount[subsystem_index] < 255)); if (subsystem_index < 0) { - return SDL_FALSE; + return false; } if (SDL_SubsystemRefCount[subsystem_index] > 0) { ++SDL_SubsystemRefCount[subsystem_index]; - return SDL_TRUE; + return true; } - return SDL_InitSubSystem(subsystem) == 0; + return SDL_InitSubSystem(subsystem); } void SDL_SetMainReady(void) { - SDL_MainIsReady = SDL_TRUE; + SDL_MainIsReady = true; +} + +// Initialize all the subsystems that require initialization before threads start +void SDL_InitMainThread(void) +{ + SDL_InitTLSData(); + SDL_InitEnvironment(); + SDL_InitTicks(); + SDL_InitFilesystem(); +} + +static void SDL_QuitMainThread(void) +{ + SDL_QuitFilesystem(); + SDL_QuitTicks(); + SDL_QuitEnvironment(); + SDL_QuitTLSData(); } -int SDL_InitSubSystem(Uint32 flags) +bool SDL_InitSubSystem(SDL_InitFlags flags) { Uint32 flags_initialized = 0; @@ -191,12 +273,7 @@ int SDL_InitSubSystem(Uint32 flags) return SDL_SetError("Application didn't initialize properly, did you include SDL_main.h in the file containing your main() function?"); } - SDL_InitLog(); - SDL_InitProperties(); - SDL_GetGlobalProperties(); - - /* Clear the error message */ - SDL_ClearError(); + SDL_InitMainThread(); #ifdef SDL_USE_LIBDBUS SDL_DBus_Init(); @@ -204,20 +281,17 @@ int SDL_InitSubSystem(Uint32 flags) #ifdef SDL_VIDEO_DRIVER_WINDOWS if (flags & (SDL_INIT_HAPTIC | SDL_INIT_JOYSTICK)) { - if (SDL_HelperWindowCreate() < 0) { + if (!SDL_HelperWindowCreate()) { goto quit_and_error; } } #endif - SDL_InitTime(); - SDL_InitTicks(); - - /* Initialize the event subsystem */ + // Initialize the event subsystem if (flags & SDL_INIT_EVENTS) { if (SDL_ShouldInitSubsystem(SDL_INIT_EVENTS)) { SDL_IncrementSubsystemRefCount(SDL_INIT_EVENTS); - if (SDL_InitEvents() < 0) { + if (!SDL_InitEvents()) { SDL_DecrementSubsystemRefCount(SDL_INIT_EVENTS); goto quit_and_error; } @@ -227,32 +301,19 @@ int SDL_InitSubSystem(Uint32 flags) flags_initialized |= SDL_INIT_EVENTS; } - /* Initialize the timer subsystem */ - if (flags & SDL_INIT_TIMER) { - if (SDL_ShouldInitSubsystem(SDL_INIT_TIMER)) { - SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER); - if (SDL_InitTimers() < 0) { - SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER); - goto quit_and_error; - } - } else { - SDL_IncrementSubsystemRefCount(SDL_INIT_TIMER); - } - flags_initialized |= SDL_INIT_TIMER; - } - - /* Initialize the video subsystem */ + // Initialize the video subsystem if (flags & SDL_INIT_VIDEO) { #ifndef SDL_VIDEO_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_VIDEO)) { - /* video implies events */ + // video implies events if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { goto quit_and_error; } SDL_IncrementSubsystemRefCount(SDL_INIT_VIDEO); - if (SDL_VideoInit(NULL) < 0) { + if (!SDL_VideoInit(NULL)) { SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); + SDL_QuitSubSystem(SDL_INIT_EVENTS); goto quit_and_error; } } else { @@ -265,18 +326,19 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - /* Initialize the audio subsystem */ + // Initialize the audio subsystem if (flags & SDL_INIT_AUDIO) { #ifndef SDL_AUDIO_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_AUDIO)) { - /* audio implies events */ + // audio implies events if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { goto quit_and_error; } SDL_IncrementSubsystemRefCount(SDL_INIT_AUDIO); - if (SDL_InitAudio(NULL) < 0) { + if (!SDL_InitAudio(NULL)) { SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); + SDL_QuitSubSystem(SDL_INIT_EVENTS); goto quit_and_error; } } else { @@ -289,18 +351,19 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - /* Initialize the joystick subsystem */ + // Initialize the joystick subsystem if (flags & SDL_INIT_JOYSTICK) { #ifndef SDL_JOYSTICK_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_JOYSTICK)) { - /* joystick implies events */ + // joystick implies events if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { goto quit_and_error; } SDL_IncrementSubsystemRefCount(SDL_INIT_JOYSTICK); - if (SDL_InitJoysticks() < 0) { + if (!SDL_InitJoysticks()) { SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); + SDL_QuitSubSystem(SDL_INIT_EVENTS); goto quit_and_error; } } else { @@ -316,14 +379,15 @@ int SDL_InitSubSystem(Uint32 flags) if (flags & SDL_INIT_GAMEPAD) { #ifndef SDL_JOYSTICK_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_GAMEPAD)) { - /* game controller implies joystick */ + // game controller implies joystick if (!SDL_InitOrIncrementSubsystem(SDL_INIT_JOYSTICK)) { goto quit_and_error; } SDL_IncrementSubsystemRefCount(SDL_INIT_GAMEPAD); - if (SDL_InitGamepads() < 0) { + if (!SDL_InitGamepads()) { SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); goto quit_and_error; } } else { @@ -336,12 +400,12 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - /* Initialize the haptic subsystem */ + // Initialize the haptic subsystem if (flags & SDL_INIT_HAPTIC) { #ifndef SDL_HAPTIC_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_HAPTIC)) { SDL_IncrementSubsystemRefCount(SDL_INIT_HAPTIC); - if (SDL_InitHaptics() < 0) { + if (!SDL_InitHaptics()) { SDL_DecrementSubsystemRefCount(SDL_INIT_HAPTIC); goto quit_and_error; } @@ -355,12 +419,12 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - /* Initialize the sensor subsystem */ + // Initialize the sensor subsystem if (flags & SDL_INIT_SENSOR) { #ifndef SDL_SENSOR_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_SENSOR)) { SDL_IncrementSubsystemRefCount(SDL_INIT_SENSOR); - if (SDL_InitSensors() < 0) { + if (!SDL_InitSensors()) { SDL_DecrementSubsystemRefCount(SDL_INIT_SENSOR); goto quit_and_error; } @@ -374,18 +438,19 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - /* Initialize the camera subsystem */ + // Initialize the camera subsystem if (flags & SDL_INIT_CAMERA) { #ifndef SDL_CAMERA_DISABLED if (SDL_ShouldInitSubsystem(SDL_INIT_CAMERA)) { - /* camera implies events */ + // camera implies events if (!SDL_InitOrIncrementSubsystem(SDL_INIT_EVENTS)) { goto quit_and_error; } SDL_IncrementSubsystemRefCount(SDL_INIT_CAMERA); - if (SDL_CameraInit(NULL) < 0) { + if (!SDL_CameraInit(NULL)) { SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); + SDL_QuitSubSystem(SDL_INIT_EVENTS); goto quit_and_error; } } else { @@ -398,29 +463,29 @@ int SDL_InitSubSystem(Uint32 flags) #endif } - (void)flags_initialized; /* make static analysis happy, since this only gets used in error cases. */ + (void)flags_initialized; // make static analysis happy, since this only gets used in error cases. - return 0; + return SDL_ClearError(); quit_and_error: SDL_QuitSubSystem(flags_initialized); - return -1; + return false; } -int SDL_Init(Uint32 flags) +bool SDL_Init(SDL_InitFlags flags) { return SDL_InitSubSystem(flags); } -void SDL_QuitSubSystem(Uint32 flags) +void SDL_QuitSubSystem(SDL_InitFlags flags) { - /* Shut down requested initialized subsystems */ + // Shut down requested initialized subsystems #ifndef SDL_CAMERA_DISABLED if (flags & SDL_INIT_CAMERA) { if (SDL_ShouldQuitSubsystem(SDL_INIT_CAMERA)) { SDL_QuitCamera(); - /* camera implies events */ + // camera implies events SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_CAMERA); @@ -440,7 +505,7 @@ void SDL_QuitSubSystem(Uint32 flags) if (flags & SDL_INIT_GAMEPAD) { if (SDL_ShouldQuitSubsystem(SDL_INIT_GAMEPAD)) { SDL_QuitGamepads(); - /* game controller implies joystick */ + // game controller implies joystick SDL_QuitSubSystem(SDL_INIT_JOYSTICK); } SDL_DecrementSubsystemRefCount(SDL_INIT_GAMEPAD); @@ -449,7 +514,7 @@ void SDL_QuitSubSystem(Uint32 flags) if (flags & SDL_INIT_JOYSTICK) { if (SDL_ShouldQuitSubsystem(SDL_INIT_JOYSTICK)) { SDL_QuitJoysticks(); - /* joystick implies events */ + // joystick implies events SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_JOYSTICK); @@ -469,7 +534,7 @@ void SDL_QuitSubSystem(Uint32 flags) if (flags & SDL_INIT_AUDIO) { if (SDL_ShouldQuitSubsystem(SDL_INIT_AUDIO)) { SDL_QuitAudio(); - /* audio implies events */ + // audio implies events SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_AUDIO); @@ -479,21 +544,15 @@ void SDL_QuitSubSystem(Uint32 flags) #ifndef SDL_VIDEO_DISABLED if (flags & SDL_INIT_VIDEO) { if (SDL_ShouldQuitSubsystem(SDL_INIT_VIDEO)) { + SDL_QuitRender(); SDL_VideoQuit(); - /* video implies events */ + // video implies events SDL_QuitSubSystem(SDL_INIT_EVENTS); } SDL_DecrementSubsystemRefCount(SDL_INIT_VIDEO); } #endif - if (flags & SDL_INIT_TIMER) { - if (SDL_ShouldQuitSubsystem(SDL_INIT_TIMER)) { - SDL_QuitTimers(); - } - SDL_DecrementSubsystemRefCount(SDL_INIT_TIMER); - } - if (flags & SDL_INIT_EVENTS) { if (SDL_ShouldQuitSubsystem(SDL_INIT_EVENTS)) { SDL_QuitEvents(); @@ -502,13 +561,13 @@ void SDL_QuitSubSystem(Uint32 flags) } } -Uint32 SDL_WasInit(Uint32 flags) +Uint32 SDL_WasInit(SDL_InitFlags flags) { int i; int num_subsystems = SDL_arraysize(SDL_SubsystemRefCount); Uint32 initialized = 0; - /* Fast path for checking one flag */ + // Fast path for checking one flag if (SDL_HasExactlyOneBitSet32(flags)) { int subsystem_index = SDL_MostSignificantBitIndex32(flags); return SDL_SubsystemRefCount[subsystem_index] ? flags : 0; @@ -520,7 +579,7 @@ Uint32 SDL_WasInit(Uint32 flags) num_subsystems = SDL_min(num_subsystems, SDL_MostSignificantBitIndex32(flags) + 1); - /* Iterate over each bit in flags, and check the matching subsystem. */ + // Iterate over each bit in flags, and check the matching subsystem. for (i = 0; i < num_subsystems; ++i) { if ((flags & 1) && SDL_SubsystemRefCount[i] > 0) { initialized |= (1 << i); @@ -534,85 +593,54 @@ Uint32 SDL_WasInit(Uint32 flags) void SDL_Quit(void) { - SDL_bInMainQuit = SDL_TRUE; + SDL_bInMainQuit = true; - /* Quit all subsystems */ + // Quit all subsystems #ifdef SDL_VIDEO_DRIVER_WINDOWS SDL_HelperWindowDestroy(); #endif SDL_QuitSubSystem(SDL_INIT_EVERYTHING); - SDL_QuitTicks(); - SDL_QuitTime(); - #ifdef SDL_USE_LIBDBUS SDL_DBus_Quit(); #endif - SDL_ClearHints(); + SDL_QuitTimers(); + + SDL_SetObjectsInvalid(); SDL_AssertionsQuit(); - SDL_QuitCPUInfo(); + SDL_QuitPixelFormatDetails(); - SDL_QuitProperties(); - SDL_QuitLog(); + SDL_QuitCPUInfo(); /* Now that every subsystem has been quit, we reset the subsystem refcount * and the list of initialized subsystems. */ SDL_memset(SDL_SubsystemRefCount, 0x0, sizeof(SDL_SubsystemRefCount)); - SDL_CleanupTLS(); - - SDL_bInMainQuit = SDL_FALSE; -} - -/* Assume we can wrap SDL_AtomicInt values and cast to Uint32 */ -SDL_COMPILE_TIME_ASSERT(sizeof_object_id, sizeof(int) == sizeof(Uint32)); + SDL_QuitLog(); + SDL_QuitHints(); + SDL_QuitProperties(); -Uint32 SDL_GetNextObjectID(void) -{ - static SDL_AtomicInt last_id; + SDL_QuitMainThread(); - Uint32 id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; - if (id == 0) { - id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; - } - return id; + SDL_bInMainQuit = false; } -/* Get the library version number */ -int SDL_GetVersion(SDL_Version *ver) +// Get the library version number +int SDL_GetVersion(void) { - static SDL_bool check_hint = SDL_TRUE; - static SDL_bool legacy_version = SDL_FALSE; - - if (!ver) { - return SDL_InvalidParamError("ver"); - } - - SDL_VERSION(ver); - - if (check_hint) { - check_hint = SDL_FALSE; - legacy_version = SDL_GetHintBoolean("SDL_LEGACY_VERSION", SDL_FALSE); - } - - if (legacy_version) { - /* Prior to SDL 2.24.0, the patch version was incremented with every release */ - ver->patch = ver->minor; - ver->minor = 0; - } - return 0; + return SDL_VERSION; } -/* Get the library source revision */ +// Get the library source revision const char *SDL_GetRevision(void) { return SDL_REVISION; } -/* Get the name of the platform */ +// Get the name of the platform const char *SDL_GetPlatform(void) { #if defined(SDL_PLATFORM_AIX) @@ -653,8 +681,6 @@ const char *SDL_GetPlatform(void) return "Solaris"; #elif defined(SDL_PLATFORM_WIN32) return "Windows"; -#elif defined(SDL_PLATFORM_WINRT) - return "WinRT"; #elif defined(SDL_PLATFORM_WINGDK) return "WinGDK"; #elif defined(SDL_PLATFORM_XBOXONE) @@ -682,23 +708,36 @@ const char *SDL_GetPlatform(void) #endif } -SDL_bool SDL_IsTablet(void) +bool SDL_IsTablet(void) { #ifdef SDL_PLATFORM_ANDROID - extern SDL_bool SDL_IsAndroidTablet(void); + extern bool SDL_IsAndroidTablet(void); return SDL_IsAndroidTablet(); #elif defined(SDL_PLATFORM_IOS) - extern SDL_bool SDL_IsIPad(void); + extern bool SDL_IsIPad(void); return SDL_IsIPad(); #else - return SDL_FALSE; + return false; +#endif +} + +bool SDL_IsTV(void) +{ +#ifdef SDL_PLATFORM_ANDROID + extern bool SDL_IsAndroidTV(void); + return SDL_IsAndroidTV(); +#elif defined(SDL_PLATFORM_IOS) + extern bool SDL_IsAppleTV(void); + return SDL_IsAppleTV(); +#else + return false; #endif } #ifdef SDL_PLATFORM_WIN32 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB) -/* FIXME: Still need to include DllMain() on Watcom C ? */ +// FIXME: Still need to include DllMain() on Watcom C ? BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { @@ -711,6 +750,6 @@ BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_rea } return TRUE; } -#endif /* Building DLL */ +#endif // Building DLL -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ +#endif // defined(SDL_PLATFORM_WIN32) diff --git a/libs/SDL3/src/SDL_assert.c b/libs/SDL3/src/SDL_assert.c index 3f0d50905..c60737f24 100644 --- a/libs/SDL3/src/SDL_assert.c +++ b/libs/SDL3/src/SDL_assert.c @@ -20,14 +20,14 @@ */ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "core/windows/SDL_windows.h" #endif #include "SDL_assert_c.h" #include "video/SDL_sysvideo.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #ifndef WS_OVERLAPPEDWINDOW #define WS_OVERLAPPEDWINDOW 0 #endif @@ -35,7 +35,7 @@ #ifdef SDL_PLATFORM_EMSCRIPTEN #include - /* older Emscriptens don't have this, but we need to for wasm64 compatibility. */ + // older Emscriptens don't have this, but we need to for wasm64 compatibility. #ifndef MAIN_THREAD_EM_ASM_PTR #ifdef __wasm64__ #error You need to upgrade your Emscripten compiler to support wasm64 @@ -45,7 +45,7 @@ #endif #endif -/* The size of the stack buffer to use for rendering assert messages. */ +// The size of the stack buffer to use for rendering assert messages. #define SDL_MAX_ASSERT_MESSAGE_STACK 256 static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, void *userdata); @@ -80,13 +80,13 @@ static void SDL_AddAssertionToReport(SDL_AssertData *data) /* (data) is always a static struct defined with the assert macros, so we don't have to worry about copying or allocating them. */ data->trigger_count++; - if (data->trigger_count == 1) { /* not yet added? */ + if (data->trigger_count == 1) { // not yet added? data->next = triggered_assertions; triggered_assertions = data; } } -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #define ENDLINE "\r\n" #else #define ENDLINE "\n" @@ -105,7 +105,7 @@ static void SDL_GenerateAssertionReport(void) { const SDL_AssertData *item = triggered_assertions; - /* only do this if the app hasn't assigned an assertion handler. */ + // only do this if the app hasn't assigned an assertion handler. if ((item) && (assertion_handler != SDL_PromptAssertion)) { debug_print("\n\nSDL assertion report.\n"); debug_print("All SDL assertions between last init/quit:\n\n"); @@ -149,7 +149,6 @@ static SDL_NORETURN void SDL_AbortAssertion(void) static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, void *userdata) { - const char *envr; SDL_AssertState state = SDL_ASSERTION_ABORT; SDL_Window *window; SDL_MessageBoxData messagebox; @@ -169,14 +168,14 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v size_t buf_len = sizeof(stack_buf); int len; - (void)userdata; /* unused in default handler. */ + (void)userdata; // unused in default handler. - /* Assume the output will fit... */ + // Assume the output will fit... len = SDL_RenderAssertMessage(message, buf_len, data); - /* .. and if it didn't, try to allocate as much room as we actually need. */ + // .. and if it didn't, try to allocate as much room as we actually need. if (len >= (int)buf_len) { - if (SDL_size_add_overflow(len, 1, &buf_len) == 0) { + if (SDL_size_add_check_overflow(len, 1, &buf_len)) { message = (char *)SDL_malloc(buf_len); if (message) { len = SDL_RenderAssertMessage(message, buf_len, data); @@ -186,7 +185,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v } } - /* Something went very wrong */ + // Something went very wrong if (len < 0) { if (message != stack_buf) { SDL_free(message); @@ -196,41 +195,41 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v debug_print("\n\n%s\n\n", message); - /* let env. variable override, so unit tests won't block in a GUI. */ - envr = SDL_getenv("SDL_ASSERT"); - if (envr) { + // let env. variable override, so unit tests won't block in a GUI. + const char *hint = SDL_GetHint(SDL_HINT_ASSERT); + if (hint) { if (message != stack_buf) { SDL_free(message); } - if (SDL_strcmp(envr, "abort") == 0) { + if (SDL_strcmp(hint, "abort") == 0) { return SDL_ASSERTION_ABORT; - } else if (SDL_strcmp(envr, "break") == 0) { + } else if (SDL_strcmp(hint, "break") == 0) { return SDL_ASSERTION_BREAK; - } else if (SDL_strcmp(envr, "retry") == 0) { + } else if (SDL_strcmp(hint, "retry") == 0) { return SDL_ASSERTION_RETRY; - } else if (SDL_strcmp(envr, "ignore") == 0) { + } else if (SDL_strcmp(hint, "ignore") == 0) { return SDL_ASSERTION_IGNORE; - } else if (SDL_strcmp(envr, "always_ignore") == 0) { + } else if (SDL_strcmp(hint, "always_ignore") == 0) { return SDL_ASSERTION_ALWAYS_IGNORE; } else { - return SDL_ASSERTION_ABORT; /* oh well. */ + return SDL_ASSERTION_ABORT; // oh well. } } - /* Leave fullscreen mode, if possible (scary!) */ + // Leave fullscreen mode, if possible (scary!) window = SDL_GetToplevelForKeyboardFocus(); if (window) { if (window->fullscreen_exclusive) { SDL_MinimizeWindow(window); } else { - /* !!! FIXME: ungrab the input if we're not fullscreen? */ - /* No need to mess with the window */ + // !!! FIXME: ungrab the input if we're not fullscreen? + // No need to mess with the window window = NULL; } } - /* Show a messagebox if we can, otherwise fall back to stdio */ + // Show a messagebox if we can, otherwise fall back to stdio SDL_zero(messagebox); messagebox.flags = SDL_MESSAGEBOX_WARNING; messagebox.window = window; @@ -239,7 +238,7 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v messagebox.numbuttons = SDL_arraysize(buttons); messagebox.buttons = buttons; - if (SDL_ShowMessageBox(&messagebox, &selected) == 0) { + if (SDL_ShowMessageBox(&messagebox, &selected)) { if (selected == -1) { state = SDL_ASSERTION_IGNORE; } else { @@ -247,10 +246,10 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v } } else { #ifdef SDL_PLATFORM_EMSCRIPTEN - /* This is nasty, but we can't block on a custom UI. */ + // This is nasty, but we can't block on a custom UI. for (;;) { - SDL_bool okay = SDL_TRUE; - /* *INDENT-OFF* */ /* clang-format off */ + bool okay = true; + /* *INDENT-OFF* */ // clang-format off char *buf = (char *) MAIN_THREAD_EM_ASM_PTR({ var str = UTF8ToString($0) + '\n\n' + @@ -261,11 +260,11 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v } return allocate(intArrayFromString(reply), 'i8', ALLOC_NORMAL); }, message); - /* *INDENT-ON* */ /* clang-format on */ + /* *INDENT-ON* */ // clang-format on if (SDL_strcmp(buf, "a") == 0) { state = SDL_ASSERTION_ABORT; -#if 0 /* (currently) no break functionality on Emscripten */ +#if 0 // (currently) no break functionality on Emscripten } else if (SDL_strcmp(buf, "b") == 0) { state = SDL_ASSERTION_BREAK; #endif @@ -276,16 +275,16 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v } else if (SDL_strcmp(buf, "A") == 0) { state = SDL_ASSERTION_ALWAYS_IGNORE; } else { - okay = SDL_FALSE; + okay = false; } - free(buf); /* This should NOT be SDL_free() */ + free(buf); // This should NOT be SDL_free() if (okay) { break; } } #elif defined(HAVE_STDIO_H) - /* this is a little hacky. */ + // this is a little hacky. for (;;) { char buf[32]; (void)fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : "); @@ -311,10 +310,10 @@ static SDL_AssertState SDLCALL SDL_PromptAssertion(const SDL_AssertData *data, v break; } } -#endif /* HAVE_STDIO_H */ +#endif // HAVE_STDIO_H } - /* Re-enter fullscreen mode */ + // Re-enter fullscreen mode if (window) { SDL_RestoreWindow(window); } @@ -334,19 +333,19 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons #ifndef SDL_THREADS_DISABLED static SDL_SpinLock spinlock = 0; SDL_LockSpinlock(&spinlock); - if (!assertion_mutex) { /* never called SDL_Init()? */ + if (!assertion_mutex) { // never called SDL_Init()? assertion_mutex = SDL_CreateMutex(); if (!assertion_mutex) { SDL_UnlockSpinlock(&spinlock); - return SDL_ASSERTION_IGNORE; /* oh well, I guess. */ + return SDL_ASSERTION_IGNORE; // oh well, I guess. } } SDL_UnlockSpinlock(&spinlock); SDL_LockMutex(assertion_mutex); -#endif /* !SDL_THREADS_DISABLED */ +#endif // !SDL_THREADS_DISABLED - /* doing this because Visual C is upset over assigning in the macro. */ + // doing this because Visual C is upset over assigning in the macro. if (data->trigger_count == 0) { data->function = func; data->filename = file; @@ -356,13 +355,13 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons SDL_AddAssertionToReport(data); assertion_running++; - if (assertion_running > 1) { /* assert during assert! Abort. */ + if (assertion_running > 1) { // assert during assert! Abort. if (assertion_running == 2) { SDL_AbortAssertion(); - } else if (assertion_running == 3) { /* Abort asserted! */ + } else if (assertion_running == 3) { // Abort asserted! SDL_ExitProcess(42); } else { - while (1) { /* do nothing but spin; what else can you do?! */ + while (1) { // do nothing but spin; what else can you do?! } } } @@ -374,17 +373,17 @@ SDL_AssertState SDL_ReportAssertion(SDL_AssertData *data, const char *func, cons switch (state) { case SDL_ASSERTION_ALWAYS_IGNORE: state = SDL_ASSERTION_IGNORE; - data->always_ignore = 1; + data->always_ignore = true; break; case SDL_ASSERTION_IGNORE: case SDL_ASSERTION_RETRY: case SDL_ASSERTION_BREAK: - break; /* macro handles these. */ + break; // macro handles these. case SDL_ASSERTION_ABORT: SDL_AbortAssertion(); - /*break; ...shouldn't return, but oh well. */ + // break; ...shouldn't return, but oh well. } assertion_running--; @@ -406,7 +405,7 @@ void SDL_AssertionsQuit(void) assertion_mutex = NULL; } #endif -#endif /* SDL_ASSERT_LEVEL > 0 */ +#endif // SDL_ASSERT_LEVEL > 0 } void SDL_SetAssertionHandler(SDL_AssertionHandler handler, void *userdata) @@ -431,7 +430,7 @@ void SDL_ResetAssertionReport(void) SDL_AssertData *item; for (item = triggered_assertions; item; item = next) { next = (SDL_AssertData *)item->next; - item->always_ignore = SDL_FALSE; + item->always_ignore = false; item->trigger_count = 0; item->next = NULL; } diff --git a/libs/SDL3/src/SDL_assert_c.h b/libs/SDL3/src/SDL_assert_c.h index f4f1d2f8b..93b1753aa 100644 --- a/libs/SDL3/src/SDL_assert_c.h +++ b/libs/SDL3/src/SDL_assert_c.h @@ -25,4 +25,4 @@ extern void SDL_AssertionsQuit(void); -#endif /* SDL_assert_c_h_ */ +#endif // SDL_assert_c_h_ diff --git a/libs/SDL3/src/SDL_error.c b/libs/SDL3/src/SDL_error.c index f01fd3c88..f5cb0c2c1 100644 --- a/libs/SDL3/src/SDL_error.c +++ b/libs/SDL3/src/SDL_error.c @@ -20,17 +20,17 @@ */ #include "SDL_internal.h" -/* Simple error handling in SDL */ +// Simple error handling in SDL #include "SDL_error_c.h" -int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +bool SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { - /* Ignore call if invalid format pointer was passed */ + // Ignore call if invalid format pointer was passed if (fmt) { va_list ap; int result; - SDL_error *error = SDL_GetErrBuf(SDL_TRUE); + SDL_error *error = SDL_GetErrBuf(true); error->error = SDL_ErrorCodeGeneric; @@ -50,19 +50,18 @@ int SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) } } - if (SDL_LogGetPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) { - /* If we are in debug mode, print out the error message */ + if (SDL_GetLogPriority(SDL_LOG_CATEGORY_ERROR) <= SDL_LOG_PRIORITY_DEBUG) { + // If we are in debug mode, print out the error message SDL_LogDebug(SDL_LOG_CATEGORY_ERROR, "%s", error->str); } } - return -1; + return false; } -/* Available for backwards compatibility */ const char *SDL_GetError(void) { - const SDL_error *error = SDL_GetErrBuf(SDL_FALSE); + const SDL_error *error = SDL_GetErrBuf(false); if (!error) { return ""; @@ -78,31 +77,23 @@ const char *SDL_GetError(void) } } -void SDL_ClearError(void) +bool SDL_ClearError(void) { - SDL_error *error = SDL_GetErrBuf(SDL_FALSE); + SDL_error *error = SDL_GetErrBuf(false); if (error) { error->error = SDL_ErrorCodeNone; } + return true; } -/* Very common errors go here */ -int SDL_Error(SDL_errorcode code) +bool SDL_OutOfMemory(void) { - switch (code) { - case SDL_ENOMEM: - SDL_GetErrBuf(SDL_TRUE)->error = SDL_ErrorCodeOutOfMemory; - return -1; - case SDL_EFREAD: - return SDL_SetError("Error reading from datastream"); - case SDL_EFWRITE: - return SDL_SetError("Error writing to datastream"); - case SDL_EFSEEK: - return SDL_SetError("Error seeking in datastream"); - case SDL_UNSUPPORTED: - return SDL_SetError("That operation is not supported"); - default: - return SDL_SetError("Unknown SDL error"); + SDL_error *error = SDL_GetErrBuf(true); + + if (error) { + error->error = SDL_ErrorCodeOutOfMemory; } + return false; } + diff --git a/libs/SDL3/src/SDL_error_c.h b/libs/SDL3/src/SDL_error_c.h index c3e4f7822..228f54720 100644 --- a/libs/SDL3/src/SDL_error_c.h +++ b/libs/SDL3/src/SDL_error_c.h @@ -43,7 +43,7 @@ typedef struct SDL_error SDL_free_func free_func; } SDL_error; -/* Defined in SDL_thread.c */ -extern SDL_error *SDL_GetErrBuf(SDL_bool create); +// Defined in SDL_thread.c +extern SDL_error *SDL_GetErrBuf(bool create); -#endif /* SDL_error_c_h_ */ +#endif // SDL_error_c_h_ diff --git a/libs/SDL3/src/SDL_guid.c b/libs/SDL3/src/SDL_guid.c index a73852ddc..b7efe9a99 100644 --- a/libs/SDL3/src/SDL_guid.c +++ b/libs/SDL3/src/SDL_guid.c @@ -20,29 +20,25 @@ */ #include "SDL_internal.h" -/* convert the guid to a printable string */ -int SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID) +// convert the guid to a printable string +void SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID) { static const char k_rgchHexToASCII[] = "0123456789abcdef"; int i; - if (!pszGUID) { - return SDL_InvalidParamError("pszGUID"); - } - if (cbGUID <= 0) { - return SDL_InvalidParamError("cbGUID"); + if ((!pszGUID) || (cbGUID <= 0)) { + return; } for (i = 0; i < sizeof(guid.data) && i < (cbGUID - 1) / 2; i++) { - /* each input byte writes 2 ascii chars, and might write a null byte. */ - /* If we don't have room for next input byte, stop */ + // each input byte writes 2 ascii chars, and might write a null byte. + // If we don't have room for next input byte, stop unsigned char c = guid.data[i]; *pszGUID++ = k_rgchHexToASCII[c >> 4]; *pszGUID++ = k_rgchHexToASCII[c & 0x0F]; } *pszGUID = '\0'; - return 0; } /*----------------------------------------------------------------------------- @@ -64,13 +60,13 @@ static unsigned char nibble(unsigned char c) return c - 'a' + 0x0a; } - /* received an invalid character, and no real way to return an error */ - /* AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); */ + // received an invalid character, and no real way to return an error + // AssertMsg1(false, "Q_nibble invalid hex character '%c' ", c); return 0; } -/* convert the string version of a guid to the struct */ -SDL_GUID SDL_GUIDFromString(const char *pchGUID) +// convert the string version of a guid to the struct +SDL_GUID SDL_StringToGUID(const char *pchGUID) { SDL_GUID guid; int maxoutputbytes = sizeof(guid); @@ -78,7 +74,7 @@ SDL_GUID SDL_GUIDFromString(const char *pchGUID) Uint8 *p; size_t i; - /* Make sure it's even */ + // Make sure it's even len = (len) & ~0x1; SDL_memset(&guid, 0x00, sizeof(guid)); diff --git a/libs/SDL3/src/SDL_hashtable.c b/libs/SDL3/src/SDL_hashtable.c index 25b893b6a..a4828836c 100644 --- a/libs/SDL3/src/SDL_hashtable.c +++ b/libs/SDL3/src/SDL_hashtable.c @@ -21,49 +21,72 @@ #include "SDL_internal.h" #include "SDL_hashtable.h" +// XXX: We can't use SDL_assert here because it's going to call into hashtable code +#include +#define HT_ASSERT(x) assert(x) + typedef struct SDL_HashItem { + // TODO: Splitting off values into a separate array might be more cache-friendly const void *key; const void *value; - struct SDL_HashItem *next; + Uint32 hash; + Uint32 probe_len : 31; + Uint32 live : 1; } SDL_HashItem; +// Must be a power of 2 >= sizeof(SDL_HashItem) +#define MAX_HASHITEM_SIZEOF 32u +SDL_COMPILE_TIME_ASSERT(sizeof_SDL_HashItem, sizeof(SDL_HashItem) <= MAX_HASHITEM_SIZEOF); + +// Anything larger than this will cause integer overflows +#define MAX_HASHTABLE_SIZE (0x80000000u / (MAX_HASHITEM_SIZEOF)) + struct SDL_HashTable { - SDL_HashItem **table; - Uint32 table_len; - SDL_bool stackable; - void *data; + SDL_HashItem *table; SDL_HashTable_HashFn hash; SDL_HashTable_KeyMatchFn keymatch; SDL_HashTable_NukeFn nuke; + void *data; + Uint32 hash_mask; + Uint32 max_probe_len; + Uint32 num_occupied_slots; + bool stackable; }; -SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const SDL_HashTable_HashFn hashfn, - const SDL_HashTable_KeyMatchFn keymatchfn, - const SDL_HashTable_NukeFn nukefn, - const SDL_bool stackable) +SDL_HashTable *SDL_CreateHashTable(void *data, + Uint32 num_buckets, + SDL_HashTable_HashFn hashfn, + SDL_HashTable_KeyMatchFn keymatchfn, + SDL_HashTable_NukeFn nukefn, + bool stackable) { SDL_HashTable *table; - // num_buckets must be a power of two so we get a solid block of bits to mask hash values against. - if ((num_buckets == 0) || ((num_buckets & (num_buckets - 1)) != 0)) { + // num_buckets must be a power of two so we can derive the bucket index with just a bit-and. + if ((num_buckets < 1) || !SDL_HasExactlyOneBitSet32(num_buckets)) { SDL_SetError("num_buckets must be a power of two"); return NULL; } - table = (SDL_HashTable *) SDL_calloc(1, sizeof (SDL_HashTable)); + if (num_buckets > MAX_HASHTABLE_SIZE) { + SDL_SetError("num_buckets is too large"); + return NULL; + } + + table = (SDL_HashTable *)SDL_calloc(1, sizeof(SDL_HashTable)); if (!table) { return NULL; } - table->table = (SDL_HashItem **) SDL_calloc(num_buckets, sizeof (SDL_HashItem *)); + table->table = (SDL_HashItem *)SDL_calloc(num_buckets, sizeof(SDL_HashItem)); if (!table->table) { SDL_free(table); return NULL; } - table->table_len = num_buckets; + table->hash_mask = num_buckets - 1; table->stackable = stackable; table->data = data; table->hash = hashfn; @@ -72,157 +95,396 @@ SDL_HashTable *SDL_CreateHashTable(void *data, const Uint32 num_buckets, const S return table; } -static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *table, const void *key) +static SDL_INLINE Uint32 calc_hash(const SDL_HashTable *restrict table, const void *key) { - return table->hash(key, table->data) & (table->table_len - 1); + const Uint32 BitMixer = 0x9E3779B1u; + return table->hash(key, table->data) * BitMixer; } - -SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value) +static SDL_INLINE Uint32 get_probe_length(Uint32 zero_idx, Uint32 actual_idx, Uint32 num_buckets) { - SDL_HashItem *item; - const Uint32 hash = calc_hash(table, key); + // returns the probe sequence length from zero_idx to actual_idx - if ( (!table->stackable) && (SDL_FindInHashTable(table, key, NULL)) ) { - return SDL_FALSE; + if (actual_idx < zero_idx) { + return num_buckets - zero_idx + actual_idx; } - // !!! FIXME: grow and rehash table if it gets too saturated. - item = (SDL_HashItem *) SDL_malloc(sizeof (SDL_HashItem)); - if (!item) { - return SDL_FALSE; - } + return actual_idx - zero_idx; +} + +static SDL_HashItem *find_item(const SDL_HashTable *restrict ht, const void *key, Uint32 hash, Uint32 *restrict i, Uint32 *restrict probe_len) +{ + Uint32 hash_mask = ht->hash_mask; + Uint32 max_probe_len = ht->max_probe_len; + + SDL_HashItem *table = ht->table; + + for (;;) { + SDL_HashItem *item = table + *i; + Uint32 item_hash = item->hash; + + if (!item->live) { + return NULL; + } + + if (item_hash == hash && ht->keymatch(item->key, key, ht->data)) { + return item; + } - item->key = key; - item->value = value; - item->next = table->table[hash]; - table->table[hash] = item; + Uint32 item_probe_len = item->probe_len; + HT_ASSERT(item_probe_len == get_probe_length(item_hash & hash_mask, (Uint32)(item - table), hash_mask + 1)); - return SDL_TRUE; + if (*probe_len > item_probe_len) { + return NULL; + } + + if (++*probe_len > max_probe_len) { + return NULL; + } + + *i = (*i + 1) & hash_mask; + } } -SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value) +static SDL_HashItem *find_first_item(const SDL_HashTable *restrict ht, const void *key, Uint32 hash) { - const Uint32 hash = calc_hash(table, key); - void *data = table->data; - SDL_HashItem *i; + Uint32 i = hash & ht->hash_mask; + Uint32 probe_len = 0; + return find_item(ht, key, hash, &i, &probe_len); +} + +static SDL_HashItem *insert_item(SDL_HashItem *restrict item_to_insert, SDL_HashItem *restrict table, Uint32 hash_mask, Uint32 *max_probe_len_ptr) +{ + Uint32 idx = item_to_insert->hash & hash_mask; + SDL_HashItem temp_item, *target = NULL; + Uint32 num_buckets = hash_mask + 1; + + for (;;) { + SDL_HashItem *candidate = table + idx; + + if (!candidate->live) { + // Found an empty slot. Put it here and we're done. + + *candidate = *item_to_insert; + + if (target == NULL) { + target = candidate; + } + + Uint32 probe_len = get_probe_length(candidate->hash & hash_mask, idx, num_buckets); + candidate->probe_len = probe_len; + + if (*max_probe_len_ptr < probe_len) { + *max_probe_len_ptr = probe_len; + } + + break; + } - for (i = table->table[hash]; i; i = i->next) { - if (table->keymatch(key, i->key, data)) { - if (_value) { - *_value = i->value; + Uint32 candidate_probe_len = candidate->probe_len; + HT_ASSERT(candidate_probe_len == get_probe_length(candidate->hash & hash_mask, idx, num_buckets)); + Uint32 new_probe_len = get_probe_length(item_to_insert->hash & hash_mask, idx, num_buckets); + + if (candidate_probe_len < new_probe_len) { + // Robin Hood hashing: the item at idx has a better probe length than our item would at this position. + // Evict it and put our item in its place, then continue looking for a new spot for the displaced item. + // This algorithm significantly reduces clustering in the table, making lookups take very few probes. + + temp_item = *candidate; + *candidate = *item_to_insert; + + if (target == NULL) { + target = candidate; + } + + *item_to_insert = temp_item; + + HT_ASSERT(new_probe_len == get_probe_length(candidate->hash & hash_mask, idx, num_buckets)); + candidate->probe_len = new_probe_len; + + if (*max_probe_len_ptr < new_probe_len) { + *max_probe_len_ptr = new_probe_len; } - return SDL_TRUE; } + + idx = (idx + 1) & hash_mask; } - return SDL_FALSE; + return target; } -SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key) +static void delete_item(SDL_HashTable *restrict ht, SDL_HashItem *item) { - const Uint32 hash = calc_hash(table, key); - SDL_HashItem *item = NULL; - SDL_HashItem *prev = NULL; - void *data = table->data; + Uint32 hash_mask = ht->hash_mask; + SDL_HashItem *table = ht->table; - for (item = table->table[hash]; item; item = item->next) { - if (table->keymatch(key, item->key, data)) { - if (prev) { - prev->next = item->next; - } else { - table->table[hash] = item->next; - } + if (ht->nuke) { + ht->nuke(item->key, item->value, ht->data); + } + ht->num_occupied_slots--; - table->nuke(item->key, item->value, data); - SDL_free(item); - return SDL_TRUE; + Uint32 idx = (Uint32)(item - ht->table); + + for (;;) { + idx = (idx + 1) & hash_mask; + SDL_HashItem *next_item = table + idx; + + if (next_item->probe_len < 1) { + SDL_zerop(item); + return; } - prev = item; + *item = *next_item; + item->probe_len -= 1; + HT_ASSERT(item->probe_len < ht->max_probe_len); + item = next_item; } - - return SDL_FALSE; } -SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter) +static bool resize(SDL_HashTable *restrict ht, Uint32 new_size) { - SDL_HashItem *item = *iter ? ((SDL_HashItem *) *iter)->next : table->table[calc_hash(table, key)]; + SDL_HashItem *old_table = ht->table; + Uint32 old_size = ht->hash_mask + 1; + Uint32 new_hash_mask = new_size - 1; + SDL_HashItem *new_table = SDL_calloc(new_size, sizeof(*new_table)); + + if (!new_table) { + return false; + } - while (item) { - if (table->keymatch(key, item->key, table->data)) { - *_value = item->value; - *iter = item; - return SDL_TRUE; + ht->max_probe_len = 0; + ht->hash_mask = new_hash_mask; + ht->table = new_table; + + for (Uint32 i = 0; i < old_size; ++i) { + SDL_HashItem *item = old_table + i; + if (item->live) { + insert_item(item, new_table, new_hash_mask, &ht->max_probe_len); } - item = item->next; } - // no more matches. - *_value = NULL; - *iter = NULL; - return SDL_FALSE; + SDL_free(old_table); + return true; } -SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter) +static bool maybe_resize(SDL_HashTable *restrict ht) { - SDL_HashItem *item = (SDL_HashItem *) *iter; - Uint32 idx = 0; + Uint32 capacity = ht->hash_mask + 1; - if (item) { - const SDL_HashItem *orig = item; - item = item->next; - if (!item) { - idx = calc_hash(table, orig->key) + 1; // !!! FIXME: we probably shouldn't rehash each time. + if (capacity >= MAX_HASHTABLE_SIZE) { + return false; + } + + Uint32 max_load_factor = 217; // range: 0-255; 217 is roughly 85% + Uint32 resize_threshold = (max_load_factor * (Uint64)capacity) >> 8; + + if (ht->num_occupied_slots > resize_threshold) { + return resize(ht, capacity * 2); + } + + return true; +} + +bool SDL_InsertIntoHashTable(SDL_HashTable *restrict table, const void *key, const void *value) +{ + SDL_HashItem *item; + Uint32 hash; + + if (!table) { + return false; + } + + hash = calc_hash(table, key); + item = find_first_item(table, key, hash); + + if (item && !table->stackable) { + // TODO: Maybe allow overwrites? We could do it more efficiently here than unset followed by insert. + return false; + } + + SDL_HashItem new_item; + new_item.key = key; + new_item.value = value; + new_item.hash = hash; + new_item.live = true; + + table->num_occupied_slots++; + + if (!maybe_resize(table)) { + table->num_occupied_slots--; + return false; + } + + // This never returns NULL + insert_item(&new_item, table->table, table->hash_mask, &table->max_probe_len); + return true; +} + +bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **value) +{ + Uint32 hash; + SDL_HashItem *i; + + if (!table) { + if (value) { + *value = NULL; } + return false; } - while (!item && (idx < table->table_len)) { - item = table->table[idx++]; // skip empty buckets... + hash = calc_hash(table, key); + i = find_first_item(table, key, hash); + if (i) { + if (value) { + *value = i->value; + } + return true; + } + return false; +} + +bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key) +{ + Uint32 hash; + SDL_HashItem *item; + + if (!table) { + return false; } - if (!item) { // no more matches? - *_key = NULL; - *iter = NULL; - return SDL_FALSE; + // FIXME: what to do for stacking hashtables? + // The original code removes just one item. + // This hashtable happens to preserve the insertion order of multi-value keys, + // so deleting the first one will always delete the least-recently inserted one. + // But maybe it makes more sense to remove all matching items? + + hash = calc_hash(table, key); + item = find_first_item(table, key, hash); + + if (!item) { + return false; + } + + delete_item(table, item); + return true; +} + +bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter) +{ + SDL_HashItem *item = (SDL_HashItem *)*iter; + + if (!table) { + return false; + } + + Uint32 i, probe_len, hash; + + if (item) { + HT_ASSERT(item >= table->table); + HT_ASSERT(item < table->table + (table->hash_mask + 1)); + + hash = item->hash; + probe_len = item->probe_len + 1; + i = ((Uint32)(item - table->table) + 1) & table->hash_mask; + item = table->table + i; + } else { + hash = calc_hash(table, key); + i = hash & table->hash_mask; + probe_len = 0; + } + + item = find_item(table, key, hash, &i, &probe_len); + + if (!item) { + *_value = NULL; + return false; } - *_key = item->key; *_value = item->value; *iter = item; - return SDL_TRUE; + return true; } -SDL_bool SDL_HashTableEmpty(SDL_HashTable *table) +bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter) { - if (table) { - Uint32 i; + SDL_HashItem *item = (SDL_HashItem *)*iter; - for (i = 0; i < table->table_len; i++) { - SDL_HashItem *item = table->table[i]; - if (item) { - return SDL_FALSE; - } + if (!table) { + return false; + } + + if (!item) { + item = table->table; + } else { + item++; + } + + HT_ASSERT(item >= table->table); + SDL_HashItem *end = table->table + (table->hash_mask + 1); + + while (item < end && !item->live) { + ++item; + } + + HT_ASSERT(item <= end); + + if (item == end) { + if (_key) { + *_key = NULL; } + if (_value) { + *_value = NULL; + } + return false; + } + + if (_key) { + *_key = item->key; + } + if (_value) { + *_value = item->value; + } + *iter = item; + + return true; +} + +bool SDL_HashTableEmpty(SDL_HashTable *table) +{ + return !(table && table->num_occupied_slots); +} + +static void nuke_all(SDL_HashTable *restrict table) +{ + void *data = table->data; + SDL_HashItem *end = table->table + (table->hash_mask + 1); + SDL_HashItem *i; + + for (i = table->table; i < end; ++i) { + if (i->live) { + table->nuke(i->key, i->value, data); + } + } +} + +void SDL_EmptyHashTable(SDL_HashTable *restrict table) +{ + if (table) { + if (table->nuke) { + nuke_all(table); + } + + SDL_memset(table->table, 0, sizeof(*table->table) * (table->hash_mask + 1)); + table->num_occupied_slots = 0; } - return SDL_TRUE; } void SDL_DestroyHashTable(SDL_HashTable *table) { if (table) { - void *data = table->data; - Uint32 i; - - for (i = 0; i < table->table_len; i++) { - SDL_HashItem *item = table->table[i]; - while (item) { - SDL_HashItem *next = item->next; - table->nuke(item->key, item->value, data); - SDL_free(item); - item = next; - } + if (table->nuke) { + nuke_all(table); } SDL_free(table->table); @@ -240,20 +502,39 @@ static SDL_INLINE Uint32 hash_string_djbxor(const char *str, size_t len) return hash; } -Uint32 SDL_HashString(const void *key, void *data) +Uint32 SDL_HashPointer(const void *key, void *unused) +{ + (void)unused; + return SDL_murmur3_32(&key, sizeof(key), 0); +} + +bool SDL_KeyMatchPointer(const void *a, const void *b, void *unused) +{ + (void)unused; + return (a == b); +} + +Uint32 SDL_HashString(const void *key, void *unused) { + (void)unused; const char *str = (const char *)key; return hash_string_djbxor(str, SDL_strlen(str)); } -SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *data) +bool SDL_KeyMatchString(const void *a, const void *b, void *unused) { + const char *a_string = (const char *)a; + const char *b_string = (const char *)b; + + (void)unused; if (a == b) { - return SDL_TRUE; // same pointer, must match. + return true; // same pointer, must match. } else if (!a || !b) { - return SDL_FALSE; // one pointer is NULL (and first test shows they aren't the same pointer), must not match. + return false; // one pointer is NULL (and first test shows they aren't the same pointer), must not match. + } else if (a_string[0] != b_string[0]) { + return false; // we know they don't match } - return (SDL_strcmp((const char *)a, (const char *)b) == 0); // Check against actual string contents. + return (SDL_strcmp(a_string, b_string) == 0); // Check against actual string contents. } // We assume we can fit the ID in the key directly @@ -261,13 +542,26 @@ SDL_COMPILE_TIME_ASSERT(SDL_HashID_KeySize, sizeof(Uint32) <= sizeof(const void Uint32 SDL_HashID(const void *key, void *unused) { + (void)unused; return (Uint32)(uintptr_t)key; } -SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused) +bool SDL_KeyMatchID(const void *a, const void *b, void *unused) { - if (a == b) { - return SDL_TRUE; - } - return SDL_FALSE; + (void)unused; + return (a == b); +} + +void SDL_NukeFreeKey(const void *key, const void *value, void *unused) +{ + (void)value; + (void)unused; + SDL_free((void *)key); +} + +void SDL_NukeFreeValue(const void *key, const void *value, void *unused) +{ + (void)key; + (void)unused; + SDL_free((void *)value); } diff --git a/libs/SDL3/src/SDL_hashtable.h b/libs/SDL3/src/SDL_hashtable.h index 96614bc17..62ff9c796 100644 --- a/libs/SDL3/src/SDL_hashtable.h +++ b/libs/SDL3/src/SDL_hashtable.h @@ -21,37 +21,44 @@ #ifndef SDL_hashtable_h_ #define SDL_hashtable_h_ -/* this is not (currently) a public API. But maybe it should be! */ +// this is not (currently) a public API. But maybe it should be! struct SDL_HashTable; typedef struct SDL_HashTable SDL_HashTable; typedef Uint32 (*SDL_HashTable_HashFn)(const void *key, void *data); -typedef SDL_bool (*SDL_HashTable_KeyMatchFn)(const void *a, const void *b, void *data); +typedef bool (*SDL_HashTable_KeyMatchFn)(const void *a, const void *b, void *data); typedef void (*SDL_HashTable_NukeFn)(const void *key, const void *value, void *data); -SDL_HashTable *SDL_CreateHashTable(void *data, - const Uint32 num_buckets, - const SDL_HashTable_HashFn hashfn, - const SDL_HashTable_KeyMatchFn keymatchfn, - const SDL_HashTable_NukeFn nukefn, - const SDL_bool stackable); +extern SDL_HashTable *SDL_CreateHashTable(void *data, + Uint32 num_buckets, + SDL_HashTable_HashFn hashfn, + SDL_HashTable_KeyMatchFn keymatchfn, + SDL_HashTable_NukeFn nukefn, + bool stackable); -void SDL_DestroyHashTable(SDL_HashTable *table); -SDL_bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value); -SDL_bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); -SDL_bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); -SDL_bool SDL_HashTableEmpty(SDL_HashTable *table); +extern void SDL_EmptyHashTable(SDL_HashTable *table); +extern void SDL_DestroyHashTable(SDL_HashTable *table); +extern bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value); +extern bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key); +extern bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **_value); +extern bool SDL_HashTableEmpty(SDL_HashTable *table); // iterate all values for a specific key. This only makes sense if the hash is stackable. If not-stackable, just use SDL_FindInHashTable(). -SDL_bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter); +extern bool SDL_IterateHashTableKey(const SDL_HashTable *table, const void *key, const void **_value, void **iter); // iterate all key/value pairs in a hash (stackable hashes can have duplicate keys with multiple values). -SDL_bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter); +extern bool SDL_IterateHashTable(const SDL_HashTable *table, const void **_key, const void **_value, void **iter); -Uint32 SDL_HashString(const void *key, void *unused); -SDL_bool SDL_KeyMatchString(const void *a, const void *b, void *unused); +extern Uint32 SDL_HashPointer(const void *key, void *unused); +extern bool SDL_KeyMatchPointer(const void *a, const void *b, void *unused); -Uint32 SDL_HashID(const void *key, void *unused); -SDL_bool SDL_KeyMatchID(const void *a, const void *b, void *unused); +extern Uint32 SDL_HashString(const void *key, void *unused); +extern bool SDL_KeyMatchString(const void *a, const void *b, void *unused); -#endif /* SDL_hashtable_h_ */ +extern Uint32 SDL_HashID(const void *key, void *unused); +extern bool SDL_KeyMatchID(const void *a, const void *b, void *unused); + +extern void SDL_NukeFreeKey(const void *key, const void *value, void *unused); +extern void SDL_NukeFreeValue(const void *key, const void *value, void *unused); + +#endif // SDL_hashtable_h_ diff --git a/libs/SDL3/src/SDL_hints.c b/libs/SDL3/src/SDL_hints.c index b3cebbf9d..6fcd8b8c2 100644 --- a/libs/SDL3/src/SDL_hints.c +++ b/libs/SDL3/src/SDL_hints.c @@ -22,9 +22,6 @@ #include "SDL_hints_c.h" -/* Assuming there aren't many hints set and they aren't being queried in - critical performance paths, we'll just use linked lists here. - */ typedef struct SDL_HintWatch { SDL_HintCallback callback; @@ -34,145 +31,205 @@ typedef struct SDL_HintWatch typedef struct SDL_Hint { - char *name; char *value; SDL_HintPriority priority; SDL_HintWatch *callbacks; - struct SDL_Hint *next; } SDL_Hint; -static SDL_Hint *SDL_hints; +static SDL_AtomicU32 SDL_hint_props; -SDL_bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority) + +void SDL_InitHints(void) { - const char *env; - SDL_Hint *hint; - SDL_HintWatch *entry; +} - if (!name) { - return SDL_FALSE; +void SDL_QuitHints(void) +{ + SDL_PropertiesID props; + do { + props = SDL_GetAtomicU32(&SDL_hint_props); + } while (!SDL_CompareAndSwapAtomicU32(&SDL_hint_props, props, 0)); + + if (props) { + SDL_DestroyProperties(props); } +} - env = SDL_getenv(name); - if (env && priority < SDL_HINT_OVERRIDE) { - return SDL_FALSE; +static SDL_PropertiesID GetHintProperties(bool create) +{ + SDL_PropertiesID props = SDL_GetAtomicU32(&SDL_hint_props); + if (!props && create) { + props = SDL_CreateProperties(); + if (!SDL_CompareAndSwapAtomicU32(&SDL_hint_props, 0, props)) { + // Somebody else created hint properties before us, just use those + SDL_DestroyProperties(props); + props = SDL_GetAtomicU32(&SDL_hint_props); + } } + return props; +} - for (hint = SDL_hints; hint; hint = hint->next) { - if (SDL_strcmp(name, hint->name) == 0) { - if (priority < hint->priority) { - return SDL_FALSE; - } - if (hint->value != value && - (!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) { +static void SDLCALL CleanupHintProperty(void *userdata, void *value) +{ + SDL_Hint *hint = (SDL_Hint *) value; + SDL_free(hint->value); + + SDL_HintWatch *entry = hint->callbacks; + while (entry) { + SDL_HintWatch *freeable = entry; + entry = entry->next; + SDL_free(freeable); + } + SDL_free(hint); +} + +bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority) +{ + if (!name || !*name) { + return SDL_InvalidParamError("name"); + } + + const char *env = SDL_getenv(name); + if (env && (priority < SDL_HINT_OVERRIDE)) { + return SDL_SetError("An environment variable is taking priority"); + } + + const SDL_PropertiesID hints = GetHintProperties(true); + if (!hints) { + return false; + } + + bool result = false; + + SDL_LockProperties(hints); + + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (hint) { + if (priority >= hint->priority) { + if (hint->value != value && (!value || !hint->value || SDL_strcmp(hint->value, value) != 0)) { char *old_value = hint->value; hint->value = value ? SDL_strdup(value) : NULL; - for (entry = hint->callbacks; entry;) { - /* Save the next entry in case this one is deleted */ + SDL_HintWatch *entry = hint->callbacks; + while (entry) { + // Save the next entry in case this one is deleted SDL_HintWatch *next = entry->next; entry->callback(entry->userdata, name, old_value, value); entry = next; } - if (old_value) { - SDL_free(old_value); - } + SDL_free(old_value); } hint->priority = priority; - return SDL_TRUE; + result = true; + } + } else { // Couldn't find the hint? Add a new one. + hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); + if (hint) { + hint->value = value ? SDL_strdup(value) : NULL; + hint->priority = priority; + hint->callbacks = NULL; + result = SDL_SetPointerPropertyWithCleanup(hints, name, hint, CleanupHintProperty, NULL); } } - /* Couldn't find the hint, add a new one */ - hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); - if (!hint) { - return SDL_FALSE; - } - hint->name = SDL_strdup(name); - hint->value = value ? SDL_strdup(value) : NULL; - hint->priority = priority; - hint->callbacks = NULL; - hint->next = SDL_hints; - SDL_hints = hint; - return SDL_TRUE; + SDL_UnlockProperties(hints); + + return result; } -SDL_bool SDL_ResetHint(const char *name) +bool SDL_ResetHint(const char *name) { - const char *env; - SDL_Hint *hint; - SDL_HintWatch *entry; - - if (!name) { - return SDL_FALSE; + if (!name || !*name) { + return SDL_InvalidParamError("name"); } - env = SDL_getenv(name); - for (hint = SDL_hints; hint; hint = hint->next) { - if (SDL_strcmp(name, hint->name) == 0) { - if ((!env && hint->value) || - (env && !hint->value) || - (env && SDL_strcmp(env, hint->value) != 0)) { - for (entry = hint->callbacks; entry;) { - /* Save the next entry in case this one is deleted */ - SDL_HintWatch *next = entry->next; - entry->callback(entry->userdata, name, hint->value, env); - entry = next; - } - } - SDL_free(hint->value); - hint->value = NULL; - hint->priority = SDL_HINT_DEFAULT; - return SDL_TRUE; - } + const char *env = SDL_getenv(name); + + const SDL_PropertiesID hints = GetHintProperties(false); + if (!hints) { + return false; } - return SDL_FALSE; -} -void SDL_ResetHints(void) -{ - const char *env; - SDL_Hint *hint; - SDL_HintWatch *entry; - - for (hint = SDL_hints; hint; hint = hint->next) { - env = SDL_getenv(hint->name); - if ((!env && hint->value) || - (env && !hint->value) || - (env && SDL_strcmp(env, hint->value) != 0)) { - for (entry = hint->callbacks; entry;) { - /* Save the next entry in case this one is deleted */ + bool result = false; + + SDL_LockProperties(hints); + + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (hint) { + if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) { + for (SDL_HintWatch *entry = hint->callbacks; entry;) { + // Save the next entry in case this one is deleted SDL_HintWatch *next = entry->next; - entry->callback(entry->userdata, hint->name, hint->value, env); + entry->callback(entry->userdata, name, hint->value, env); entry = next; } } SDL_free(hint->value); hint->value = NULL; hint->priority = SDL_HINT_DEFAULT; + result = true; } + + SDL_UnlockProperties(hints); + + return result; +} + +static void SDLCALL ResetHintsCallback(void *userdata, SDL_PropertiesID hints, const char *name) +{ + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (!hint) { + return; // uh...okay. + } + + const char *env = SDL_getenv(name); + if ((!env && hint->value) || (env && !hint->value) || (env && SDL_strcmp(env, hint->value) != 0)) { + SDL_HintWatch *entry = hint->callbacks; + while (entry) { + // Save the next entry in case this one is deleted + SDL_HintWatch *next = entry->next; + entry->callback(entry->userdata, name, hint->value, env); + entry = next; + } + } + SDL_free(hint->value); + hint->value = NULL; + hint->priority = SDL_HINT_DEFAULT; +} + +void SDL_ResetHints(void) +{ + SDL_EnumerateProperties(GetHintProperties(false), ResetHintsCallback, NULL); } -SDL_bool SDL_SetHint(const char *name, const char *value) +bool SDL_SetHint(const char *name, const char *value) { return SDL_SetHintWithPriority(name, value, SDL_HINT_NORMAL); } const char *SDL_GetHint(const char *name) { - const char *env; - SDL_Hint *hint; - - env = SDL_getenv(name); - for (hint = SDL_hints; hint; hint = hint->next) { - if (SDL_strcmp(name, hint->name) == 0) { - if (!env || hint->priority == SDL_HINT_OVERRIDE) { - return hint->value; + if (!name) { + return NULL; + } + + const char *result = SDL_getenv(name); + + const SDL_PropertiesID hints = GetHintProperties(false); + if (hints) { + SDL_LockProperties(hints); + + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (hint) { + if (!result || hint->priority == SDL_HINT_OVERRIDE) { + result = SDL_GetPersistentString(hint->value); } - break; } + + SDL_UnlockProperties(hints); } - return env; + + return result; } int SDL_GetStringInteger(const char *value, int default_value) @@ -192,121 +249,107 @@ int SDL_GetStringInteger(const char *value, int default_value) return default_value; } -SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value) +bool SDL_GetStringBoolean(const char *value, bool default_value) { if (!value || !*value) { return default_value; } if (*value == '0' || SDL_strcasecmp(value, "false") == 0) { - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } -SDL_bool SDL_GetHintBoolean(const char *name, SDL_bool default_value) +bool SDL_GetHintBoolean(const char *name, bool default_value) { const char *hint = SDL_GetHint(name); return SDL_GetStringBoolean(hint, default_value); } -int SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata) +bool SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata) { - SDL_Hint *hint; - SDL_HintWatch *entry; - const char *value; - if (!name || !*name) { return SDL_InvalidParamError("name"); - } - if (!callback) { + } else if (!callback) { return SDL_InvalidParamError("callback"); } - SDL_DelHintCallback(name, callback, userdata); + const SDL_PropertiesID hints = GetHintProperties(true); + if (!hints) { + return false; + } - entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); + SDL_HintWatch *entry = (SDL_HintWatch *)SDL_malloc(sizeof(*entry)); if (!entry) { - return -1; + return false; } entry->callback = callback; entry->userdata = userdata; - for (hint = SDL_hints; hint; hint = hint->next) { - if (SDL_strcmp(name, hint->name) == 0) { - break; - } - } - if (!hint) { - /* Need to add a hint entry for this watcher */ + bool result = false; + + SDL_LockProperties(hints); + + SDL_RemoveHintCallback(name, callback, userdata); + + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (hint) { + result = true; + } else { // Need to add a hint entry for this watcher hint = (SDL_Hint *)SDL_malloc(sizeof(*hint)); if (!hint) { SDL_free(entry); - return -1; - } - hint->name = SDL_strdup(name); - if (!hint->name) { - SDL_free(entry); - SDL_free(hint); - return -1; + SDL_UnlockProperties(hints); + return false; + } else { + hint->value = NULL; + hint->priority = SDL_HINT_DEFAULT; + hint->callbacks = NULL; + result = SDL_SetPointerPropertyWithCleanup(hints, name, hint, CleanupHintProperty, NULL); } - hint->value = NULL; - hint->priority = SDL_HINT_DEFAULT; - hint->callbacks = NULL; - hint->next = SDL_hints; - SDL_hints = hint; } - /* Add it to the callbacks for this hint */ + // Add it to the callbacks for this hint entry->next = hint->callbacks; hint->callbacks = entry; - /* Now call it with the current value */ - value = SDL_GetHint(name); + // Now call it with the current value + const char *value = SDL_GetHint(name); callback(userdata, name, value, value); - return 0; -} -void SDL_DelHintCallback(const char *name, SDL_HintCallback callback, void *userdata) -{ - SDL_Hint *hint; - SDL_HintWatch *entry, *prev; - - for (hint = SDL_hints; hint; hint = hint->next) { - if (SDL_strcmp(name, hint->name) == 0) { - prev = NULL; - for (entry = hint->callbacks; entry; entry = entry->next) { - if (callback == entry->callback && userdata == entry->userdata) { - if (prev) { - prev->next = entry->next; - } else { - hint->callbacks = entry->next; - } - SDL_free(entry); - break; - } - prev = entry; - } - return; - } - } + SDL_UnlockProperties(hints); + + return result; } -void SDL_ClearHints(void) +void SDL_RemoveHintCallback(const char *name, SDL_HintCallback callback, void *userdata) { - SDL_Hint *hint; - SDL_HintWatch *entry; + if (!name || !*name) { + return; + } - while (SDL_hints) { - hint = SDL_hints; - SDL_hints = hint->next; + const SDL_PropertiesID hints = GetHintProperties(false); + if (!hints) { + return; + } - SDL_free(hint->name); - SDL_free(hint->value); - for (entry = hint->callbacks; entry;) { - SDL_HintWatch *freeable = entry; - entry = entry->next; - SDL_free(freeable); + SDL_LockProperties(hints); + SDL_Hint *hint = (SDL_Hint *)SDL_GetPointerProperty(hints, name, NULL); + if (hint) { + SDL_HintWatch *prev = NULL; + for (SDL_HintWatch *entry = hint->callbacks; entry; entry = entry->next) { + if ((callback == entry->callback) && (userdata == entry->userdata)) { + if (prev) { + prev->next = entry->next; + } else { + hint->callbacks = entry->next; + } + SDL_free(entry); + break; + } + prev = entry; } - SDL_free(hint); } + SDL_UnlockProperties(hints); } + diff --git a/libs/SDL3/src/SDL_hints_c.h b/libs/SDL3/src/SDL_hints_c.h index 486280ec6..ab254e364 100644 --- a/libs/SDL3/src/SDL_hints_c.h +++ b/libs/SDL3/src/SDL_hints_c.h @@ -20,13 +20,14 @@ */ #include "SDL_internal.h" -/* This file defines useful function for working with SDL hints */ +// This file defines useful function for working with SDL hints #ifndef SDL_hints_c_h_ #define SDL_hints_c_h_ -extern SDL_bool SDL_GetStringBoolean(const char *value, SDL_bool default_value); +extern void SDL_InitHints(void); +extern bool SDL_GetStringBoolean(const char *value, bool default_value); extern int SDL_GetStringInteger(const char *value, int default_value); -extern void SDL_ClearHints(void); +extern void SDL_QuitHints(void); -#endif /* SDL_hints_c_h_ */ +#endif // SDL_hints_c_h_ diff --git a/libs/SDL3/src/SDL_internal.h b/libs/SDL3/src/SDL_internal.h index a404a7818..75fa957a5 100644 --- a/libs/SDL3/src/SDL_internal.h +++ b/libs/SDL3/src/SDL_internal.h @@ -21,12 +21,12 @@ #ifndef SDL_internal_h_ #define SDL_internal_h_ -/* Many of SDL's features require _GNU_SOURCE on various platforms */ +// Many of SDL's features require _GNU_SOURCE on various platforms #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -/* Need this so Linux systems define fseek64o, ftell64o and off64_t */ +// Need this so Linux systems define fseek64o, ftell64o and off64_t #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE 1 #endif @@ -44,11 +44,11 @@ #define HAVE_GCC_DIAGNOSTIC_PRAGMA 1 #endif -#ifdef _MSC_VER /* We use constant comparison for generated code */ +#ifdef _MSC_VER // We use constant comparison for generated code #pragma warning(disable : 6326) #endif -#ifdef _MSC_VER /* SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe */ +#ifdef _MSC_VER // SDL_MAX_SMALL_ALLOC_STACKSIZE is smaller than _ALLOCA_S_THRESHOLD and should be generally safe #pragma warning(disable : 6255) #endif #define SDL_MAX_SMALL_ALLOC_STACKSIZE 128 @@ -60,23 +60,23 @@ SDL_free(ptr); \ } -#include "build_config/SDL_build_config.h" +#include "SDL_build_config.h" #include "dynapi/SDL_dynapi.h" #if SDL_DYNAMIC_API #include "dynapi/SDL_dynapi_overrides.h" -/* force DECLSPEC off...it's all internal symbols now. +/* force SDL_DECLSPEC off...it's all internal symbols now. These will have actual #defines during SDL_dynapi.c only */ -#ifdef DECLSPEC -#undef DECLSPEC +#ifdef SDL_DECLSPEC +#undef SDL_DECLSPEC #endif -#define DECLSPEC +#define SDL_DECLSPEC #endif #ifdef SDL_PLATFORM_APPLE #ifndef _DARWIN_C_SOURCE -#define _DARWIN_C_SOURCE 1 /* for memset_pattern4() */ +#define _DARWIN_C_SOURCE 1 // for memset_pattern4() #endif #endif @@ -121,7 +121,7 @@ #include #endif -/* If you run into a warning that O_CLOEXEC is redefined, update the SDL configuration header for your platform to add HAVE_O_CLOEXEC */ +// If you run into a warning that O_CLOEXEC is redefined, update the SDL configuration header for your platform to add HAVE_O_CLOEXEC #ifndef HAVE_O_CLOEXEC #define O_CLOEXEC 0 #endif @@ -191,102 +191,67 @@ #define SDL_HAVE_YUV !SDL_LEAN_AND_MEAN #endif -#ifndef SDL_RENDER_DISABLED -/* define the not defined ones as 0 */ -#ifndef SDL_VIDEO_RENDER_D3D -#define SDL_VIDEO_RENDER_D3D 0 -#endif -#ifndef SDL_VIDEO_RENDER_D3D11 -#define SDL_VIDEO_RENDER_D3D11 0 -#endif -#ifndef SDL_VIDEO_RENDER_D3D12 -#define SDL_VIDEO_RENDER_D3D12 0 -#endif -#ifndef SDL_VIDEO_RENDER_METAL -#define SDL_VIDEO_RENDER_METAL 0 -#endif -#ifndef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 0 -#endif -#ifndef SDL_VIDEO_RENDER_OGL_ES2 -#define SDL_VIDEO_RENDER_OGL_ES2 0 -#endif -#ifndef SDL_VIDEO_RENDER_PS2 -#define SDL_VIDEO_RENDER_PS2 0 -#endif -#ifndef SDL_VIDEO_RENDER_PSP -#define SDL_VIDEO_RENDER_PSP 0 -#endif -#ifndef SDL_VIDEO_RENDER_VITA_GXM -#define SDL_VIDEO_RENDER_VITA_GXM 0 -#endif -#ifndef SDL_VIDEO_RENDER_VULKAN -#define SDL_VIDEO_RENDER_VULKAN 0 -#endif -#else /* define all as 0 */ +#ifdef SDL_RENDER_DISABLED #undef SDL_VIDEO_RENDER_SW -#define SDL_VIDEO_RENDER_SW 0 #undef SDL_VIDEO_RENDER_D3D -#define SDL_VIDEO_RENDER_D3D 0 #undef SDL_VIDEO_RENDER_D3D11 -#define SDL_VIDEO_RENDER_D3D11 0 #undef SDL_VIDEO_RENDER_D3D12 -#define SDL_VIDEO_RENDER_D3D12 0 +#undef SDL_VIDEO_RENDER_GPU #undef SDL_VIDEO_RENDER_METAL -#define SDL_VIDEO_RENDER_METAL 0 #undef SDL_VIDEO_RENDER_OGL -#define SDL_VIDEO_RENDER_OGL 0 #undef SDL_VIDEO_RENDER_OGL_ES2 -#define SDL_VIDEO_RENDER_OGL_ES2 0 #undef SDL_VIDEO_RENDER_PS2 -#define SDL_VIDEO_RENDER_PS2 0 #undef SDL_VIDEO_RENDER_PSP -#define SDL_VIDEO_RENDER_PSP 0 #undef SDL_VIDEO_RENDER_VITA_GXM -#define SDL_VIDEO_RENDER_VITA_GXM 0 #undef SDL_VIDEO_RENDER_VULKAN -#define SDL_VIDEO_RENDER_VULKAN 0 -#endif /* SDL_RENDER_DISABLED */ - -#define SDL_HAS_RENDER_DRIVER \ - (SDL_VIDEO_RENDER_SW | \ - SDL_VIDEO_RENDER_D3D | \ - SDL_VIDEO_RENDER_D3D11 | \ - SDL_VIDEO_RENDER_D3D12 | \ - SDL_VIDEO_RENDER_METAL | \ - SDL_VIDEO_RENDER_OGL | \ - SDL_VIDEO_RENDER_OGL_ES2 | \ - SDL_VIDEO_RENDER_PS2 | \ - SDL_VIDEO_RENDER_PSP | \ - SDL_VIDEO_RENDER_VITA_GXM | \ - SDL_VIDEO_RENDER_VULKAN ) - -#if !defined(SDL_RENDER_DISABLED) && !SDL_HAS_RENDER_DRIVER -#error SDL_RENDER enabled without any backend drivers. +#endif // SDL_RENDER_DISABLED + +#ifdef SDL_GPU_DISABLED +#undef SDL_GPU_D3D11 +#undef SDL_GPU_D3D12 +#undef SDL_GPU_METAL +#undef SDL_GPU_VULKAN +#undef SDL_VIDEO_RENDER_GPU +#endif // SDL_GPU_DISABLED + +#if !defined(HAVE_LIBC) +// If not using _any_ C runtime, these have to be defined before SDL_thread.h +// gets included, so internal SDL_CreateThread calls will not try to reference +// the (unavailable and unneeded) _beginthreadex/_endthreadex functions. +#define SDL_BeginThreadFunction NULL +#define SDL_EndThreadFunction NULL #endif +/* Enable internal definitions in SDL API headers */ +#define SDL_INTERNAL + #include #include -#define SDL_MAIN_NOIMPL /* don't drag in header-only implementation of SDL_main */ +#define SDL_MAIN_NOIMPL // don't drag in header-only implementation of SDL_main #include -/* The internal implementations of these functions have up to nanosecond precision. - We can expose these functions as part of the API if we want to later. -*/ -/* Set up for C function definitions, even when using C++ */ +// Set up for C function definitions, even when using C++ #ifdef __cplusplus extern "C" { #endif -extern DECLSPEC Uint32 SDLCALL SDL_GetNextObjectID(void); -extern DECLSPEC int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS); -extern DECLSPEC int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); -extern DECLSPEC SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); +#include "SDL_utils_c.h" +#include "SDL_hashtable.h" + +// Do any initialization that needs to happen before threads are started +extern void SDL_InitMainThread(void); + +/* The internal implementations of these functions have up to nanosecond precision. + We can expose these functions as part of the API if we want to later. +*/ +extern bool SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeoutNS); +extern bool SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS); +extern bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS); -/* Ends C function definitions when using C++ */ +// Ends C function definitions when using C++ #ifdef __cplusplus } #endif -#endif /* SDL_internal_h_ */ +#endif // SDL_internal_h_ diff --git a/libs/SDL3/src/SDL_list.c b/libs/SDL3/src/SDL_list.c index 8c95876f8..d66cf0a8f 100644 --- a/libs/SDL3/src/SDL_list.c +++ b/libs/SDL3/src/SDL_list.c @@ -22,27 +22,27 @@ #include "./SDL_list.h" -/* Push */ -int SDL_ListAdd(SDL_ListNode **head, void *ent) +// Push +bool SDL_ListAdd(SDL_ListNode **head, void *ent) { SDL_ListNode *node = (SDL_ListNode *)SDL_malloc(sizeof(*node)); if (!node) { - return -1; + return false; } node->entry = ent; node->next = *head; *head = node; - return 0; + return true; } -/* Pop from end as a FIFO (if add with SDL_ListAdd) */ +// Pop from end as a FIFO (if add with SDL_ListAdd) void SDL_ListPop(SDL_ListNode **head, void **ent) { SDL_ListNode **ptr = head; - /* Invalid or empty */ + // Invalid or empty if (!head || !*head) { return; } diff --git a/libs/SDL3/src/SDL_list.h b/libs/SDL3/src/SDL_list.h index 583f78aa0..aa2de3bb8 100644 --- a/libs/SDL3/src/SDL_list.h +++ b/libs/SDL3/src/SDL_list.h @@ -28,9 +28,9 @@ typedef struct SDL_ListNode struct SDL_ListNode *next; } SDL_ListNode; -int SDL_ListAdd(SDL_ListNode **head, void *ent); +bool SDL_ListAdd(SDL_ListNode **head, void *ent); void SDL_ListPop(SDL_ListNode **head, void **ent); void SDL_ListRemove(SDL_ListNode **head, void *ent); void SDL_ListClear(SDL_ListNode **head); -#endif /* SDL_list_h_ */ +#endif // SDL_list_h_ diff --git a/libs/SDL3/src/SDL_log.c b/libs/SDL3/src/SDL_log.c index 2baf16a0f..1b9be017e 100644 --- a/libs/SDL3/src/SDL_log.c +++ b/libs/SDL3/src/SDL_log.c @@ -20,11 +20,11 @@ */ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "core/windows/SDL_windows.h" #endif -/* Simple log messages in SDL */ +// Simple log messages in SDL #include "SDL_log_c.h" @@ -38,7 +38,7 @@ #include "stdlib/SDL_vacopy.h" -/* The size of the stack buffer to use for rendering log messages. */ +// The size of the stack buffer to use for rendering log messages. #define SDL_MAX_LOG_MESSAGE_STACK 256 #define DEFAULT_CATEGORY -1 @@ -50,24 +50,31 @@ typedef struct SDL_LogLevel struct SDL_LogLevel *next; } SDL_LogLevel; -/* The default log output function */ + +// The default log output function static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message); -static SDL_LogLevel *SDL_loglevels; -static SDL_bool SDL_forced_priority = SDL_FALSE; -static SDL_LogPriority SDL_forced_priority_level; -static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput; -static void *SDL_log_userdata = NULL; -static SDL_Mutex *log_function_mutex = NULL; +static void CleanupLogPriorities(void); +static void CleanupLogPrefixes(void); + +static SDL_InitState SDL_log_init; +static SDL_Mutex *SDL_log_lock; +static SDL_Mutex *SDL_log_function_lock; +static SDL_LogLevel *SDL_loglevels SDL_GUARDED_BY(SDL_log_lock); +static SDL_LogPriority SDL_log_priorities[SDL_LOG_CATEGORY_CUSTOM] SDL_GUARDED_BY(SDL_log_lock); +static SDL_LogPriority SDL_log_default_priority SDL_GUARDED_BY(SDL_log_lock); +static SDL_LogOutputFunction SDL_log_function SDL_GUARDED_BY(SDL_log_function_lock) = SDL_LogOutput; +static void *SDL_log_userdata SDL_GUARDED_BY(SDL_log_function_lock) = NULL; #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #endif -/* If this list changes, update the documentation for SDL_HINT_LOGGING */ -static const char *SDL_priority_prefixes[] = { +// If this list changes, update the documentation for SDL_HINT_LOGGING +static const char * const SDL_priority_names[] = { NULL, + "TRACE", "VERBOSE", "DEBUG", "INFO", @@ -75,10 +82,13 @@ static const char *SDL_priority_prefixes[] = { "ERROR", "CRITICAL" }; -SDL_COMPILE_TIME_ASSERT(priority_prefixes, SDL_arraysize(SDL_priority_prefixes) == SDL_NUM_LOG_PRIORITIES); +SDL_COMPILE_TIME_ASSERT(priority_names, SDL_arraysize(SDL_priority_names) == SDL_LOG_PRIORITY_COUNT); -/* If this list changes, update the documentation for SDL_HINT_LOGGING */ -static const char *SDL_category_prefixes[] = { +// This is guarded by SDL_log_function_lock because it's the logging function that calls GetLogPriorityPrefix() +static char *SDL_priority_prefixes[SDL_LOG_PRIORITY_COUNT] SDL_GUARDED_BY(SDL_log_function_lock); + +// If this list changes, update the documentation for SDL_HINT_LOGGING +static const char * const SDL_category_names[] = { "APP", "ERROR", "ASSERT", @@ -87,138 +97,242 @@ static const char *SDL_category_prefixes[] = { "VIDEO", "RENDER", "INPUT", - "TEST" + "TEST", + "GPU" }; -SDL_COMPILE_TIME_ASSERT(category_prefixes, SDL_arraysize(SDL_category_prefixes) == SDL_LOG_CATEGORY_RESERVED1); +SDL_COMPILE_TIME_ASSERT(category_names, SDL_arraysize(SDL_category_names) == SDL_LOG_CATEGORY_RESERVED2); #ifdef HAVE_GCC_DIAGNOSTIC_PRAGMA #pragma GCC diagnostic pop #endif #ifdef SDL_PLATFORM_ANDROID -static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = { +static int SDL_android_priority[] = { ANDROID_LOG_UNKNOWN, ANDROID_LOG_VERBOSE, + ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL }; -#endif /* SDL_PLATFORM_ANDROID */ +SDL_COMPILE_TIME_ASSERT(android_priority, SDL_arraysize(SDL_android_priority) == SDL_LOG_PRIORITY_COUNT); +#endif // SDL_PLATFORM_ANDROID + +static void SDLCALL SDL_LoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_ResetLogPriorities(); +} void SDL_InitLog(void) { - if (!log_function_mutex) { - /* if this fails we'll try to continue without it. */ - log_function_mutex = SDL_CreateMutex(); + if (!SDL_ShouldInit(&SDL_log_init)) { + return; } + + // If these fail we'll continue without them. + SDL_log_lock = SDL_CreateMutex(); + SDL_log_function_lock = SDL_CreateMutex(); + + SDL_AddHintCallback(SDL_HINT_LOGGING, SDL_LoggingChanged, NULL); + + SDL_SetInitialized(&SDL_log_init, true); } void SDL_QuitLog(void) { - SDL_LogResetPriorities(); - if (log_function_mutex) { - SDL_DestroyMutex(log_function_mutex); - log_function_mutex = NULL; + if (!SDL_ShouldQuit(&SDL_log_init)) { + return; } + + SDL_RemoveHintCallback(SDL_HINT_LOGGING, SDL_LoggingChanged, NULL); + + CleanupLogPriorities(); + CleanupLogPrefixes(); + + if (SDL_log_lock) { + SDL_DestroyMutex(SDL_log_lock); + SDL_log_lock = NULL; + } + if (SDL_log_function_lock) { + SDL_DestroyMutex(SDL_log_function_lock); + SDL_log_function_lock = NULL; + } + + SDL_SetInitialized(&SDL_log_init, false); } -void SDL_LogSetAllPriority(SDL_LogPriority priority) +static void SDL_CheckInitLog(void) { - SDL_LogLevel *entry; + int status = SDL_GetAtomicInt(&SDL_log_init.status); + if (status == SDL_INIT_STATUS_INITIALIZED || + (status == SDL_INIT_STATUS_INITIALIZING && SDL_log_init.thread == SDL_GetCurrentThreadID())) { + return; + } + + SDL_InitLog(); +} - for (entry = SDL_loglevels; entry; entry = entry->next) { - entry->priority = priority; +static void CleanupLogPriorities(void) +{ + while (SDL_loglevels) { + SDL_LogLevel *entry = SDL_loglevels; + SDL_loglevels = entry->next; + SDL_free(entry); } +} - SDL_forced_priority = SDL_TRUE; - SDL_forced_priority_level = priority; +void SDL_SetLogPriorities(SDL_LogPriority priority) +{ + SDL_CheckInitLog(); + + SDL_LockMutex(SDL_log_lock); + { + CleanupLogPriorities(); + + SDL_log_default_priority = priority; + for (int i = 0; i < SDL_arraysize(SDL_log_priorities); ++i) { + SDL_log_priorities[i] = priority; + } + } + SDL_UnlockMutex(SDL_log_lock); } -void SDL_LogSetPriority(int category, SDL_LogPriority priority) +void SDL_SetLogPriority(int category, SDL_LogPriority priority) { SDL_LogLevel *entry; - for (entry = SDL_loglevels; entry; entry = entry->next) { - if (entry->category == category) { - entry->priority = priority; - return; + SDL_CheckInitLog(); + + SDL_LockMutex(SDL_log_lock); + { + if (category >= 0 && category < SDL_arraysize(SDL_log_priorities)) { + SDL_log_priorities[category] = priority; + } else { + for (entry = SDL_loglevels; entry; entry = entry->next) { + if (entry->category == category) { + entry->priority = priority; + break; + } + } + + if (!entry) { + entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry)); + if (entry) { + entry->category = category; + entry->priority = priority; + entry->next = SDL_loglevels; + SDL_loglevels = entry; + } + } } } + SDL_UnlockMutex(SDL_log_lock); +} + +SDL_LogPriority SDL_GetLogPriority(int category) +{ + SDL_LogLevel *entry; + SDL_LogPriority priority = SDL_LOG_PRIORITY_INVALID; + + SDL_CheckInitLog(); + + // Bypass the lock for known categories + // Technically if the priority was set on a different CPU the value might not + // be visible on this CPU for a while, but in practice it's fast enough that + // this performance improvement is worthwhile. + if (category >= 0 && category < SDL_arraysize(SDL_log_priorities)) { + return SDL_log_priorities[category]; + } - /* Create a new entry */ - entry = (SDL_LogLevel *)SDL_malloc(sizeof(*entry)); - if (entry) { - entry->category = category; - entry->priority = priority; - entry->next = SDL_loglevels; - SDL_loglevels = entry; + SDL_LockMutex(SDL_log_lock); + { + if (category >= 0 && category < SDL_arraysize(SDL_log_priorities)) { + priority = SDL_log_priorities[category]; + } else { + for (entry = SDL_loglevels; entry; entry = entry->next) { + if (entry->category == category) { + priority = entry->priority; + break; + } + } + if (priority == SDL_LOG_PRIORITY_INVALID) { + priority = SDL_log_default_priority; + } + } } + SDL_UnlockMutex(SDL_log_lock); + + return priority; } -static SDL_bool SDL_ParseLogCategory(const char *string, size_t length, int *category) +static bool ParseLogCategory(const char *string, size_t length, int *category) { int i; if (SDL_isdigit(*string)) { *category = SDL_atoi(string); - return SDL_TRUE; + return true; } if (*string == '*') { *category = DEFAULT_CATEGORY; - return SDL_TRUE; + return true; } - for (i = 0; i < SDL_arraysize(SDL_category_prefixes); ++i) { - if (SDL_strncasecmp(string, SDL_category_prefixes[i], length) == 0) { + for (i = 0; i < SDL_arraysize(SDL_category_names); ++i) { + if (SDL_strncasecmp(string, SDL_category_names[i], length) == 0) { *category = i; - return SDL_TRUE; + return true; } } - return SDL_FALSE; + return false; } -static SDL_bool SDL_ParseLogPriority(const char *string, size_t length, SDL_LogPriority *priority) +static bool ParseLogPriority(const char *string, size_t length, SDL_LogPriority *priority) { int i; if (SDL_isdigit(*string)) { i = SDL_atoi(string); if (i == 0) { - /* 0 has a special meaning of "disable this category" */ - *priority = SDL_NUM_LOG_PRIORITIES; - return SDL_TRUE; + // 0 has a special meaning of "disable this category" + *priority = SDL_LOG_PRIORITY_COUNT; + return true; } - if (i >= SDL_LOG_PRIORITY_VERBOSE && i < SDL_NUM_LOG_PRIORITIES) { + if (i > SDL_LOG_PRIORITY_INVALID && i < SDL_LOG_PRIORITY_COUNT) { *priority = (SDL_LogPriority)i; - return SDL_TRUE; + return true; } - return SDL_FALSE; + return false; } if (SDL_strncasecmp(string, "quiet", length) == 0) { - *priority = SDL_NUM_LOG_PRIORITIES; - return SDL_TRUE; + *priority = SDL_LOG_PRIORITY_COUNT; + return true; } - for (i = SDL_LOG_PRIORITY_VERBOSE; i < SDL_NUM_LOG_PRIORITIES; ++i) { - if (SDL_strncasecmp(string, SDL_priority_prefixes[i], length) == 0) { + for (i = SDL_LOG_PRIORITY_INVALID + 1; i < SDL_LOG_PRIORITY_COUNT; ++i) { + if (SDL_strncasecmp(string, SDL_priority_names[i], length) == 0) { *priority = (SDL_LogPriority)i; - return SDL_TRUE; + return true; } } - return SDL_FALSE; + return false; } -static SDL_bool SDL_ParseLogCategoryPriority(const char *hint, int category, SDL_LogPriority *priority) +static void ParseLogPriorities(const char *hint) { const char *name, *next; - int current_category; + int category = DEFAULT_CATEGORY; + SDL_LogPriority priority = SDL_LOG_PRIORITY_INVALID; - if (category == DEFAULT_CATEGORY && SDL_strchr(hint, '=') == NULL) { - return SDL_ParseLogPriority(hint, SDL_strlen(hint), priority); + if (SDL_strchr(hint, '=') == NULL) { + if (ParseLogPriority(hint, SDL_strlen(hint), &priority)) { + SDL_SetLogPriorities(priority); + } + return; } for (name = hint; name; name = next) { @@ -231,75 +345,134 @@ static SDL_bool SDL_ParseLogCategoryPriority(const char *hint, int category, SDL ++next; } - if (SDL_ParseLogCategory(name, (sep - name), ¤t_category)) { - if (current_category == category) { - const char *value = sep + 1; - size_t len; - if (next) { - len = (next - value - 1); + if (ParseLogCategory(name, (sep - name), &category)) { + const char *value = sep + 1; + size_t len; + if (next) { + len = (next - value - 1); + } else { + len = SDL_strlen(value); + } + if (ParseLogPriority(value, len, &priority)) { + if (category == DEFAULT_CATEGORY) { + for (int i = 0; i < SDL_arraysize(SDL_log_priorities); ++i) { + if (SDL_log_priorities[i] == SDL_LOG_PRIORITY_INVALID) { + SDL_log_priorities[i] = priority; + } + } + SDL_log_default_priority = priority; } else { - len = SDL_strlen(value); + SDL_SetLogPriority(category, priority); } - return SDL_ParseLogPriority(value, len, priority); } } } - return SDL_FALSE; } -static SDL_LogPriority SDL_GetDefaultLogPriority(int category) +void SDL_ResetLogPriorities(void) { - const char *hint = SDL_GetHint(SDL_HINT_LOGGING); - if (hint) { - SDL_LogPriority priority; + SDL_CheckInitLog(); + + SDL_LockMutex(SDL_log_lock); + { + CleanupLogPriorities(); - if (SDL_ParseLogCategoryPriority(hint, category, &priority)) { - return priority; + SDL_log_default_priority = SDL_LOG_PRIORITY_INVALID; + for (int i = 0; i < SDL_arraysize(SDL_log_priorities); ++i) { + SDL_log_priorities[i] = SDL_LOG_PRIORITY_INVALID; } - if (SDL_ParseLogCategoryPriority(hint, DEFAULT_CATEGORY, &priority)) { - return priority; + + const char *hint = SDL_GetHint(SDL_HINT_LOGGING); + if (hint) { + ParseLogPriorities(hint); } - } - switch (category) { - case SDL_LOG_CATEGORY_APPLICATION: - return SDL_LOG_PRIORITY_INFO; - case SDL_LOG_CATEGORY_ASSERT: - return SDL_LOG_PRIORITY_WARN; - case SDL_LOG_CATEGORY_TEST: - return SDL_LOG_PRIORITY_VERBOSE; - default: - return SDL_LOG_PRIORITY_ERROR; + if (SDL_log_default_priority == SDL_LOG_PRIORITY_INVALID) { + SDL_log_default_priority = SDL_LOG_PRIORITY_ERROR; + } + for (int i = 0; i < SDL_arraysize(SDL_log_priorities); ++i) { + if (SDL_log_priorities[i] != SDL_LOG_PRIORITY_INVALID) { + continue; + } + + switch (i) { + case SDL_LOG_CATEGORY_APPLICATION: + SDL_log_priorities[i] = SDL_LOG_PRIORITY_INFO; + break; + case SDL_LOG_CATEGORY_ASSERT: + SDL_log_priorities[i] = SDL_LOG_PRIORITY_WARN; + break; + case SDL_LOG_CATEGORY_TEST: + SDL_log_priorities[i] = SDL_LOG_PRIORITY_VERBOSE; + break; + default: + SDL_log_priorities[i] = SDL_LOG_PRIORITY_ERROR; + break; + } + } } + SDL_UnlockMutex(SDL_log_lock); } -SDL_LogPriority SDL_LogGetPriority(int category) +static void CleanupLogPrefixes(void) { - SDL_LogLevel *entry; - - for (entry = SDL_loglevels; entry; entry = entry->next) { - if (entry->category == category) { - return entry->priority; + for (int i = 0; i < SDL_arraysize(SDL_priority_prefixes); ++i) { + if (SDL_priority_prefixes[i]) { + SDL_free(SDL_priority_prefixes[i]); + SDL_priority_prefixes[i] = NULL; } } +} + +static const char *GetLogPriorityPrefix(SDL_LogPriority priority) +{ + if (priority <= SDL_LOG_PRIORITY_INVALID || priority >= SDL_LOG_PRIORITY_COUNT) { + return ""; + } - if (SDL_forced_priority) { - return SDL_forced_priority_level; + if (SDL_priority_prefixes[priority]) { + return SDL_priority_prefixes[priority]; } - return SDL_GetDefaultLogPriority(category); + switch (priority) { + case SDL_LOG_PRIORITY_WARN: + return "WARNING: "; + case SDL_LOG_PRIORITY_ERROR: + return "ERROR: "; + case SDL_LOG_PRIORITY_CRITICAL: + return "ERROR: "; + default: + return ""; + } } -void SDL_LogResetPriorities(void) +bool SDL_SetLogPriorityPrefix(SDL_LogPriority priority, const char *prefix) { - SDL_LogLevel *entry; + char *prefix_copy; - while (SDL_loglevels) { - entry = SDL_loglevels; - SDL_loglevels = entry->next; - SDL_free(entry); + if (priority <= SDL_LOG_PRIORITY_INVALID || priority >= SDL_LOG_PRIORITY_COUNT) { + return SDL_InvalidParamError("priority"); + } + + if (!prefix || !*prefix) { + prefix_copy = SDL_strdup(""); + } else { + prefix_copy = SDL_strdup(prefix); + } + if (!prefix_copy) { + return false; } - SDL_forced_priority = SDL_FALSE; + + SDL_LockMutex(SDL_log_function_lock); + { + if (SDL_priority_prefixes[priority]) { + SDL_free(SDL_priority_prefixes[priority]); + } + SDL_priority_prefixes[priority] = prefix_copy; + } + SDL_UnlockMutex(SDL_log_function_lock); + + return true; } void SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) @@ -311,6 +484,15 @@ void SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) va_end(ap); } +void SDL_LogTrace(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + SDL_LogMessageV(category, SDL_LOG_PRIORITY_TRACE, fmt, ap); + va_end(ap); +} + void SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { va_list ap; @@ -377,15 +559,15 @@ void SDL_LogMessage(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_ST #ifdef SDL_PLATFORM_ANDROID static const char *GetCategoryPrefix(int category) { - if (category < SDL_LOG_CATEGORY_RESERVED1) { - return SDL_category_prefixes[category]; + if (category < SDL_LOG_CATEGORY_RESERVED2) { + return SDL_category_names[category]; } if (category < SDL_LOG_CATEGORY_CUSTOM) { return "RESERVED"; } return "CUSTOM"; } -#endif /* SDL_PLATFORM_ANDROID */ +#endif // SDL_PLATFORM_ANDROID void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_STRING const char *fmt, va_list ap) { @@ -395,27 +577,17 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S int len; va_list aq; - /* Nothing to do if we don't have an output function */ + // Nothing to do if we don't have an output function if (!SDL_log_function) { return; } - /* Make sure we don't exceed array bounds */ - if ((int)priority < 0 || priority >= SDL_NUM_LOG_PRIORITIES) { - return; - } - - /* See if we want to do anything with this message */ - if (priority < SDL_LogGetPriority(category)) { + // See if we want to do anything with this message + if (priority < SDL_GetLogPriority(category)) { return; } - if (!log_function_mutex) { - /* this mutex creation can race if you log from two threads at startup. You should have called SDL_Init first! */ - log_function_mutex = SDL_CreateMutex(); - } - - /* Render into stack buffer */ + // Render into stack buffer va_copy(aq, ap); len = SDL_vsnprintf(stack_buf, sizeof(stack_buf), fmt, aq); va_end(aq); @@ -424,9 +596,9 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S return; } - /* If message truncated, allocate and re-render */ - if (len >= sizeof(stack_buf) && SDL_size_add_overflow(len, 1, &len_plus_term) == 0) { - /* Allocate exactly what we need, including the zero-terminator */ + // If message truncated, allocate and re-render + if (len >= sizeof(stack_buf) && SDL_size_add_check_overflow(len, 1, &len_plus_term)) { + // Allocate exactly what we need, including the zero-terminator message = (char *)SDL_malloc(len_plus_term); if (!message) { return; @@ -438,96 +610,101 @@ void SDL_LogMessageV(int category, SDL_LogPriority priority, SDL_PRINTF_FORMAT_S message = stack_buf; } - /* Chop off final endline. */ + // Chop off final endline. if ((len > 0) && (message[len - 1] == '\n')) { message[--len] = '\0'; - if ((len > 0) && (message[len - 1] == '\r')) { /* catch "\r\n", too. */ + if ((len > 0) && (message[len - 1] == '\r')) { // catch "\r\n", too. message[--len] = '\0'; } } - SDL_LockMutex(log_function_mutex); - SDL_log_function(SDL_log_userdata, category, priority, message); - SDL_UnlockMutex(log_function_mutex); + SDL_LockMutex(SDL_log_function_lock); + { + SDL_log_function(SDL_log_userdata, category, priority, message); + } + SDL_UnlockMutex(SDL_log_function_lock); - /* Free only if dynamically allocated */ + // Free only if dynamically allocated if (message != stack_buf) { SDL_free(message); } } -#if defined(SDL_PLATFORM_WIN32) && !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) -/* Flag tracking the attachment of the console: 0=unattached, 1=attached to a console, 2=attached to a file, -1=error */ -static int consoleAttached = 0; +#if defined(SDL_PLATFORM_WIN32) && !defined(SDL_PLATFORM_GDK) +enum { + CONSOLE_UNATTACHED = 0, + CONSOLE_ATTACHED_CONSOLE = 1, + CONSOLE_ATTACHED_FILE = 2, + CONSOLE_ATTACHED_ERROR = -1, +} consoleAttached = CONSOLE_UNATTACHED; -/* Handle to stderr output of console. */ +// Handle to stderr output of console. static HANDLE stderrHandle = NULL; #endif static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, const char *message) { -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) - /* Way too many allocations here, urgh */ - /* Note: One can't call SDL_SetError here, since that function itself logs. */ +#if defined(SDL_PLATFORM_WINDOWS) + // Way too many allocations here, urgh + // Note: One can't call SDL_SetError here, since that function itself logs. { char *output; size_t length; LPTSTR tstr; - SDL_bool isstack; + bool isstack; -#if !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) +#if !defined(SDL_PLATFORM_GDK) BOOL attachResult; DWORD attachError; - DWORD charsWritten; DWORD consoleMode; + DWORD charsWritten; - /* Maybe attach console and get stderr handle */ - if (consoleAttached == 0) { + // Maybe attach console and get stderr handle + if (consoleAttached == CONSOLE_UNATTACHED) { attachResult = AttachConsole(ATTACH_PARENT_PROCESS); if (!attachResult) { attachError = GetLastError(); if (attachError == ERROR_INVALID_HANDLE) { - /* This is expected when running from Visual Studio */ - /*OutputDebugString(TEXT("Parent process has no console\r\n"));*/ - consoleAttached = -1; + // This is expected when running from Visual Studio + // OutputDebugString(TEXT("Parent process has no console\r\n")); + consoleAttached = CONSOLE_ATTACHED_ERROR; } else if (attachError == ERROR_GEN_FAILURE) { OutputDebugString(TEXT("Could not attach to console of parent process\r\n")); - consoleAttached = -1; + consoleAttached = CONSOLE_ATTACHED_ERROR; } else if (attachError == ERROR_ACCESS_DENIED) { - /* Already attached */ - consoleAttached = 1; + // Already attached + consoleAttached = CONSOLE_ATTACHED_CONSOLE; } else { OutputDebugString(TEXT("Error attaching console\r\n")); - consoleAttached = -1; + consoleAttached = CONSOLE_ATTACHED_ERROR; } } else { - /* Newly attached */ - consoleAttached = 1; + // Newly attached + consoleAttached = CONSOLE_ATTACHED_CONSOLE; } - if (consoleAttached == 1) { + if (consoleAttached == CONSOLE_ATTACHED_CONSOLE) { stderrHandle = GetStdHandle(STD_ERROR_HANDLE); if (GetConsoleMode(stderrHandle, &consoleMode) == 0) { - /* WriteConsole fails if the output is redirected to a file. Must use WriteFile instead. */ - consoleAttached = 2; + // WriteConsole fails if the output is redirected to a file. Must use WriteFile instead. + consoleAttached = CONSOLE_ATTACHED_FILE; } } } -#endif /* !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) */ - - length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1; +#endif // !defined(SDL_PLATFORM_GDK) + length = SDL_strlen(GetLogPriorityPrefix(priority)) + SDL_strlen(message) + 1 + 1 + 1; output = SDL_small_alloc(char, length, &isstack); - (void)SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message); + (void)SDL_snprintf(output, length, "%s%s\r\n", GetLogPriorityPrefix(priority), message); tstr = WIN_UTF8ToString(output); - /* Output to debugger */ + // Output to debugger OutputDebugString(tstr); -#if !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) - /* Screen output to stderr, if console was attached. */ - if (consoleAttached == 1) { +#if !defined(SDL_PLATFORM_GDK) + // Screen output to stderr, if console was attached. + if (consoleAttached == CONSOLE_ATTACHED_CONSOLE) { if (!WriteConsole(stderrHandle, tstr, (DWORD)SDL_tcslen(tstr), &charsWritten, NULL)) { OutputDebugString(TEXT("Error calling WriteConsole\r\n")); if (GetLastError() == ERROR_NOT_ENOUGH_MEMORY) { @@ -535,12 +712,12 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority } } - } else if (consoleAttached == 2) { + } else if (consoleAttached == CONSOLE_ATTACHED_FILE) { if (!WriteFile(stderrHandle, output, (DWORD)SDL_strlen(output), &charsWritten, NULL)) { OutputDebugString(TEXT("Error calling WriteFile\r\n")); } } -#endif /* !defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_GDK) */ +#endif // !defined(SDL_PLATFORM_GDK) SDL_free(tstr); SDL_small_free(output, isstack); @@ -557,7 +734,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority */ extern void SDL_NSLog(const char *prefix, const char *text); { - SDL_NSLog(SDL_priority_prefixes[priority], message); + SDL_NSLog(GetLogPriorityPrefix(priority), message); return; } #elif defined(SDL_PLATFORM_PSP) || defined(SDL_PLATFORM_PS2) @@ -565,7 +742,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority FILE *pFile; pFile = fopen("SDL_Log.txt", "a"); if (pFile) { - (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); + (void)fprintf(pFile, "%s%s\n", GetLogPriorityPrefix(priority), message); (void)fclose(pFile); } } @@ -574,7 +751,7 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority FILE *pFile; pFile = fopen("ux0:/data/SDL_Log.txt", "a"); if (pFile) { - (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); + (void)fprintf(pFile, "%s%s\n", GetLogPriorityPrefix(priority), message); (void)fclose(pFile); } } @@ -583,29 +760,38 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority FILE *pFile; pFile = fopen("sdmc:/3ds/SDL_Log.txt", "a"); if (pFile) { - (void)fprintf(pFile, "%s: %s\n", SDL_priority_prefixes[priority], message); + (void)fprintf(pFile, "%s%s\n", GetLogPriorityPrefix(priority), message); (void)fclose(pFile); } } #endif #if defined(HAVE_STDIO_H) && \ - !(defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))) - (void)fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message); + !(defined(SDL_PLATFORM_APPLE) && (defined(SDL_VIDEO_DRIVER_COCOA) || defined(SDL_VIDEO_DRIVER_UIKIT))) && \ + !(defined(SDL_PLATFORM_WIN32)) + (void)fprintf(stderr, "%s%s\n", GetLogPriorityPrefix(priority), message); #endif } void SDL_GetLogOutputFunction(SDL_LogOutputFunction *callback, void **userdata) { - if (callback) { - *callback = SDL_log_function; - } - if (userdata) { - *userdata = SDL_log_userdata; + SDL_LockMutex(SDL_log_function_lock); + { + if (callback) { + *callback = SDL_log_function; + } + if (userdata) { + *userdata = SDL_log_userdata; + } } + SDL_UnlockMutex(SDL_log_function_lock); } void SDL_SetLogOutputFunction(SDL_LogOutputFunction callback, void *userdata) { - SDL_log_function = callback; - SDL_log_userdata = userdata; + SDL_LockMutex(SDL_log_function_lock); + { + SDL_log_function = callback; + SDL_log_userdata = userdata; + } + SDL_UnlockMutex(SDL_log_function_lock); } diff --git a/libs/SDL3/src/SDL_log_c.h b/libs/SDL3/src/SDL_log_c.h index 3da88d684..bb79ed60c 100644 --- a/libs/SDL3/src/SDL_log_c.h +++ b/libs/SDL3/src/SDL_log_c.h @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* This file defines useful function for working with SDL logging */ +// This file defines useful function for working with SDL logging #ifndef SDL_log_c_h_ #define SDL_log_c_h_ @@ -28,4 +28,4 @@ extern void SDL_InitLog(void); extern void SDL_QuitLog(void); -#endif /* SDL_log_c_h_ */ +#endif // SDL_log_c_h_ diff --git a/libs/SDL3/src/SDL_properties.c b/libs/SDL3/src/SDL_properties.c index fd209c456..0055bd530 100644 --- a/libs/SDL3/src/SDL_properties.c +++ b/libs/SDL3/src/SDL_properties.c @@ -1,5 +1,5 @@ /* - Simple DiretMedia Layer + Simple DirectMedia Layer Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" -#include "SDL_hashtable.h" + #include "SDL_hints_c.h" #include "SDL_properties_c.h" @@ -33,12 +33,12 @@ typedef struct char *string_value; Sint64 number_value; float float_value; - SDL_bool boolean_value; + bool boolean_value; } value; char *string_storage; - void (SDLCALL *cleanup)(void *userdata, void *value); + SDL_CleanupPropertyCallback cleanup; void *userdata; } SDL_Property; @@ -48,13 +48,14 @@ typedef struct SDL_Mutex *lock; } SDL_Properties; +static SDL_InitState SDL_properties_init; static SDL_HashTable *SDL_properties; static SDL_Mutex *SDL_properties_lock; static SDL_PropertiesID SDL_last_properties_id; -static SDL_PropertiesID SDL_global_properties; +static SDL_AtomicU32 SDL_global_properties; -static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void *data, SDL_bool cleanup) +static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void *data, bool cleanup) { SDL_Property *property = (SDL_Property *)value; if (property) { @@ -70,9 +71,7 @@ static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void default: break; } - if (property->string_storage) { - SDL_free(property->string_storage); - } + SDL_free(property->string_storage); } SDL_free((void *)key); SDL_free((void *)value); @@ -80,7 +79,7 @@ static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void static void SDL_FreeProperty(const void *key, const void *value, void *data) { - SDL_FreePropertyWithCleanup(key, value, data, SDL_TRUE); + SDL_FreePropertyWithCleanup(key, value, data, true); } static void SDL_FreeProperties(const void *key, const void *value, void *data) @@ -99,29 +98,44 @@ static void SDL_FreeProperties(const void *key, const void *value, void *data) } } -int SDL_InitProperties(void) +bool SDL_InitProperties(void) { - if (!SDL_properties_lock) { - SDL_properties_lock = SDL_CreateMutex(); - if (!SDL_properties_lock) { - return -1; - } + if (!SDL_ShouldInit(&SDL_properties_init)) { + return true; } + + // If this fails we'll continue without it. + SDL_properties_lock = SDL_CreateMutex(); + + SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, false); if (!SDL_properties) { - SDL_properties = SDL_CreateHashTable(NULL, 16, SDL_HashID, SDL_KeyMatchID, SDL_FreeProperties, SDL_FALSE); - if (!SDL_properties) { - return -1; - } + goto error; } - return 0; + + SDL_SetInitialized(&SDL_properties_init, true); + return true; + +error: + SDL_SetInitialized(&SDL_properties_init, true); + SDL_QuitProperties(); + return false; } void SDL_QuitProperties(void) { - if (SDL_global_properties) { - SDL_DestroyProperties(SDL_global_properties); - SDL_global_properties = 0; + if (!SDL_ShouldQuit(&SDL_properties_init)) { + return; + } + + SDL_PropertiesID props; + do { + props = SDL_GetAtomicU32(&SDL_global_properties); + } while (!SDL_CompareAndSwapAtomicU32(&SDL_global_properties, props, 0)); + + if (props) { + SDL_DestroyProperties(props); } + if (SDL_properties) { SDL_DestroyHashTable(SDL_properties); SDL_properties = NULL; @@ -130,23 +144,36 @@ void SDL_QuitProperties(void) SDL_DestroyMutex(SDL_properties_lock); SDL_properties_lock = NULL; } + + SDL_SetInitialized(&SDL_properties_init, false); +} + +static bool SDL_CheckInitProperties(void) +{ + return SDL_InitProperties(); } SDL_PropertiesID SDL_GetGlobalProperties(void) { - if (!SDL_global_properties) { - SDL_global_properties = SDL_CreateProperties(); + SDL_PropertiesID props = SDL_GetAtomicU32(&SDL_global_properties); + if (!props) { + props = SDL_CreateProperties(); + if (!SDL_CompareAndSwapAtomicU32(&SDL_global_properties, 0, props)) { + // Somebody else created global properties before us, just use those + SDL_DestroyProperties(props); + props = SDL_GetAtomicU32(&SDL_global_properties); + } } - return SDL_global_properties; + return props; } SDL_PropertiesID SDL_CreateProperties(void) { SDL_PropertiesID props = 0; SDL_Properties *properties = NULL; - SDL_bool inserted = SDL_FALSE; + bool inserted = false; - if (!SDL_properties && SDL_InitProperties() < 0) { + if (!SDL_CheckInitProperties()) { return 0; } @@ -154,18 +181,13 @@ SDL_PropertiesID SDL_CreateProperties(void) if (!properties) { goto error; } - properties->props = SDL_CreateHashTable(NULL, 4, SDL_HashString, SDL_KeyMatchString, SDL_FreeProperty, SDL_FALSE); + properties->props = SDL_CreateHashTable(NULL, 4, SDL_HashString, SDL_KeyMatchString, SDL_FreeProperty, false); if (!properties->props) { goto error; } - properties->lock = SDL_CreateMutex(); - if (!properties->lock) { - goto error; - } - if (SDL_InitProperties() < 0) { - goto error; - } + // If this fails we'll continue without it. + properties->lock = SDL_CreateMutex(); SDL_LockMutex(SDL_properties_lock); ++SDL_last_properties_id; @@ -174,12 +196,12 @@ SDL_PropertiesID SDL_CreateProperties(void) } props = SDL_last_properties_id; if (SDL_InsertIntoHashTable(SDL_properties, (const void *)(uintptr_t)props, properties)) { - inserted = SDL_TRUE; + inserted = true; } SDL_UnlockMutex(SDL_properties_lock); if (inserted) { - /* All done! */ + // All done! return props; } @@ -188,11 +210,11 @@ SDL_PropertiesID SDL_CreateProperties(void) return 0; } -int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) +bool SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) { SDL_Properties *src_properties = NULL; SDL_Properties *dst_properties = NULL; - int result = 0; + bool result = true; if (!src) { return SDL_InvalidParamError("src"); @@ -227,7 +249,7 @@ int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) SDL_Property *dst_property; if (src_property->cleanup) { - /* Can't copy properties with cleanup functions, we don't know how to duplicate the data */ + // Can't copy properties with cleanup functions, we don't know how to duplicate the data continue; } @@ -235,13 +257,13 @@ int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) dst_name = SDL_strdup(src_name); if (!dst_name) { - result = -1; + result = false; continue; } dst_property = (SDL_Property *)SDL_malloc(sizeof(*dst_property)); if (!dst_property) { SDL_free(dst_name); - result = -1; + result = false; continue; } SDL_copyp(dst_property, src_property); @@ -249,8 +271,8 @@ int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) dst_property->value.string_value = SDL_strdup(src_property->value.string_value); } if (!SDL_InsertIntoHashTable(dst_properties->props, dst_name, dst_property)) { - SDL_FreePropertyWithCleanup(dst_name, dst_property, NULL, SDL_FALSE); - result = -1; + SDL_FreePropertyWithCleanup(dst_name, dst_property, NULL, false); + result = false; } } } @@ -260,7 +282,7 @@ int SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst) return result; } -int SDL_LockProperties(SDL_PropertiesID props) +bool SDL_LockProperties(SDL_PropertiesID props) { SDL_Properties *properties = NULL; @@ -277,7 +299,7 @@ int SDL_LockProperties(SDL_PropertiesID props) } SDL_LockMutex(properties->lock); - return 0; + return true; } void SDL_UnlockProperties(SDL_PropertiesID props) @@ -299,17 +321,17 @@ void SDL_UnlockProperties(SDL_PropertiesID props) SDL_UnlockMutex(properties->lock); } -static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property) +static bool SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_Property *property) { SDL_Properties *properties = NULL; - int result = 0; + bool result = true; if (!props) { - SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); + SDL_FreePropertyWithCleanup(NULL, property, NULL, true); return SDL_InvalidParamError("props"); } if (!name || !*name) { - SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); + SDL_FreePropertyWithCleanup(NULL, property, NULL, true); return SDL_InvalidParamError("name"); } @@ -318,7 +340,7 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ SDL_UnlockMutex(SDL_properties_lock); if (!properties) { - SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); + SDL_FreePropertyWithCleanup(NULL, property, NULL, true); return SDL_InvalidParamError("props"); } @@ -328,8 +350,8 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ if (property) { char *key = SDL_strdup(name); if (!SDL_InsertIntoHashTable(properties->props, key, property)) { - SDL_FreePropertyWithCleanup(key, property, NULL, SDL_FALSE); - result = -1; + SDL_FreePropertyWithCleanup(key, property, NULL, true); + result = false; } } } @@ -338,18 +360,24 @@ static int SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL_ return result; } -int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, void (SDLCALL *cleanup)(void *userdata, void *value), void *userdata) +bool SDL_SetPointerPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *value, SDL_CleanupPropertyCallback cleanup, void *userdata) { SDL_Property *property; if (!value) { + if (cleanup) { + cleanup(userdata, value); + } return SDL_ClearProperty(props, name); } property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - SDL_FreePropertyWithCleanup(NULL, property, NULL, SDL_FALSE); - return -1; + if (cleanup) { + cleanup(userdata, value); + } + SDL_FreePropertyWithCleanup(NULL, property, NULL, false); + return false; } property->type = SDL_PROPERTY_TYPE_POINTER; property->value.pointer_value = value; @@ -358,7 +386,7 @@ int SDL_SetPropertyWithCleanup(SDL_PropertiesID props, const char *name, void *v return SDL_PrivateSetProperty(props, name, property); } -int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) +bool SDL_SetPointerProperty(SDL_PropertiesID props, const char *name, void *value) { SDL_Property *property; @@ -368,7 +396,7 @@ int SDL_SetProperty(SDL_PropertiesID props, const char *name, void *value) property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return -1; + return false; } property->type = SDL_PROPERTY_TYPE_POINTER; property->value.pointer_value = value; @@ -380,9 +408,9 @@ static void SDLCALL CleanupFreeableProperty(void *userdata, void *value) SDL_free(value); } -int SDL_SetFreeableProperty(SDL_PropertiesID props, const char *name, void *value) +bool SDL_SetFreeableProperty(SDL_PropertiesID props, const char *name, void *value) { - return SDL_SetPropertyWithCleanup(props, name, value, CleanupFreeableProperty, NULL); + return SDL_SetPointerPropertyWithCleanup(props, name, value, CleanupFreeableProperty, NULL); } static void SDLCALL CleanupSurface(void *userdata, void *value) @@ -392,12 +420,12 @@ static void SDLCALL CleanupSurface(void *userdata, void *value) SDL_DestroySurface(surface); } -int SDL_SetSurfaceProperty(SDL_PropertiesID props, const char *name, SDL_Surface *surface) +bool SDL_SetSurfaceProperty(SDL_PropertiesID props, const char *name, SDL_Surface *surface) { - return SDL_SetPropertyWithCleanup(props, name, surface, CleanupSurface, NULL); + return SDL_SetPointerPropertyWithCleanup(props, name, surface, CleanupSurface, NULL); } -int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value) +bool SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char *value) { SDL_Property *property; @@ -407,51 +435,51 @@ int SDL_SetStringProperty(SDL_PropertiesID props, const char *name, const char * property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return -1; + return false; } property->type = SDL_PROPERTY_TYPE_STRING; property->value.string_value = SDL_strdup(value); if (!property->value.string_value) { SDL_free(property); - return -1; + return false; } return SDL_PrivateSetProperty(props, name, property); } -int SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value) +bool SDL_SetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 value) { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return -1; + return false; } property->type = SDL_PROPERTY_TYPE_NUMBER; property->value.number_value = value; return SDL_PrivateSetProperty(props, name, property); } -int SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value) +bool SDL_SetFloatProperty(SDL_PropertiesID props, const char *name, float value) { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return -1; + return false; } property->type = SDL_PROPERTY_TYPE_FLOAT; property->value.float_value = value; return SDL_PrivateSetProperty(props, name, property); } -int SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool value) +bool SDL_SetBooleanProperty(SDL_PropertiesID props, const char *name, bool value) { SDL_Property *property = (SDL_Property *)SDL_calloc(1, sizeof(*property)); if (!property) { - return -1; + return false; } property->type = SDL_PROPERTY_TYPE_BOOLEAN; - property->value.boolean_value = value ? SDL_TRUE : SDL_FALSE; + property->value.boolean_value = value ? true : false; return SDL_PrivateSetProperty(props, name, property); } -SDL_bool SDL_HasProperty(SDL_PropertiesID props, const char *name) +bool SDL_HasProperty(SDL_PropertiesID props, const char *name) { return (SDL_GetPropertyType(props, name) != SDL_PROPERTY_TYPE_INVALID); } @@ -488,7 +516,7 @@ SDL_PropertyType SDL_GetPropertyType(SDL_PropertiesID props, const char *name) return type; } -void *SDL_GetProperty(SDL_PropertiesID props, const char *name, void *default_value) +void *SDL_GetPointerProperty(SDL_PropertiesID props, const char *name, void *default_value) { SDL_Properties *properties = NULL; void *value = default_value; @@ -546,12 +574,6 @@ const char *SDL_GetStringProperty(SDL_PropertiesID props, const char *name, cons return value; } - /* Note that taking the lock here only guarantees that we won't read the - * hashtable while it's being modified. The value itself can easily be - * freed from another thread after it is returned here. - * - * FIXME: Should we SDL_strdup() the return value to avoid this? - */ SDL_LockMutex(properties->lock); { SDL_Property *property = NULL; @@ -619,7 +641,7 @@ Sint64 SDL_GetNumberProperty(SDL_PropertiesID props, const char *name, Sint64 de if (SDL_FindInHashTable(properties->props, name, (const void **)&property)) { switch (property->type) { case SDL_PROPERTY_TYPE_STRING: - value = SDL_strtoll(property->value.string_value, NULL, 0); + value = (Sint64)SDL_strtoll(property->value.string_value, NULL, 0); break; case SDL_PROPERTY_TYPE_NUMBER: value = property->value.number_value; @@ -687,10 +709,10 @@ float SDL_GetFloatProperty(SDL_PropertiesID props, const char *name, float defau return value; } -SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bool default_value) +bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, bool default_value) { SDL_Properties *properties = NULL; - SDL_bool value = default_value; + bool value = default_value ? true : false; if (!props) { return value; @@ -734,12 +756,12 @@ SDL_bool SDL_GetBooleanProperty(SDL_PropertiesID props, const char *name, SDL_bo return value; } -int SDL_ClearProperty(SDL_PropertiesID props, const char *name) +bool SDL_ClearProperty(SDL_PropertiesID props, const char *name) { return SDL_PrivateSetProperty(props, name, NULL); } -int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata) +bool SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallback callback, void *userdata) { SDL_Properties *properties = NULL; @@ -770,7 +792,39 @@ int SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCallb } SDL_UnlockMutex(properties->lock); - return 0; + return true; +} + +static void SDLCALL SDL_DumpPropertiesCallback(void *userdata, SDL_PropertiesID props, const char *name) +{ + switch (SDL_GetPropertyType(props, name)) { + case SDL_PROPERTY_TYPE_POINTER: + SDL_Log("%s: %p\n", name, SDL_GetPointerProperty(props, name, NULL)); + break; + case SDL_PROPERTY_TYPE_STRING: + SDL_Log("%s: \"%s\"\n", name, SDL_GetStringProperty(props, name, "")); + break; + case SDL_PROPERTY_TYPE_NUMBER: + { + Sint64 value = SDL_GetNumberProperty(props, name, 0); + SDL_Log("%s: %" SDL_PRIs64 " (%" SDL_PRIx64 ")\n", name, value, value); + } + break; + case SDL_PROPERTY_TYPE_FLOAT: + SDL_Log("%s: %g\n", name, SDL_GetFloatProperty(props, name, 0.0f)); + break; + case SDL_PROPERTY_TYPE_BOOLEAN: + SDL_Log("%s: %s\n", name, SDL_GetBooleanProperty(props, name, false) ? "true" : "false"); + break; + default: + SDL_Log("%s UNKNOWN TYPE\n", name); + break; + } +} + +bool SDL_DumpProperties(SDL_PropertiesID props) +{ + return SDL_EnumerateProperties(props, SDL_DumpPropertiesCallback, NULL); } void SDL_DestroyProperties(SDL_PropertiesID props) diff --git a/libs/SDL3/src/SDL_properties_c.h b/libs/SDL3/src/SDL_properties_c.h index d996fa12f..e7a471cdd 100644 --- a/libs/SDL3/src/SDL_properties_c.h +++ b/libs/SDL3/src/SDL_properties_c.h @@ -1,5 +1,5 @@ /* - Simple DiretMedia Layer + Simple DirectMedia Layer Copyright (C) 1997-2024 Sam Lantinga This software is provided 'as-is', without any express or implied @@ -19,7 +19,8 @@ 3. This notice may not be removed or altered from any source distribution. */ -extern int SDL_InitProperties(void); -extern int SDL_SetFreeableProperty(SDL_PropertiesID props, const char *name, void *value); -extern int SDL_SetSurfaceProperty(SDL_PropertiesID props, const char *name, SDL_Surface *surface); +extern bool SDL_InitProperties(void); +extern bool SDL_SetFreeableProperty(SDL_PropertiesID props, const char *name, void *value); +extern bool SDL_SetSurfaceProperty(SDL_PropertiesID props, const char *name, SDL_Surface *surface); +extern bool SDL_DumpProperties(SDL_PropertiesID props); extern void SDL_QuitProperties(void); diff --git a/libs/SDL3/src/SDL_utils.c b/libs/SDL3/src/SDL_utils.c index 581964b0d..b1fb89af6 100644 --- a/libs/SDL3/src/SDL_utils.c +++ b/libs/SDL3/src/SDL_utils.c @@ -20,20 +20,22 @@ */ #include "SDL_internal.h" -#include "SDL_utils_c.h" +#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE) +#include +#endif -/* Common utility functions that aren't in the public API */ +// Common utility functions that aren't in the public API int SDL_powerof2(int x) { int value; if (x <= 0) { - /* Return some sane value - we shouldn't hit this in our use cases */ + // Return some sane value - we shouldn't hit this in our use cases return 1; } - /* This trick works for 32-bit values */ + // This trick works for 32-bit values { SDL_COMPILE_TIME_ASSERT(SDL_powerof2, sizeof(x) == sizeof(Uint32)); } @@ -49,15 +51,330 @@ int SDL_powerof2(int x) return value; } -SDL_bool SDL_endswith(const char *string, const char *suffix) +Uint32 SDL_CalculateGCD(Uint32 a, Uint32 b) +{ + if (b == 0) { + return a; + } + return SDL_CalculateGCD(b, (a % b)); +} + +// Algorithm adapted with thanks from John Cook's blog post: +// http://www.johndcook.com/blog/2010/10/20/best-rational-approximation +void SDL_CalculateFraction(float x, int *numerator, int *denominator) +{ + const int N = 1000; + int a = 0, b = 1; + int c = 1, d = 0; + + while (b <= N && d <= N) { + float mediant = (float)(a + c) / (b + d); + if (x == mediant) { + if (b + d <= N) { + *numerator = a + c; + *denominator = b + d; + } else if (d > b) { + *numerator = c; + *denominator = d; + } else { + *numerator = a; + *denominator = b; + } + return; + } else if (x > mediant) { + a = a + c; + b = b + d; + } else { + c = a + c; + d = b + d; + } + } + if (b > N) { + *numerator = c; + *denominator = d; + } else { + *numerator = a; + *denominator = b; + } +} + +bool SDL_startswith(const char *string, const char *prefix) +{ + if (SDL_strncmp(string, prefix, SDL_strlen(prefix)) == 0) { + return true; + } + return false; +} + +bool SDL_endswith(const char *string, const char *suffix) { size_t string_length = string ? SDL_strlen(string) : 0; size_t suffix_length = suffix ? SDL_strlen(suffix) : 0; if (suffix_length > 0 && suffix_length <= string_length) { if (SDL_memcmp(string + string_length - suffix_length, suffix, suffix_length) == 0) { - return SDL_TRUE; + return true; + } + } + return false; +} + +SDL_COMPILE_TIME_ASSERT(sizeof_object_id, sizeof(int) == sizeof(Uint32)); + +Uint32 SDL_GetNextObjectID(void) +{ + static SDL_AtomicInt last_id; + + Uint32 id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; + if (id == 0) { + id = (Uint32)SDL_AtomicIncRef(&last_id) + 1; + } + return id; +} + +static SDL_HashTable *SDL_objects; + +static Uint32 SDL_HashObject(const void *key, void *unused) +{ + return (Uint32)(uintptr_t)key; +} + +static bool SDL_KeyMatchObject(const void *a, const void *b, void *unused) +{ + return (a == b); +} + +void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid) +{ + SDL_assert(object != NULL); + + if (valid) { + if (!SDL_objects) { + SDL_objects = SDL_CreateHashTable(NULL, 32, SDL_HashObject, SDL_KeyMatchObject, NULL, false); + } + + SDL_InsertIntoHashTable(SDL_objects, object, (void *)(uintptr_t)type); + } else { + if (SDL_objects) { + SDL_RemoveFromHashTable(SDL_objects, object); } } - return SDL_FALSE; +} + +bool SDL_ObjectValid(void *object, SDL_ObjectType type) +{ + if (!object) { + return false; + } + + const void *object_type; + if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) { + return false; + } + + return (((SDL_ObjectType)(uintptr_t)object_type) == type); +} + +void SDL_SetObjectsInvalid(void) +{ + if (SDL_objects) { + // Log any leaked objects + const void *object, *object_type; + void *iter = NULL; + while (SDL_IterateHashTable(SDL_objects, &object, &object_type, &iter)) { + const char *type; + switch ((SDL_ObjectType)(uintptr_t)object_type) { + case SDL_OBJECT_TYPE_WINDOW: + type = "SDL_Window"; + break; + case SDL_OBJECT_TYPE_RENDERER: + type = "SDL_Renderer"; + break; + case SDL_OBJECT_TYPE_TEXTURE: + type = "SDL_Texture"; + break; + case SDL_OBJECT_TYPE_JOYSTICK: + type = "SDL_Joystick"; + break; + case SDL_OBJECT_TYPE_GAMEPAD: + type = "SDL_Gamepad"; + break; + case SDL_OBJECT_TYPE_HAPTIC: + type = "SDL_Haptic"; + break; + case SDL_OBJECT_TYPE_SENSOR: + type = "SDL_Sensor"; + break; + case SDL_OBJECT_TYPE_HIDAPI_DEVICE: + type = "hidapi device"; + break; + case SDL_OBJECT_TYPE_HIDAPI_JOYSTICK: + type = "hidapi joystick"; + break; + default: + type = "unknown object"; + break; + } + SDL_Log("Leaked %s (%p)\n", type, object); + } + SDL_assert(SDL_HashTableEmpty(SDL_objects)); + + SDL_DestroyHashTable(SDL_objects); + SDL_objects = NULL; + } +} + +static int SDL_URIDecode(const char *src, char *dst, int len) +{ + int ri, wi, di; + char decode = '\0'; + if (!src || !dst || len < 0) { + return -1; + } + if (len == 0) { + len = (int)SDL_strlen(src); + } + for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) { + if (di == 0) { + // start decoding + if (src[ri] == '%') { + decode = '\0'; + di += 1; + continue; + } + // normal write + dst[wi] = src[ri]; + wi += 1; + } else if (di == 1 || di == 2) { + char off = '\0'; + char isa = src[ri] >= 'a' && src[ri] <= 'f'; + char isA = src[ri] >= 'A' && src[ri] <= 'F'; + char isn = src[ri] >= '0' && src[ri] <= '9'; + if (!(isa || isA || isn)) { + // not a hexadecimal + int sri; + for (sri = ri - di; sri <= ri; sri += 1) { + dst[wi] = src[sri]; + wi += 1; + } + di = 0; + continue; + } + // itsy bitsy magicsy + if (isn) { + off = 0 - '0'; + } else if (isa) { + off = 10 - 'a'; + } else if (isA) { + off = 10 - 'A'; + } + decode |= (src[ri] + off) << (2 - di) * 4; + if (di == 2) { + dst[wi] = decode; + wi += 1; + di = 0; + } else { + di += 1; + } + } + } + dst[wi] = '\0'; + return wi; +} + +int SDL_URIToLocal(const char *src, char *dst) +{ + if (SDL_memcmp(src, "file:/", 6) == 0) { + src += 6; // local file? + } else if (SDL_strstr(src, ":/") != NULL) { + return -1; // wrong scheme + } + + bool local = src[0] != '/' || (src[0] != '\0' && src[1] == '/'); + + // Check the hostname, if present. RFC 3986 states that the hostname component of a URI is not case-sensitive. + if (!local && src[0] == '/' && src[2] != '/') { + char *hostname_end = SDL_strchr(src + 1, '/'); + if (hostname_end) { + const size_t src_len = hostname_end - (src + 1); + size_t hostname_len; + +#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE) + char hostname[257]; + if (gethostname(hostname, 255) == 0) { + hostname[256] = '\0'; + hostname_len = SDL_strlen(hostname); + if (hostname_len == src_len && SDL_strncasecmp(src + 1, hostname, src_len) == 0) { + src = hostname_end + 1; + local = true; + } + } +#endif + + if (!local) { + static const char *localhost = "localhost"; + hostname_len = SDL_strlen(localhost); + if (hostname_len == src_len && SDL_strncasecmp(src + 1, localhost, src_len) == 0) { + src = hostname_end + 1; + local = true; + } + } + } + } + + if (local) { + // Convert URI escape sequences to real characters + if (src[0] == '/') { + src++; + } else { + src--; + } + return SDL_URIDecode(src, dst, 0); + } + return -1; +} + +// This is a set of per-thread persistent strings that we can return from the SDL API. +// This is used for short strings that might persist past the lifetime of the object +// they are related to. + +static SDL_TLSID SDL_string_storage; + +static void SDL_FreePersistentStrings( void *value ) +{ + SDL_HashTable *strings = (SDL_HashTable *)value; + SDL_DestroyHashTable(strings); +} + +const char *SDL_GetPersistentString(const char *string) +{ + if (!string) { + return NULL; + } + if (!*string) { + return ""; + } + + SDL_HashTable *strings = (SDL_HashTable *)SDL_GetTLS(&SDL_string_storage); + if (!strings) { + strings = SDL_CreateHashTable(NULL, 32, SDL_HashString, SDL_KeyMatchString, SDL_NukeFreeValue, false); + if (!strings) { + return NULL; + } + + SDL_SetTLS(&SDL_string_storage, strings, SDL_FreePersistentStrings); + } + + const char *result; + if (!SDL_FindInHashTable(strings, string, (const void **)&result)) { + char *new_string = SDL_strdup(string); + if (!new_string) { + return NULL; + } + + // If the hash table insert fails, at least we can return the string we allocated + SDL_InsertIntoHashTable(strings, new_string, new_string); + result = new_string; + } + return result; } diff --git a/libs/SDL3/src/SDL_utils_c.h b/libs/SDL3/src/SDL_utils_c.h index 98658c361..adb150a92 100644 --- a/libs/SDL3/src/SDL_utils_c.h +++ b/libs/SDL3/src/SDL_utils_c.h @@ -18,16 +18,56 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_internal.h" +// This is included in SDL_internal.h +//#include "SDL_internal.h" #ifndef SDL_utils_h_ #define SDL_utils_h_ -/* Common utility functions that aren't in the public API */ +// Common utility functions that aren't in the public API -/* Return the smallest power of 2 greater than or equal to 'x' */ +// Return the smallest power of 2 greater than or equal to 'x' extern int SDL_powerof2(int x); -SDL_bool SDL_endswith(const char *string, const char *suffix); +extern Uint32 SDL_CalculateGCD(Uint32 a, Uint32 b); +extern void SDL_CalculateFraction(float x, int *numerator, int *denominator); -#endif /* SDL_utils_h_ */ +extern bool SDL_startswith(const char *string, const char *prefix); +extern bool SDL_endswith(const char *string, const char *suffix); + +/** Convert URI to a local filename, stripping the "file://" + * preamble and hostname if present, and writes the result + * to the dst buffer. Since URI-encoded characters take + * three times the space of normal characters, src and dst + * can safely point to the same buffer for in situ conversion. + * + * Returns the number of decoded bytes that wound up in + * the destination buffer, excluding the terminating NULL byte. + * + * On error, -1 is returned. + */ +extern int SDL_URIToLocal(const char *src, char *dst); + +typedef enum +{ + SDL_OBJECT_TYPE_UNKNOWN, + SDL_OBJECT_TYPE_WINDOW, + SDL_OBJECT_TYPE_RENDERER, + SDL_OBJECT_TYPE_TEXTURE, + SDL_OBJECT_TYPE_JOYSTICK, + SDL_OBJECT_TYPE_GAMEPAD, + SDL_OBJECT_TYPE_HAPTIC, + SDL_OBJECT_TYPE_SENSOR, + SDL_OBJECT_TYPE_HIDAPI_DEVICE, + SDL_OBJECT_TYPE_HIDAPI_JOYSTICK, + +} SDL_ObjectType; + +extern Uint32 SDL_GetNextObjectID(void); +extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid); +extern bool SDL_ObjectValid(void *object, SDL_ObjectType type); +extern void SDL_SetObjectsInvalid(void); + +extern const char *SDL_GetPersistentString(const char *string); + +#endif // SDL_utils_h_ diff --git a/libs/SDL3/src/atomic/SDL_atomic.c b/libs/SDL3/src/atomic/SDL_atomic.c index e350c15b1..70ee1607d 100644 --- a/libs/SDL3/src/atomic/SDL_atomic.c +++ b/libs/SDL3/src/atomic/SDL_atomic.c @@ -25,7 +25,7 @@ #define HAVE_MSC_ATOMICS 1 #endif -#ifdef SDL_PLATFORM_MACOS /* !!! FIXME: should we favor gcc atomics? */ +#ifdef SDL_PLATFORM_MACOS // !!! FIXME: should we favor gcc atomics? #include #endif @@ -33,7 +33,7 @@ #include #endif -/* The __atomic_load_n() intrinsic showed up in different times for different compilers. */ +// The __atomic_load_n() intrinsic showed up in different times for different compilers. #ifdef __clang__ #if __has_builtin(__atomic_load_n) || defined(HAVE_GCC_ATOMICS) /* !!! FIXME: this advertises as available in the NDK but uses an external symbol we don't have. @@ -48,7 +48,7 @@ #endif #endif -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off #if defined(__WATCOMC__) && defined(__386__) SDL_COMPILE_TIME_ASSERT(intsize, 4==sizeof(int)); #define HAVE_WATCOM_ATOMICS @@ -74,8 +74,8 @@ extern __inline int _SDL_xadd_watcom(volatile int *a, int v); value [eax] \ modify exact [eax]; -#endif /* __WATCOMC__ && __386__ */ -/* *INDENT-ON* */ /* clang-format on */ +#endif // __WATCOMC__ && __386__ +/* *INDENT-ON* */ // clang-format on /* If any of the operations are not provided then we must emulate some @@ -122,36 +122,68 @@ static SDL_INLINE void leaveLock(void *a) } #endif -SDL_bool SDL_AtomicCompareAndSwap(SDL_AtomicInt *a, int oldval, int newval) +bool SDL_CompareAndSwapAtomicInt(SDL_AtomicInt *a, int oldval, int newval) { #ifdef HAVE_MSC_ATOMICS SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(long) == sizeof(a->value)); return _InterlockedCompareExchange((long *)&a->value, (long)newval, (long)oldval) == (long)oldval; #elif defined(HAVE_WATCOM_ATOMICS) - return _SDL_cmpxchg_watcom(&a->value, newval, oldval); + return _SDL_cmpxchg_watcom((volatile int *)&a->value, newval, oldval); #elif defined(HAVE_GCC_ATOMICS) return __sync_bool_compare_and_swap(&a->value, oldval, newval); -#elif defined(SDL_PLATFORM_MACOS) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ +#elif defined(SDL_PLATFORM_MACOS) // this is deprecated in 10.12 sdk; favor gcc atomics. return OSAtomicCompareAndSwap32Barrier(oldval, newval, &a->value); #elif defined(SDL_PLATFORM_SOLARIS) + SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(uint_t) == sizeof(a->value)); return ((int)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval); #elif defined(EMULATE_CAS) - SDL_bool retval = SDL_FALSE; + bool result = false; enterLock(a); if (a->value == oldval) { a->value = newval; - retval = SDL_TRUE; + result = true; } leaveLock(a); - return retval; + return result; #else #error Please define your platform. #endif } -SDL_bool SDL_AtomicCompareAndSwapPointer(void **a, void *oldval, void *newval) +bool SDL_CompareAndSwapAtomicU32(SDL_AtomicU32 *a, Uint32 oldval, Uint32 newval) +{ +#ifdef HAVE_MSC_ATOMICS + SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(long) == sizeof(a->value)); + return _InterlockedCompareExchange((long *)&a->value, (long)newval, (long)oldval) == (long)oldval; +#elif defined(HAVE_WATCOM_ATOMICS) + SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(int) == sizeof(a->value)); + return _SDL_cmpxchg_watcom((volatile int *)&a->value, (int)newval, (int)oldval); +#elif defined(HAVE_GCC_ATOMICS) + return __sync_bool_compare_and_swap(&a->value, oldval, newval); +#elif defined(SDL_PLATFORM_MACOS) // this is deprecated in 10.12 sdk; favor gcc atomics. + return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t*)&a->value); +#elif defined(SDL_PLATFORM_SOLARIS) + SDL_COMPILE_TIME_ASSERT(atomic_cas, sizeof(uint_t) == sizeof(a->value)); + return ((Uint32)atomic_cas_uint((volatile uint_t *)&a->value, (uint_t)oldval, (uint_t)newval) == oldval); +#elif defined(EMULATE_CAS) + bool result = false; + + enterLock(a); + if (a->value == oldval) { + a->value = newval; + result = true; + } + leaveLock(a); + + return result; +#else +#error Please define your platform. +#endif +} + +bool SDL_CompareAndSwapAtomicPointer(void **a, void *oldval, void *newval) { #ifdef HAVE_MSC_ATOMICS return _InterlockedCompareExchangePointer(a, newval, oldval) == oldval; @@ -159,29 +191,29 @@ SDL_bool SDL_AtomicCompareAndSwapPointer(void **a, void *oldval, void *newval) return _SDL_cmpxchg_watcom((int *)a, (long)newval, (long)oldval); #elif defined(HAVE_GCC_ATOMICS) return __sync_bool_compare_and_swap(a, oldval, newval); -#elif defined(SDL_PLATFORM_MACOS) && defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ +#elif defined(SDL_PLATFORM_MACOS) && defined(__LP64__) // this is deprecated in 10.12 sdk; favor gcc atomics. return OSAtomicCompareAndSwap64Barrier((int64_t)oldval, (int64_t)newval, (int64_t *)a); -#elif defined(SDL_PLATFORM_MACOS) && !defined(__LP64__) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ +#elif defined(SDL_PLATFORM_MACOS) && !defined(__LP64__) // this is deprecated in 10.12 sdk; favor gcc atomics. return OSAtomicCompareAndSwap32Barrier((int32_t)oldval, (int32_t)newval, (int32_t *)a); #elif defined(SDL_PLATFORM_SOLARIS) return (atomic_cas_ptr(a, oldval, newval) == oldval); #elif defined(EMULATE_CAS) - SDL_bool retval = SDL_FALSE; + bool result = false; enterLock(a); if (*a == oldval) { *a = newval; - retval = SDL_TRUE; + result = true; } leaveLock(a); - return retval; + return result; #else #error Please define your platform. #endif } -int SDL_AtomicSet(SDL_AtomicInt *a, int v) +int SDL_SetAtomicInt(SDL_AtomicInt *a, int v) { #ifdef HAVE_MSC_ATOMICS SDL_COMPILE_TIME_ASSERT(atomic_set, sizeof(long) == sizeof(a->value)); @@ -191,17 +223,39 @@ int SDL_AtomicSet(SDL_AtomicInt *a, int v) #elif defined(HAVE_GCC_ATOMICS) return __sync_lock_test_and_set(&a->value, v); #elif defined(SDL_PLATFORM_SOLARIS) + SDL_COMPILE_TIME_ASSERT(atomic_set, sizeof(uint_t) == sizeof(a->value)); return (int)atomic_swap_uint((volatile uint_t *)&a->value, v); #else int value; do { value = a->value; - } while (!SDL_AtomicCompareAndSwap(a, value, v)); + } while (!SDL_CompareAndSwapAtomicInt(a, value, v)); return value; #endif } -void *SDL_AtomicSetPtr(void **a, void *v) +Uint32 SDL_SetAtomicU32(SDL_AtomicU32 *a, Uint32 v) +{ +#ifdef HAVE_MSC_ATOMICS + SDL_COMPILE_TIME_ASSERT(atomic_set, sizeof(long) == sizeof(a->value)); + return _InterlockedExchange((long *)&a->value, v); +#elif defined(HAVE_WATCOM_ATOMICS) + return _SDL_xchg_watcom(&a->value, v); +#elif defined(HAVE_GCC_ATOMICS) + return __sync_lock_test_and_set(&a->value, v); +#elif defined(SDL_PLATFORM_SOLARIS) + SDL_COMPILE_TIME_ASSERT(atomic_set, sizeof(uint_t) == sizeof(a->value)); + return (Uint32)atomic_swap_uint((volatile uint_t *)&a->value, v); +#else + Uint32 value; + do { + value = a->value; + } while (!SDL_CompareAndSwapAtomicU32(a, value, v)); + return value; +#endif +} + +void *SDL_SetAtomicPointer(void **a, void *v) { #ifdef HAVE_MSC_ATOMICS return _InterlockedExchangePointer(a, v); @@ -215,18 +269,19 @@ void *SDL_AtomicSetPtr(void **a, void *v) void *value; do { value = *a; - } while (!SDL_AtomicCompareAndSwapPointer(a, value, v)); + } while (!SDL_CompareAndSwapAtomicPointer(a, value, v)); return value; #endif } -int SDL_AtomicAdd(SDL_AtomicInt *a, int v) +int SDL_AddAtomicInt(SDL_AtomicInt *a, int v) { #ifdef HAVE_MSC_ATOMICS SDL_COMPILE_TIME_ASSERT(atomic_add, sizeof(long) == sizeof(a->value)); return _InterlockedExchangeAdd((long *)&a->value, v); #elif defined(HAVE_WATCOM_ATOMICS) - return _SDL_xadd_watcom(&a->value, v); + SDL_COMPILE_TIME_ASSERT(atomic_add, sizeof(int) == sizeof(a->value)); + return _SDL_xadd_watcom((volatile int *)&a->value, v); #elif defined(HAVE_GCC_ATOMICS) return __sync_fetch_and_add(&a->value, v); #elif defined(SDL_PLATFORM_SOLARIS) @@ -238,12 +293,12 @@ int SDL_AtomicAdd(SDL_AtomicInt *a, int v) int value; do { value = a->value; - } while (!SDL_AtomicCompareAndSwap(a, value, (value + v))); + } while (!SDL_CompareAndSwapAtomicInt(a, value, (value + v))); return value; #endif } -int SDL_AtomicGet(SDL_AtomicInt *a) +int SDL_GetAtomicInt(SDL_AtomicInt *a) { #ifdef HAVE_ATOMIC_LOAD_N return __atomic_load_n(&a->value, __ATOMIC_SEQ_CST); @@ -254,20 +309,46 @@ int SDL_AtomicGet(SDL_AtomicInt *a) return _SDL_xadd_watcom(&a->value, 0); #elif defined(HAVE_GCC_ATOMICS) return __sync_or_and_fetch(&a->value, 0); -#elif defined(SDL_PLATFORM_MACOS) /* this is deprecated in 10.12 sdk; favor gcc atomics. */ +#elif defined(SDL_PLATFORM_MACOS) // this is deprecated in 10.12 sdk; favor gcc atomics. return sizeof(a->value) == sizeof(uint32_t) ? OSAtomicOr32Barrier(0, (volatile uint32_t *)&a->value) : OSAtomicAdd64Barrier(0, (volatile int64_t *)&a->value); #elif defined(SDL_PLATFORM_SOLARIS) - return atomic_or_uint((volatile uint_t *)&a->value, 0); + return atomic_or_uint_nv((volatile uint_t *)&a->value, 0); #else int value; do { value = a->value; - } while (!SDL_AtomicCompareAndSwap(a, value, value)); + } while (!SDL_CompareAndSwapAtomicInt(a, value, value)); + return value; +#endif +} + +Uint32 SDL_GetAtomicU32(SDL_AtomicU32 *a) +{ +#ifdef HAVE_ATOMIC_LOAD_N + return __atomic_load_n(&a->value, __ATOMIC_SEQ_CST); +#elif defined(HAVE_MSC_ATOMICS) + SDL_COMPILE_TIME_ASSERT(atomic_get, sizeof(long) == sizeof(a->value)); + return (Uint32)_InterlockedOr((long *)&a->value, 0); +#elif defined(HAVE_WATCOM_ATOMICS) + SDL_COMPILE_TIME_ASSERT(atomic_get, sizeof(int) == sizeof(a->value)); + return (Uint32)_SDL_xadd_watcom((volatile int *)&a->value, 0); +#elif defined(HAVE_GCC_ATOMICS) + return __sync_or_and_fetch(&a->value, 0); +#elif defined(SDL_PLATFORM_MACOS) // this is deprecated in 10.12 sdk; favor gcc atomics. + return OSAtomicOr32Barrier(0, (volatile uint32_t *)&a->value); +#elif defined(SDL_PLATFORM_SOLARIS) + SDL_COMPILE_TIME_ASSERT(atomic_get, sizeof(uint_t) == sizeof(a->value)); + return (Uint32)atomic_or_uint_nv((volatile uint_t *)&a->value, 0); +#else + Uint32 value; + do { + value = a->value; + } while (!SDL_CompareAndSwapAtomicU32(a, value, value)); return value; #endif } -void *SDL_AtomicGetPtr(void **a) +void *SDL_GetAtomicPointer(void **a) { #ifdef HAVE_ATOMIC_LOAD_N return __atomic_load_n(a, __ATOMIC_SEQ_CST); @@ -281,7 +362,7 @@ void *SDL_AtomicGetPtr(void **a) void *value; do { value = *a; - } while (!SDL_AtomicCompareAndSwapPointer(a, value, value)); + } while (!SDL_CompareAndSwapAtomicPointer(a, value, value)); return value; #endif } diff --git a/libs/SDL3/src/atomic/SDL_spinlock.c b/libs/SDL3/src/atomic/SDL_spinlock.c index 0896b41cc..b1f476985 100644 --- a/libs/SDL3/src/atomic/SDL_spinlock.c +++ b/libs/SDL3/src/atomic/SDL_spinlock.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "../core/windows/SDL_windows.h" #endif @@ -44,7 +44,7 @@ #include #endif -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off #if defined(__WATCOMC__) && defined(__386__) SDL_COMPILE_TIME_ASSERT(locksize, 4==sizeof(SDL_SpinLock)); extern __inline int _SDL_xchg_watcom(volatile int *a, int v); @@ -53,11 +53,11 @@ extern __inline int _SDL_xchg_watcom(volatile int *a, int v); parm [ecx] [eax] \ value [eax] \ modify exact [eax]; -#endif /* __WATCOMC__ && __386__ */ -/* *INDENT-ON* */ /* clang-format on */ +#endif // __WATCOMC__ && __386__ +/* *INDENT-ON* */ // clang-format on -/* This function is where all the magic happens... */ -SDL_bool SDL_TryLockSpinlock(SDL_SpinLock *lock) +// This function is where all the magic happens... +bool SDL_TryLockSpinlock(SDL_SpinLock *lock) { #if defined(HAVE_GCC_ATOMICS) || defined(HAVE_GCC_SYNC_LOCK_TEST_AND_SET) return __sync_lock_test_and_set(lock, 1) == 0; @@ -116,47 +116,47 @@ SDL_bool SDL_TryLockSpinlock(SDL_SpinLock *lock) return result == 0; #elif defined(SDL_PLATFORM_MACOS) || defined(SDL_PLATFORM_IOS) || defined(SDL_PLATFORM_TVOS) - /* Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. */ + // Maybe used for PowerPC, but the Intel asm or gcc atomics are favored. return OSAtomicCompareAndSwap32Barrier(0, 1, lock); #elif defined(SDL_PLATFORM_SOLARIS) && defined(_LP64) - /* Used for Solaris with non-gcc compilers. */ + // Used for Solaris with non-gcc compilers. return ((int)atomic_cas_64((volatile uint64_t *)lock, 0, 1) == 0); #elif defined(SDL_PLATFORM_SOLARIS) && !defined(_LP64) - /* Used for Solaris with non-gcc compilers. */ + // Used for Solaris with non-gcc compilers. return ((int)atomic_cas_32((volatile uint32_t *)lock, 0, 1) == 0); #elif defined(PS2) uint32_t oldintr; - SDL_bool res = SDL_FALSE; - // disable interuption + bool res = false; + // disable interruption oldintr = DIntr(); if (*lock == 0) { *lock = 1; - res = SDL_TRUE; + res = true; } - // enable interuption + // enable interruption if (oldintr) { EIntr(); } return res; #else - /* Terrible terrible damage */ + // Terrible terrible damage static SDL_Mutex *_spinlock_mutex; if (!_spinlock_mutex) { - /* Race condition on first lock... */ + // Race condition on first lock... _spinlock_mutex = SDL_CreateMutex(); } SDL_LockMutex(_spinlock_mutex); if (*lock == 0) { *lock = 1; SDL_UnlockMutex(_spinlock_mutex); - return SDL_TRUE; + return true; } else { SDL_UnlockMutex(_spinlock_mutex); - return SDL_FALSE; + return false; } #endif } @@ -164,13 +164,13 @@ SDL_bool SDL_TryLockSpinlock(SDL_SpinLock *lock) void SDL_LockSpinlock(SDL_SpinLock *lock) { int iterations = 0; - /* FIXME: Should we have an eventual timeout? */ + // FIXME: Should we have an eventual timeout? while (!SDL_TryLockSpinlock(lock)) { if (iterations < 32) { iterations++; SDL_CPUPauseInstruction(); } else { - /* !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. */ + // !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. SDL_Delay(0); } } @@ -193,7 +193,7 @@ void SDL_UnlockSpinlock(SDL_SpinLock *lock) *lock = 0; #elif defined(SDL_PLATFORM_SOLARIS) - /* Used for Solaris when not using gcc. */ + // Used for Solaris when not using gcc. *lock = 0; membar_producer(); diff --git a/libs/SDL3/src/audio/SDL_audio.c b/libs/SDL3/src/audio/SDL_audio.c index 5ca394dbe..b232bef59 100644 --- a/libs/SDL3/src/audio/SDL_audio.c +++ b/libs/SDL3/src/audio/SDL_audio.c @@ -23,11 +23,13 @@ #include "SDL_audio_c.h" #include "SDL_sysaudio.h" #include "../thread/SDL_systhread.h" -#include "../SDL_utils_c.h" // Available audio drivers static const AudioBootStrap *const bootstrap[] = { #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO +#ifdef SDL_AUDIO_DRIVER_PIPEWIRE + &PIPEWIRE_PREFERRED_bootstrap, +#endif &PULSEAUDIO_bootstrap, #endif #ifdef SDL_AUDIO_DRIVER_PIPEWIRE @@ -60,9 +62,6 @@ static const AudioBootStrap *const bootstrap[] = { #ifdef SDL_AUDIO_DRIVER_OPENSLES &OPENSLES_bootstrap, #endif -#ifdef SDL_AUDIO_DRIVER_ANDROID - &ANDROIDAUDIO_bootstrap, -#endif #ifdef SDL_AUDIO_DRIVER_PS2 &PS2AUDIO_bootstrap, #endif @@ -98,15 +97,41 @@ static const AudioBootStrap *const bootstrap[] = { static SDL_AudioDriver current_audio; +// Deduplicated list of audio bootstrap drivers. +static const AudioBootStrap *deduped_bootstrap[SDL_arraysize(bootstrap) - 1]; + int SDL_GetNumAudioDrivers(void) { - return SDL_arraysize(bootstrap) - 1; + static int num_drivers = -1; + + if (num_drivers >= 0) { + return num_drivers; + } + + num_drivers = 0; + + // Build a list of unique audio drivers. + for (int i = 0; bootstrap[i] != NULL; ++i) { + bool duplicate = false; + for (int j = 0; j < i; ++j) { + if (SDL_strcmp(bootstrap[i]->name, bootstrap[j]->name) == 0) { + duplicate = true; + break; + } + } + + if (!duplicate) { + deduped_bootstrap[num_drivers++] = bootstrap[i]; + } + } + + return num_drivers; } const char *SDL_GetAudioDriver(int index) { if (index >= 0 && index < SDL_GetNumAudioDrivers()) { - return bootstrap[index]->name; + return deduped_bootstrap[index]->name; } return NULL; } @@ -137,6 +162,16 @@ static int GetDefaultSampleFramesFromFreq(const int freq) } } +int *SDL_ChannelMapDup(const int *origchmap, int channels) +{ + const size_t chmaplen = sizeof (*origchmap) * channels; + int *chmap = (int *)SDL_malloc(chmaplen); + if (chmap) { + SDL_memcpy(chmap, origchmap, chmaplen); + } + return chmap; +} + void OnAudioStreamCreated(SDL_AudioStream *stream) { SDL_assert(stream != NULL); @@ -181,7 +216,7 @@ void OnAudioStreamDestroy(SDL_AudioStream *stream) } // device should be locked when calling this. -static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) +static bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) { SDL_assert(device != NULL); return ( @@ -196,8 +231,16 @@ static SDL_bool AudioDeviceCanUseSimpleCopy(SDL_AudioDevice *device) // should hold device->lock before calling. static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) { - if (!device->iscapture) { // for capture devices, we only want to move to float32 for postmix, which we'll handle elsewhere. - const SDL_bool simple_copy = AudioDeviceCanUseSimpleCopy(device); + if (device->recording) { // for recording devices, we only want to move to float32 for postmix and gain, which we'll handle elsewhere. + // we _do_ need to make sure the channel map is correct, though... + for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { + // set the proper end of the stream to the device's channel map. This will obtain stream->lock itself. + SetAudioStreamChannelMap(stream, &stream->src_spec, &stream->src_chmap, device->chmap, device->spec.channels, -1); + } + } + } else { + const bool simple_copy = AudioDeviceCanUseSimpleCopy(device); SDL_AudioSpec spec; device->simple_copy = simple_copy; @@ -213,29 +256,40 @@ static void UpdateAudioStreamFormatsPhysical(SDL_AudioDevice *device) // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. SDL_LockMutex(stream->lock); SDL_copyp(&stream->dst_spec, &spec); + SetAudioStreamChannelMap(stream, &stream->dst_spec, &stream->dst_chmap, device->chmap, spec.channels, -1); // this should be fast for normal cases, though! SDL_UnlockMutex(stream->lock); } } } } +bool SDL_AudioSpecsEqual(const SDL_AudioSpec *a, const SDL_AudioSpec *b, const int *channel_map_a, const int *channel_map_b) +{ + if ((a->format != b->format) || (a->channels != b->channels) || (a->freq != b->freq) || ((channel_map_a != NULL) != (channel_map_b != NULL))) { + return false; + } else if (channel_map_a && (SDL_memcmp(channel_map_a, channel_map_b, sizeof (*channel_map_a) * a->channels) != 0)) { + return false; + } + return true; +} + // Zombie device implementation... // These get used when a device is disconnected or fails, so audiostreams don't overflow with data that isn't being // consumed and apps relying on audio callbacks don't stop making progress. -static int ZombieWaitDevice(SDL_AudioDevice *device) +static bool ZombieWaitDevice(SDL_AudioDevice *device) { - if (!SDL_AtomicGet(&device->shutdown)) { + if (!SDL_GetAtomicInt(&device->shutdown)) { const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); SDL_Delay((frames * 1000) / device->spec.freq); } - return 0; + return true; } -static int ZombiePlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool ZombiePlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { - return 0; // no-op, just throw the audio away. + return true; // no-op, just throw the audio away. } static Uint8 *ZombieGetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -243,14 +297,14 @@ static Uint8 *ZombieGetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->work_buffer; } -static int ZombieCaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int ZombieRecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { // return a full buffer of silence every time. SDL_memset(buffer, device->silence_value, buflen); return buflen; } -static void ZombieFlushCapture(SDL_AudioDevice *device) +static void ZombieFlushRecording(SDL_AudioDevice *device) { // no-op, this is all imaginary. } @@ -273,19 +327,19 @@ static void ZombieFlushCapture(SDL_AudioDevice *device) static void ClosePhysicalAudioDevice(SDL_AudioDevice *device); -SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_CAPTURE < SDL_AUDIO_DEVICE_DEFAULT_OUTPUT); +SDL_COMPILE_TIME_ASSERT(check_lowest_audio_default_value, SDL_AUDIO_DEVICE_DEFAULT_RECORDING < SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK); static SDL_AtomicInt last_device_instance_id; // increments on each device add to provide unique instance IDs -static SDL_AudioDeviceID AssignAudioDeviceInstanceId(SDL_bool iscapture, SDL_bool islogical) +static SDL_AudioDeviceID AssignAudioDeviceInstanceId(bool recording, bool islogical) { /* Assign an instance id! Start at 2, in case there are things from the SDL2 era that still think 1 is a special value. - Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_OUTPUT, etc. */ + Also, make sure we don't assign SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, etc. */ - // The bottom two bits of the instance id tells you if it's an output device (1<<0), and if it's a physical device (1<<1). - const SDL_AudioDeviceID flags = (iscapture ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); + // The bottom two bits of the instance id tells you if it's an playback device (1<<0), and if it's a physical device (1<<1). + const SDL_AudioDeviceID flags = (recording ? 0 : (1<<0)) | (islogical ? 0 : (1<<1)); const SDL_AudioDeviceID instance_id = (((SDL_AudioDeviceID) (SDL_AtomicIncRef(&last_device_instance_id) + 1)) << 2) | flags; - SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) ); + SDL_assert( (instance_id >= 2) && (instance_id < SDL_AUDIO_DEVICE_DEFAULT_RECORDING) ); return instance_id; } @@ -320,7 +374,7 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, SDL_LogicalAudioDevice *logdev = NULL; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = !(devid & (1<<1)); + const bool islogical = !(devid & (1<<1)); if (islogical) { // don't bother looking if it's not a logical device id value. SDL_LockRWLockForReading(current_audio.device_hash_lock); SDL_FindInHashTable(current_audio.device_hash, (const void *) (uintptr_t) devid, (const void **) &logdev); @@ -334,9 +388,9 @@ static SDL_LogicalAudioDevice *ObtainLogicalAudioDevice(SDL_AudioDeviceID devid, if (logdev) { // we have to release the device_hash_lock before we take the device lock, to avoid deadlocks, so do a loop // to make sure the correct physical device gets locked, in case we're in a race with the default changing. - while (SDL_TRUE) { + while (true) { SDL_LockMutex(device->lock); - SDL_AudioDevice *recheck_device = (SDL_AudioDevice *) SDL_AtomicGetPtr((void **) &logdev->physical_device); + SDL_AudioDevice *recheck_device = (SDL_AudioDevice *) SDL_GetAtomicPointer((void **) &logdev->physical_device); if (device == recheck_device) { break; } @@ -366,7 +420,7 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // ! SDL_AudioDevice *device = NULL; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool islogical = !(devid & (1<<1)); + const bool islogical = !(devid & (1<<1)); if (islogical) { ObtainLogicalAudioDevice(devid, &device); } else if (!SDL_GetCurrentAudioDriver()) { // (the `islogical` path, above, checks this in ObtainLogicalAudioDevice.) @@ -388,19 +442,19 @@ static SDL_AudioDevice *ObtainPhysicalAudioDevice(SDL_AudioDeviceID devid) // ! static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceID devid) // !!! FIXME: SDL_ACQUIRE { - const SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); + const bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) || (devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING)); if (!wants_default) { return ObtainPhysicalAudioDevice(devid); } const SDL_AudioDeviceID orig_devid = devid; - while (SDL_TRUE) { + while (true) { SDL_LockRWLockForReading(current_audio.device_hash_lock); - if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) { - devid = current_audio.default_output_device_id; - } else if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) { - devid = current_audio.default_capture_device_id; + if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) { + devid = current_audio.default_playback_device_id; + } else if (orig_devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) { + devid = current_audio.default_recording_device_id; } SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -415,12 +469,12 @@ static SDL_AudioDevice *ObtainPhysicalAudioDeviceDefaultAllowed(SDL_AudioDeviceI } // make sure the default didn't change while we were waiting for the lock... - SDL_bool got_it = SDL_FALSE; + bool got_it = false; SDL_LockRWLockForReading(current_audio.device_hash_lock); - if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) && (devid == current_audio.default_output_device_id)) { - got_it = SDL_TRUE; - } else if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE) && (devid == current_audio.default_capture_device_id)) { - got_it = SDL_TRUE; + if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) && (devid == current_audio.default_playback_device_id)) { + got_it = true; + } else if ((orig_devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING) && (devid == current_audio.default_recording_device_id)) { + got_it = true; } SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -493,6 +547,7 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device) SDL_DestroyMutex(device->lock); SDL_DestroyCondition(device->close_cond); SDL_free(device->work_buffer); + SDL_free(device->chmap); SDL_free(device->name); SDL_free(device); } @@ -504,7 +559,7 @@ void UnrefPhysicalAudioDevice(SDL_AudioDevice *device) // take it out of the device list. SDL_LockRWLockForWriting(current_audio.device_hash_lock); if (SDL_RemoveFromHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id)) { - SDL_AtomicAdd(device->iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count, -1); + SDL_AddAtomicInt(device->recording ? ¤t_audio.recording_device_count : ¤t_audio.playback_device_count, -1); } SDL_UnlockRWLock(current_audio.device_hash_lock); DestroyPhysicalAudioDevice(device); // ...and nuke it. @@ -516,12 +571,12 @@ void RefPhysicalAudioDevice(SDL_AudioDevice *device) SDL_AtomicIncRef(&device->refcount); } -static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool iscapture, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) +static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, bool recording, const SDL_AudioSpec *spec, void *handle, SDL_AtomicInt *device_count) { SDL_assert(name != NULL); SDL_LockRWLockForReading(current_audio.device_hash_lock); - const int shutting_down = SDL_AtomicGet(¤t_audio.shutting_down); + const int shutting_down = SDL_GetAtomicInt(¤t_audio.shutting_down); SDL_UnlockRWLock(current_audio.device_hash_lock); if (shutting_down) { return NULL; // we're shutting down, don't add any devices that are hotplugged at the last possible moment. @@ -553,20 +608,20 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc return NULL; } - SDL_AtomicSet(&device->shutdown, 0); - SDL_AtomicSet(&device->zombie, 0); - device->iscapture = iscapture; + SDL_SetAtomicInt(&device->shutdown, 0); + SDL_SetAtomicInt(&device->zombie, 0); + device->recording = recording; SDL_copyp(&device->spec, spec); SDL_copyp(&device->default_spec, spec); device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq); device->silence_value = SDL_GetSilenceValueForFormat(device->spec.format); device->handle = handle; - device->instance_id = AssignAudioDeviceInstanceId(iscapture, /*islogical=*/SDL_FALSE); + device->instance_id = AssignAudioDeviceInstanceId(recording, /*islogical=*/false); SDL_LockRWLockForWriting(current_audio.device_hash_lock); if (SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) device->instance_id, device)) { - SDL_AtomicAdd(device_count, 1); + SDL_AddAtomicInt(device_count, 1); } else { SDL_DestroyCondition(device->close_cond); SDL_DestroyMutex(device->lock); @@ -580,28 +635,29 @@ static SDL_AudioDevice *CreatePhysicalAudioDevice(const char *name, SDL_bool isc return device; } -static SDL_AudioDevice *CreateAudioCaptureDevice(const char *name, const SDL_AudioSpec *spec, void *handle) +static SDL_AudioDevice *CreateAudioRecordingDevice(const char *name, const SDL_AudioSpec *spec, void *handle) { - SDL_assert(current_audio.impl.HasCaptureSupport); - return CreatePhysicalAudioDevice(name, SDL_TRUE, spec, handle, ¤t_audio.capture_device_count); + SDL_assert(current_audio.impl.HasRecordingSupport); + return CreatePhysicalAudioDevice(name, true, spec, handle, ¤t_audio.recording_device_count); } -static SDL_AudioDevice *CreateAudioOutputDevice(const char *name, const SDL_AudioSpec *spec, void *handle) +static SDL_AudioDevice *CreateAudioPlaybackDevice(const char *name, const SDL_AudioSpec *spec, void *handle) { - return CreatePhysicalAudioDevice(name, SDL_FALSE, spec, handle, ¤t_audio.output_device_count); + return CreatePhysicalAudioDevice(name, false, spec, handle, ¤t_audio.playback_device_count); } // The audio backends call this when a new device is plugged in. -SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *inspec, void *handle) +SDL_AudioDevice *SDL_AddAudioDevice(bool recording, const char *name, const SDL_AudioSpec *inspec, void *handle) { - // device handles MUST be unique! If the target reuses the same handle for hardware with both input and output interfaces, wrap it in a pointer you SDL_malloc'd! + // device handles MUST be unique! If the target reuses the same handle for hardware with both recording and playback interfaces, wrap it in a pointer you SDL_malloc'd! SDL_assert(SDL_FindPhysicalAudioDeviceByHandle(handle) == NULL); - const SDL_AudioFormat default_format = iscapture ? DEFAULT_AUDIO_CAPTURE_FORMAT : DEFAULT_AUDIO_OUTPUT_FORMAT; - const int default_channels = iscapture ? DEFAULT_AUDIO_CAPTURE_CHANNELS : DEFAULT_AUDIO_OUTPUT_CHANNELS; - const int default_freq = iscapture ? DEFAULT_AUDIO_CAPTURE_FREQUENCY : DEFAULT_AUDIO_OUTPUT_FREQUENCY; + const SDL_AudioFormat default_format = recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT; + const int default_channels = recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS; + const int default_freq = recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY; SDL_AudioSpec spec; + SDL_zero(spec); if (!inspec) { spec.format = default_format; spec.channels = default_channels; @@ -612,7 +668,7 @@ SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, spec.freq = (inspec->freq != 0) ? inspec->freq : default_freq; } - SDL_AudioDevice *device = iscapture ? CreateAudioCaptureDevice(name, &spec, handle) : CreateAudioOutputDevice(name, &spec, handle); + SDL_AudioDevice *device = recording ? CreateAudioRecordingDevice(name, &spec, handle) : CreateAudioPlaybackDevice(name, &spec, handle); // Add a device add event to the pending list, to be pushed when the event queue is pumped (away from any of our internal threads). if (device) { @@ -652,10 +708,10 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) SDL_LockRWLockForReading(current_audio.device_hash_lock); const SDL_AudioDeviceID devid = device->instance_id; - const SDL_bool is_default_device = ((devid == current_audio.default_output_device_id) || (devid == current_audio.default_capture_device_id)); + const bool is_default_device = ((devid == current_audio.default_playback_device_id) || (devid == current_audio.default_recording_device_id)); SDL_UnlockRWLock(current_audio.device_hash_lock); - const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&device->zombie, 0, 1); + const bool first_disconnect = SDL_CompareAndSwapAtomicInt(&device->zombie, 0, 1); if (first_disconnect) { // if already disconnected this device, don't do it twice. // Swap in "Zombie" versions of the usual platform interfaces, so the device will keep // making progress until the app closes it. Otherwise, streams might continue to @@ -664,9 +720,9 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) device->WaitDevice = ZombieWaitDevice; device->GetDeviceBuf = ZombieGetDeviceBuf; device->PlayDevice = ZombiePlayDevice; - device->WaitCaptureDevice = ZombieWaitDevice; - device->CaptureFromDevice = ZombieCaptureFromDevice; - device->FlushCapture = ZombieFlushCapture; + device->WaitRecordingDevice = ZombieWaitDevice; + device->RecordDevice = ZombieRecordDevice; + device->FlushRecording = ZombieFlushRecording; // on default devices, dump any logical devices that explicitly opened this device. Things that opened the system default can stay. // on non-default devices, dump everything. @@ -714,10 +770,10 @@ void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device) // stubs for audio drivers that don't need a specific entry point... static void SDL_AudioThreadDeinit_Default(SDL_AudioDevice *device) { /* no-op. */ } -static int SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } -static int SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return 0; /* no-op. */ } -static int SDL_AudioWaitCaptureDevice_Default(SDL_AudioDevice *device) { return 0; /* no-op. */ } -static void SDL_AudioFlushCapture_Default(SDL_AudioDevice *device) { /* no-op. */ } +static bool SDL_AudioWaitDevice_Default(SDL_AudioDevice *device) { return true; /* no-op. */ } +static bool SDL_AudioPlayDevice_Default(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { return true; /* no-op. */ } +static bool SDL_AudioWaitRecordingDevice_Default(SDL_AudioDevice *device) { return true; /* no-op. */ } +static void SDL_AudioFlushRecording_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioCloseDevice_Default(SDL_AudioDevice *device) { /* no-op. */ } static void SDL_AudioDeinitializeStart_Default(void) { /* no-op. */ } static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ } @@ -725,18 +781,18 @@ static void SDL_AudioFreeDeviceHandle_Default(SDL_AudioDevice *device) { /* no-o static void SDL_AudioThreadInit_Default(SDL_AudioDevice *device) { - SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); + SDL_SetCurrentThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); } -static void SDL_AudioDetectDevices_Default(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void SDL_AudioDetectDevices_Default(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { // you have to write your own implementation if these assertions fail. - SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice); - SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport); + SDL_assert(current_audio.impl.OnlyHasDefaultPlaybackDevice); + SDL_assert(current_audio.impl.OnlyHasDefaultRecordingDevice || !current_audio.impl.HasRecordingSupport); - *default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)((size_t)0x1)); - if (current_audio.impl.HasCaptureSupport) { - *default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)((size_t)0x2)); + *default_playback = SDL_AddAudioDevice(false, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)((size_t)0x1)); + if (current_audio.impl.HasRecordingSupport) { + *default_recording = SDL_AddAudioDevice(true, DEFAULT_RECORDING_DEVNAME, NULL, (void *)((size_t)0x2)); } } @@ -746,12 +802,13 @@ static Uint8 *SDL_AudioGetDeviceBuf_Default(SDL_AudioDevice *device, int *buffer return NULL; } -static int SDL_AudioCaptureFromDevice_Default(SDL_AudioDevice *device, void *buffer, int buflen) +static int SDL_AudioRecordDevice_Default(SDL_AudioDevice *device, void *buffer, int buflen) { - return SDL_Unsupported(); + SDL_Unsupported(); + return -1; } -static int SDL_AudioOpenDevice_Default(SDL_AudioDevice *device) +static bool SDL_AudioOpenDevice_Default(SDL_AudioDevice *device) { return SDL_Unsupported(); } @@ -767,9 +824,9 @@ static void CompleteAudioEntryPoints(void) FILL_STUB(WaitDevice); FILL_STUB(PlayDevice); FILL_STUB(GetDeviceBuf); - FILL_STUB(WaitCaptureDevice); - FILL_STUB(CaptureFromDevice); - FILL_STUB(FlushCapture); + FILL_STUB(WaitRecordingDevice); + FILL_STUB(RecordDevice); + FILL_STUB(FlushRecording); FILL_STUB(CloseDevice); FILL_STUB(FreeDeviceHandle); FILL_STUB(DeinitializeStart); @@ -777,10 +834,10 @@ static void CompleteAudioEntryPoints(void) #undef FILL_STUB } -static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) +static SDL_AudioDevice *GetFirstAddedAudioDevice(const bool recording) { - SDL_AudioDeviceID highest = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_OUTPUT; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. - SDL_AudioDevice *retval = NULL; + SDL_AudioDeviceID highest = (SDL_AudioDeviceID) SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; // According to AssignAudioDeviceInstanceId, nothing can have a value this large. + SDL_AudioDevice *result = NULL; // (Device IDs increase as new devices are added, so the first device added has the lowest SDL_AudioDeviceID value.) SDL_LockRWLockForReading(current_audio.device_hash_lock); @@ -790,28 +847,28 @@ static SDL_AudioDevice *GetFirstAddedAudioDevice(const SDL_bool iscapture) void *iter = NULL; while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; - // bit #0 of devid is set for output devices and unset for capture. + // bit #0 of devid is set for playback devices and unset for recording. // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool devid_iscapture = !(devid & (1 << 0)); - const SDL_bool isphysical = (devid & (1 << 1)); - if (isphysical && (devid_iscapture == iscapture) && (devid < highest)) { + const bool devid_recording = !(devid & (1 << 0)); + const bool isphysical = (devid & (1 << 1)); + if (isphysical && (devid_recording == recording) && (devid < highest)) { highest = devid; - retval = (SDL_AudioDevice *) value; + result = (SDL_AudioDevice *) value; } } SDL_UnlockRWLock(current_audio.device_hash_lock); - return retval; + return result; } static Uint32 HashAudioDeviceID(const void *key, void *data) { // shift right 2, to dump the first two bits, since these are flags - // (capture vs playback, logical vs physical) and the rest are unique incrementing integers. + // (recording vs playback, logical vs physical) and the rest are unique incrementing integers. return ((Uint32) ((uintptr_t) key)) >> 2; } -static SDL_bool MatchAudioDeviceID(const void *a, const void *b, void *data) +static bool MatchAudioDeviceID(const void *a, const void *b, void *data) { return (a == b); } @@ -822,27 +879,27 @@ static void NukeAudioDeviceHashItem(const void *key, const void *value, void *da } // !!! FIXME: the video subsystem does SDL_VideoInit, not SDL_InitVideo. Make this match. -int SDL_InitAudio(const char *driver_name) +bool SDL_InitAudio(const char *driver_name) { if (SDL_GetCurrentAudioDriver()) { SDL_QuitAudio(); // shutdown driver if already running. } // make sure device IDs start at 2 (because of SDL2 legacy interface), but don't reset the counter on each init, in case the app is holding an old device ID somewhere. - SDL_AtomicCompareAndSwap(&last_device_instance_id, 0, 2); + SDL_CompareAndSwapAtomicInt(&last_device_instance_id, 0, 2); SDL_ChooseAudioConverters(); SDL_SetupAudioResampler(); SDL_RWLock *device_hash_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole audio subsystem. if (!device_hash_lock) { - return -1; + return false; } - SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashAudioDeviceID, MatchAudioDeviceID, NukeAudioDeviceHashItem, SDL_FALSE); + SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashAudioDeviceID, MatchAudioDeviceID, NukeAudioDeviceHashItem, false); if (!device_hash) { SDL_DestroyRWLock(device_hash_lock); - return -1; + return false; } // Select the proper audio driver @@ -850,8 +907,8 @@ int SDL_InitAudio(const char *driver_name) driver_name = SDL_GetHint(SDL_HINT_AUDIO_DRIVER); } - SDL_bool initialized = SDL_FALSE; - SDL_bool tried_to_init = SDL_FALSE; + bool initialized = false; + bool tried_to_init = false; if (driver_name && *driver_name != 0) { char *driver_name_copy = SDL_strdup(driver_name); @@ -860,7 +917,7 @@ int SDL_InitAudio(const char *driver_name) if (!driver_name_copy) { SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); - return -1; + return false; } while (driver_attempt && *driver_attempt != 0 && !initialized) { @@ -878,7 +935,7 @@ int SDL_InitAudio(const char *driver_name) for (int i = 0; bootstrap[i]; ++i) { if (SDL_strcasecmp(bootstrap[i]->name, driver_attempt) == 0) { - tried_to_init = SDL_TRUE; + tried_to_init = true; SDL_zero(current_audio); current_audio.pending_events_tail = ¤t_audio.pending_events; current_audio.device_hash_lock = device_hash_lock; @@ -886,9 +943,9 @@ int SDL_InitAudio(const char *driver_name) if (bootstrap[i]->init(¤t_audio.impl)) { current_audio.name = bootstrap[i]->name; current_audio.desc = bootstrap[i]->desc; - initialized = SDL_TRUE; + initialized = true; + break; } - break; } } @@ -902,7 +959,7 @@ int SDL_InitAudio(const char *driver_name) continue; } - tried_to_init = SDL_TRUE; + tried_to_init = true; SDL_zero(current_audio); current_audio.pending_events_tail = ¤t_audio.pending_events; current_audio.device_hash_lock = device_hash_lock; @@ -910,7 +967,7 @@ int SDL_InitAudio(const char *driver_name) if (bootstrap[i]->init(¤t_audio.impl)) { current_audio.name = bootstrap[i]->name; current_audio.desc = bootstrap[i]->desc; - initialized = SDL_TRUE; + initialized = true; } } } @@ -928,36 +985,36 @@ int SDL_InitAudio(const char *driver_name) SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); SDL_zero(current_audio); - return -1; // No driver was available, so fail. + return false; // No driver was available, so fail. } CompleteAudioEntryPoints(); // Make sure we have a list of devices available at startup... - SDL_AudioDevice *default_output = NULL; - SDL_AudioDevice *default_capture = NULL; - current_audio.impl.DetectDevices(&default_output, &default_capture); + SDL_AudioDevice *default_playback = NULL; + SDL_AudioDevice *default_recording = NULL; + current_audio.impl.DetectDevices(&default_playback, &default_recording); // If no default was _ever_ specified, just take the first device we see, if any. - if (!default_output) { - default_output = GetFirstAddedAudioDevice(/*iscapture=*/SDL_FALSE); + if (!default_playback) { + default_playback = GetFirstAddedAudioDevice(/*recording=*/false); } - if (!default_capture) { - default_capture = GetFirstAddedAudioDevice(/*iscapture=*/SDL_TRUE); + if (!default_recording) { + default_recording = GetFirstAddedAudioDevice(/*recording=*/true); } - if (default_output) { - current_audio.default_output_device_id = default_output->instance_id; - RefPhysicalAudioDevice(default_output); // extra ref on default devices. + if (default_playback) { + current_audio.default_playback_device_id = default_playback->instance_id; + RefPhysicalAudioDevice(default_playback); // extra ref on default devices. } - if (default_capture) { - current_audio.default_capture_device_id = default_capture->instance_id; - RefPhysicalAudioDevice(default_capture); // extra ref on default devices. + if (default_recording) { + current_audio.default_recording_device_id = default_recording->instance_id; + RefPhysicalAudioDevice(default_recording); // extra ref on default devices. } - return 0; + return true; } void SDL_QuitAudio(void) @@ -974,13 +1031,13 @@ void SDL_QuitAudio(void) } SDL_LockRWLockForWriting(current_audio.device_hash_lock); - SDL_AtomicSet(¤t_audio.shutting_down, 1); + SDL_SetAtomicInt(¤t_audio.shutting_down, 1); SDL_HashTable *device_hash = current_audio.device_hash; current_audio.device_hash = NULL; SDL_PendingAudioDeviceEvent *pending_events = current_audio.pending_events.next; current_audio.pending_events.next = NULL; - SDL_AtomicSet(¤t_audio.output_device_count, 0); - SDL_AtomicSet(¤t_audio.capture_device_count, 0); + SDL_SetAtomicInt(¤t_audio.playback_device_count, 0); + SDL_SetAtomicInt(¤t_audio.recording_device_count, 0); SDL_UnlockRWLock(current_audio.device_hash_lock); SDL_PendingAudioDeviceEvent *pending_next = NULL; @@ -995,7 +1052,7 @@ void SDL_QuitAudio(void) while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { // bit #1 of devid is set for physical devices and unset for logical. const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; - const SDL_bool isphysical = (devid & (1<<1)); + const bool isphysical = (devid & (1<<1)); if (isphysical) { DestroyPhysicalAudioDevice((SDL_AudioDevice *) value); } @@ -1017,38 +1074,38 @@ void SDL_AudioThreadFinalize(SDL_AudioDevice *device) static void MixFloat32Audio(float *dst, const float *src, const int buffer_size) { - if (SDL_MixAudioFormat((Uint8 *) dst, (const Uint8 *) src, SDL_AUDIO_F32, buffer_size, SDL_MIX_MAXVOLUME) < 0) { + if (!SDL_MixAudio((Uint8 *) dst, (const Uint8 *) src, SDL_AUDIO_F32, buffer_size, 1.0f)) { SDL_assert(!"This shouldn't happen."); } } -// Output device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. +// Playback device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. -void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device) +void SDL_PlaybackAudioThreadSetup(SDL_AudioDevice *device) { - SDL_assert(!device->iscapture); + SDL_assert(!device->recording); current_audio.impl.ThreadInit(device); } -SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) +bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device) { - SDL_assert(!device->iscapture); + SDL_assert(!device->recording); SDL_LockMutex(device->lock); - if (SDL_AtomicGet(&device->shutdown)) { + if (SDL_GetAtomicInt(&device->shutdown)) { SDL_UnlockMutex(device->lock); - return SDL_FALSE; // we're done, shut it down. + return false; // we're done, shut it down. } - SDL_bool failed = SDL_FALSE; + bool failed = false; int buffer_size = device->buffer_size; Uint8 *device_buffer = device->GetDeviceBuf(device, &buffer_size); if (buffer_size == 0) { // WASAPI (maybe others, later) does this to say "just abandon this iteration and try again next time." } else if (!device_buffer) { - failed = SDL_TRUE; + failed = true; } else { SDL_assert(buffer_size <= device->buffer_size); // you can ask for less, but not more. SDL_assert(AudioDeviceCanUseSimpleCopy(device) == device->simple_copy); // make sure this hasn't gotten out of sync. @@ -1059,11 +1116,11 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_AudioStream *stream = logdev->bound_streams; // We should have updated this elsewhere if the format changed! - SDL_assert(AUDIO_SPECS_EQUAL(stream->dst_spec, device->spec)); + SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &device->spec, stream->dst_chmap, device->chmap)); - const int br = SDL_AtomicGet(&logdev->paused) ? 0 : SDL_GetAudioStreamData(stream, device_buffer, buffer_size); + const int br = SDL_GetAtomicInt(&logdev->paused) ? 0 : SDL_GetAudioStreamDataAdjustGain(stream, device_buffer, buffer_size, logdev->gain); if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow. - failed = SDL_TRUE; + failed = true; SDL_memset(device_buffer, device->silence_value, buffer_size); // just supply silence to the device before we die. } else if (br < buffer_size) { SDL_memset(device_buffer + br, device->silence_value, buffer_size - br); // silence whatever we didn't write to. @@ -1076,14 +1133,13 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_assert(work_buffer_size <= device->work_buffer_size); + SDL_copyp(&outspec, &device->spec); outspec.format = SDL_AUDIO_F32; - outspec.channels = device->spec.channels; - outspec.freq = device->spec.freq; SDL_memset(final_mix_buffer, '\0', work_buffer_size); // start with silence. for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { - if (SDL_AtomicGet(&logdev->paused)) { + if (SDL_GetAtomicInt(&logdev->paused)) { continue; // paused? Skip this logical device. } @@ -1096,15 +1152,15 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // We should have updated this elsewhere if the format changed! - SDL_assert(AUDIO_SPECS_EQUAL(stream->dst_spec, outspec)); + SDL_assert(SDL_AudioSpecsEqual(&stream->dst_spec, &outspec, stream->dst_chmap, device->chmap)); /* this will hold a lock on `stream` while getting. We don't explicitly lock the streams for iterating here because the binding linked list can only change while the device lock is held. (we _do_ lock the stream during binding/unbinding to make sure that two threads can't try to bind the same stream to different devices at the same time, though.) */ - const int br = SDL_GetAudioStreamData(stream, device->work_buffer, work_buffer_size); + const int br = SDL_GetAudioStreamDataAdjustGain(stream, device->work_buffer, work_buffer_size, logdev->gain); if (br < 0) { // Probably OOM. Kill the audio device; the whole thing is likely dying soon anyhow. - failed = SDL_TRUE; + failed = true; break; } else if (br > 0) { // it's okay if we get less than requested, we mix what we have. MixFloat32Audio(mix_buffer, (float *) device->work_buffer, br); @@ -1120,15 +1176,15 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) if (((Uint8 *) final_mix_buffer) != device_buffer) { // !!! FIXME: we can't promise the device buf is aligned/padded for SIMD. - //ConvertAudio(needed_samples * device->spec.channels, final_mix_buffer, SDL_AUDIO_F32, device->spec.channels, device_buffer, device->spec.format, device->spec.channels, device->work_buffer); - ConvertAudio(needed_samples / device->spec.channels, final_mix_buffer, SDL_AUDIO_F32, device->spec.channels, device->work_buffer, device->spec.format, device->spec.channels, NULL); + //ConvertAudio(needed_samples / device->spec.channels, final_mix_buffer, SDL_AUDIO_F32, device->spec.channels, NULL, device_buffer, device->spec.format, device->spec.channels, NULL, NULL, 1.0f); + ConvertAudio(needed_samples / device->spec.channels, final_mix_buffer, SDL_AUDIO_F32, device->spec.channels, NULL, device->work_buffer, device->spec.format, device->spec.channels, NULL, NULL, 1.0f); SDL_memcpy(device_buffer, device->work_buffer, buffer_size); } } // PlayDevice SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitDevice instead! - if (device->PlayDevice(device, device_buffer, buffer_size) < 0) { - failed = SDL_TRUE; + if (!device->PlayDevice(device, device_buffer, buffer_size)) { + failed = true; } } @@ -1138,93 +1194,94 @@ SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device) SDL_AudioDeviceDisconnected(device); // doh. } - return SDL_TRUE; // always go on if not shutting down, even if device failed. + return true; // always go on if not shutting down, even if device failed. } -void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device) +void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device) { - SDL_assert(!device->iscapture); + SDL_assert(!device->recording); const int frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); // Wait for the audio to drain if device didn't die. - if (!SDL_AtomicGet(&device->zombie)) { + if (!SDL_GetAtomicInt(&device->zombie)) { SDL_Delay(((frames * 1000) / device->spec.freq) * 2); } current_audio.impl.ThreadDeinit(device); SDL_AudioThreadFinalize(device); } -static int SDLCALL OutputAudioThread(void *devicep) // thread entry point +static int SDLCALL PlaybackAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; SDL_assert(device != NULL); - SDL_assert(!device->iscapture); - SDL_OutputAudioThreadSetup(device); + SDL_assert(!device->recording); + SDL_PlaybackAudioThreadSetup(device); do { - if (device->WaitDevice(device) < 0) { + if (!device->WaitDevice(device)) { SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) } - } while (SDL_OutputAudioThreadIterate(device)); + } while (SDL_PlaybackAudioThreadIterate(device)); - SDL_OutputAudioThreadShutdown(device); + SDL_PlaybackAudioThreadShutdown(device); return 0; } -// Capture device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. +// Recording device thread. This is split into chunks, so backends that need to control this directly can use the pieces they need without duplicating effort. -void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device) +void SDL_RecordingAudioThreadSetup(SDL_AudioDevice *device) { - SDL_assert(device->iscapture); + SDL_assert(device->recording); current_audio.impl.ThreadInit(device); } -SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) +bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device) { - SDL_assert(device->iscapture); + SDL_assert(device->recording); SDL_LockMutex(device->lock); - if (SDL_AtomicGet(&device->shutdown)) { + if (SDL_GetAtomicInt(&device->shutdown)) { SDL_UnlockMutex(device->lock); - return SDL_FALSE; // we're done, shut it down. + return false; // we're done, shut it down. } - SDL_bool failed = SDL_FALSE; + bool failed = false; if (!device->logical_devices) { - device->FlushCapture(device); // nothing wants data, dump anything pending. + device->FlushRecording(device); // nothing wants data, dump anything pending. } else { - // this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitCaptureDevice! - int br = device->CaptureFromDevice(device, device->work_buffer, device->buffer_size); + // this SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitRecordingDevice! + int br = device->RecordDevice(device, device->work_buffer, device->buffer_size); if (br < 0) { // uhoh, device failed for some reason! - failed = SDL_TRUE; + failed = true; } else if (br > 0) { // queue the new data to each bound stream. for (SDL_LogicalAudioDevice *logdev = device->logical_devices; logdev; logdev = logdev->next) { - if (SDL_AtomicGet(&logdev->paused)) { + if (SDL_GetAtomicInt(&logdev->paused)) { continue; // paused? Skip this logical device. } void *output_buffer = device->work_buffer; - // I don't know why someone would want a postmix on a capture device, but we offer it for API consistency. - if (logdev->postmix) { + // I don't know why someone would want a postmix on a recording device, but we offer it for API consistency. + if (logdev->postmix || (logdev->gain != 1.0f)) { // move to float format. SDL_AudioSpec outspec; + SDL_copyp(&outspec, &device->spec); outspec.format = SDL_AUDIO_F32; - outspec.channels = device->spec.channels; - outspec.freq = device->spec.freq; output_buffer = device->postmix_buffer; const int frames = br / SDL_AUDIO_FRAMESIZE(device->spec); br = frames * SDL_AUDIO_FRAMESIZE(outspec); - ConvertAudio(frames, device->work_buffer, device->spec.format, outspec.channels, device->postmix_buffer, SDL_AUDIO_F32, outspec.channels, NULL); - logdev->postmix(logdev->postmix_userdata, &outspec, device->postmix_buffer, br); + ConvertAudio(frames, device->work_buffer, device->spec.format, outspec.channels, NULL, device->postmix_buffer, SDL_AUDIO_F32, outspec.channels, NULL, NULL, logdev->gain); + if (logdev->postmix) { + logdev->postmix(logdev->postmix_userdata, &outspec, device->postmix_buffer, br); + } } for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // We should have updated this elsewhere if the format changed! - SDL_assert(stream->src_spec.format == (logdev->postmix ? SDL_AUDIO_F32 : device->spec.format)); + SDL_assert(stream->src_spec.format == ((logdev->postmix || (logdev->gain != 1.0f)) ? SDL_AUDIO_F32 : device->spec.format)); SDL_assert(stream->src_spec.channels == device->spec.channels); SDL_assert(stream->src_spec.freq == device->spec.freq); @@ -1232,9 +1289,9 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) for iterating here because the binding linked list can only change while the device lock is held. (we _do_ lock the stream during binding/unbinding to make sure that two threads can't try to bind the same stream to different devices at the same time, though.) */ - if (SDL_PutAudioStreamData(stream, output_buffer, br) < 0) { + if (!SDL_PutAudioStreamData(stream, output_buffer, br)) { // oh crud, we probably ran out of memory. This is possibly an overreaction to kill the audio device, but it's likely the whole thing is going down in a moment anyhow. - failed = SDL_TRUE; + failed = true; break; } } @@ -1248,66 +1305,64 @@ SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device) SDL_AudioDeviceDisconnected(device); // doh. } - return SDL_TRUE; // always go on if not shutting down, even if device failed. + return true; // always go on if not shutting down, even if device failed. } -void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device) +void SDL_RecordingAudioThreadShutdown(SDL_AudioDevice *device) { - SDL_assert(device->iscapture); - device->FlushCapture(device); + SDL_assert(device->recording); + device->FlushRecording(device); current_audio.impl.ThreadDeinit(device); SDL_AudioThreadFinalize(device); } -static int SDLCALL CaptureAudioThread(void *devicep) // thread entry point +static int SDLCALL RecordingAudioThread(void *devicep) // thread entry point { SDL_AudioDevice *device = (SDL_AudioDevice *)devicep; SDL_assert(device != NULL); - SDL_assert(device->iscapture); - SDL_CaptureAudioThreadSetup(device); + SDL_assert(device->recording); + SDL_RecordingAudioThreadSetup(device); do { - if (device->WaitCaptureDevice(device) < 0) { + if (!device->WaitRecordingDevice(device)) { SDL_AudioDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) } - } while (SDL_CaptureAudioThreadIterate(device)); + } while (SDL_RecordingAudioThreadIterate(device)); - SDL_CaptureAudioThreadShutdown(device); + SDL_RecordingAudioThreadShutdown(device); return 0; } -static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture) +static SDL_AudioDeviceID *GetAudioDevices(int *count, bool recording) { - SDL_AudioDeviceID *retval = NULL; + SDL_AudioDeviceID *result = NULL; int num_devices = 0; if (SDL_GetCurrentAudioDriver()) { SDL_LockRWLockForReading(current_audio.device_hash_lock); { - num_devices = SDL_AtomicGet(iscapture ? ¤t_audio.capture_device_count : ¤t_audio.output_device_count); - retval = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); - if (retval) { + num_devices = SDL_GetAtomicInt(recording ? ¤t_audio.recording_device_count : ¤t_audio.playback_device_count); + result = (SDL_AudioDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_AudioDeviceID)); + if (result) { int devs_seen = 0; const void *key; const void *value; void *iter = NULL; while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; - // bit #0 of devid is set for output devices and unset for capture. + // bit #0 of devid is set for playback devices and unset for recording. // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool devid_iscapture = !(devid & (1<<0)); - const SDL_bool isphysical = (devid & (1<<1)); - if (isphysical && (devid_iscapture == iscapture)) { + const bool devid_recording = !(devid & (1<<0)); + const bool isphysical = (devid & (1<<1)); + if (isphysical && (devid_recording == recording)) { SDL_assert(devs_seen < num_devices); - retval[devs_seen++] = devid; + result[devs_seen++] = devid; } } SDL_assert(devs_seen == num_devices); - retval[devs_seen] = 0; // null-terminated. - } else { - SDL_OutOfMemory(); + result[devs_seen] = 0; // null-terminated. } } SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -1316,27 +1371,27 @@ static SDL_AudioDeviceID *GetAudioDevices(int *count, SDL_bool iscapture) } if (count) { - if (retval) { + if (result) { *count = num_devices; } else { *count = 0; } } - return retval; + return result; } -SDL_AudioDeviceID *SDL_GetAudioOutputDevices(int *count) +SDL_AudioDeviceID *SDL_GetAudioPlaybackDevices(int *count) { - return GetAudioDevices(count, SDL_FALSE); + return GetAudioDevices(count, false); } -SDL_AudioDeviceID *SDL_GetAudioCaptureDevices(int *count) +SDL_AudioDeviceID *SDL_GetAudioRecordingDevices(int *count) { - return GetAudioDevices(count, SDL_TRUE); + return GetAudioDevices(count, true); } -SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata) +SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata) { if (!SDL_GetCurrentAudioDriver()) { SDL_SetError("Audio subsystem is not initialized"); @@ -1351,7 +1406,7 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_ while (SDL_IterateHashTable(current_audio.device_hash, &key, &value, &iter)) { const SDL_AudioDeviceID devid = (SDL_AudioDeviceID) (uintptr_t) key; // bit #1 of devid is set for physical devices and unset for logical. - const SDL_bool isphysical = (devid & (1<<1)); + const bool isphysical = (devid & (1<<1)); if (isphysical) { SDL_AudioDevice *device = (SDL_AudioDevice *) value; if (callback(device, userdata)) { // found it? @@ -1366,7 +1421,7 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_ return NULL; } -static SDL_bool TestDeviceHandleCallback(SDL_AudioDevice *device, void *handle) +static bool TestDeviceHandleCallback(SDL_AudioDevice *device, void *handle) { return device->handle == handle; } @@ -1376,38 +1431,57 @@ SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle) return SDL_FindPhysicalAudioDeviceByCallback(TestDeviceHandleCallback, handle); } -char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) +const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid) { - char *retval = NULL; + const char *result = NULL; SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid); if (device) { - retval = SDL_strdup(device->name); + result = SDL_GetPersistentString(device->name); } ReleaseAudioDevice(device); - return retval; + return result; } -int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames) +bool SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames) { if (!spec) { return SDL_InvalidParamError("spec"); } - int retval = -1; + bool result = false; SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); if (device) { SDL_copyp(spec, &device->spec); if (sample_frames) { *sample_frames = device->sample_frames; } - retval = 0; + result = true; } ReleaseAudioDevice(device); - return retval; + return result; } +int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count) +{ + int *result = NULL; + int channels = 0; + SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); + if (device) { + channels = device->spec.channels; + result = SDL_ChannelMapDup(device->chmap, channels); + } + ReleaseAudioDevice(device); + + if (count) { + *count = channels; + } + + return result; +} + + // this is awkward, but this makes sure we can release the device lock // so the device thread can terminate but also not have two things // race to close or open the device while the lock is unprotected. @@ -1416,7 +1490,7 @@ int SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int * // BE CAREFUL WITH THIS. static void SerializePhysicalDeviceClose(SDL_AudioDevice *device) { - while (SDL_AtomicGet(&device->shutdown)) { + while (SDL_GetAtomicInt(&device->shutdown)) { SDL_WaitCondition(device->close_cond, device->lock); } } @@ -1426,7 +1500,7 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) { SerializePhysicalDeviceClose(device); - SDL_AtomicSet(&device->shutdown, 1); + SDL_SetAtomicInt(&device->shutdown, 1); // YOU MUST PROTECT KEY POINTS WITH SerializePhysicalDeviceClose() WHILE THE THREAD JOINS SDL_UnlockMutex(device->lock); @@ -1438,12 +1512,12 @@ static void ClosePhysicalAudioDevice(SDL_AudioDevice *device) if (device->currently_opened) { current_audio.impl.CloseDevice(device); // if ProvidesOwnCallbackThread, this must join on any existing device thread before returning! - device->currently_opened = SDL_FALSE; + device->currently_opened = false; device->hidden = NULL; // just in case. } SDL_LockMutex(device->lock); - SDL_AtomicSet(&device->shutdown, 0); // ready to go again. + SDL_SetAtomicInt(&device->shutdown, 0); // ready to go again. SDL_BroadcastCondition(device->close_cond); // release anyone waiting in SerializePhysicalDeviceClose; they'll still block until we release device->lock, though. SDL_aligned_free(device->work_buffer); @@ -1496,17 +1570,17 @@ static SDL_AudioFormat ParseAudioFormatString(const char *string) CHECK_FMT_STRING(F32); #undef CHECK_FMT_STRING } - return 0; + return SDL_AUDIO_UNKNOWN; } -static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) +static void PrepareAudioFormat(bool recording, SDL_AudioSpec *spec) { if (spec->freq == 0) { - spec->freq = iscapture ? DEFAULT_AUDIO_CAPTURE_FREQUENCY : DEFAULT_AUDIO_OUTPUT_FREQUENCY; + spec->freq = recording ? DEFAULT_AUDIO_RECORDING_FREQUENCY : DEFAULT_AUDIO_PLAYBACK_FREQUENCY; - const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY"); // !!! FIXME: should be a hint? - if (env) { - const int val = SDL_atoi(env); + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_FREQUENCY); + if (hint) { + const int val = SDL_atoi(hint); if (val > 0) { spec->freq = val; } @@ -1514,10 +1588,11 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) } if (spec->channels == 0) { - spec->channels = iscapture ? DEFAULT_AUDIO_CAPTURE_CHANNELS : DEFAULT_AUDIO_OUTPUT_CHANNELS;; - const char *env = SDL_getenv("SDL_AUDIO_CHANNELS"); - if (env) { - const int val = SDL_atoi(env); + spec->channels = recording ? DEFAULT_AUDIO_RECORDING_CHANNELS : DEFAULT_AUDIO_PLAYBACK_CHANNELS; + + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_CHANNELS); + if (hint) { + const int val = SDL_atoi(hint); if (val > 0) { spec->channels = val; } @@ -1525,8 +1600,8 @@ static void PrepareAudioFormat(SDL_bool iscapture, SDL_AudioSpec *spec) } if (spec->format == 0) { - const SDL_AudioFormat val = ParseAudioFormatString(SDL_getenv("SDL_AUDIO_FORMAT")); - spec->format = (val != 0) ? val : (iscapture ? DEFAULT_AUDIO_CAPTURE_FORMAT : DEFAULT_AUDIO_OUTPUT_FORMAT); + const SDL_AudioFormat val = ParseAudioFormatString(SDL_GetHint(SDL_HINT_AUDIO_FORMAT)); + spec->format = (val != SDL_AUDIO_UNKNOWN) ? val : (recording ? DEFAULT_AUDIO_RECORDING_FORMAT : DEFAULT_AUDIO_PLAYBACK_FORMAT); } } @@ -1540,36 +1615,36 @@ void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device) char *SDL_GetAudioThreadName(SDL_AudioDevice *device, char *buf, size_t buflen) { - (void)SDL_snprintf(buf, buflen, "SDLAudio%c%d", (device->iscapture) ? 'C' : 'P', (int) device->instance_id); + (void)SDL_snprintf(buf, buflen, "SDLAudio%c%d", (device->recording) ? 'C' : 'P', (int) device->instance_id); return buf; } // this expects the device lock to be held. -static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec *inspec) +static bool OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec *inspec) { SerializePhysicalDeviceClose(device); // make sure another thread that's closing didn't release the lock to let the device thread join... if (device->currently_opened) { - return 0; // we're already good. + return true; // we're already good. } // Just pretend to open a zombie device. It can still collect logical devices on a default device under the assumption they will all migrate when the default device is officially changed. - if (SDL_AtomicGet(&device->zombie)) { - return 0; // Braaaaaaaaains. + if (SDL_GetAtomicInt(&device->zombie)) { + return true; // Braaaaaaaaains. } // These start with the backend's implementation, but we might swap them out with zombie versions later. device->WaitDevice = current_audio.impl.WaitDevice; device->PlayDevice = current_audio.impl.PlayDevice; device->GetDeviceBuf = current_audio.impl.GetDeviceBuf; - device->WaitCaptureDevice = current_audio.impl.WaitCaptureDevice; - device->CaptureFromDevice = current_audio.impl.CaptureFromDevice; - device->FlushCapture = current_audio.impl.FlushCapture; + device->WaitRecordingDevice = current_audio.impl.WaitRecordingDevice; + device->RecordDevice = current_audio.impl.RecordDevice; + device->FlushRecording = current_audio.impl.FlushRecording; SDL_AudioSpec spec; SDL_copyp(&spec, inspec ? inspec : &device->default_spec); - PrepareAudioFormat(device->iscapture, &spec); + PrepareAudioFormat(device->recording, &spec); /* We allow the device format to change if it's better than the current settings (by various definitions of "better"). This prevents something low quality, like an old game using S8/8000Hz audio, from ruining a music thing playing at CD quality that tries to open later. @@ -1581,35 +1656,34 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec device->sample_frames = GetDefaultSampleFramesFromFreq(device->spec.freq); SDL_UpdatedAudioDeviceFormat(device); // start this off sane. - device->currently_opened = SDL_TRUE; // mark this true even if impl.OpenDevice fails, so we know to clean up. - if (current_audio.impl.OpenDevice(device) < 0) { + device->currently_opened = true; // mark this true even if impl.OpenDevice fails, so we know to clean up. + if (!current_audio.impl.OpenDevice(device)) { ClosePhysicalAudioDevice(device); // clean up anything the backend left half-initialized. - return -1; + return false; } SDL_UpdatedAudioDeviceFormat(device); // in case the backend changed things and forgot to call this. // Allocate a scratch audio buffer - device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->work_buffer) { ClosePhysicalAudioDevice(device); - return -1; + return false; } if (device->spec.format != SDL_AUDIO_F32) { - device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->mix_buffer) { ClosePhysicalAudioDevice(device); - return -1; + return false; } } // Start the audio thread if necessary if (!current_audio.impl.ProvidesOwnCallbackThread) { - const size_t stacksize = 0; // just take the system default, since audio streams might have callbacks. char threadname[64]; SDL_GetAudioThreadName(device, threadname, sizeof (threadname)); - device->thread = SDL_CreateThreadInternal(device->iscapture ? CaptureAudioThread : OutputAudioThread, threadname, stacksize, device); + device->thread = SDL_CreateThread(device->recording ? RecordingAudioThread : PlaybackAudioThread, threadname, device); if (!device->thread) { ClosePhysicalAudioDevice(device); @@ -1617,7 +1691,7 @@ static int OpenPhysicalAudioDevice(SDL_AudioDevice *device, const SDL_AudioSpec } } - return 0; + return true; } SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec) @@ -1627,11 +1701,11 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp return 0; } - SDL_bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_OUTPUT) || (devid == SDL_AUDIO_DEVICE_DEFAULT_CAPTURE)); + bool wants_default = ((devid == SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK) || (devid == SDL_AUDIO_DEVICE_DEFAULT_RECORDING)); // this will let you use a logical device to make a new logical device on the parent physical device. Could be useful? SDL_AudioDevice *device = NULL; - const SDL_bool islogical = (!wants_default && !(devid & (1<<1))); + const bool islogical = (!wants_default && !(devid & (1<<1))); if (!islogical) { device = ObtainPhysicalAudioDeviceDefaultAllowed(devid); } else { @@ -1641,22 +1715,23 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp } } - SDL_AudioDeviceID retval = 0; + SDL_AudioDeviceID result = 0; if (device) { SDL_LogicalAudioDevice *logdev = NULL; - if (!wants_default && SDL_AtomicGet(&device->zombie)) { + if (!wants_default && SDL_GetAtomicInt(&device->zombie)) { // uhoh, this device is undead, and just waiting to be cleaned up. Refuse explicit opens. SDL_SetError("Device was already lost and can't accept new opens"); } else if ((logdev = (SDL_LogicalAudioDevice *) SDL_calloc(1, sizeof (SDL_LogicalAudioDevice))) == NULL) { - /* SDL_calloc already called SDL_OutOfMemory */ - } else if (OpenPhysicalAudioDevice(device, spec) == -1) { // if this is the first thing using this physical device, open at the OS level if necessary... + // SDL_calloc already called SDL_OutOfMemory + } else if (!OpenPhysicalAudioDevice(device, spec)) { // if this is the first thing using this physical device, open at the OS level if necessary... SDL_free(logdev); } else { RefPhysicalAudioDevice(device); // unref'd on successful SDL_CloseAudioDevice - SDL_AtomicSet(&logdev->paused, 0); - retval = logdev->instance_id = AssignAudioDeviceInstanceId(device->iscapture, /*islogical=*/SDL_TRUE); + SDL_SetAtomicInt(&logdev->paused, 0); + result = logdev->instance_id = AssignAudioDeviceInstanceId(device->recording, /*islogical=*/true); logdev->physical_device = device; + logdev->gain = 1.0f; logdev->opened_as_default = wants_default; logdev->next = device->logical_devices; if (device->logical_devices) { @@ -1667,76 +1742,115 @@ SDL_AudioDeviceID SDL_OpenAudioDevice(SDL_AudioDeviceID devid, const SDL_AudioSp } ReleaseAudioDevice(device); - if (retval) { + if (result) { SDL_LockRWLockForWriting(current_audio.device_hash_lock); - const SDL_bool inserted = SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) retval, logdev); + const bool inserted = SDL_InsertIntoHashTable(current_audio.device_hash, (const void *) (uintptr_t) result, logdev); SDL_UnlockRWLock(current_audio.device_hash_lock); if (!inserted) { - SDL_CloseAudioDevice(retval); - retval = 0; + SDL_CloseAudioDevice(result); + result = 0; } } } - return retval; + return result; } -static int SetLogicalAudioDevicePauseState(SDL_AudioDeviceID devid, int value) +static bool SetLogicalAudioDevicePauseState(SDL_AudioDeviceID devid, int value) { SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); if (logdev) { - SDL_AtomicSet(&logdev->paused, value); + SDL_SetAtomicInt(&logdev->paused, value); } ReleaseAudioDevice(device); - return logdev ? 0 : -1; // ObtainLogicalAudioDevice will have set an error. + return logdev ? true : false; // ObtainLogicalAudioDevice will have set an error. } -int SDL_PauseAudioDevice(SDL_AudioDeviceID devid) +bool SDL_PauseAudioDevice(SDL_AudioDeviceID devid) { return SetLogicalAudioDevicePauseState(devid, 1); } -int SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid) +bool SDLCALL SDL_ResumeAudioDevice(SDL_AudioDeviceID devid) { return SetLogicalAudioDevicePauseState(devid, 0); } -SDL_bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid) +bool SDL_AudioDevicePaused(SDL_AudioDeviceID devid) +{ + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); + bool result = false; + if (logdev && SDL_GetAtomicInt(&logdev->paused)) { + result = true; + } + ReleaseAudioDevice(device); + return result; +} + +float SDL_GetAudioDeviceGain(SDL_AudioDeviceID devid) +{ + SDL_AudioDevice *device = NULL; + SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); + const float result = logdev ? logdev->gain : -1.0f; + ReleaseAudioDevice(device); + return result; +} + +bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain) { + if (gain < 0.0f) { + return SDL_InvalidParamError("gain"); + } + SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); - SDL_bool retval = SDL_FALSE; - if (logdev && SDL_AtomicGet(&logdev->paused)) { - retval = SDL_TRUE; + bool result = false; + if (logdev) { + logdev->gain = gain; + if (device->recording) { + const bool need_float32 = (logdev->postmix || logdev->gain != 1.0f); + for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { + // set the proper end of the stream to the device's format. + // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. + SDL_LockMutex(stream->lock); + stream->src_spec.format = need_float32 ? SDL_AUDIO_F32 : device->spec.format; + SDL_UnlockMutex(stream->lock); + } + } + + UpdateAudioStreamFormatsPhysical(device); + result = true; } ReleaseAudioDevice(device); - return retval; + return result; } -int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallback callback, void *userdata) +bool SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallback callback, void *userdata) { SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(devid, &device); - int retval = 0; + bool result = true; if (logdev) { if (callback && !device->postmix_buffer) { - device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->postmix_buffer) { - retval = -1; + result = false; } } - if (retval == 0) { + if (result) { logdev->postmix = callback; logdev->postmix_userdata = userdata; - if (device->iscapture) { + if (device->recording) { + const bool need_float32 = (callback || logdev->gain != 1.0f); for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { // set the proper end of the stream to the device's format. // SDL_SetAudioStreamFormat does a ton of validation just to memcpy an audiospec. SDL_LockMutex(stream->lock); - stream->src_spec.format = callback ? SDL_AUDIO_F32 : device->spec.format; + stream->src_spec.format = need_float32 ? SDL_AUDIO_F32 : device->spec.format; SDL_UnlockMutex(stream->lock); } } @@ -1745,18 +1859,18 @@ int SDL_SetAudioPostmixCallback(SDL_AudioDeviceID devid, SDL_AudioPostmixCallbac UpdateAudioStreamFormatsPhysical(device); } ReleaseAudioDevice(device); - return retval; + return result; } -int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams) +bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int num_streams) { - const SDL_bool islogical = !(devid & (1<<1)); + const bool islogical = !(devid & (1<<1)); SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = NULL; - int retval = 0; + bool result = true; if (num_streams == 0) { - return 0; // nothing to do + return true; // nothing to do } else if (num_streams < 0) { return SDL_InvalidParamError("num_streams"); } else if (!streams) { @@ -1767,9 +1881,9 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int logdev = ObtainLogicalAudioDevice(devid, &device); if (!logdev) { - retval = -1; // ObtainLogicalAudioDevice set the error string. + result = false; // ObtainLogicalAudioDevice set the error string. } else if (logdev->simplified) { - retval = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream"); + result = SDL_SetError("Cannot change stream bindings on device opened with SDL_OpenAudioDeviceStream"); } else { // !!! FIXME: We'll set the device's side's format below, but maybe we should refuse to bind a stream if the app's side doesn't have a format set yet. @@ -1782,18 +1896,19 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int for (int i = 0; i < num_streams; i++) { SDL_AudioStream *stream = streams[i]; if (!stream) { - retval = SDL_SetError("Stream #%d is NULL", i); + SDL_SetError("Stream #%d is NULL", i); + result = false; // to pacify the static analyzer, that doesn't realize SDL_SetError() always returns false. } else { SDL_LockMutex(stream->lock); SDL_assert((stream->bound_device == NULL) == ((stream->prev_binding == NULL) || (stream->next_binding == NULL))); if (stream->bound_device) { - retval = SDL_SetError("Stream #%d is already bound to a device", i); + result = SDL_SetError("Stream #%d is already bound to a device", i); } else if (stream->simplified) { // You can get here if you closed the device instead of destroying the stream. - retval = SDL_SetError("Cannot change binding on a stream created with SDL_OpenAudioDeviceStream"); + result = SDL_SetError("Cannot change binding on a stream created with SDL_OpenAudioDeviceStream"); } } - if (retval != 0) { + if (!result) { int j; for (j = 0; j < i; j++) { SDL_UnlockMutex(streams[j]->lock); @@ -1806,35 +1921,30 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int } } - if (retval == 0) { + if (result) { // Now that everything is verified, chain everything together. - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; for (int i = 0; i < num_streams; i++) { -#ifdef _MSC_VER /* Visual Studio analyzer can't tell that streams[i] isn't NULL if retval is 0 */ -#pragma warning(push) -#pragma warning(disable : 28182) -#endif SDL_AudioStream *stream = streams[i]; + if (stream) { // shouldn't be NULL, but just in case... + stream->bound_device = logdev; + stream->prev_binding = NULL; + stream->next_binding = logdev->bound_streams; + if (logdev->bound_streams) { + logdev->bound_streams->prev_binding = stream; + } + logdev->bound_streams = stream; - stream->bound_device = logdev; - stream->prev_binding = NULL; - stream->next_binding = logdev->bound_streams; - if (logdev->bound_streams) { - logdev->bound_streams->prev_binding = stream; - } - logdev->bound_streams = stream; - - if (iscapture) { - SDL_copyp(&stream->src_spec, &device->spec); - if (logdev->postmix) { - stream->src_spec.format = SDL_AUDIO_F32; + if (recording) { + SDL_copyp(&stream->src_spec, &device->spec); + if (logdev->postmix) { + stream->src_spec.format = SDL_AUDIO_F32; + } + SDL_SetAudioStreamInputChannelMap(stream, device->chmap, device->spec.channels); // this should be fast for normal cases, though! } - } - SDL_UnlockMutex(stream->lock); -#ifdef _MSC_VER -#pragma warning(pop) -#endif + SDL_UnlockMutex(stream->lock); + } } } @@ -1842,10 +1952,10 @@ int SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream **streams, int ReleaseAudioDevice(device); - return retval; + return result; } -int SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream) +bool SDL_BindAudioStream(SDL_AudioDeviceID devid, SDL_AudioStream *stream) { return SDL_BindAudioStreams(devid, &stream, 1); } @@ -1862,7 +1972,7 @@ void SDL_UnbindAudioStreams(SDL_AudioStream **streams, int num_streams) continue; // nothing to do, it's a NULL stream. } - while (SDL_TRUE) { + while (true) { SDL_LockMutex(stream->lock); // lock to check this and then release it, in case the device isn't locked yet. SDL_LogicalAudioDevice *bounddev = stream->bound_device; SDL_UnlockMutex(stream->lock); @@ -1925,15 +2035,22 @@ void SDL_UnbindAudioStream(SDL_AudioStream *stream) SDL_AudioDeviceID SDL_GetAudioStreamDevice(SDL_AudioStream *stream) { - SDL_AudioDeviceID retval = 0; - if (stream) { - SDL_LockMutex(stream->lock); - if (stream->bound_device) { - retval = stream->bound_device->instance_id; - } - SDL_UnlockMutex(stream->lock); + SDL_AudioDeviceID result = 0; + + if (!stream) { + SDL_InvalidParamError("stream"); + return 0; + } + + SDL_LockMutex(stream->lock); + if (stream->bound_device) { + result = stream->bound_device->instance_id; + } else { + SDL_SetError("Audio stream not bound to an audio device"); } - return retval; + SDL_UnlockMutex(stream->lock); + + return result; } SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_AudioSpec *spec, SDL_AudioStreamCallback callback, void *userdata) @@ -1943,44 +2060,51 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au return NULL; // error string should already be set. } - SDL_bool failed = SDL_FALSE; + bool failed = false; SDL_AudioStream *stream = NULL; SDL_AudioDevice *device = NULL; SDL_LogicalAudioDevice *logdev = ObtainLogicalAudioDevice(logdevid, &device); if (!logdev) { // this shouldn't happen, but just in case. - failed = SDL_TRUE; + failed = true; } else { - SDL_AtomicSet(&logdev->paused, 1); // start the device paused, to match SDL2. + SDL_SetAtomicInt(&logdev->paused, 1); // start the device paused, to match SDL2. SDL_assert(device != NULL); - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; + + // if the app didn't request a format _at all_, just make a stream that does no conversion; they can query for it later. + SDL_AudioSpec tmpspec; + if (!spec) { + SDL_copyp(&tmpspec, &device->spec); + spec = &tmpspec; + } - if (iscapture) { + if (recording) { stream = SDL_CreateAudioStream(&device->spec, spec); } else { stream = SDL_CreateAudioStream(spec, &device->spec); } if (!stream) { - failed = SDL_TRUE; + failed = true; } else { // don't do all the complicated validation and locking of SDL_BindAudioStream just to set a few fields here. logdev->bound_streams = stream; - logdev->simplified = SDL_TRUE; // forbid further binding changes on this logical device. + logdev->simplified = true; // forbid further binding changes on this logical device. stream->bound_device = logdev; - stream->simplified = SDL_TRUE; // so we know to close the audio device when this is destroyed. + stream->simplified = true; // so we know to close the audio device when this is destroyed. UpdateAudioStreamFormatsPhysical(device); if (callback) { - int rc; - if (iscapture) { + bool rc; + if (recording) { rc = SDL_SetAudioStreamPutCallback(stream, callback, userdata); } else { rc = SDL_SetAudioStreamGetCallback(stream, callback, userdata); } - SDL_assert(rc == 0); // should only fail if stream==NULL atm. + SDL_assert(rc); // should only fail if stream==NULL atm. } } } @@ -1996,18 +2120,50 @@ SDL_AudioStream *SDL_OpenAudioDeviceStream(SDL_AudioDeviceID devid, const SDL_Au return stream; } +bool SDL_PauseAudioStreamDevice(SDL_AudioStream *stream) +{ + SDL_AudioDeviceID devid = SDL_GetAudioStreamDevice(stream); + if (!devid) { + return false; + } + + return SDL_PauseAudioDevice(devid); +} + +bool SDL_ResumeAudioStreamDevice(SDL_AudioStream *stream) +{ + SDL_AudioDeviceID devid = SDL_GetAudioStreamDevice(stream); + if (!devid) { + return false; + } + + return SDL_ResumeAudioDevice(devid); +} + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define NATIVE(type) SDL_AUDIO_##type##LE +#define SWAPPED(type) SDL_AUDIO_##type##BE +#else +#define NATIVE(type) SDL_AUDIO_##type##BE +#define SWAPPED(type) SDL_AUDIO_##type##LE +#endif + #define NUM_FORMATS 8 +// always favor Float32 in native byte order, since we're probably going to convert to that for processing anyhow. static const SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS + 1] = { - { SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_S16LE, SDL_AUDIO_S16BE, SDL_AUDIO_S32LE, SDL_AUDIO_S32BE, SDL_AUDIO_F32LE, SDL_AUDIO_F32BE, 0 }, - { SDL_AUDIO_S8, SDL_AUDIO_U8, SDL_AUDIO_S16LE, SDL_AUDIO_S16BE, SDL_AUDIO_S32LE, SDL_AUDIO_S32BE, SDL_AUDIO_F32LE, SDL_AUDIO_F32BE, 0 }, - { SDL_AUDIO_S16LE, SDL_AUDIO_S16BE, SDL_AUDIO_S32LE, SDL_AUDIO_S32BE, SDL_AUDIO_F32LE, SDL_AUDIO_F32BE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, - { SDL_AUDIO_S16BE, SDL_AUDIO_S16LE, SDL_AUDIO_S32BE, SDL_AUDIO_S32LE, SDL_AUDIO_F32BE, SDL_AUDIO_F32LE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, - { SDL_AUDIO_S32LE, SDL_AUDIO_S32BE, SDL_AUDIO_F32LE, SDL_AUDIO_F32BE, SDL_AUDIO_S16LE, SDL_AUDIO_S16BE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, - { SDL_AUDIO_S32BE, SDL_AUDIO_S32LE, SDL_AUDIO_F32BE, SDL_AUDIO_F32LE, SDL_AUDIO_S16BE, SDL_AUDIO_S16LE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, - { SDL_AUDIO_F32LE, SDL_AUDIO_F32BE, SDL_AUDIO_S32LE, SDL_AUDIO_S32BE, SDL_AUDIO_S16LE, SDL_AUDIO_S16BE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, - { SDL_AUDIO_F32BE, SDL_AUDIO_F32LE, SDL_AUDIO_S32BE, SDL_AUDIO_S32LE, SDL_AUDIO_S16BE, SDL_AUDIO_S16LE, SDL_AUDIO_U8, SDL_AUDIO_S8, 0 }, + { SDL_AUDIO_U8, NATIVE(F32), SWAPPED(F32), SDL_AUDIO_S8, NATIVE(S16), SWAPPED(S16), NATIVE(S32), SWAPPED(S32), SDL_AUDIO_UNKNOWN }, + { SDL_AUDIO_S8, NATIVE(F32), SWAPPED(F32), SDL_AUDIO_U8, NATIVE(S16), SWAPPED(S16), NATIVE(S32), SWAPPED(S32), SDL_AUDIO_UNKNOWN }, + { NATIVE(S16), NATIVE(F32), SWAPPED(F32), SWAPPED(S16), NATIVE(S32), SWAPPED(S32), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, + { SWAPPED(S16), NATIVE(F32), SWAPPED(F32), NATIVE(S16), SWAPPED(S32), NATIVE(S32), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, + { NATIVE(S32), NATIVE(F32), SWAPPED(F32), SWAPPED(S32), NATIVE(S16), SWAPPED(S16), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, + { SWAPPED(S32), NATIVE(F32), SWAPPED(F32), NATIVE(S32), SWAPPED(S16), NATIVE(S16), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, + { NATIVE(F32), SWAPPED(F32), NATIVE(S32), SWAPPED(S32), NATIVE(S16), SWAPPED(S16), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, + { SWAPPED(F32), NATIVE(F32), SWAPPED(S32), NATIVE(S32), SWAPPED(S16), NATIVE(S16), SDL_AUDIO_U8, SDL_AUDIO_S8, SDL_AUDIO_UNKNOWN }, }; +#undef NATIVE +#undef SWAPPED + const SDL_AudioFormat *SDL_ClosestAudioFormats(SDL_AudioFormat format) { for (int i = 0; i < NUM_FORMATS; i++) { @@ -2018,6 +2174,25 @@ const SDL_AudioFormat *SDL_ClosestAudioFormats(SDL_AudioFormat format) return &format_list[0][NUM_FORMATS]; // not found; return what looks like a list with only a zero in it. } +const char *SDL_GetAudioFormatName(SDL_AudioFormat format) +{ + switch (format) { +#define CASE(X) \ + case X: return #X; + CASE(SDL_AUDIO_U8) + CASE(SDL_AUDIO_S8) + CASE(SDL_AUDIO_S16LE) + CASE(SDL_AUDIO_S16BE) + CASE(SDL_AUDIO_S32LE) + CASE(SDL_AUDIO_S32BE) + CASE(SDL_AUDIO_F32LE) + CASE(SDL_AUDIO_F32BE) +#undef CASE + default: + return "SDL_AUDIO_UNKNOWN"; + } +} + int SDL_GetSilenceValueForFormat(SDL_AudioFormat format) { return (format == SDL_AUDIO_U8) ? 0x80 : 0x00; @@ -2030,17 +2205,17 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) return; // uhoh. } - const SDL_bool iscapture = new_default_device->iscapture; + const bool recording = new_default_device->recording; // change the official default over right away, so new opens will go to the new device. SDL_LockRWLockForWriting(current_audio.device_hash_lock); - const SDL_AudioDeviceID current_devid = iscapture ? current_audio.default_capture_device_id : current_audio.default_output_device_id; - const SDL_bool is_already_default = (new_default_device->instance_id == current_devid); + const SDL_AudioDeviceID current_devid = recording ? current_audio.default_recording_device_id : current_audio.default_playback_device_id; + const bool is_already_default = (new_default_device->instance_id == current_devid); if (!is_already_default) { - if (iscapture) { - current_audio.default_capture_device_id = new_default_device->instance_id; + if (recording) { + current_audio.default_recording_device_id = new_default_device->instance_id; } else { - current_audio.default_output_device_id = new_default_device->instance_id; + current_audio.default_playback_device_id = new_default_device->instance_id; } } SDL_UnlockRWLock(current_audio.device_hash_lock); @@ -2066,18 +2241,18 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (current_default_device) { // migrate any logical devices that were opened as a default to the new physical device... - SDL_assert(current_default_device->iscapture == iscapture); + SDL_assert(current_default_device->recording == recording); // See if we have to open the new physical device, and if so, find the best audiospec for it. SDL_AudioSpec spec; - SDL_bool needs_migration = SDL_FALSE; + bool needs_migration = false; SDL_zero(spec); for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev; logdev = logdev->next) { if (logdev->opened_as_default) { - needs_migration = SDL_TRUE; + needs_migration = true; for (SDL_AudioStream *stream = logdev->bound_streams; stream; stream = stream->next_binding) { - const SDL_AudioSpec *streamspec = iscapture ? &stream->dst_spec : &stream->src_spec; + const SDL_AudioSpec *streamspec = recording ? &stream->dst_spec : &stream->src_spec; if (SDL_AUDIO_BITSIZE(streamspec->format) > SDL_AUDIO_BITSIZE(spec.format)) { spec.format = streamspec->format; } @@ -2093,13 +2268,14 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) if (needs_migration) { // New default physical device not been opened yet? Open at the OS level... - if (OpenPhysicalAudioDevice(new_default_device, &spec) == -1) { - needs_migration = SDL_FALSE; // uhoh, just leave everything on the old default, nothing to be done. + if (!OpenPhysicalAudioDevice(new_default_device, &spec)) { + needs_migration = false; // uhoh, just leave everything on the old default, nothing to be done. } } if (needs_migration) { - const SDL_bool spec_changed = !AUDIO_SPECS_EQUAL(current_default_device->spec, new_default_device->spec); + // we don't currently report channel map changes, so we'll leave them as NULL for now. + const bool spec_changed = !SDL_AudioSpecsEqual(¤t_default_device->spec, &new_default_device->spec, NULL, NULL); SDL_LogicalAudioDevice *next = NULL; for (SDL_LogicalAudioDevice *logdev = current_default_device->logical_devices; logdev; logdev = next) { next = logdev->next; @@ -2126,7 +2302,7 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) new_default_device->logical_devices = logdev; SDL_UnlockRWLock(current_audio.device_hash_lock); - SDL_assert(SDL_AtomicGet(¤t_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase... + SDL_assert(SDL_GetAtomicInt(¤t_default_device->refcount) > 1); // we should hold at least one extra reference to this device, beyond logical devices, during this phase... RefPhysicalAudioDevice(new_default_device); UnrefPhysicalAudioDevice(current_default_device); @@ -2175,42 +2351,43 @@ void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) } } -int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) +bool SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) { const int orig_work_buffer_size = device->work_buffer_size; - if (AUDIO_SPECS_EQUAL(device->spec, *newspec) && new_sample_frames == device->sample_frames) { - return 0; // we're already in that format. + // we don't currently have any place where channel maps change from under you, but we can check that if necessary later. + if (SDL_AudioSpecsEqual(&device->spec, newspec, NULL, NULL) && (new_sample_frames == device->sample_frames)) { + return true; // we're already in that format. } SDL_copyp(&device->spec, newspec); UpdateAudioStreamFormatsPhysical(device); - SDL_bool kill_device = SDL_FALSE; + bool kill_device = false; device->sample_frames = new_sample_frames; SDL_UpdatedAudioDeviceFormat(device); if (device->work_buffer && (device->work_buffer_size > orig_work_buffer_size)) { SDL_aligned_free(device->work_buffer); - device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->work_buffer = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->work_buffer) { - kill_device = SDL_TRUE; + kill_device = true; } if (device->postmix_buffer) { SDL_aligned_free(device->postmix_buffer); - device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->postmix_buffer = (float *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->postmix_buffer) { - kill_device = SDL_TRUE; + kill_device = true; } } SDL_aligned_free(device->mix_buffer); device->mix_buffer = NULL; if (device->spec.format != SDL_AUDIO_F32) { - device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), device->work_buffer_size); + device->mix_buffer = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), device->work_buffer_size); if (!device->mix_buffer) { - kill_device = SDL_TRUE; + kill_device = true; } } } @@ -2256,15 +2433,18 @@ int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL } } - return kill_device ? -1 : 0; + if (kill_device) { + return false; + } + return true; } -int SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) +bool SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames) { ObtainPhysicalAudioDeviceObj(device); - const int retval = SDL_AudioDeviceFormatChangedAlreadyLocked(device, newspec, new_sample_frames); + const bool result = SDL_AudioDeviceFormatChangedAlreadyLocked(device, newspec, new_sample_frames); ReleaseAudioDevice(device); - return retval; + return result; } // This is an internal function, so SDL_PumpEvents() can check for pending audio device events. @@ -2294,7 +2474,7 @@ void SDL_UpdateAudio(void) SDL_zero(event); event.type = i->type; event.adevice.which = (Uint32) i->devid; - event.adevice.iscapture = (i->devid & (1<<0)) ? 0 : 1; // bit #0 of devid is set for output devices and unset for capture. + event.adevice.recording = ((i->devid & (1<<0)) == 0); // bit #0 of devid is set for playback devices and unset for recording. SDL_PushEvent(&event); } SDL_free(i); diff --git a/libs/SDL3/src/audio/SDL_audio_c.h b/libs/SDL3/src/audio/SDL_audio_c.h index 95cac81aa..148489f17 100644 --- a/libs/SDL3/src/audio/SDL_audio_c.h +++ b/libs/SDL3/src/audio/SDL_audio_c.h @@ -24,4 +24,4 @@ extern void SDL_UpdateAudio(void); -#endif /* SDL_audio_c_h_ */ +#endif // SDL_audio_c_h_ diff --git a/libs/SDL3/src/audio/SDL_audio_channel_converters.h b/libs/SDL3/src/audio/SDL_audio_channel_converters.h index a005a7ee2..bee3858dc 100644 --- a/libs/SDL3/src/audio/SDL_audio_channel_converters.h +++ b/libs/SDL3/src/audio/SDL_audio_channel_converters.h @@ -1055,7 +1055,7 @@ static void SDL_Convert71To61(float *dst, const float *src, int num_frames) } -static const SDL_AudioChannelConverter channel_converters[8][8] = { /* [from][to] */ +static const SDL_AudioChannelConverter channel_converters[8][8] = { // [from][to] { NULL, SDL_ConvertMonoToStereo, SDL_ConvertMonoTo21, SDL_ConvertMonoToQuad, SDL_ConvertMonoTo41, SDL_ConvertMonoTo51, SDL_ConvertMonoTo61, SDL_ConvertMonoTo71 }, { SDL_ConvertStereoToMono, NULL, SDL_ConvertStereoTo21, SDL_ConvertStereoToQuad, SDL_ConvertStereoTo41, SDL_ConvertStereoTo51, SDL_ConvertStereoTo61, SDL_ConvertStereoTo71 }, { SDL_Convert21ToMono, SDL_Convert21ToStereo, NULL, SDL_Convert21ToQuad, SDL_Convert21To41, SDL_Convert21To51, SDL_Convert21To61, SDL_Convert21To71 }, diff --git a/libs/SDL3/src/audio/SDL_audio_resampler_filter.h b/libs/SDL3/src/audio/SDL_audio_resampler_filter.h deleted file mode 100644 index ae12a97ac..000000000 --- a/libs/SDL3/src/audio/SDL_audio_resampler_filter.h +++ /dev/null @@ -1,544 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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. -*/ - -// DO NOT EDIT, THIS FILE WAS GENERATED BY build-scripts/gen_audio_resampler_filter.c - -#define RESAMPLER_ZERO_CROSSINGS 5 -#define RESAMPLER_BITS_PER_SAMPLE 16 -#define RESAMPLER_BITS_PER_ZERO_CROSSING ((RESAMPLER_BITS_PER_SAMPLE / 2) + 1) -#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << RESAMPLER_BITS_PER_ZERO_CROSSING) -#define RESAMPLER_FILTER_SIZE (RESAMPLER_SAMPLES_PER_ZERO_CROSSING * RESAMPLER_ZERO_CROSSINGS) - -static const float ResamplerFilter[RESAMPLER_FILTER_SIZE] = { - 1.000000000f, 0.000000000f,-0.000000000f, 0.000000000f,-0.000000000f, - 0.999993165f,-0.001679888f, 0.000529080f,-0.000151513f, 0.000027455f, - 0.999972661f,-0.003351212f, 0.001055794f,-0.000302183f, 0.000054683f, - 0.999938488f,-0.005013955f, 0.001580128f,-0.000452009f, 0.000081685f, - 0.999890647f,-0.006668099f, 0.002102071f,-0.000600987f, 0.000108459f, - 0.999829139f,-0.008313629f, 0.002621611f,-0.000749115f, 0.000135007f, - 0.999753966f,-0.009950528f, 0.003138734f,-0.000896389f, 0.000161328f, - 0.999665131f,-0.011578779f, 0.003653429f,-0.001042807f, 0.000187423f, - 0.999562634f,-0.013198368f, 0.004165684f,-0.001188367f, 0.000213291f, - 0.999446480f,-0.014809279f, 0.004675488f,-0.001333066f, 0.000238933f, - 0.999316672f,-0.016411497f, 0.005182828f,-0.001476901f, 0.000264348f, - 0.999173212f,-0.018005007f, 0.005687694f,-0.001619871f, 0.000289537f, - 0.999016105f,-0.019589795f, 0.006190074f,-0.001761971f, 0.000314501f, - 0.998845356f,-0.021165846f, 0.006689957f,-0.001903201f, 0.000339239f, - 0.998660968f,-0.022733147f, 0.007187332f,-0.002043558f, 0.000363751f, - 0.998462946f,-0.024291684f, 0.007682189f,-0.002183039f, 0.000388037f, - 0.998251297f,-0.025841443f, 0.008174516f,-0.002321643f, 0.000412099f, - 0.998026026f,-0.027382413f, 0.008664303f,-0.002459367f, 0.000435935f, - 0.997787138f,-0.028914579f, 0.009151540f,-0.002596209f, 0.000459547f, - 0.997534641f,-0.030437930f, 0.009636217f,-0.002732167f, 0.000482934f, - 0.997268542f,-0.031952453f, 0.010118324f,-0.002867240f, 0.000506097f, - 0.996988847f,-0.033458137f, 0.010597850f,-0.003001425f, 0.000529036f, - 0.996695563f,-0.034954970f, 0.011074786f,-0.003134721f, 0.000551752f, - 0.996388700f,-0.036442941f, 0.011549123f,-0.003267125f, 0.000574244f, - 0.996068266f,-0.037922039f, 0.012020851f,-0.003398637f, 0.000596512f, - 0.995734268f,-0.039392253f, 0.012489961f,-0.003529253f, 0.000618558f, - 0.995386717f,-0.040853574f, 0.012956443f,-0.003658973f, 0.000640382f, - 0.995025621f,-0.042305990f, 0.013420290f,-0.003787796f, 0.000661984f, - 0.994650990f,-0.043749493f, 0.013881491f,-0.003915718f, 0.000683363f, - 0.994262835f,-0.045184072f, 0.014340039f,-0.004042740f, 0.000704522f, - 0.993861166f,-0.046609719f, 0.014795924f,-0.004168860f, 0.000725459f, - 0.993445994f,-0.048026424f, 0.015249139f,-0.004294075f, 0.000746176f, - 0.993017331f,-0.049434180f, 0.015699676f,-0.004418386f, 0.000766672f, - 0.992575187f,-0.050832978f, 0.016147525f,-0.004541790f, 0.000786949f, - 0.992119574f,-0.052222809f, 0.016592680f,-0.004664287f, 0.000807006f, - 0.991650506f,-0.053603666f, 0.017035133f,-0.004785875f, 0.000826844f, - 0.991167995f,-0.054975543f, 0.017474875f,-0.004906553f, 0.000846464f, - 0.990672054f,-0.056338431f, 0.017911900f,-0.005026320f, 0.000865865f, - 0.990162696f,-0.057692323f, 0.018346201f,-0.005145175f, 0.000885049f, - 0.989639935f,-0.059037214f, 0.018777770f,-0.005263117f, 0.000904016f, - 0.989103786f,-0.060373097f, 0.019206599f,-0.005380146f, 0.000922766f, - 0.988554262f,-0.061699966f, 0.019632684f,-0.005496260f, 0.000941300f, - 0.987991380f,-0.063017815f, 0.020056015f,-0.005611458f, 0.000959619f, - 0.987415153f,-0.064326639f, 0.020476588f,-0.005725741f, 0.000977722f, - 0.986825598f,-0.065626433f, 0.020894396f,-0.005839106f, 0.000995611f, - 0.986222730f,-0.066917192f, 0.021309432f,-0.005951554f, 0.001013285f, - 0.985606567f,-0.068198912f, 0.021721690f,-0.006063084f, 0.001030746f, - 0.984977124f,-0.069471588f, 0.022131165f,-0.006173695f, 0.001047994f, - 0.984334418f,-0.070735217f, 0.022537850f,-0.006283387f, 0.001065030f, - 0.983678468f,-0.071989794f, 0.022941741f,-0.006392159f, 0.001081853f, - 0.983009290f,-0.073235317f, 0.023342830f,-0.006500011f, 0.001098466f, - 0.982326903f,-0.074471782f, 0.023741114f,-0.006606943f, 0.001114868f, - 0.981631326f,-0.075699186f, 0.024136587f,-0.006712954f, 0.001131059f, - 0.980922577f,-0.076917527f, 0.024529243f,-0.006818044f, 0.001147042f, - 0.980200675f,-0.078126804f, 0.024919078f,-0.006922213f, 0.001162815f, - 0.979465640f,-0.079327013f, 0.025306087f,-0.007025460f, 0.001178380f, - 0.978717491f,-0.080518153f, 0.025690266f,-0.007127786f, 0.001193738f, - 0.977956250f,-0.081700223f, 0.026071609f,-0.007229191f, 0.001208889f, - 0.977181936f,-0.082873221f, 0.026450113f,-0.007329674f, 0.001223833f, - 0.976394570f,-0.084037148f, 0.026825773f,-0.007429235f, 0.001238572f, - 0.975594175f,-0.085192002f, 0.027198586f,-0.007527875f, 0.001253106f, - 0.974780770f,-0.086337783f, 0.027568547f,-0.007625593f, 0.001267436f, - 0.973954379f,-0.087474491f, 0.027935652f,-0.007722391f, 0.001281562f, - 0.973115024f,-0.088602126f, 0.028299898f,-0.007818267f, 0.001295485f, - 0.972262727f,-0.089720690f, 0.028661282f,-0.007913223f, 0.001309207f, - 0.971397512f,-0.090830182f, 0.029019799f,-0.008007258f, 0.001322726f, - 0.970519401f,-0.091930604f, 0.029375448f,-0.008100373f, 0.001336045f, - 0.969628418f,-0.093021958f, 0.029728224f,-0.008192568f, 0.001349164f, - 0.968724588f,-0.094104245f, 0.030078125f,-0.008283845f, 0.001362084f, - 0.967807935f,-0.095177467f, 0.030425148f,-0.008374202f, 0.001374806f, - 0.966878483f,-0.096241627f, 0.030769290f,-0.008463642f, 0.001387329f, - 0.965936258f,-0.097296726f, 0.031110550f,-0.008552163f, 0.001399656f, - 0.964981285f,-0.098342768f, 0.031448923f,-0.008639768f, 0.001411786f, - 0.964013590f,-0.099379756f, 0.031784409f,-0.008726456f, 0.001423721f, - 0.963033199f,-0.100407693f, 0.032117005f,-0.008812229f, 0.001435461f, - 0.962040138f,-0.101426582f, 0.032446709f,-0.008897086f, 0.001447008f, - 0.961034434f,-0.102436428f, 0.032773519f,-0.008981030f, 0.001458361f, - 0.960016114f,-0.103437235f, 0.033097434f,-0.009064060f, 0.001469522f, - 0.958985206f,-0.104429007f, 0.033418451f,-0.009146178f, 0.001480492f, - 0.957941737f,-0.105411749f, 0.033736571f,-0.009227385f, 0.001491271f, - 0.956885736f,-0.106385466f, 0.034051790f,-0.009307680f, 0.001501860f, - 0.955817231f,-0.107350163f, 0.034364109f,-0.009387067f, 0.001512261f, - 0.954736250f,-0.108305845f, 0.034673526f,-0.009465545f, 0.001522473f, - 0.953642823f,-0.109252518f, 0.034980040f,-0.009543115f, 0.001532497f, - 0.952536979f,-0.110190189f, 0.035283651f,-0.009619779f, 0.001542336f, - 0.951418748f,-0.111118864f, 0.035584357f,-0.009695538f, 0.001551988f, - 0.950288160f,-0.112038548f, 0.035882158f,-0.009770393f, 0.001561456f, - 0.949145245f,-0.112949250f, 0.036177055f,-0.009844346f, 0.001570741f, - 0.947990034f,-0.113850976f, 0.036469046f,-0.009917397f, 0.001579842f, - 0.946822559f,-0.114743733f, 0.036758132f,-0.009989548f, 0.001588761f, - 0.945642850f,-0.115627529f, 0.037044312f,-0.010060800f, 0.001597498f, - 0.944450939f,-0.116502372f, 0.037327588f,-0.010131156f, 0.001606056f, - 0.943246858f,-0.117368270f, 0.037607958f,-0.010200615f, 0.001614434f, - 0.942030639f,-0.118225231f, 0.037885424f,-0.010269180f, 0.001622633f, - 0.940802316f,-0.119073264f, 0.038159985f,-0.010336852f, 0.001630655f, - 0.939561921f,-0.119912378f, 0.038431644f,-0.010403633f, 0.001638500f, - 0.938309487f,-0.120742582f, 0.038700400f,-0.010469524f, 0.001646169f, - 0.937045048f,-0.121563886f, 0.038966254f,-0.010534527f, 0.001653663f, - 0.935768638f,-0.122376299f, 0.039229208f,-0.010598644f, 0.001660984f, - 0.934480291f,-0.123179830f, 0.039489262f,-0.010661876f, 0.001668131f, - 0.933180042f,-0.123974491f, 0.039746418f,-0.010724225f, 0.001675106f, - 0.931867925f,-0.124760291f, 0.040000678f,-0.010785693f, 0.001681910f, - 0.930543975f,-0.125537242f, 0.040252042f,-0.010846282f, 0.001688544f, - 0.929208228f,-0.126305353f, 0.040500513f,-0.010905994f, 0.001695008f, - 0.927860720f,-0.127064637f, 0.040746092f,-0.010964829f, 0.001701305f, - 0.926501487f,-0.127815104f, 0.040988782f,-0.011022792f, 0.001707433f, - 0.925130565f,-0.128556767f, 0.041228583f,-0.011079882f, 0.001713396f, - 0.923747991f,-0.129289637f, 0.041465499f,-0.011136103f, 0.001719193f, - 0.922353802f,-0.130013726f, 0.041699532f,-0.011191456f, 0.001724825f, - 0.920948034f,-0.130729047f, 0.041930683f,-0.011245944f, 0.001730294f, - 0.919530726f,-0.131435613f, 0.042158956f,-0.011299568f, 0.001735601f, - 0.918101916f,-0.132133435f, 0.042384354f,-0.011352330f, 0.001740746f, - 0.916661641f,-0.132822528f, 0.042606878f,-0.011404234f, 0.001745730f, - 0.915209940f,-0.133502905f, 0.042826532f,-0.011455280f, 0.001750555f, - 0.913746852f,-0.134174578f, 0.043043318f,-0.011505472f, 0.001755221f, - 0.912272416f,-0.134837563f, 0.043257241f,-0.011554812f, 0.001759730f, - 0.910786671f,-0.135491873f, 0.043468303f,-0.011603301f, 0.001764082f, - 0.909289657f,-0.136137522f, 0.043676506f,-0.011650942f, 0.001768278f, - 0.907781413f,-0.136774525f, 0.043881856f,-0.011697738f, 0.001772320f, - 0.906261980f,-0.137402897f, 0.044084355f,-0.011743690f, 0.001776208f, - 0.904731398f,-0.138022653f, 0.044284007f,-0.011788802f, 0.001779944f, - 0.903189708f,-0.138633807f, 0.044480816f,-0.011833076f, 0.001783528f, - 0.901636952f,-0.139236376f, 0.044674785f,-0.011876514f, 0.001786962f, - 0.900073170f,-0.139830375f, 0.044865920f,-0.011919118f, 0.001790246f, - 0.898498403f,-0.140415819f, 0.045054222f,-0.011960892f, 0.001793381f, - 0.896912695f,-0.140992726f, 0.045239698f,-0.012001838f, 0.001796369f, - 0.895316086f,-0.141561111f, 0.045422352f,-0.012041958f, 0.001799211f, - 0.893708620f,-0.142120991f, 0.045602186f,-0.012081256f, 0.001801907f, - 0.892090339f,-0.142672383f, 0.045779208f,-0.012119733f, 0.001804459f, - 0.890461286f,-0.143215304f, 0.045953420f,-0.012157393f, 0.001806868f, - 0.888821505f,-0.143749771f, 0.046124828f,-0.012194238f, 0.001809134f, - 0.887171038f,-0.144275802f, 0.046293436f,-0.012230270f, 0.001811259f, - 0.885509930f,-0.144793414f, 0.046459250f,-0.012265494f, 0.001813243f, - 0.883838224f,-0.145302625f, 0.046622274f,-0.012299911f, 0.001815089f, - 0.882155965f,-0.145803453f, 0.046782515f,-0.012333524f, 0.001816796f, - 0.880463198f,-0.146295917f, 0.046939976f,-0.012366337f, 0.001818366f, - 0.878759967f,-0.146780035f, 0.047094664f,-0.012398351f, 0.001819800f, - 0.877046317f,-0.147255826f, 0.047246583f,-0.012429571f, 0.001821099f, - 0.875322295f,-0.147723309f, 0.047395741f,-0.012459998f, 0.001822264f, - 0.873587944f,-0.148182503f, 0.047542141f,-0.012489637f, 0.001823295f, - 0.871843312f,-0.148633428f, 0.047685790f,-0.012518489f, 0.001824196f, - 0.870088444f,-0.149076103f, 0.047826695f,-0.012546558f, 0.001824965f, - 0.868323386f,-0.149510548f, 0.047964860f,-0.012573847f, 0.001825604f, - 0.866548186f,-0.149936783f, 0.048100292f,-0.012600359f, 0.001826115f, - 0.864762890f,-0.150354828f, 0.048232997f,-0.012626097f, 0.001826498f, - 0.862967545f,-0.150764704f, 0.048362981f,-0.012651064f, 0.001826754f, - 0.861162199f,-0.151166432f, 0.048490252f,-0.012675264f, 0.001826885f, - 0.859346899f,-0.151560031f, 0.048614814f,-0.012698699f, 0.001826891f, - 0.857521693f,-0.151945524f, 0.048736676f,-0.012721373f, 0.001826774f, - 0.855686629f,-0.152322931f, 0.048855842f,-0.012743288f, 0.001826534f, - 0.853841755f,-0.152692274f, 0.048972321f,-0.012764449f, 0.001826173f, - 0.851987121f,-0.153053574f, 0.049086119f,-0.012784858f, 0.001825691f, - 0.850122774f,-0.153406854f, 0.049197244f,-0.012804518f, 0.001825091f, - 0.848248764f,-0.153752135f, 0.049305701f,-0.012823434f, 0.001824372f, - 0.846365140f,-0.154089440f, 0.049411498f,-0.012841607f, 0.001823536f, - 0.844471951f,-0.154418791f, 0.049514643f,-0.012859042f, 0.001822584f, - 0.842569248f,-0.154740210f, 0.049615142f,-0.012875742f, 0.001821517f, - 0.840657079f,-0.155053721f, 0.049713003f,-0.012891710f, 0.001820336f, - 0.838735496f,-0.155359346f, 0.049808234f,-0.012906950f, 0.001819042f, - 0.836804549f,-0.155657108f, 0.049900842f,-0.012921465f, 0.001817636f, - 0.834864288f,-0.155947032f, 0.049990834f,-0.012935259f, 0.001816120f, - 0.832914765f,-0.156229140f, 0.050078219f,-0.012948334f, 0.001814493f, - 0.830956029f,-0.156503456f, 0.050163005f,-0.012960695f, 0.001812758f, - 0.828988133f,-0.156770004f, 0.050245198f,-0.012972345f, 0.001810916f, - 0.827011128f,-0.157028808f, 0.050324808f,-0.012983287f, 0.001808967f, - 0.825025066f,-0.157279893f, 0.050401842f,-0.012993525f, 0.001806912f, - 0.823029998f,-0.157523282f, 0.050476308f,-0.013003063f, 0.001804753f, - 0.821025977f,-0.157759001f, 0.050548215f,-0.013011904f, 0.001802491f, - 0.819013055f,-0.157987074f, 0.050617571f,-0.013020051f, 0.001800126f, - 0.816991284f,-0.158207526f, 0.050684384f,-0.013027509f, 0.001797660f, - 0.814960718f,-0.158420382f, 0.050748664f,-0.013034280f, 0.001795094f, - 0.812921409f,-0.158625668f, 0.050810417f,-0.013040370f, 0.001792428f, - 0.810873410f,-0.158823410f, 0.050869654f,-0.013045780f, 0.001789664f, - 0.808816775f,-0.159013631f, 0.050926382f,-0.013050515f, 0.001786804f, - 0.806751557f,-0.159196360f, 0.050980610f,-0.013054579f, 0.001783847f, - 0.804677811f,-0.159371620f, 0.051032348f,-0.013057974f, 0.001780795f, - 0.802595589f,-0.159539440f, 0.051081605f,-0.013060706f, 0.001777649f, - 0.800504946f,-0.159699844f, 0.051128389f,-0.013062778f, 0.001774411f, - 0.798405936f,-0.159852860f, 0.051172709f,-0.013064192f, 0.001771080f, - 0.796298614f,-0.159998514f, 0.051214574f,-0.013064954f, 0.001767659f, - 0.794183034f,-0.160136832f, 0.051253995f,-0.013065067f, 0.001764147f, - 0.792059252f,-0.160267843f, 0.051290979f,-0.013064535f, 0.001760547f, - 0.789927322f,-0.160391572f, 0.051325537f,-0.013063361f, 0.001756860f, - 0.787787300f,-0.160508047f, 0.051357678f,-0.013061549f, 0.001753085f, - 0.785639241f,-0.160617296f, 0.051387412f,-0.013059104f, 0.001749225f, - 0.783483200f,-0.160719346f, 0.051414747f,-0.013056029f, 0.001745280f, - 0.781319234f,-0.160814225f, 0.051439694f,-0.013052327f, 0.001741252f, - 0.779147398f,-0.160901960f, 0.051462263f,-0.013048003f, 0.001737141f, - 0.776967749f,-0.160982580f, 0.051482462f,-0.013043061f, 0.001732948f, - 0.774780342f,-0.161056113f, 0.051500303f,-0.013037504f, 0.001728675f, - 0.772585234f,-0.161122587f, 0.051515795f,-0.013031336f, 0.001724323f, - 0.770382481f,-0.161182031f, 0.051528947f,-0.013024562f, 0.001719892f, - 0.768172142f,-0.161234473f, 0.051539771f,-0.013017185f, 0.001715383f, - 0.765954271f,-0.161279942f, 0.051548275f,-0.013009209f, 0.001710798f, - 0.763728927f,-0.161318466f, 0.051554471f,-0.013000638f, 0.001706137f, - 0.761496167f,-0.161350075f, 0.051558368f,-0.012991476f, 0.001701402f, - 0.759256048f,-0.161374798f, 0.051559977f,-0.012981727f, 0.001696593f, - 0.757008627f,-0.161392665f, 0.051559309f,-0.012971395f, 0.001691712f, - 0.754753963f,-0.161403704f, 0.051556372f,-0.012960484f, 0.001686760f, - 0.752492113f,-0.161407945f, 0.051551179f,-0.012948997f, 0.001681737f, - 0.750223135f,-0.161405418f, 0.051543739f,-0.012936940f, 0.001676644f, - 0.747947088f,-0.161396153f, 0.051534064f,-0.012924315f, 0.001671483f, - 0.745664029f,-0.161380179f, 0.051522163f,-0.012911128f, 0.001666254f, - 0.743374018f,-0.161357527f, 0.051508048f,-0.012897381f, 0.001660959f, - 0.741077112f,-0.161328227f, 0.051491729f,-0.012883079f, 0.001655598f, - 0.738773370f,-0.161292309f, 0.051473217f,-0.012868227f, 0.001650173f, - 0.736462852f,-0.161249804f, 0.051452522f,-0.012852827f, 0.001644684f, - 0.734145616f,-0.161200742f, 0.051429657f,-0.012836884f, 0.001639133f, - 0.731821721f,-0.161145154f, 0.051404631f,-0.012820403f, 0.001633520f, - 0.729491227f,-0.161083070f, 0.051377457f,-0.012803386f, 0.001627846f, - 0.727154193f,-0.161014523f, 0.051348144f,-0.012785839f, 0.001622112f, - 0.724810678f,-0.160939542f, 0.051316704f,-0.012767765f, 0.001616320f, - 0.722460743f,-0.160858158f, 0.051283148f,-0.012749169f, 0.001610470f, - 0.720104446f,-0.160770404f, 0.051247488f,-0.012730054f, 0.001604563f, - 0.717741848f,-0.160676310f, 0.051209734f,-0.012710425f, 0.001598600f, - 0.715373009f,-0.160575909f, 0.051169898f,-0.012690285f, 0.001592582f, - 0.712997988f,-0.160469230f, 0.051127991f,-0.012669640f, 0.001586510f, - 0.710616847f,-0.160356307f, 0.051084025f,-0.012648492f, 0.001580385f, - 0.708229645f,-0.160237171f, 0.051038012f,-0.012626846f, 0.001574207f, - 0.705836443f,-0.160111854f, 0.050989962f,-0.012604706f, 0.001567979f, - 0.703437301f,-0.159980389f, 0.050939887f,-0.012582077f, 0.001561700f, - 0.701032280f,-0.159842806f, 0.050887799f,-0.012558961f, 0.001555372f, - 0.698621441f,-0.159699138f, 0.050833709f,-0.012535365f, 0.001548995f, - 0.696204845f,-0.159549419f, 0.050777630f,-0.012511290f, 0.001542571f, - 0.693782552f,-0.159393679f, 0.050719572f,-0.012486743f, 0.001536101f, - 0.691354624f,-0.159231952f, 0.050659547f,-0.012461726f, 0.001529584f, - 0.688921121f,-0.159064270f, 0.050597568f,-0.012436245f, 0.001523023f, - 0.686482106f,-0.158890666f, 0.050533646f,-0.012410302f, 0.001516417f, - 0.684037639f,-0.158711173f, 0.050467793f,-0.012383903f, 0.001509769f, - 0.681587783f,-0.158525823f, 0.050400021f,-0.012357051f, 0.001503079f, - 0.679132597f,-0.158334650f, 0.050330342f,-0.012329751f, 0.001496347f, - 0.676672145f,-0.158137687f, 0.050258767f,-0.012302006f, 0.001489575f, - 0.674206487f,-0.157934966f, 0.050185310f,-0.012273821f, 0.001482764f, - 0.671735685f,-0.157726522f, 0.050109981f,-0.012245200f, 0.001475914f, - 0.669259802f,-0.157512387f, 0.050032793f,-0.012216147f, 0.001469026f, - 0.666778900f,-0.157292594f, 0.049953758f,-0.012186667f, 0.001462101f, - 0.664293039f,-0.157067178f, 0.049872888f,-0.012156762f, 0.001455141f, - 0.661802283f,-0.156836172f, 0.049790195f,-0.012126439f, 0.001448145f, - 0.659306693f,-0.156599609f, 0.049705692f,-0.012095699f, 0.001441115f, - 0.656806333f,-0.156357523f, 0.049619391f,-0.012064549f, 0.001434051f, - 0.654301263f,-0.156109948f, 0.049531303f,-0.012032992f, 0.001426955f, - 0.651791546f,-0.155856918f, 0.049441442f,-0.012001031f, 0.001419827f, - 0.649277246f,-0.155598467f, 0.049349819f,-0.011968672f, 0.001412668f, - 0.646758423f,-0.155334628f, 0.049256448f,-0.011935918f, 0.001405479f, - 0.644235142f,-0.155065436f, 0.049161340f,-0.011902774f, 0.001398261f, - 0.641707464f,-0.154790925f, 0.049064507f,-0.011869243f, 0.001391015f, - 0.639175452f,-0.154511129f, 0.048965963f,-0.011835330f, 0.001383741f, - 0.636639169f,-0.154226083f, 0.048865719f,-0.011801038f, 0.001376440f, - 0.634098677f,-0.153935820f, 0.048763788f,-0.011766373f, 0.001369113f, - 0.631554040f,-0.153640376f, 0.048660183f,-0.011731337f, 0.001361761f, - 0.629005320f,-0.153339784f, 0.048554915f,-0.011695936f, 0.001354384f, - 0.626452580f,-0.153034079f, 0.048447999f,-0.011660173f, 0.001346984f, - 0.623895883f,-0.152723296f, 0.048339445f,-0.011624053f, 0.001339561f, - 0.621335293f,-0.152407470f, 0.048229267f,-0.011587579f, 0.001332116f, - 0.618770871f,-0.152086634f, 0.048117478f,-0.011550756f, 0.001324650f, - 0.616202682f,-0.151760824f, 0.048004090f,-0.011513587f, 0.001317164f, - 0.613630788f,-0.151430075f, 0.047889115f,-0.011476077f, 0.001309657f, - 0.611055252f,-0.151094421f, 0.047772566f,-0.011438230f, 0.001302132f, - 0.608476138f,-0.150753897f, 0.047654456f,-0.011400050f, 0.001294589f, - 0.605893509f,-0.150408538f, 0.047534798f,-0.011361541f, 0.001287028f, - 0.603307427f,-0.150058380f, 0.047413604f,-0.011322706f, 0.001279451f, - 0.600717957f,-0.149703457f, 0.047290887f,-0.011283552f, 0.001271857f, - 0.598125161f,-0.149343804f, 0.047166660f,-0.011244080f, 0.001264249f, - 0.595529103f,-0.148979456f, 0.047040936f,-0.011204296f, 0.001256626f, - 0.592929846f,-0.148610450f, 0.046913726f,-0.011164202f, 0.001248990f, - 0.590327454f,-0.148236818f, 0.046785045f,-0.011123805f, 0.001241340f, - 0.587721989f,-0.147858598f, 0.046654904f,-0.011083106f, 0.001233679f, - 0.585113515f,-0.147475824f, 0.046523317f,-0.011042111f, 0.001226005f, - 0.582502096f,-0.147088532f, 0.046390297f,-0.011000824f, 0.001218321f, - 0.579887795f,-0.146696757f, 0.046255856f,-0.010959248f, 0.001210627f, - 0.577270674f,-0.146300533f, 0.046120007f,-0.010917387f, 0.001202924f, - 0.574650799f,-0.145899898f, 0.045982762f,-0.010875246f, 0.001195211f, - 0.572028231f,-0.145494885f, 0.045844136f,-0.010832828f, 0.001187491f, - 0.569403034f,-0.145085532f, 0.045704140f,-0.010790137f, 0.001179764f, - 0.566775272f,-0.144671872f, 0.045562787f,-0.010747178f, 0.001172030f, - 0.564145009f,-0.144253941f, 0.045420091f,-0.010703955f, 0.001164289f, - 0.561512306f,-0.143831776f, 0.045276064f,-0.010660470f, 0.001156544f, - 0.558877229f,-0.143405412f, 0.045130719f,-0.010616729f, 0.001148794f, - 0.556239839f,-0.142974883f, 0.044984069f,-0.010572735f, 0.001141040f, - 0.553600201f,-0.142540227f, 0.044836126f,-0.010528493f, 0.001133283f, - 0.550958378f,-0.142101478f, 0.044686904f,-0.010484005f, 0.001125523f, - 0.548314433f,-0.141658672f, 0.044536416f,-0.010439276f, 0.001117761f, - 0.545668429f,-0.141211844f, 0.044384675f,-0.010394310f, 0.001109997f, - 0.543020430f,-0.140761032f, 0.044231692f,-0.010349111f, 0.001102233f, - 0.540370499f,-0.140306269f, 0.044077482f,-0.010303683f, 0.001094469f, - 0.537718699f,-0.139847592f, 0.043922057f,-0.010258029f, 0.001086705f, - 0.535065094f,-0.139385036f, 0.043765430f,-0.010212153f, 0.001078942f, - 0.532409746f,-0.138918637f, 0.043607614f,-0.010166060f, 0.001071182f, - 0.529752718f,-0.138448432f, 0.043448622f,-0.010119753f, 0.001063423f, - 0.527094075f,-0.137974455f, 0.043288466f,-0.010073235f, 0.001055668f, - 0.524433878f,-0.137496742f, 0.043127159f,-0.010026512f, 0.001047916f, - 0.521772191f,-0.137015329f, 0.042964716f,-0.009979586f, 0.001040168f, - 0.519109077f,-0.136530252f, 0.042801147f,-0.009932461f, 0.001032425f, - 0.516444599f,-0.136041547f, 0.042636467f,-0.009885141f, 0.001024687f, - 0.513778819f,-0.135549248f, 0.042470687f,-0.009837631f, 0.001016955f, - 0.511111801f,-0.135053393f, 0.042303821f,-0.009789933f, 0.001009230f, - 0.508443608f,-0.134554017f, 0.042135882f,-0.009742051f, 0.001001511f, - 0.505774302f,-0.134051154f, 0.041966883f,-0.009693990f, 0.000993800f, - 0.503103946f,-0.133544842f, 0.041796836f,-0.009645752f, 0.000986098f, - 0.500432602f,-0.133035116f, 0.041625754f,-0.009597342f, 0.000978404f, - 0.497760334f,-0.132522012f, 0.041453650f,-0.009548764f, 0.000970719f, - 0.495087203f,-0.132005564f, 0.041280536f,-0.009500020f, 0.000963044f, - 0.492413273f,-0.131485810f, 0.041106427f,-0.009451116f, 0.000955380f, - 0.489738606f,-0.130962784f, 0.040931333f,-0.009402053f, 0.000947726f, - 0.487063264f,-0.130436523f, 0.040755269f,-0.009352837f, 0.000940083f, - 0.484387309f,-0.129907061f, 0.040578247f,-0.009303470f, 0.000932453f, - 0.481710804f,-0.129374435f, 0.040400279f,-0.009253957f, 0.000924835f, - 0.479033811f,-0.128838680f, 0.040221378f,-0.009204300f, 0.000917229f, - 0.476356392f,-0.128299831f, 0.040041558f,-0.009154505f, 0.000909637f, - 0.473678610f,-0.127757925f, 0.039860830f,-0.009104573f, 0.000902059f, - 0.471000525f,-0.127212997f, 0.039679208f,-0.009054509f, 0.000894496f, - 0.468322201f,-0.126665082f, 0.039496704f,-0.009004316f, 0.000886947f, - 0.465643698f,-0.126114216f, 0.039313331f,-0.008953998f, 0.000879414f, - 0.462965079f,-0.125560435f, 0.039129101f,-0.008903558f, 0.000871896f, - 0.460286405f,-0.125003773f, 0.038944027f,-0.008853000f, 0.000864395f, - 0.457607738f,-0.124444266f, 0.038758122f,-0.008802328f, 0.000856910f, - 0.454929140f,-0.123881950f, 0.038571399f,-0.008751544f, 0.000849443f, - 0.452250671f,-0.123316860f, 0.038383869f,-0.008700653f, 0.000841994f, - 0.449572393f,-0.122749031f, 0.038195545f,-0.008649657f, 0.000834562f, - 0.446894368f,-0.122178499f, 0.038006440f,-0.008598561f, 0.000827149f, - 0.444216656f,-0.121605299f, 0.037816567f,-0.008547367f, 0.000819755f, - 0.441539319f,-0.121029465f, 0.037625937f,-0.008496080f, 0.000812381f, - 0.438862417f,-0.120451035f, 0.037434564f,-0.008444702f, 0.000805026f, - 0.436186011f,-0.119870041f, 0.037242460f,-0.008393237f, 0.000797692f, - 0.433510163f,-0.119286520f, 0.037049637f,-0.008341688f, 0.000790378f, - 0.430834932f,-0.118700507f, 0.036856108f,-0.008290058f, 0.000783086f, - 0.428160380f,-0.118112036f, 0.036661885f,-0.008238352f, 0.000775815f, - 0.425486566f,-0.117521144f, 0.036466980f,-0.008186572f, 0.000768565f, - 0.422813551f,-0.116927863f, 0.036271406f,-0.008134722f, 0.000761339f, - 0.420141396f,-0.116332231f, 0.036075174f,-0.008082804f, 0.000754135f, - 0.417470160f,-0.115734281f, 0.035878299f,-0.008030823f, 0.000746954f, - 0.414799903f,-0.115134048f, 0.035680790f,-0.007978781f, 0.000739796f, - 0.412130686f,-0.114531567f, 0.035482662f,-0.007926681f, 0.000732662f, - 0.409462568f,-0.113926872f, 0.035283926f,-0.007874528f, 0.000725553f, - 0.406795609f,-0.113320000f, 0.035084593f,-0.007822324f, 0.000718468f, - 0.404129868f,-0.112710983f, 0.034884678f,-0.007770072f, 0.000711408f, - 0.401465405f,-0.112099857f, 0.034684190f,-0.007717775f, 0.000704373f, - 0.398802279f,-0.111486655f, 0.034483143f,-0.007665437f, 0.000697364f, - 0.396140548f,-0.110871414f, 0.034281549f,-0.007613061f, 0.000690381f, - 0.393480274f,-0.110254166f, 0.034079419f,-0.007560650f, 0.000683424f, - 0.390821513f,-0.109634947f, 0.033876767f,-0.007508207f, 0.000676494f, - 0.388164325f,-0.109013790f, 0.033673602f,-0.007455735f, 0.000669590f, - 0.385508769f,-0.108390730f, 0.033469939f,-0.007403238f, 0.000662714f, - 0.382854903f,-0.107765801f, 0.033265787f,-0.007350717f, 0.000655866f, - 0.380202785f,-0.107139037f, 0.033061161f,-0.007298177f, 0.000649046f, - 0.377552474f,-0.106510472f, 0.032856070f,-0.007245621f, 0.000642253f, - 0.374904028f,-0.105880140f, 0.032650528f,-0.007193050f, 0.000635490f, - 0.372257505f,-0.105248075f, 0.032444545f,-0.007140469f, 0.000628755f, - 0.369612962f,-0.104614312f, 0.032238134f,-0.007087881f, 0.000622049f, - 0.366970458f,-0.103978882f, 0.032031306f,-0.007035287f, 0.000615373f, - 0.364330050f,-0.103341821f, 0.031824073f,-0.006982692f, 0.000608726f, - 0.361691794f,-0.102703162f, 0.031616447f,-0.006930098f, 0.000602110f, - 0.359055750f,-0.102062939f, 0.031408439f,-0.006877508f, 0.000595523f, - 0.356421972f,-0.101421184f, 0.031200061f,-0.006824926f, 0.000588967f, - 0.353790520f,-0.100777932f, 0.030991325f,-0.006772353f, 0.000582442f, - 0.351161448f,-0.100133216f, 0.030782241f,-0.006719792f, 0.000575948f, - 0.348534815f,-0.099487069f, 0.030572821f,-0.006667247f, 0.000569485f, - 0.345910675f,-0.098839524f, 0.030363078f,-0.006614721f, 0.000563054f, - 0.343289087f,-0.098190615f, 0.030153021f,-0.006562215f, 0.000556654f, - 0.340670105f,-0.097540374f, 0.029942663f,-0.006509734f, 0.000550287f, - 0.338053786f,-0.096888834f, 0.029732015f,-0.006457279f, 0.000543951f, - 0.335440186f,-0.096236029f, 0.029521089f,-0.006404853f, 0.000537649f, - 0.332829360f,-0.095581991f, 0.029309894f,-0.006352460f, 0.000531378f, - 0.330221364f,-0.094926753f, 0.029098443f,-0.006300101f, 0.000525141f, - 0.327616253f,-0.094270347f, 0.028886747f,-0.006247780f, 0.000518937f, - 0.325014082f,-0.093612807f, 0.028674817f,-0.006195500f, 0.000512766f, - 0.322414906f,-0.092954163f, 0.028462663f,-0.006143262f, 0.000506629f, - 0.319818781f,-0.092294450f, 0.028250298f,-0.006091069f, 0.000500525f, - 0.317225760f,-0.091633699f, 0.028037732f,-0.006038925f, 0.000494456f, - 0.314635898f,-0.090971943f, 0.027824976f,-0.005986831f, 0.000488420f, - 0.312049250f,-0.090309213f, 0.027612040f,-0.005934790f, 0.000482419f, - 0.309465869f,-0.089645542f, 0.027398936f,-0.005882806f, 0.000476453f, - 0.306885810f,-0.088980961f, 0.027185675f,-0.005830879f, 0.000470521f, - 0.304309126f,-0.088315503f, 0.026972268f,-0.005779014f, 0.000464623f, - 0.301735870f,-0.087649199f, 0.026758724f,-0.005727211f, 0.000458761f, - 0.299166097f,-0.086982081f, 0.026545055f,-0.005675475f, 0.000452934f, - 0.296599859f,-0.086314180f, 0.026331272f,-0.005623807f, 0.000447143f, - 0.294037209f,-0.085645528f, 0.026117385f,-0.005572209f, 0.000441387f, - 0.291478200f,-0.084976157f, 0.025903405f,-0.005520685f, 0.000435666f, - 0.288922885f,-0.084306097f, 0.025689341f,-0.005469237f, 0.000429981f, - 0.286371316f,-0.083635380f, 0.025475206f,-0.005417866f, 0.000424332f, - 0.283823545f,-0.082964036f, 0.025261008f,-0.005366575f, 0.000418720f, - 0.281279624f,-0.082292098f, 0.025046759f,-0.005315368f, 0.000413143f, - 0.278739606f,-0.081619595f, 0.024832469f,-0.005264245f, 0.000407603f, - 0.276203542f,-0.080946559f, 0.024618148f,-0.005213209f, 0.000402099f, - 0.273671482f,-0.080273020f, 0.024403807f,-0.005162263f, 0.000396632f, - 0.271143479f,-0.079599009f, 0.024189455f,-0.005111409f, 0.000391201f, - 0.268619584f,-0.078924556f, 0.023975103f,-0.005060649f, 0.000385807f, - 0.266099847f,-0.078249692f, 0.023760760f,-0.005009985f, 0.000380450f, - 0.263584318f,-0.077574447f, 0.023546438f,-0.004959420f, 0.000375130f, - 0.261073049f,-0.076898851f, 0.023332145f,-0.004908956f, 0.000369847f, - 0.258566090f,-0.076222934f, 0.023117893f,-0.004858594f, 0.000364602f, - 0.256063490f,-0.075546727f, 0.022903690f,-0.004808337f, 0.000359393f, - 0.253565299f,-0.074870258f, 0.022689547f,-0.004758188f, 0.000354222f, - 0.251071568f,-0.074193558f, 0.022475473f,-0.004708148f, 0.000349088f, - 0.248582344f,-0.073516656f, 0.022261479f,-0.004658219f, 0.000343992f, - 0.246097678f,-0.072839582f, 0.022047574f,-0.004608404f, 0.000338934f, - 0.243617618f,-0.072162365f, 0.021833767f,-0.004558704f, 0.000333913f, - 0.241142213f,-0.071485035f, 0.021620069f,-0.004509122f, 0.000328930f, - 0.238671511f,-0.070807621f, 0.021406488f,-0.004459659f, 0.000323984f, - 0.236205561f,-0.070130151f, 0.021193035f,-0.004410318f, 0.000319077f, - 0.233744411f,-0.069452655f, 0.020979718f,-0.004361100f, 0.000314207f, - 0.231288109f,-0.068775161f, 0.020766548f,-0.004312008f, 0.000309375f, - 0.228836701f,-0.068097699f, 0.020553533f,-0.004263043f, 0.000304582f, - 0.226390237f,-0.067420297f, 0.020340683f,-0.004214207f, 0.000299826f, - 0.223948762f,-0.066742982f, 0.020128008f,-0.004165503f, 0.000295108f, - 0.221512323f,-0.066065785f, 0.019915515f,-0.004116932f, 0.000290429f, - 0.219080968f,-0.065388732f, 0.019703215f,-0.004068496f, 0.000285787f, - 0.216654743f,-0.064711852f, 0.019491117f,-0.004020196f, 0.000281184f, - 0.214233694f,-0.064035173f, 0.019279229f,-0.003972036f, 0.000276619f, - 0.211817866f,-0.063358724f, 0.019067561f,-0.003924015f, 0.000272092f, - 0.209407307f,-0.062682530f, 0.018856122f,-0.003876137f, 0.000267604f, - 0.207002061f,-0.062006621f, 0.018644920f,-0.003828403f, 0.000263153f, - 0.204602173f,-0.061331024f, 0.018433965f,-0.003780814f, 0.000258741f, - 0.202207689f,-0.060655766f, 0.018223264f,-0.003733373f, 0.000254367f, - 0.199818654f,-0.059980874f, 0.018012827f,-0.003686081f, 0.000250032f, - 0.197435111f,-0.059306375f, 0.017802663f,-0.003638940f, 0.000245734f, - 0.195057107f,-0.058632298f, 0.017592780f,-0.003591951f, 0.000241475f, - 0.192684683f,-0.057958667f, 0.017383186f,-0.003545116f, 0.000237254f, - 0.190317885f,-0.057285511f, 0.017173891f,-0.003498437f, 0.000233071f, - 0.187956756f,-0.056612855f, 0.016964902f,-0.003451915f, 0.000228927f, - 0.185601339f,-0.055940727f, 0.016756228f,-0.003405553f, 0.000224821f, - 0.183251678f,-0.055269152f, 0.016547878f,-0.003359350f, 0.000220752f, - 0.180907815f,-0.054598157f, 0.016339859f,-0.003313310f, 0.000216722f, - 0.178569792f,-0.053927768f, 0.016132180f,-0.003267434f, 0.000212731f, - 0.176237654f,-0.053258011f, 0.015924850f,-0.003221722f, 0.000208777f, - 0.173911440f,-0.052588912f, 0.015717875f,-0.003176177f, 0.000204861f, - 0.171591194f,-0.051920496f, 0.015511264f,-0.003130800f, 0.000200983f, - 0.169276957f,-0.051252790f, 0.015305026f,-0.003085592f, 0.000197143f, - 0.166968771f,-0.050585817f, 0.015099168f,-0.003040555f, 0.000193341f, - 0.164666676f,-0.049919605f, 0.014893698f,-0.002995691f, 0.000189577f, - 0.162370713f,-0.049254177f, 0.014688624f,-0.002951000f, 0.000185851f, - 0.160080923f,-0.048589560f, 0.014483954f,-0.002906485f, 0.000182163f, - 0.157797346f,-0.047925777f, 0.014279695f,-0.002862145f, 0.000178512f, - 0.155520023f,-0.047262854f, 0.014075855f,-0.002817984f, 0.000174899f, - 0.153248993f,-0.046600815f, 0.013872442f,-0.002774001f, 0.000171324f, - 0.150984296f,-0.045939685f, 0.013669462f,-0.002730199f, 0.000167786f, - 0.148725971f,-0.045279488f, 0.013466925f,-0.002686579f, 0.000164285f, - 0.146474057f,-0.044620249f, 0.013264837f,-0.002643141f, 0.000160822f, - 0.144228593f,-0.043961991f, 0.013063205f,-0.002599888f, 0.000157396f, - 0.141989618f,-0.043304738f, 0.012862038f,-0.002556820f, 0.000154008f, - 0.139757169f,-0.042648514f, 0.012661341f,-0.002513938f, 0.000150656f, - 0.137531285f,-0.041993344f, 0.012461123f,-0.002471244f, 0.000147342f, - 0.135312004f,-0.041339249f, 0.012261390f,-0.002428739f, 0.000144064f, - 0.133099362f,-0.040686254f, 0.012062150f,-0.002386425f, 0.000140824f, - 0.130893398f,-0.040034383f, 0.011863409f,-0.002344301f, 0.000137620f, - 0.128694148f,-0.039383657f, 0.011665175f,-0.002302370f, 0.000134453f, - 0.126501649f,-0.038734100f, 0.011467454f,-0.002260631f, 0.000131323f, - 0.124315937f,-0.038085735f, 0.011270254f,-0.002219088f, 0.000128229f, - 0.122137048f,-0.037438584f, 0.011073581f,-0.002177740f, 0.000125171f, - 0.119965018f,-0.036792671f, 0.010877441f,-0.002136588f, 0.000122150f, - 0.117799883f,-0.036148017f, 0.010681842f,-0.002095634f, 0.000119165f, - 0.115641679f,-0.035504644f, 0.010486791f,-0.002054878f, 0.000116216f, - 0.113490439f,-0.034862575f, 0.010292293f,-0.002014322f, 0.000113304f, - 0.111346199f,-0.034221832f, 0.010098355f,-0.001973967f, 0.000110427f, - 0.109208994f,-0.033582436f, 0.009904984f,-0.001933813f, 0.000107585f, - 0.107078857f,-0.032944409f, 0.009712186f,-0.001893861f, 0.000104780f, - 0.104955823f,-0.032307773f, 0.009519967f,-0.001854112f, 0.000102010f, - 0.102839925f,-0.031672548f, 0.009328334f,-0.001814568f, 0.000099275f, - 0.100731196f,-0.031038757f, 0.009137293f,-0.001775228f, 0.000096576f, - 0.098629671f,-0.030406420f, 0.008946849f,-0.001736095f, 0.000093911f, - 0.096535380f,-0.029775558f, 0.008757010f,-0.001697168f, 0.000091282f, - 0.094448358f,-0.029146192f, 0.008567781f,-0.001658448f, 0.000088688f, - 0.092368636f,-0.028518343f, 0.008379168f,-0.001619937f, 0.000086128f, - 0.090296247f,-0.027892030f, 0.008191177f,-0.001581635f, 0.000083603f, - 0.088231221f,-0.027267275f, 0.008003813f,-0.001543542f, 0.000081113f, - 0.086173591f,-0.026644097f, 0.007817084f,-0.001505661f, 0.000078656f, - 0.084123388f,-0.026022517f, 0.007630993f,-0.001467990f, 0.000076234f, - 0.082080642f,-0.025402554f, 0.007445548f,-0.001430532f, 0.000073846f, - 0.080045384f,-0.024784228f, 0.007260753f,-0.001393286f, 0.000071492f, - 0.078017645f,-0.024167559f, 0.007076615f,-0.001356254f, 0.000069172f, - 0.075997454f,-0.023552566f, 0.006893138f,-0.001319435f, 0.000066885f, - 0.073984841f,-0.022939269f, 0.006710328f,-0.001282832f, 0.000064632f, - 0.071979836f,-0.022327686f, 0.006528191f,-0.001246443f, 0.000062412f, - 0.069982467f,-0.021717836f, 0.006346731f,-0.001210271f, 0.000060225f, - 0.067992764f,-0.021109739f, 0.006165955f,-0.001174315f, 0.000058072f, - 0.066010755f,-0.020503413f, 0.005985866f,-0.001138576f, 0.000055951f, - 0.064036468f,-0.019898876f, 0.005806472f,-0.001103055f, 0.000053862f, - 0.062069932f,-0.019296147f, 0.005627775f,-0.001067751f, 0.000051807f, - 0.060111174f,-0.018695244f, 0.005449782f,-0.001032667f, 0.000049783f, - 0.058160222f,-0.018096185f, 0.005272497f,-0.000997801f, 0.000047792f, - 0.056217102f,-0.017498988f, 0.005095926f,-0.000963156f, 0.000045833f, - 0.054281842f,-0.016903671f, 0.004920073f,-0.000928730f, 0.000043905f, - 0.052354468f,-0.016310251f, 0.004744943f,-0.000894525f, 0.000042010f, - 0.050435006f,-0.015718746f, 0.004570540f,-0.000860541f, 0.000040146f, - 0.048523483f,-0.015129173f, 0.004396870f,-0.000826779f, 0.000038313f, - 0.046619924f,-0.014541549f, 0.004223937f,-0.000793238f, 0.000036511f, - 0.044724355f,-0.013955892f, 0.004051745f,-0.000759920f, 0.000034740f, - 0.042836800f,-0.013372217f, 0.003880299f,-0.000726824f, 0.000033000f, - 0.040957285f,-0.012790543f, 0.003709604f,-0.000693951f, 0.000031291f, - 0.039085833f,-0.012210884f, 0.003539663f,-0.000661301f, 0.000029612f, - 0.037222470f,-0.011633259f, 0.003370481f,-0.000628876f, 0.000027964f, - 0.035367219f,-0.011057682f, 0.003202062f,-0.000596674f, 0.000026345f, - 0.033520103f,-0.010484170f, 0.003034411f,-0.000564696f, 0.000024756f, - 0.031681147f,-0.009912739f, 0.002867532f,-0.000532943f, 0.000023197f, - 0.029850373f,-0.009343404f, 0.002701428f,-0.000501414f, 0.000021668f, - 0.028027804f,-0.008776182f, 0.002536104f,-0.000470111f, 0.000020168f, - 0.026213462f,-0.008211087f, 0.002371564f,-0.000439032f, 0.000018697f, - 0.024407370f,-0.007648135f, 0.002207811f,-0.000408180f, 0.000017255f, - 0.022609549f,-0.007087341f, 0.002044849f,-0.000377553f, 0.000015842f, - 0.020820021f,-0.006528720f, 0.001882682f,-0.000347151f, 0.000014457f, - 0.019038808f,-0.005972286f, 0.001721315f,-0.000316976f, 0.000013101f, - 0.017265930f,-0.005418056f, 0.001560750f,-0.000287027f, 0.000011773f, - 0.015501408f,-0.004866042f, 0.001400991f,-0.000257305f, 0.000010473f, - 0.013745262f,-0.004316260f, 0.001242041f,-0.000227808f, 0.000009201f, - 0.011997513f,-0.003768723f, 0.001083905f,-0.000198539f, 0.000007956f, - 0.010258180f,-0.003223445f, 0.000926585f,-0.000169495f, 0.000006739f, - 0.008527283f,-0.002680442f, 0.000770086f,-0.000140679f, 0.000005549f, - 0.006804842f,-0.002139725f, 0.000614409f,-0.000112090f, 0.000004386f, - 0.005090874f,-0.001601309f, 0.000459559f,-0.000083727f, 0.000003250f, - 0.003385399f,-0.001065208f, 0.000305539f,-0.000055591f, 0.000002140f, - 0.001688435f,-0.000531434f, 0.000152351f,-0.000027682f, 0.000001057f, -}; - diff --git a/libs/SDL3/src/audio/SDL_audiocvt.c b/libs/SDL3/src/audio/SDL_audiocvt.c index 77dc4df23..831b36e8c 100644 --- a/libs/SDL3/src/audio/SDL_audiocvt.c +++ b/libs/SDL3/src/audio/SDL_audiocvt.c @@ -29,39 +29,6 @@ #define SDL_INT_MAX ((int)(~0u>>1)) #endif -/* - * CHANNEL LAYOUTS AS SDL EXPECTS THEM: - * - * (Even if the platform expects something else later, that - * SDL will swizzle between the app and the platform). - * - * Abbreviations: - * - FRONT=single mono speaker - * - FL=front left speaker - * - FR=front right speaker - * - FC=front center speaker - * - BL=back left speaker - * - BR=back right speaker - * - SR=surround right speaker - * - SL=surround left speaker - * - BC=back center speaker - * - LFE=low-frequency speaker - * - * These are listed in the order they are laid out in - * memory, so "FL+FR" means "the front left speaker is - * layed out in memory first, then the front right, then - * it repeats for the next audio frame". - * - * 1 channel (mono) layout: FRONT - * 2 channels (stereo) layout: FL+FR - * 3 channels (2.1) layout: FL+FR+LFE - * 4 channels (quad) layout: FL+FR+BL+BR - * 5 channels (4.1) layout: FL+FR+LFE+BL+BR - * 6 channels (5.1) layout: FL+FR+FC+LFE+BL+BR - * 7 channels (6.1) layout: FL+FR+FC+LFE+BC+SL+SR - * 8 channels (7.1) layout: FL+FR+FC+LFE+BL+BR+SL+SR - */ - #ifdef SDL_SSE3_INTRINSICS // Convert from stereo to mono. Average left and right. static void SDL_TARGETING("sse3") SDL_ConvertStereoToMono_SSE3(float *dst, const float *src, int num_frames) @@ -132,60 +99,7 @@ static void SDL_TARGETING("sse") SDL_ConvertMonoToStereo_SSE(float *dst, const f // Include the autogenerated channel converters... #include "SDL_audio_channel_converters.h" - -static void AudioConvertByteswap(void *dst, const void *src, int num_samples, int bitsize) -{ -#if DEBUG_AUDIO_CONVERT - SDL_Log("SDL_AUDIO_CONVERT: Converting %d-bit byte order", bitsize); -#endif - - switch (bitsize) { -#define CASESWAP(b) \ - case b: { \ - const Uint##b *tsrc = (const Uint##b *)src; \ - Uint##b *tdst = (Uint##b *)dst; \ - for (int i = 0; i < num_samples; i++) { \ - tdst[i] = SDL_Swap##b(tsrc[i]); \ - } \ - break; \ - } - - CASESWAP(16); - CASESWAP(32); - -#undef CASESWAP - - default: - SDL_assert(!"unhandled byteswap datatype!"); - break; - } -} - -static void AudioConvertToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt) -{ - // Endian conversion is handled separately - switch (src_fmt & ~SDL_AUDIO_MASK_BIG_ENDIAN) { - case SDL_AUDIO_S8: SDL_Convert_S8_to_F32(dst, (const Sint8 *) src, num_samples); break; - case SDL_AUDIO_U8: SDL_Convert_U8_to_F32(dst, (const Uint8 *) src, num_samples); break; - case SDL_AUDIO_S16LE: SDL_Convert_S16_to_F32(dst, (const Sint16 *) src, num_samples); break; - case SDL_AUDIO_S32LE: SDL_Convert_S32_to_F32(dst, (const Sint32 *) src, num_samples); break; - default: SDL_assert(!"Unexpected audio format!"); break; - } -} - -static void AudioConvertFromFloat(void *dst, const float *src, int num_samples, SDL_AudioFormat dst_fmt) -{ - // Endian conversion is handled separately - switch (dst_fmt & ~SDL_AUDIO_MASK_BIG_ENDIAN) { - case SDL_AUDIO_S8: SDL_Convert_F32_to_S8((Sint8 *) dst, src, num_samples); break; - case SDL_AUDIO_U8: SDL_Convert_F32_to_U8((Uint8 *) dst, src, num_samples); break; - case SDL_AUDIO_S16LE: SDL_Convert_F32_to_S16((Sint16 *) dst, src, num_samples); break; - case SDL_AUDIO_S32LE: SDL_Convert_F32_to_S32((Sint32 *) dst, src, num_samples); break; - default: SDL_assert(!"Unexpected audio format!"); break; - } -} - -static SDL_bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt) +static bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt) { switch (fmt) { case SDL_AUDIO_U8: @@ -196,20 +110,85 @@ static SDL_bool SDL_IsSupportedAudioFormat(const SDL_AudioFormat fmt) case SDL_AUDIO_S32BE: case SDL_AUDIO_F32LE: case SDL_AUDIO_F32BE: - return SDL_TRUE; // supported. + return true; // supported. default: break; } - return SDL_FALSE; // unsupported. + return false; // unsupported. } -static SDL_bool SDL_IsSupportedChannelCount(const int channels) +static bool SDL_IsSupportedChannelCount(const int channels) { return ((channels >= 1) && (channels <= 8)); } +bool SDL_ChannelMapIsBogus(const int *chmap, int channels) +{ + if (chmap) { + for (int i = 0; i < channels; i++) { + const int mapping = chmap[i]; + if ((mapping < 0) || (mapping >= channels)) { + return true; + } + } + } + return false; +} + +bool SDL_ChannelMapIsDefault(const int *chmap, int channels) +{ + if (chmap) { + for (int i = 0; i < channels; i++) { + if (chmap[i] != i) { + return false; + } + } + } + return true; +} + +// Swizzle audio channels. src and dst can be the same pointer. It does not change the buffer size. +static void SwizzleAudio(const int num_frames, void *dst, const void *src, int channels, const int *map, int bitsize) +{ + #define CHANNEL_SWIZZLE(bits) { \ + Uint##bits *tdst = (Uint##bits *) dst; /* treat as UintX; we only care about moving bits and not the type here. */ \ + const Uint##bits *tsrc = (const Uint##bits *) src; \ + if (src != dst) { /* don't need to copy to a temporary frame first. */ \ + for (int i = 0; i < num_frames; i++, tsrc += channels, tdst += channels) { \ + for (int ch = 0; ch < channels; ch++) { \ + tdst[ch] = tsrc[map[ch]]; \ + } \ + } \ + } else { \ + bool isstack; \ + Uint##bits *tmp = (Uint##bits *) SDL_small_alloc(int, channels, &isstack); /* !!! FIXME: allocate this when setting the channel map instead. */ \ + if (tmp) { \ + for (int i = 0; i < num_frames; i++, tsrc += channels, tdst += channels) { \ + for (int ch = 0; ch < channels; ch++) { \ + tmp[ch] = tsrc[map[ch]]; \ + } \ + for (int ch = 0; ch < channels; ch++) { \ + tdst[ch] = tmp[ch]; \ + } \ + } \ + SDL_small_free(tmp, isstack); \ + } \ + } \ + } + + switch (bitsize) { + case 8: CHANNEL_SWIZZLE(8); break; + case 16: CHANNEL_SWIZZLE(16); break; + case 32: CHANNEL_SWIZZLE(32); break; + // we don't currently have int64 or double audio datatypes, so no `case 64` for now. + default: SDL_assert(!"Unsupported audio datatype size"); break; + } + + #undef CHANNEL_SWIZZLE +} + // This does type and channel conversions _but not resampling_ (resampling happens in SDL_AudioStream). // This does not check parameter validity, (beyond asserts), it expects you did that already! @@ -218,8 +197,14 @@ static SDL_bool SDL_IsSupportedChannelCount(const int channels) // // The scratch buffer must be able to store `num_frames * CalculateMaxSampleFrameSize(src_format, src_channels, dst_format, dst_channels)` bytes. // If the scratch buffer is NULL, this restriction applies to the output buffer instead. -void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, int src_channels, - void *dst, SDL_AudioFormat dst_format, int dst_channels, void* scratch) +// +// Since this is a convenient point that audio goes through even if it doesn't need format conversion, +// we also handle gain adjustment here, so we don't have to make another pass over the data later. +// Strictly speaking, this is also a "conversion". :) +void ConvertAudio(int num_frames, + const void *src, SDL_AudioFormat src_format, int src_channels, const int *src_map, + void *dst, SDL_AudioFormat dst_format, int dst_channels, const int *dst_map, + void* scratch, float gain) { SDL_assert(src != NULL); SDL_assert(dst != NULL); @@ -242,11 +227,13 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i const int dst_sample_frame_size = (dst_bitsize / 8) * dst_channels; /* Type conversion goes like this now: + - swizzle through source channel map to "standard" layout. - byteswap to CPU native format first if necessary. - convert to native Float32 if necessary. - change channel count if necessary. - convert to final data format. - byteswap back to foreign format if necessary. + - swizzle through dest channel map from "standard" layout. The expectation is we can process data faster in float32 (possibly with SIMD), and making several passes over the same @@ -255,25 +242,32 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i (script-generated) custom converters for every data type and it was a bloat on SDL compile times and final library size. */ + // swizzle input to "standard" format if necessary. + if (src_map) { + void* buf = scratch ? scratch : dst; // use scratch if available, since it has to be big enough to hold src, unless it's NULL, then dst has to be. + SwizzleAudio(num_frames, buf, src, src_channels, src_map, src_bitsize); + src = buf; + } + // see if we can skip float conversion entirely. - if (src_channels == dst_channels) { + if ((src_channels == dst_channels) && (gain == 1.0f)) { if (src_format == dst_format) { // nothing to do, we're already in the right format, just copy it over if necessary. - if (src != dst) { + if (dst_map) { + SwizzleAudio(num_frames, dst, src, dst_channels, dst_map, dst_bitsize); + } else if (src != dst) { SDL_memcpy(dst, src, num_frames * dst_sample_frame_size); } return; } // just a byteswap needed? - if ((src_format & ~SDL_AUDIO_MASK_BIG_ENDIAN) == (dst_format & ~SDL_AUDIO_MASK_BIG_ENDIAN)) { - if (src_bitsize == 8) { - if (src != dst) { - SDL_memcpy(dst, src, num_frames * dst_sample_frame_size); - } - return; // nothing to do, it's a 1-byte format. + if ((src_format ^ dst_format) == SDL_AUDIO_MASK_BIG_ENDIAN) { + if (dst_map) { // do this first, in case we duplicate channels, we can avoid an extra copy if src != dst. + SwizzleAudio(num_frames, dst, src, dst_channels, dst_map, dst_bitsize); + src = dst; } - AudioConvertByteswap(dst, src, num_frames * src_channels, src_bitsize); + ConvertAudioSwapEndian(dst, src, num_frames * dst_channels, dst_bitsize); return; // all done. } } @@ -282,23 +276,31 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i scratch = dst; } - const SDL_bool srcbyteswap = (SDL_AUDIO_ISBIGENDIAN(src_format) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && (src_bitsize > 8); - const SDL_bool srcconvert = !SDL_AUDIO_ISFLOAT(src_format); - const SDL_bool channelconvert = src_channels != dst_channels; - const SDL_bool dstconvert = !SDL_AUDIO_ISFLOAT(dst_format); - const SDL_bool dstbyteswap = (SDL_AUDIO_ISBIGENDIAN(dst_format) != 0) == (SDL_BYTEORDER == SDL_LIL_ENDIAN) && (dst_bitsize > 8); - - // make sure we're in native byte order. - if (srcbyteswap) { - // No point writing straight to dst. If we only need a byteswap, we wouldn't be bere. - AudioConvertByteswap(scratch, src, num_frames * src_channels, src_bitsize); - src = scratch; - } + const bool srcconvert = src_format != SDL_AUDIO_F32; + const bool channelconvert = src_channels != dst_channels; + const bool dstconvert = dst_format != SDL_AUDIO_F32; // get us to float format. if (srcconvert) { - void* buf = (channelconvert || dstconvert || dstbyteswap) ? scratch : dst; - AudioConvertToFloat((float *) buf, src, num_frames * src_channels, src_format); + void* buf = (channelconvert || dstconvert) ? scratch : dst; + ConvertAudioToFloat((float *) buf, src, num_frames * src_channels, src_format); + src = buf; + } + + // Gain adjustment + if (gain != 1.0f) { + float *buf = (float *)(dstconvert ? scratch : dst); + const int total_samples = num_frames * src_channels; + if (src == buf) { + for (int i = 0; i < total_samples; i++) { + buf[i] *= gain; + } + } else { + float *fsrc = (float *)src; + for (int i = 0; i < total_samples; i++) { + buf[i] = fsrc[i] * gain; + } + } src = buf; } @@ -330,7 +332,7 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i channel_converter = override; } - void* buf = (dstconvert || dstbyteswap) ? scratch : dst; + void* buf = dstconvert ? scratch : dst; channel_converter((float *) buf, (const float *) src, num_frames); src = buf; } @@ -339,17 +341,15 @@ void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, i // Move to final data type. if (dstconvert) { - AudioConvertFromFloat(dst, (const float *) src, num_frames * dst_channels, dst_format); + ConvertAudioFromFloat(dst, (const float *) src, num_frames * dst_channels, dst_format); src = dst; } - // make sure we're in final byte order. - if (dstbyteswap) { - AudioConvertByteswap(dst, src, num_frames * dst_channels, dst_bitsize); - src = dst; // we've written to dst, future work will convert in-place. - } - SDL_assert(src == dst); // if we got here, we _had_ to have done _something_. Otherwise, we should have memcpy'd! + + if (dst_map) { + SwizzleAudio(num_frames, dst, src, dst_channels, dst_map, dst_bitsize); + } } // Calculate the largest frame size needed to convert between the two formats. @@ -377,29 +377,27 @@ static Sint64 GetAudioStreamResampleRate(SDL_AudioStream* stream, int src_freq, return resample_rate; } -static int UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSpec *spec) +static bool UpdateAudioStreamInputSpec(SDL_AudioStream *stream, const SDL_AudioSpec *spec, const int *chmap) { - if (AUDIO_SPECS_EQUAL(stream->input_spec, *spec)) { - return 0; + if (SDL_AudioSpecsEqual(&stream->input_spec, spec, stream->input_chmap, chmap)) { + return true; } - const size_t history_buffer_allocation = SDL_GetResamplerHistoryFrames() * SDL_AUDIO_FRAMESIZE(*spec); - Uint8 *history_buffer = stream->history_buffer; + if (!SDL_ResetAudioQueueHistory(stream->queue, SDL_GetResamplerHistoryFrames())) { + return false; + } - if (stream->history_buffer_allocation < history_buffer_allocation) { - history_buffer = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), history_buffer_allocation); - if (!history_buffer) { - return -1; - } - SDL_aligned_free(stream->history_buffer); - stream->history_buffer = history_buffer; - stream->history_buffer_allocation = history_buffer_allocation; + if (!chmap) { + stream->input_chmap = NULL; + } else { + const size_t chmaplen = sizeof (*chmap) * spec->channels; + stream->input_chmap = stream->input_chmap_storage; + SDL_memcpy(stream->input_chmap, chmap, chmaplen); } - SDL_memset(history_buffer, SDL_GetSilenceValueForFormat(spec->format), history_buffer_allocation); SDL_copyp(&stream->input_spec, spec); - return 0; + return true; } SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec) @@ -407,34 +405,35 @@ SDL_AudioStream *SDL_CreateAudioStream(const SDL_AudioSpec *src_spec, const SDL_ SDL_ChooseAudioConverters(); SDL_SetupAudioResampler(); - SDL_AudioStream *retval = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream)); - if (!retval) { + SDL_AudioStream *result = (SDL_AudioStream *)SDL_calloc(1, sizeof(SDL_AudioStream)); + if (!result) { return NULL; } - retval->freq_ratio = 1.0f; - retval->queue = SDL_CreateAudioQueue(4096); + result->freq_ratio = 1.0f; + result->gain = 1.0f; + result->queue = SDL_CreateAudioQueue(8192); - if (!retval->queue) { - SDL_free(retval); + if (!result->queue) { + SDL_free(result); return NULL; } - retval->lock = SDL_CreateMutex(); - if (!retval->lock) { - SDL_free(retval->queue); - SDL_free(retval); + result->lock = SDL_CreateMutex(); + if (!result->lock) { + SDL_free(result->queue); + SDL_free(result); return NULL; } - OnAudioStreamCreated(retval); + OnAudioStreamCreated(result); - if (SDL_SetAudioStreamFormat(retval, src_spec, dst_spec) == -1) { - SDL_DestroyAudioStream(retval); + if (!SDL_SetAudioStreamFormat(result, src_spec, dst_spec)) { + SDL_DestroyAudioStream(result); return NULL; } - return retval; + return result; } SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream) @@ -449,7 +448,7 @@ SDL_PropertiesID SDL_GetAudioStreamProperties(SDL_AudioStream *stream) return stream->props; } -int SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata) +bool SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -458,10 +457,10 @@ int SDL_SetAudioStreamGetCallback(SDL_AudioStream *stream, SDL_AudioStreamCallba stream->get_callback = callback; stream->get_callback_userdata = userdata; SDL_UnlockMutex(stream->lock); - return 0; + return true; } -int SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata) +bool SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallback callback, void *userdata) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -470,28 +469,28 @@ int SDL_SetAudioStreamPutCallback(SDL_AudioStream *stream, SDL_AudioStreamCallba stream->put_callback = callback; stream->put_callback_userdata = userdata; SDL_UnlockMutex(stream->lock); - return 0; + return true; } -int SDL_LockAudioStream(SDL_AudioStream *stream) +bool SDL_LockAudioStream(SDL_AudioStream *stream) { if (!stream) { return SDL_InvalidParamError("stream"); } SDL_LockMutex(stream->lock); - return 0; + return true; } -int SDL_UnlockAudioStream(SDL_AudioStream *stream) +bool SDL_UnlockAudioStream(SDL_AudioStream *stream) { if (!stream) { return SDL_InvalidParamError("stream"); } SDL_UnlockMutex(stream->lock); - return 0; + return true; } -int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec) +bool SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, SDL_AudioSpec *dst_spec) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -512,10 +511,10 @@ int SDL_GetAudioStreamFormat(SDL_AudioStream *stream, SDL_AudioSpec *src_spec, S return SDL_SetError("Stream has no destination format"); } - return 0; + return true; } -int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec) +bool SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_spec, const SDL_AudioSpec *dst_spec) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -557,24 +556,120 @@ int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_s // quietly refuse to change the format of the end currently bound to a device. if (stream->bound_device) { - if (stream->bound_device->physical_device->iscapture) { - dst_spec = NULL; - } else { + if (stream->bound_device->physical_device->recording) { src_spec = NULL; + } else { + dst_spec = NULL; } } if (src_spec) { + if (src_spec->channels != stream->src_spec.channels) { + SDL_free(stream->src_chmap); + stream->src_chmap = NULL; + } SDL_copyp(&stream->src_spec, src_spec); } if (dst_spec) { + if (dst_spec->channels != stream->dst_spec.channels) { + SDL_free(stream->dst_chmap); + stream->dst_chmap = NULL; + } SDL_copyp(&stream->dst_spec, dst_spec); } SDL_UnlockMutex(stream->lock); - return 0; + return true; +} + +bool SetAudioStreamChannelMap(SDL_AudioStream *stream, const SDL_AudioSpec *spec, int **stream_chmap, const int *chmap, int channels, int isinput) +{ + if (!stream) { + return SDL_InvalidParamError("stream"); + } + + bool result = true; + + SDL_LockMutex(stream->lock); + + if (channels != spec->channels) { + result = SDL_SetError("Wrong number of channels"); + } else if (!*stream_chmap && !chmap) { + // already at default, we're good. + } else if (*stream_chmap && chmap && (SDL_memcmp(*stream_chmap, chmap, sizeof (*chmap) * channels) == 0)) { + // already have this map, don't allocate/copy it again. + } else if (SDL_ChannelMapIsBogus(chmap, channels)) { + result = SDL_SetError("Invalid channel mapping"); + } else if ((isinput != -1) && stream->bound_device && (!!isinput == !!stream->bound_device->physical_device->recording)) { + // quietly refuse to change the format of the end currently bound to a device. + } else { + if (SDL_ChannelMapIsDefault(chmap, channels)) { + chmap = NULL; // just apply a default mapping. + } + if (chmap) { + int *dupmap = SDL_ChannelMapDup(chmap, channels); + if (!dupmap) { + result = SDL_SetError("Invalid channel mapping"); + } else { + SDL_free(*stream_chmap); + *stream_chmap = dupmap; + } + } else { + SDL_free(*stream_chmap); + *stream_chmap = NULL; + } + } + + SDL_UnlockMutex(stream->lock); + return result; +} + +bool SDL_SetAudioStreamInputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels) +{ + return SetAudioStreamChannelMap(stream, &stream->src_spec, &stream->src_chmap, chmap, channels, true); +} + +bool SDL_SetAudioStreamOutputChannelMap(SDL_AudioStream *stream, const int *chmap, int channels) +{ + return SetAudioStreamChannelMap(stream, &stream->dst_spec, &stream->dst_chmap, chmap, channels, false); +} + +int *SDL_GetAudioStreamInputChannelMap(SDL_AudioStream *stream, int *count) +{ + int *result = NULL; + int channels = 0; + if (stream) { + SDL_LockMutex(stream->lock); + channels = stream->src_spec.channels; + result = SDL_ChannelMapDup(stream->src_chmap, channels); + SDL_UnlockMutex(stream->lock); + } + + if (count) { + *count = channels; + } + + return result; +} + +int *SDL_GetAudioStreamOutputChannelMap(SDL_AudioStream *stream, int *count) +{ + int *result = NULL; + int channels = 0; + if (stream) { + SDL_LockMutex(stream->lock); + channels = stream->dst_spec.channels; + result = SDL_ChannelMapDup(stream->dst_chmap, channels); + SDL_UnlockMutex(stream->lock); + } + + if (count) { + *count = channels; + } + + return result; } float SDL_GetAudioStreamFrequencyRatio(SDL_AudioStream *stream) @@ -591,7 +686,7 @@ float SDL_GetAudioStreamFrequencyRatio(SDL_AudioStream *stream) return freq_ratio; } -int SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio) +bool SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -611,10 +706,39 @@ int SDL_SetAudioStreamFrequencyRatio(SDL_AudioStream *stream, float freq_ratio) stream->freq_ratio = freq_ratio; SDL_UnlockMutex(stream->lock); - return 0; + return true; } -static int CheckAudioStreamIsFullySetup(SDL_AudioStream *stream) +float SDL_GetAudioStreamGain(SDL_AudioStream *stream) +{ + if (!stream) { + SDL_InvalidParamError("stream"); + return -1.0f; + } + + SDL_LockMutex(stream->lock); + const float gain = stream->gain; + SDL_UnlockMutex(stream->lock); + + return gain; +} + +bool SDL_SetAudioStreamGain(SDL_AudioStream *stream, float gain) +{ + if (!stream) { + return SDL_InvalidParamError("stream"); + } else if (gain < 0.0f) { + return SDL_InvalidParamError("gain"); + } + + SDL_LockMutex(stream->lock); + stream->gain = gain; + SDL_UnlockMutex(stream->lock); + + return true; +} + +static bool CheckAudioStreamIsFullySetup(SDL_AudioStream *stream) { if (stream->src_spec.format == 0) { return SDL_SetError("Stream has no source format"); @@ -622,30 +746,20 @@ static int CheckAudioStreamIsFullySetup(SDL_AudioStream *stream) return SDL_SetError("Stream has no destination format"); } - return 0; + return true; } -int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) +static bool PutAudioStreamBuffer(SDL_AudioStream *stream, const void *buf, int len, SDL_ReleaseAudioBufferCallback callback, void* userdata) { #if DEBUG_AUDIOSTREAM SDL_Log("AUDIOSTREAM: wants to put %d bytes", len); #endif - if (!stream) { - return SDL_InvalidParamError("stream"); - } else if (!buf) { - return SDL_InvalidParamError("buf"); - } else if (len < 0) { - return SDL_InvalidParamError("len"); - } else if (len == 0) { - return 0; // nothing to do. - } - SDL_LockMutex(stream->lock); - if (CheckAudioStreamIsFullySetup(stream) != 0) { + if (!CheckAudioStreamIsFullySetup(stream)) { SDL_UnlockMutex(stream->lock); - return -1; + return false; } if ((len % SDL_AUDIO_FRAMESIZE(stream->src_spec)) != 0) { @@ -655,38 +769,26 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) SDL_AudioTrack* track = NULL; - // When copying in large amounts of data, try and do as much work as possible - // outside of the stream lock, otherwise the output device is likely to be starved. - const int large_input_thresh = 1024 * 1024; - - if (len >= large_input_thresh) { - SDL_AudioSpec src_spec; - SDL_copyp(&src_spec, &stream->src_spec); - - SDL_UnlockMutex(stream->lock); - - size_t chunk_size = SDL_GetAudioQueueChunkSize(stream->queue); - track = SDL_CreateChunkedAudioTrack(&src_spec, (const Uint8 *)buf, len, chunk_size); + if (callback) { + track = SDL_CreateAudioTrack(stream->queue, &stream->src_spec, stream->src_chmap, (Uint8 *)buf, len, len, callback, userdata); if (!track) { - return -1; + SDL_UnlockMutex(stream->lock); + return false; } - - SDL_LockMutex(stream->lock); } const int prev_available = stream->put_callback ? SDL_GetAudioStreamAvailable(stream) : 0; - int retval = 0; + bool result = true; if (track) { SDL_AddTrackToAudioQueue(stream->queue, track); } else { - retval = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, (const Uint8 *)buf, len); + result = SDL_WriteToAudioQueue(stream->queue, &stream->src_spec, stream->src_chmap, (const Uint8 *)buf, len); } - if (retval == 0) { - stream->total_bytes_queued += len; + if (result) { if (stream->put_callback) { const int newavail = SDL_GetAudioStreamAvailable(stream) - prev_available; stream->put_callback(stream->put_callback_userdata, stream, newavail, newavail); @@ -695,10 +797,51 @@ int SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) SDL_UnlockMutex(stream->lock); - return retval; + return result; +} + +static void SDLCALL FreeAllocatedAudioBuffer(void *userdata, const void *buf, int len) +{ + SDL_free((void*) buf); +} + +bool SDL_PutAudioStreamData(SDL_AudioStream *stream, const void *buf, int len) +{ + if (!stream) { + return SDL_InvalidParamError("stream"); + } else if (!buf) { + return SDL_InvalidParamError("buf"); + } else if (len < 0) { + return SDL_InvalidParamError("len"); + } else if (len == 0) { + return true; // nothing to do. + } + + // When copying in large amounts of data, try and do as much work as possible + // outside of the stream lock, otherwise the output device is likely to be starved. + const int large_input_thresh = 64 * 1024; + + if (len >= large_input_thresh) { + void *data = SDL_malloc(len); + + if (!data) { + return false; + } + + SDL_memcpy(data, buf, len); + buf = data; + + bool ret = PutAudioStreamBuffer(stream, buf, len, FreeAllocatedAudioBuffer, NULL); + if (!ret) { + SDL_free(data); + } + return ret; + } + + return PutAudioStreamBuffer(stream, buf, len, NULL, NULL); } -int SDL_FlushAudioStream(SDL_AudioStream *stream) +bool SDL_FlushAudioStream(SDL_AudioStream *stream) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -708,7 +851,7 @@ int SDL_FlushAudioStream(SDL_AudioStream *stream) SDL_FlushAudioQueue(stream->queue); SDL_UnlockMutex(stream->lock); - return 0; + return true; } /* this does not save the previous contents of stream->work_buffer. It's a work buffer!! @@ -719,7 +862,7 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne return stream->work_buffer; } - Uint8 *ptr = (Uint8 *) SDL_aligned_alloc(SDL_SIMDGetAlignment(), newlen); + Uint8 *ptr = (Uint8 *) SDL_aligned_alloc(SDL_GetSIMDAlignment(), newlen); if (!ptr) { return NULL; // previous work buffer is still valid! } @@ -730,48 +873,28 @@ static Uint8 *EnsureAudioStreamWorkBufferSize(SDL_AudioStream *stream, size_t ne return ptr; } -static void UpdateAudioStreamHistoryBuffer(SDL_AudioStream* stream, - Uint8* input_buffer, int input_bytes, Uint8* left_padding, int padding_bytes) -{ - const int history_buffer_frames = SDL_GetResamplerHistoryFrames(); - - // Even if we aren't currently resampling, we always need to update the history buffer - Uint8 *history_buffer = stream->history_buffer; - int history_bytes = history_buffer_frames * SDL_AUDIO_FRAMESIZE(stream->input_spec); - - if (left_padding) { - // Fill in the left padding using the history buffer - SDL_assert(padding_bytes <= history_bytes); - SDL_memcpy(left_padding, history_buffer + history_bytes - padding_bytes, padding_bytes); - } - - // Update the history buffer using the new input data - if (input_bytes >= history_bytes) { - SDL_memcpy(history_buffer, input_buffer + (input_bytes - history_bytes), history_bytes); - } else { - int preserve_bytes = history_bytes - input_bytes; - SDL_memmove(history_buffer, history_buffer + input_bytes, preserve_bytes); - SDL_memcpy(history_buffer + preserve_bytes, input_buffer, input_bytes); - } -} - static Sint64 NextAudioStreamIter(SDL_AudioStream* stream, void** inout_iter, - Sint64* inout_resample_offset, SDL_AudioSpec* out_spec, SDL_bool* out_flushed) + Sint64* inout_resample_offset, SDL_AudioSpec* out_spec, int **out_chmap, bool* out_flushed) { SDL_AudioSpec spec; - SDL_bool flushed; - size_t queued_bytes = SDL_NextAudioQueueIter(stream->queue, inout_iter, &spec, &flushed); + bool flushed; + int *chmap; + size_t queued_bytes = SDL_NextAudioQueueIter(stream->queue, inout_iter, &spec, &chmap, &flushed); if (out_spec) { SDL_copyp(out_spec, &spec); } + if (out_chmap) { + *out_chmap = chmap; + } + // There is infinite audio available, whether or not we are resampling if (queued_bytes == SDL_SIZE_MAX) { *inout_resample_offset = 0; if (out_flushed) { - *out_flushed = SDL_FALSE; + *out_flushed = false; } return SDL_MAX_SINT32; @@ -813,7 +936,7 @@ static Sint64 GetAudioStreamAvailableFrames(SDL_AudioStream* stream, Sint64* out Sint64 output_frames = 0; while (iter) { - output_frames += NextAudioStreamIter(stream, &iter, &resample_offset, NULL, NULL); + output_frames += NextAudioStreamIter(stream, &iter, &resample_offset, NULL, NULL, NULL); // Already got loads of frames. Just clamp it to something reasonable if (output_frames >= SDL_MAX_SINT32) { @@ -829,33 +952,33 @@ static Sint64 GetAudioStreamAvailableFrames(SDL_AudioStream* stream, Sint64* out return output_frames; } -static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spec, SDL_bool* out_flushed) +static Sint64 GetAudioStreamHead(SDL_AudioStream* stream, SDL_AudioSpec* out_spec, int **out_chmap, bool* out_flushed) { void* iter = SDL_BeginAudioQueueIter(stream->queue); if (!iter) { SDL_zerop(out_spec); - *out_flushed = SDL_FALSE; + *out_flushed = false; return 0; } Sint64 resample_offset = stream->resample_offset; - return NextAudioStreamIter(stream, &iter, &resample_offset, out_spec, out_flushed); + return NextAudioStreamIter(stream, &iter, &resample_offset, out_spec, out_chmap, out_flushed); } // You must hold stream->lock and validate your parameters before calling this! // Enough input data MUST be available! -static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int output_frames) +static bool GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int output_frames, float gain) { const SDL_AudioSpec* src_spec = &stream->input_spec; const SDL_AudioSpec* dst_spec = &stream->dst_spec; const SDL_AudioFormat src_format = src_spec->format; const int src_channels = src_spec->channels; - const int src_frame_size = SDL_AUDIO_FRAMESIZE(*src_spec); const SDL_AudioFormat dst_format = dst_spec->format; const int dst_channels = dst_spec->channels; + const int *dst_map = stream->dst_chmap; const int max_frame_size = CalculateMaxFrameSize(src_format, src_channels, dst_format, dst_channels); const Sint64 resample_rate = GetAudioStreamResampleRate(stream, src_spec->freq, stream->resample_offset); @@ -868,48 +991,34 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou // Not resampling? It's an easy conversion (and maybe not even that!) if (resample_rate == 0) { - Uint8* input_buffer = NULL; + Uint8* work_buffer = NULL; - // If no conversion is happening, read straight into the output buffer. - // Note, this is just to avoid extra copies. - // Some other formats may fit directly into the output buffer, but i'd rather process data in a SIMD-aligned buffer. - if ((src_format == dst_format) && (src_channels == dst_channels)) { - input_buffer = (Uint8 *)buf; - } else { - input_buffer = EnsureAudioStreamWorkBufferSize(stream, output_frames * max_frame_size); + // Ensure we have enough scratch space for any conversions + if ((src_format != dst_format) || (src_channels != dst_channels)) { + work_buffer = EnsureAudioStreamWorkBufferSize(stream, output_frames * max_frame_size); - if (!input_buffer) { - return -1; + if (!work_buffer) { + return false; } } - const int input_bytes = output_frames * src_frame_size; - if (SDL_ReadFromAudioQueue(stream->queue, input_buffer, input_bytes) != 0) { - SDL_assert(!"Not enough data in queue (read)"); - } - - stream->total_bytes_queued -= input_bytes; - - // Even if we aren't currently resampling, we always need to update the history buffer - UpdateAudioStreamHistoryBuffer(stream, input_buffer, input_bytes, NULL, 0); - - // Convert the data, if necessary - if (buf != input_buffer) { - ConvertAudio(output_frames, input_buffer, src_format, src_channels, buf, dst_format, dst_channels, input_buffer); + if (SDL_ReadFromAudioQueue(stream->queue, (Uint8 *)buf, dst_format, dst_channels, dst_map, 0, output_frames, 0, work_buffer, gain) != buf) { + return SDL_SetError("Not enough data in queue"); } - return 0; + return true; } // Time to do some resampling! // Calculate the number of input frames necessary for this request. // Because resampling happens "between" frames, The same number of output_frames // can require a different number of input_frames, depending on the resample_offset. - // Infact, input_frames can sometimes even be zero when upsampling. + // In fact, input_frames can sometimes even be zero when upsampling. const int input_frames = (int) SDL_GetResamplerInputFrames(output_frames, resample_rate, stream->resample_offset); - const int input_bytes = input_frames * src_frame_size; - const int resampler_padding_frames = SDL_GetResamplerPaddingFrames(resample_rate); + const int padding_frames = SDL_GetResamplerPaddingFrames(resample_rate); + + const SDL_AudioFormat resample_format = SDL_AUDIO_F32; // If increasing channels, do it after resampling, since we'd just // do more work to resample duplicate channels. If we're decreasing, do @@ -918,7 +1027,7 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou const int resample_channels = SDL_min(src_channels, dst_channels); // The size of the frame used when resampling - const int resample_frame_size = resample_channels * sizeof(float); + const int resample_frame_size = SDL_AUDIO_BYTESIZE(resample_format) * resample_channels; // The main portion of the work_buffer can be used to store 3 things: // src_sample_frame_size * (left_padding+input_buffer+right_padding) @@ -929,20 +1038,20 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou // resample_frame_size * output_frames // // Note, ConvertAudio requires (num_frames * max_sample_frame_size) of scratch space - const int work_buffer_frames = input_frames + (resampler_padding_frames * 2); + const int work_buffer_frames = input_frames + (padding_frames * 2); int work_buffer_capacity = work_buffer_frames * max_frame_size; int resample_buffer_offset = -1; // Check if we can resample directly into the output buffer. // Note, this is just to avoid extra copies. // Some other formats may fit directly into the output buffer, but i'd rather process data in a SIMD-aligned buffer. - if ((dst_format != SDL_AUDIO_F32) || (dst_channels != resample_channels)) { + if ((dst_format != resample_format) || (dst_channels != resample_channels)) { // Allocate space for converting the resampled output to the destination format int resample_convert_bytes = output_frames * max_frame_size; work_buffer_capacity = SDL_max(work_buffer_capacity, resample_convert_bytes); // SIMD-align the buffer - int simd_alignment = (int) SDL_SIMDGetAlignment(); + int simd_alignment = (int) SDL_GetSIMDAlignment(); work_buffer_capacity += simd_alignment - 1; work_buffer_capacity -= work_buffer_capacity % simd_alignment; @@ -955,48 +1064,24 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou Uint8* work_buffer = EnsureAudioStreamWorkBufferSize(stream, work_buffer_capacity); if (!work_buffer) { - return -1; + return false; } - const int padding_bytes = resampler_padding_frames * src_frame_size; - - Uint8* work_buffer_tail = work_buffer; - - // Split the work_buffer into [left_padding][input_buffer][right_padding] - Uint8* left_padding = work_buffer_tail; - work_buffer_tail += padding_bytes; - - Uint8* input_buffer = work_buffer_tail; - work_buffer_tail += input_bytes; - - Uint8* right_padding = work_buffer_tail; - work_buffer_tail += padding_bytes; - - SDL_assert((work_buffer_tail - work_buffer) <= work_buffer_capacity); - - // Now read unconverted data from the queue into the work buffer to fulfill the request. - if (SDL_ReadFromAudioQueue(stream->queue, input_buffer, input_bytes) != 0) { - SDL_assert(!"Not enough data in queue (resample read)"); - } - stream->total_bytes_queued -= input_bytes; + // adjust gain either before resampling or after, depending on which point has less + // samples to process. + const float preresample_gain = (input_frames > output_frames) ? 1.0f : gain; + const float postresample_gain = (input_frames > output_frames) ? gain : 1.0f; - // Update the history buffer and fill in the left padding - UpdateAudioStreamHistoryBuffer(stream, input_buffer, input_bytes, left_padding, padding_bytes); + // (dst channel map is NULL because we'll do the final swizzle on ConvertAudio after resample.) + const Uint8* input_buffer = SDL_ReadFromAudioQueue(stream->queue, + NULL, resample_format, resample_channels, NULL, + padding_frames, input_frames, padding_frames, work_buffer, preresample_gain); - // Fill in the right padding by peeking into the input queue (missing data is filled with silence) - if (SDL_PeekIntoAudioQueue(stream->queue, right_padding, padding_bytes) != 0) { - SDL_assert(!"Not enough data in queue (resample peek)"); + if (!input_buffer) { + return SDL_SetError("Not enough data in queue (resample)"); } - SDL_assert(work_buffer_frames == input_frames + (resampler_padding_frames * 2)); - - // Resampling! get the work buffer to float32 format, etc, in-place. - ConvertAudio(work_buffer_frames, work_buffer, src_format, src_channels, work_buffer, SDL_AUDIO_F32, resample_channels, NULL); - - // Update the work_buffer pointers based on the new frame size - input_buffer = work_buffer + ((input_buffer - work_buffer) / src_frame_size * resample_frame_size); - work_buffer_tail = work_buffer + ((work_buffer_tail - work_buffer) / src_frame_size * resample_frame_size); - SDL_assert((work_buffer_tail - work_buffer) <= work_buffer_capacity); + input_buffer += padding_frames * resample_frame_size; // Decide where the resampled output goes void* resample_buffer = (resample_buffer_offset != -1) ? (work_buffer + resample_buffer_offset) : buf; @@ -1006,16 +1091,14 @@ static int GetAudioStreamDataInternal(SDL_AudioStream *stream, void *buf, int ou (float*) resample_buffer, output_frames, resample_rate, &stream->resample_offset); - // Convert to the final format, if necessary - if (buf != resample_buffer) { - ConvertAudio(output_frames, resample_buffer, SDL_AUDIO_F32, resample_channels, buf, dst_format, dst_channels, work_buffer); - } + // Convert to the final format, if necessary (src channel map is NULL because SDL_ReadFromAudioQueue already handled this). + ConvertAudio(output_frames, resample_buffer, resample_format, resample_channels, NULL, buf, dst_format, dst_channels, dst_map, work_buffer, postresample_gain); - return 0; + return true; } // get converted/resampled data from the stream -int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) +int SDL_GetAudioStreamDataAdjustGain(SDL_AudioStream *stream, void *voidbuf, int len, float extra_gain) { Uint8 *buf = (Uint8 *) voidbuf; @@ -1024,22 +1107,26 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) #endif if (!stream) { - return SDL_InvalidParamError("stream"); + SDL_InvalidParamError("stream"); + return -1; } else if (!buf) { - return SDL_InvalidParamError("buf"); + SDL_InvalidParamError("buf"); + return -1; } else if (len < 0) { - return SDL_InvalidParamError("len"); + SDL_InvalidParamError("len"); + return -1; } else if (len == 0) { return 0; // nothing to do. } SDL_LockMutex(stream->lock); - if (CheckAudioStreamIsFullySetup(stream) != 0) { + if (!CheckAudioStreamIsFullySetup(stream)) { SDL_UnlockMutex(stream->lock); return -1; } + const float gain = stream->gain * extra_gain; const int dst_frame_size = SDL_AUDIO_FRAMESIZE(stream->dst_spec); len -= len % dst_frame_size; // chop off any fractional sample frame. @@ -1074,21 +1161,23 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) while (total < len) { // Audio is processed a track at a time. SDL_AudioSpec input_spec; - SDL_bool flushed; - const Sint64 available_frames = GetAudioStreamHead(stream, &input_spec, &flushed); + int *input_chmap; + bool flushed; + const Sint64 available_frames = GetAudioStreamHead(stream, &input_spec, &input_chmap, &flushed); if (available_frames == 0) { if (flushed) { SDL_PopAudioQueueHead(stream->queue); SDL_zero(stream->input_spec); stream->resample_offset = 0; + stream->input_chmap = NULL; continue; } // There are no frames available, but the track hasn't been flushed, so more might be added later. break; } - if (UpdateAudioStreamInputSpec(stream, &input_spec) != 0) { + if (!UpdateAudioStreamInputSpec(stream, &input_spec, input_chmap)) { total = total ? total : -1; break; } @@ -1099,7 +1188,7 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) output_frames = SDL_min(output_frames, chunk_size); output_frames = (int) SDL_min(output_frames, available_frames); - if (GetAudioStreamDataInternal(stream, &buf[total], output_frames) != 0) { + if (!GetAudioStreamDataInternal(stream, &buf[total], output_frames, gain)) { total = total ? total : -1; break; } @@ -1116,16 +1205,22 @@ int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) return total; } +int SDL_GetAudioStreamData(SDL_AudioStream *stream, void *voidbuf, int len) +{ + return SDL_GetAudioStreamDataAdjustGain(stream, voidbuf, len, 1.0f); +} + // number of converted/resampled bytes available for output int SDL_GetAudioStreamAvailable(SDL_AudioStream *stream) { if (!stream) { - return SDL_InvalidParamError("stream"); + SDL_InvalidParamError("stream"); + return -1; } SDL_LockMutex(stream->lock); - if (CheckAudioStreamIsFullySetup(stream) != 0) { + if (!CheckAudioStreamIsFullySetup(stream)) { SDL_UnlockMutex(stream->lock); return 0; } @@ -1145,18 +1240,21 @@ int SDL_GetAudioStreamAvailable(SDL_AudioStream *stream) int SDL_GetAudioStreamQueued(SDL_AudioStream *stream) { if (!stream) { - return SDL_InvalidParamError("stream"); + SDL_InvalidParamError("stream"); + return -1; } SDL_LockMutex(stream->lock); - const Uint64 total = stream->total_bytes_queued; + + size_t total = SDL_GetAudioQueueQueued(stream->queue); + SDL_UnlockMutex(stream->lock); // if this overflows an int, just clamp it to a maximum. return (int) SDL_min(total, SDL_INT_MAX); } -int SDL_ClearAudioStream(SDL_AudioStream *stream) +bool SDL_ClearAudioStream(SDL_AudioStream *stream) { if (!stream) { return SDL_InvalidParamError("stream"); @@ -1166,11 +1264,11 @@ int SDL_ClearAudioStream(SDL_AudioStream *stream) SDL_ClearAudioQueue(stream->queue); SDL_zero(stream->input_spec); + stream->input_chmap = NULL; stream->resample_offset = 0; - stream->total_bytes_queued = 0; SDL_UnlockMutex(stream->lock); - return 0; + return true; } void SDL_DestroyAudioStream(SDL_AudioStream *stream) @@ -1183,7 +1281,7 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream) OnAudioStreamDestroy(stream); - const SDL_bool simplified = stream->simplified; + const bool simplified = stream->simplified; if (simplified) { if (stream->bound_device) { SDL_assert(stream->bound_device->simplified); @@ -1193,7 +1291,6 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream) SDL_UnbindAudioStream(stream); } - SDL_aligned_free(stream->history_buffer); SDL_aligned_free(stream->work_buffer); SDL_DestroyAudioQueue(stream->queue); SDL_DestroyMutex(stream->lock); @@ -1201,8 +1298,12 @@ void SDL_DestroyAudioStream(SDL_AudioStream *stream) SDL_free(stream); } -int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, - const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len) +static void SDLCALL DontFreeThisAudioBuffer(void *userdata, const void *buf, int len) +{ + // We don't own the buffer, but know it will outlive the stream +} + +bool SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data, int src_len, const SDL_AudioSpec *dst_spec, Uint8 **dst_data, int *dst_len) { if (dst_data) { *dst_data = NULL; @@ -1222,30 +1323,31 @@ int SDL_ConvertAudioSamples(const SDL_AudioSpec *src_spec, const Uint8 *src_data return SDL_InvalidParamError("dst_len"); } - int retval = -1; + bool result = false; Uint8 *dst = NULL; int dstlen = 0; SDL_AudioStream *stream = SDL_CreateAudioStream(src_spec, dst_spec); if (stream) { - if ((SDL_PutAudioStreamData(stream, src_data, src_len) == 0) && (SDL_FlushAudioStream(stream) == 0)) { + if (PutAudioStreamBuffer(stream, src_data, src_len, DontFreeThisAudioBuffer, NULL) && + SDL_FlushAudioStream(stream)) { dstlen = SDL_GetAudioStreamAvailable(stream); if (dstlen >= 0) { dst = (Uint8 *)SDL_malloc(dstlen); if (dst) { - retval = (SDL_GetAudioStreamData(stream, dst, dstlen) >= 0) ? 0 : -1; + result = (SDL_GetAudioStreamData(stream, dst, dstlen) == dstlen); } } } } - if (retval == -1) { - SDL_free(dst); - } else { + if (result) { *dst_data = dst; *dst_len = dstlen; + } else { + SDL_free(dst); } SDL_DestroyAudioStream(stream); - return retval; + return result; } diff --git a/libs/SDL3/src/audio/SDL_audiodev.c b/libs/SDL3/src/audio/SDL_audiodev.c index 46e4c4dbf..f48a5b25d 100644 --- a/libs/SDL3/src/audio/SDL_audiodev.c +++ b/libs/SDL3/src/audio/SDL_audiodev.c @@ -45,13 +45,13 @@ #define SDL_PATH_DEV_AUDIO "/dev/audio" #endif -static void test_device(const SDL_bool iscapture, const char *fname, int flags, SDL_bool (*test)(int fd)) +static void test_device(const bool recording, const char *fname, int flags, bool (*test)(int fd)) { struct stat sb; const int audio_fd = open(fname, flags | O_CLOEXEC, 0); if (audio_fd >= 0) { if ((fstat(audio_fd, &sb) == 0) && (S_ISCHR(sb.st_mode))) { - const SDL_bool okay = test(audio_fd); + const bool okay = test(audio_fd); close(audio_fd); if (okay) { static size_t dummyhandle = 0; @@ -63,7 +63,7 @@ static void test_device(const SDL_bool iscapture, const char *fname, int flags, * information, making this information inaccessible at * enumeration time */ - SDL_AddAudioDevice(iscapture, fname, NULL, (void *)(uintptr_t)dummyhandle); + SDL_AddAudioDevice(recording, fname, NULL, (void *)(uintptr_t)dummyhandle); } } else { close(audio_fd); @@ -71,14 +71,14 @@ static void test_device(const SDL_bool iscapture, const char *fname, int flags, } } -static SDL_bool test_stub(int fd) +static bool test_stub(int fd) { - return SDL_TRUE; + return true; } -static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SDL_bool classic, SDL_bool (*test)(int)) +static void SDL_EnumUnixAudioDevices_Internal(const bool recording, const bool classic, bool (*test)(int)) { - const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; + const int flags = recording ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT; const char *audiodev; char audiopath[1024]; @@ -87,10 +87,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD } // Figure out what our audio device is - audiodev = SDL_getenv("SDL_PATH_DSP"); - if (!audiodev) { - audiodev = SDL_getenv("AUDIODEV"); - } + audiodev = SDL_getenv("AUDIODEV"); if (!audiodev) { if (classic) { audiodev = SDL_PATH_DEV_AUDIO; @@ -105,7 +102,7 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD } } } - test_device(iscapture, audiodev, flags, test); + test_device(recording, audiodev, flags, test); if (SDL_strlen(audiodev) < (sizeof(audiopath) - 3)) { int instance = 0; @@ -113,15 +110,15 @@ static void SDL_EnumUnixAudioDevices_Internal(const SDL_bool iscapture, const SD (void)SDL_snprintf(audiopath, SDL_arraysize(audiopath), "%s%d", audiodev, instance); instance++; - test_device(iscapture, audiopath, flags, test); + test_device(recording, audiopath, flags, test); } } } -void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int)) +void SDL_EnumUnixAudioDevices(const bool classic, bool (*test)(int)) { - SDL_EnumUnixAudioDevices_Internal(SDL_TRUE, classic, test); - SDL_EnumUnixAudioDevices_Internal(SDL_FALSE, classic, test); + SDL_EnumUnixAudioDevices_Internal(true, classic, test); + SDL_EnumUnixAudioDevices_Internal(false, classic, test); } #endif // Audio device selection diff --git a/libs/SDL3/src/audio/SDL_audiodev_c.h b/libs/SDL3/src/audio/SDL_audiodev_c.h index 8ea867c25..8f3444803 100644 --- a/libs/SDL3/src/audio/SDL_audiodev_c.h +++ b/libs/SDL3/src/audio/SDL_audiodev_c.h @@ -36,6 +36,6 @@ #define OPEN_FLAGS_INPUT (O_RDONLY | O_NONBLOCK) #endif -extern void SDL_EnumUnixAudioDevices(const SDL_bool classic, SDL_bool (*test)(int)); +extern void SDL_EnumUnixAudioDevices(const bool classic, bool (*test)(int)); #endif // SDL_audiodev_c_h_ diff --git a/libs/SDL3/src/audio/SDL_audioqueue.c b/libs/SDL3/src/audio/SDL_audioqueue.c index 923873676..ec5800be4 100644 --- a/libs/SDL3/src/audio/SDL_audioqueue.c +++ b/libs/SDL3/src/audio/SDL_audioqueue.c @@ -21,253 +21,132 @@ #include "SDL_internal.h" #include "SDL_audioqueue.h" +#include "SDL_sysaudio.h" -#define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq)) +typedef struct SDL_MemoryPool SDL_MemoryPool; + +struct SDL_MemoryPool +{ + void *free_blocks; + size_t block_size; + size_t num_free; + size_t max_free; +}; struct SDL_AudioTrack { SDL_AudioSpec spec; - SDL_bool flushed; + int *chmap; + bool flushed; SDL_AudioTrack *next; - size_t (*avail)(void *ctx); - int (*write)(void *ctx, const Uint8 *buf, size_t len); - size_t (*read)(void *ctx, Uint8 *buf, size_t len, SDL_bool advance); - void (*destroy)(void *ctx); + void *userdata; + SDL_ReleaseAudioBufferCallback callback; + + Uint8 *data; + size_t head; + size_t tail; + size_t capacity; + + int chmap_storage[SDL_MAX_CHANNELMAP_CHANNELS]; // !!! FIXME: this needs to grow if SDL ever supports more channels. But if it grows, we should probably be more clever about allocations. }; struct SDL_AudioQueue { SDL_AudioTrack *head; SDL_AudioTrack *tail; - size_t chunk_size; -}; -typedef struct SDL_AudioChunk SDL_AudioChunk; + Uint8 *history_buffer; + size_t history_length; + size_t history_capacity; -struct SDL_AudioChunk -{ - SDL_AudioChunk *next; - size_t head; - size_t tail; - Uint8 data[SDL_VARIABLE_LENGTH_ARRAY]; + SDL_MemoryPool track_pool; + SDL_MemoryPool chunk_pool; }; -typedef struct SDL_ChunkedAudioTrack -{ - SDL_AudioTrack track; - - size_t chunk_size; - - SDL_AudioChunk *head; - SDL_AudioChunk *tail; - size_t queued_bytes; - - SDL_AudioChunk *free_chunks; - size_t num_free_chunks; -} SDL_ChunkedAudioTrack; - -static void DestroyAudioChunk(SDL_AudioChunk *chunk) +// Allocate a new block, avoiding checking for ones already in the pool +static void *AllocNewMemoryPoolBlock(const SDL_MemoryPool *pool) { - SDL_free(chunk); + return SDL_malloc(pool->block_size); } -static void DestroyAudioChunks(SDL_AudioChunk *chunk) +// Allocate a new block, first checking if there are any in the pool +static void *AllocMemoryPoolBlock(SDL_MemoryPool *pool) { - while (chunk) { - SDL_AudioChunk *next = chunk->next; - DestroyAudioChunk(chunk); - chunk = next; + if (pool->num_free == 0) { + return AllocNewMemoryPoolBlock(pool); } -} -static void ResetAudioChunk(SDL_AudioChunk *chunk) -{ - chunk->next = NULL; - chunk->head = 0; - chunk->tail = 0; + void *block = pool->free_blocks; + pool->free_blocks = *(void **)block; + --pool->num_free; + return block; } -static SDL_AudioChunk *CreateAudioChunk(size_t chunk_size) +// Free a block, or add it to the pool if there's room +static void FreeMemoryPoolBlock(SDL_MemoryPool *pool, void *block) { - SDL_AudioChunk *chunk = (SDL_AudioChunk *)SDL_malloc(sizeof(*chunk) + chunk_size); - - if (!chunk) { - return NULL; - } - - ResetAudioChunk(chunk); - - return chunk; -} - -static void DestroyAudioTrackChunk(SDL_ChunkedAudioTrack *track, SDL_AudioChunk *chunk) -{ - // Keeping a list of free chunks reduces memory allocations, - // But also increases the amount of work to perform when freeing the track. - const size_t max_free_bytes = 64 * 1024; - - if (track->chunk_size * track->num_free_chunks < max_free_bytes) { - chunk->next = track->free_chunks; - track->free_chunks = chunk; - ++track->num_free_chunks; + if (pool->num_free < pool->max_free) { + *(void **)block = pool->free_blocks; + pool->free_blocks = block; + ++pool->num_free; } else { - DestroyAudioChunk(chunk); + SDL_free(block); } } -static SDL_AudioChunk *CreateAudioTrackChunk(SDL_ChunkedAudioTrack *track) +// Destroy a pool and all of its blocks +static void DestroyMemoryPool(SDL_MemoryPool *pool) { - if (track->num_free_chunks > 0) { - SDL_AudioChunk *chunk = track->free_chunks; - - track->free_chunks = chunk->next; - --track->num_free_chunks; - - ResetAudioChunk(chunk); - - return chunk; + void *block = pool->free_blocks; + pool->free_blocks = NULL; + pool->num_free = 0; + + while (block) { + void *next = *(void **)block; + SDL_free(block); + block = next; } - - return CreateAudioChunk(track->chunk_size); } -static size_t AvailChunkedAudioTrack(void *ctx) +// Keeping a list of free chunks reduces memory allocations, +// But also increases the amount of work to perform when freeing the track. +static void InitMemoryPool(SDL_MemoryPool *pool, size_t block_size, size_t max_free) { - SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; + SDL_zerop(pool); - return track->queued_bytes; + SDL_assert(block_size >= sizeof(void *)); + pool->block_size = block_size; + pool->max_free = max_free; } -static int WriteToChunkedAudioTrack(void *ctx, const Uint8 *data, size_t len) +// Allocates a number of blocks and adds them to the pool +static bool ReserveMemoryPoolBlocks(SDL_MemoryPool *pool, size_t num_blocks) { - SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; - - SDL_AudioChunk *chunk = track->tail; - - // Handle the first chunk - if (!chunk) { - chunk = CreateAudioTrackChunk(track); + for (; num_blocks; --num_blocks) { + void *block = AllocNewMemoryPoolBlock(pool); - if (!chunk) { - return -1; + if (block == NULL) { + return false; } - SDL_assert((track->head == NULL) && (track->tail == NULL) && (track->queued_bytes == 0)); - track->head = chunk; - track->tail = chunk; + *(void **)block = pool->free_blocks; + pool->free_blocks = block; + ++pool->num_free; } - size_t total = 0; - size_t old_tail = chunk->tail; - size_t chunk_size = track->chunk_size; - - while (chunk) { - size_t to_write = chunk_size - chunk->tail; - to_write = SDL_min(to_write, len - total); - SDL_memcpy(&chunk->data[chunk->tail], &data[total], to_write); - total += to_write; - - chunk->tail += to_write; - - if (total == len) { - break; - } - - SDL_AudioChunk *next = CreateAudioTrackChunk(track); - chunk->next = next; - chunk = next; - } - - // Roll back the changes if we couldn't write all the data - if (!chunk) { - chunk = track->tail; - - SDL_AudioChunk *next = chunk->next; - chunk->next = NULL; - chunk->tail = old_tail; - - DestroyAudioChunks(next); - - return -1; - } - - track->tail = chunk; - track->queued_bytes += total; - - return 0; + return true; } -static size_t ReadFromChunkedAudioTrack(void *ctx, Uint8 *data, size_t len, SDL_bool advance) -{ - SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; - SDL_AudioChunk *chunk = track->head; - - size_t total = 0; - size_t head = 0; - - while (chunk) { - head = chunk->head; - - size_t to_read = chunk->tail - head; - to_read = SDL_min(to_read, len - total); - SDL_memcpy(&data[total], &chunk->data[head], to_read); - total += to_read; - - SDL_AudioChunk *next = chunk->next; - - if (total == len) { - head += to_read; - break; - } - - if (advance) { - DestroyAudioTrackChunk(track, chunk); - } - - chunk = next; - } - - if (advance) { - if (chunk) { - chunk->head = head; - track->head = chunk; - } else { - track->head = NULL; - track->tail = NULL; - } - - track->queued_bytes -= total; - } - - return total; -} - -static void DestroyChunkedAudioTrack(void *ctx) -{ - SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)ctx; - DestroyAudioChunks(track->head); - DestroyAudioChunks(track->free_chunks); - SDL_free(track); -} - -static SDL_AudioTrack *CreateChunkedAudioTrack(const SDL_AudioSpec *spec, size_t chunk_size) +void SDL_DestroyAudioQueue(SDL_AudioQueue *queue) { - SDL_ChunkedAudioTrack *track = (SDL_ChunkedAudioTrack *)SDL_calloc(1, sizeof(*track)); - - if (!track) { - return NULL; - } - - SDL_copyp(&track->track.spec, spec); - track->track.avail = AvailChunkedAudioTrack; - track->track.write = WriteToChunkedAudioTrack; - track->track.read = ReadFromChunkedAudioTrack; - track->track.destroy = DestroyChunkedAudioTrack; + SDL_ClearAudioQueue(queue); - track->chunk_size = chunk_size; + DestroyMemoryPool(&queue->track_pool); + DestroyMemoryPool(&queue->chunk_pool); + SDL_aligned_free(queue->history_buffer); - return &track->track; + SDL_free(queue); } SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size) @@ -278,35 +157,42 @@ SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size) return NULL; } - queue->chunk_size = chunk_size; + InitMemoryPool(&queue->track_pool, sizeof(SDL_AudioTrack), 8); + InitMemoryPool(&queue->chunk_pool, chunk_size, 4); + + if (!ReserveMemoryPoolBlocks(&queue->track_pool, 2)) { + SDL_DestroyAudioQueue(queue); + return NULL; + } return queue; } -void SDL_DestroyAudioQueue(SDL_AudioQueue *queue) +static void DestroyAudioTrack(SDL_AudioQueue *queue, SDL_AudioTrack *track) { - SDL_ClearAudioQueue(queue); + track->callback(track->userdata, track->data, (int)track->capacity); - SDL_free(queue); + FreeMemoryPoolBlock(&queue->track_pool, track); } void SDL_ClearAudioQueue(SDL_AudioQueue *queue) { SDL_AudioTrack *track = queue->head; + queue->head = NULL; queue->tail = NULL; + queue->history_length = 0; while (track) { SDL_AudioTrack *next = track->next; - track->destroy(track); + DestroyAudioTrack(queue, track); track = next; } } -static void SDL_FlushAudioTrack(SDL_AudioTrack *track) +static void FlushAudioTrack(SDL_AudioTrack *track) { - track->flushed = SDL_TRUE; - track->write = NULL; + track->flushed = true; } void SDL_FlushAudioQueue(SDL_AudioQueue *queue) @@ -314,7 +200,7 @@ void SDL_FlushAudioQueue(SDL_AudioQueue *queue) SDL_AudioTrack *track = queue->tail; if (track) { - SDL_FlushAudioTrack(track); + FlushAudioTrack(track); } } @@ -323,10 +209,10 @@ void SDL_PopAudioQueueHead(SDL_AudioQueue *queue) SDL_AudioTrack *track = queue->head; for (;;) { - SDL_bool flushed = track->flushed; + bool flushed = track->flushed; SDL_AudioTrack *next = track->next; - track->destroy(track); + DestroyAudioTrack(queue, track); track = next; if (flushed) { @@ -335,27 +221,66 @@ void SDL_PopAudioQueueHead(SDL_AudioQueue *queue) } queue->head = track; + queue->history_length = 0; if (!track) { queue->tail = NULL; } } -size_t SDL_GetAudioQueueChunkSize(SDL_AudioQueue *queue) +SDL_AudioTrack *SDL_CreateAudioTrack( + SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const int *chmap, + Uint8 *data, size_t len, size_t capacity, + SDL_ReleaseAudioBufferCallback callback, void *userdata) { - return queue->chunk_size; + SDL_AudioTrack *track = (SDL_AudioTrack *)AllocMemoryPoolBlock(&queue->track_pool); + + if (!track) { + return NULL; + } + + SDL_zerop(track); + + if (chmap) { + SDL_assert(SDL_arraysize(track->chmap_storage) >= spec->channels); + SDL_memcpy(track->chmap_storage, chmap, sizeof (*chmap) * spec->channels); + track->chmap = track->chmap_storage; + } + + SDL_copyp(&track->spec, spec); + + track->userdata = userdata; + track->callback = callback; + track->data = data; + track->head = 0; + track->tail = len; + track->capacity = capacity; + + return track; } -SDL_AudioTrack *SDL_CreateChunkedAudioTrack(const SDL_AudioSpec *spec, const Uint8 *data, size_t len, size_t chunk_size) +static void SDLCALL FreeChunkedAudioBuffer(void *userdata, const void *buf, int len) { - SDL_AudioTrack *track = CreateChunkedAudioTrack(spec, chunk_size); + SDL_AudioQueue *queue = (SDL_AudioQueue *)userdata; - if (!track) { + FreeMemoryPoolBlock(&queue->chunk_pool, (void *)buf); +} + +static SDL_AudioTrack *CreateChunkedAudioTrack(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const int *chmap) +{ + Uint8 *chunk = (Uint8 *)AllocMemoryPoolBlock(&queue->chunk_pool); + + if (!chunk) { return NULL; } - if (track->write(track, data, len) != 0) { - track->destroy(track); + size_t capacity = queue->chunk_pool.block_size; + capacity -= capacity % SDL_AUDIO_FRAMESIZE(*spec); + + SDL_AudioTrack *track = SDL_CreateAudioTrack(queue, spec, chmap, chunk, 0, capacity, FreeChunkedAudioBuffer, queue); + + if (!track) { + FreeMemoryPoolBlock(&queue->chunk_pool, chunk); return NULL; } @@ -368,8 +293,8 @@ void SDL_AddTrackToAudioQueue(SDL_AudioQueue *queue, SDL_AudioTrack *track) if (tail) { // If the spec has changed, make sure to flush the previous track - if (!AUDIO_SPECS_EQUAL(tail->spec, track->spec)) { - SDL_FlushAudioTrack(tail); + if (!SDL_AudioSpecsEqual(&tail->spec, &track->spec, tail->chmap, track->chmap)) { + FlushAudioTrack(tail); } tail->next = track; @@ -380,37 +305,64 @@ void SDL_AddTrackToAudioQueue(SDL_AudioQueue *queue, SDL_AudioTrack *track) queue->tail = track; } -int SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const Uint8 *data, size_t len) +static size_t WriteToAudioTrack(SDL_AudioTrack *track, const Uint8 *data, size_t len) { - if (len == 0) { + if (track->flushed || track->tail >= track->capacity) { return 0; } + len = SDL_min(len, track->capacity - track->tail); + SDL_memcpy(&track->data[track->tail], data, len); + track->tail += len; + + return len; +} + +bool SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const int *chmap, const Uint8 *data, size_t len) +{ + if (len == 0) { + return true; + } + SDL_AudioTrack *track = queue->tail; - if ((track) && !AUDIO_SPECS_EQUAL(track->spec, *spec)) { - SDL_FlushAudioTrack(track); + if (track) { + if (!SDL_AudioSpecsEqual(&track->spec, spec, track->chmap, chmap)) { + FlushAudioTrack(track); + } + } else { + SDL_assert(!queue->head); + track = CreateChunkedAudioTrack(queue, spec, chmap); + + if (!track) { + return false; + } + + queue->head = track; + queue->tail = track; } - if ((!track) || (!track->write)) { - SDL_AudioTrack *new_track = CreateChunkedAudioTrack(spec, queue->chunk_size); + for (;;) { + const size_t written = WriteToAudioTrack(track, data, len); + data += written; + len -= written; - if (!new_track) { - return -1; + if (len == 0) { + break; } - if (track) { - track->next = new_track; - } else { - queue->head = new_track; + SDL_AudioTrack *new_track = CreateChunkedAudioTrack(queue, spec, chmap); + + if (!new_track) { + return false; } + track->next = new_track; queue->tail = new_track; - track = new_track; } - return track->write(track, data, len); + return true; } void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue) @@ -418,25 +370,26 @@ void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue) return queue->head; } -size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, SDL_bool *out_flushed) +size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, int **out_chmap, bool *out_flushed) { SDL_AudioTrack *iter = (SDL_AudioTrack *)(*inout_iter); SDL_assert(iter != NULL); SDL_copyp(out_spec, &iter->spec); + *out_chmap = iter->chmap; - SDL_bool flushed = SDL_FALSE; + bool flushed = false; size_t queued_bytes = 0; while (iter) { SDL_AudioTrack *track = iter; iter = iter->next; - size_t avail = track->avail(track); + size_t avail = track->tail - track->head; if (avail >= SDL_SIZE_MAX - queued_bytes) { queued_bytes = SDL_SIZE_MAX; - flushed = SDL_FALSE; + flushed = false; break; } @@ -454,61 +407,246 @@ size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_Audi return queued_bytes; } -int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) +static const Uint8 *PeekIntoAudioQueuePast(SDL_AudioQueue *queue, Uint8 *data, size_t len) { - size_t total = 0; SDL_AudioTrack *track = queue->head; - for (;;) { - if (!track) { - return SDL_SetError("Reading past end of queue"); - } + if (track->head >= len) { + return &track->data[track->head - len]; + } - total += track->read(track, &data[total], len - total, SDL_TRUE); + size_t past = len - track->head; + + if (past > queue->history_length) { + return NULL; + } + + SDL_memcpy(data, &queue->history_buffer[queue->history_length - past], past); + SDL_memcpy(&data[past], track->data, track->head); + + return data; +} + +static void UpdateAudioQueueHistory(SDL_AudioQueue *queue, + const Uint8 *data, size_t len) +{ + Uint8 *history_buffer = queue->history_buffer; + size_t history_bytes = queue->history_length; + + if (len >= history_bytes) { + SDL_memcpy(history_buffer, &data[len - history_bytes], history_bytes); + } else { + size_t preserve = history_bytes - len; + SDL_memmove(history_buffer, &history_buffer[len], preserve); + SDL_memcpy(&history_buffer[preserve], data, len); + } +} + +static const Uint8 *ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) +{ + SDL_AudioTrack *track = queue->head; + + if (track->tail - track->head >= len) { + const Uint8 *ptr = &track->data[track->head]; + track->head += len; + return ptr; + } + + size_t total = 0; + + for (;;) { + size_t avail = SDL_min(len - total, track->tail - track->head); + SDL_memcpy(&data[total], &track->data[track->head], avail); + track->head += avail; + total += avail; if (total == len) { - return 0; + break; } if (track->flushed) { - return SDL_SetError("Reading past end of flushed track"); + SDL_SetError("Reading past end of flushed track"); + return NULL; } SDL_AudioTrack *next = track->next; if (!next) { - return SDL_SetError("Reading past end of incomplete track"); + SDL_SetError("Reading past end of incomplete track"); + return NULL; } - queue->head = next; + UpdateAudioQueueHistory(queue, track->data, track->tail); - track->destroy(track); + queue->head = next; + DestroyAudioTrack(queue, track); track = next; } + + return data; } -int SDL_PeekIntoAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len) +static const Uint8 *PeekIntoAudioQueueFuture(SDL_AudioQueue *queue, Uint8 *data, size_t len) { - size_t total = 0; SDL_AudioTrack *track = queue->head; - for (;;) { - if (!track) { - return SDL_SetError("Peeking past end of queue"); - } + if (track->tail - track->head >= len) { + return &track->data[track->head]; + } + + size_t total = 0; - total += track->read(track, &data[total], len - total, SDL_FALSE); + for (;;) { + size_t avail = SDL_min(len - total, track->tail - track->head); + SDL_memcpy(&data[total], &track->data[track->head], avail); + total += avail; if (total == len) { - return 0; + break; } if (track->flushed) { // If we have run out of data, fill the rest with silence. SDL_memset(&data[total], SDL_GetSilenceValueForFormat(track->spec.format), len - total); - return 0; + break; } track = track->next; + + if (!track) { + SDL_SetError("Peeking past end of incomplete track"); + return NULL; + } } + + return data; +} + +const Uint8 *SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, + Uint8 *dst, SDL_AudioFormat dst_format, int dst_channels, const int *dst_map, + int past_frames, int present_frames, int future_frames, + Uint8 *scratch, float gain) +{ + SDL_AudioTrack *track = queue->head; + + if (!track) { + return NULL; + } + + SDL_AudioFormat src_format = track->spec.format; + int src_channels = track->spec.channels; + const int *src_map = track->chmap; + + size_t src_frame_size = SDL_AUDIO_BYTESIZE(src_format) * src_channels; + size_t dst_frame_size = SDL_AUDIO_BYTESIZE(dst_format) * dst_channels; + + size_t src_past_bytes = past_frames * src_frame_size; + size_t src_present_bytes = present_frames * src_frame_size; + size_t src_future_bytes = future_frames * src_frame_size; + + size_t dst_past_bytes = past_frames * dst_frame_size; + size_t dst_present_bytes = present_frames * dst_frame_size; + size_t dst_future_bytes = future_frames * dst_frame_size; + + bool convert = (src_format != dst_format) || (src_channels != dst_channels); + + if (convert && !dst) { + // The user didn't ask for the data to be copied, but we need to convert it, so store it in the scratch buffer + dst = scratch; + } + + // Can we get all of the data straight from this track? + if ((track->head >= src_past_bytes) && ((track->tail - track->head) >= (src_present_bytes + src_future_bytes))) { + const Uint8 *ptr = &track->data[track->head - src_past_bytes]; + track->head += src_present_bytes; + + // Do we still need to copy/convert the data? + if (dst) { + ConvertAudio(past_frames + present_frames + future_frames, ptr, + src_format, src_channels, src_map, dst, dst_format, dst_channels, dst_map, scratch, gain); + ptr = dst; + } + + return ptr; + } + + if (!dst) { + // The user didn't ask for the data to be copied, but we need to, so store it in the scratch buffer + dst = scratch; + } else if (!convert) { + // We are only copying, not converting, so copy straight into the dst buffer + scratch = dst; + } + + Uint8 *ptr = dst; + + if (src_past_bytes) { + ConvertAudio(past_frames, PeekIntoAudioQueuePast(queue, scratch, src_past_bytes), src_format, src_channels, src_map, dst, dst_format, dst_channels, dst_map, scratch, gain); + dst += dst_past_bytes; + scratch += dst_past_bytes; + } + + if (src_present_bytes) { + ConvertAudio(present_frames, ReadFromAudioQueue(queue, scratch, src_present_bytes), src_format, src_channels, src_map, dst, dst_format, dst_channels, dst_map, scratch, gain); + dst += dst_present_bytes; + scratch += dst_present_bytes; + } + + if (src_future_bytes) { + ConvertAudio(future_frames, PeekIntoAudioQueueFuture(queue, scratch, src_future_bytes), src_format, src_channels, src_map, dst, dst_format, dst_channels, dst_map, scratch, gain); + dst += dst_future_bytes; + scratch += dst_future_bytes; + } + + return ptr; +} + +size_t SDL_GetAudioQueueQueued(SDL_AudioQueue *queue) +{ + size_t total = 0; + void *iter = SDL_BeginAudioQueueIter(queue); + + while (iter) { + SDL_AudioSpec src_spec; + int *src_chmap; + bool flushed; + + size_t avail = SDL_NextAudioQueueIter(queue, &iter, &src_spec, &src_chmap, &flushed); + + if (avail >= SDL_SIZE_MAX - total) { + total = SDL_SIZE_MAX; + break; + } + + total += avail; + } + + return total; +} + +bool SDL_ResetAudioQueueHistory(SDL_AudioQueue *queue, int num_frames) +{ + SDL_AudioTrack *track = queue->head; + + if (!track) { + return false; + } + + size_t length = num_frames * SDL_AUDIO_FRAMESIZE(track->spec); + Uint8 *history_buffer = queue->history_buffer; + + if (queue->history_capacity < length) { + history_buffer = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), length); + if (!history_buffer) { + return false; + } + SDL_aligned_free(queue->history_buffer); + queue->history_buffer = history_buffer; + queue->history_capacity = length; + } + + queue->history_length = length; + SDL_memset(history_buffer, SDL_GetSilenceValueForFormat(track->spec.format), length); + + return true; } diff --git a/libs/SDL3/src/audio/SDL_audioqueue.h b/libs/SDL3/src/audio/SDL_audioqueue.h index 9b18a5c5e..3a6a5fe50 100644 --- a/libs/SDL3/src/audio/SDL_audioqueue.h +++ b/libs/SDL3/src/audio/SDL_audioqueue.h @@ -25,53 +25,55 @@ // Internal functions used by SDL_AudioStream for queueing audio. +typedef void (SDLCALL *SDL_ReleaseAudioBufferCallback)(void *userdata, const void *buffer, int buflen); + typedef struct SDL_AudioQueue SDL_AudioQueue; typedef struct SDL_AudioTrack SDL_AudioTrack; // Create a new audio queue -SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size); +extern SDL_AudioQueue *SDL_CreateAudioQueue(size_t chunk_size); // Destroy an audio queue -void SDL_DestroyAudioQueue(SDL_AudioQueue *queue); +extern void SDL_DestroyAudioQueue(SDL_AudioQueue *queue); // Completely clear the queue -void SDL_ClearAudioQueue(SDL_AudioQueue *queue); +extern void SDL_ClearAudioQueue(SDL_AudioQueue *queue); // Mark the last track as flushed -void SDL_FlushAudioQueue(SDL_AudioQueue *queue); +extern void SDL_FlushAudioQueue(SDL_AudioQueue *queue); // Pop the current head track // REQUIRES: The head track must exist, and must have been flushed -void SDL_PopAudioQueueHead(SDL_AudioQueue *queue); - -// Get the chunk size, mostly for use with SDL_CreateChunkedAudioTrack -// This can be called from any thread -size_t SDL_GetAudioQueueChunkSize(SDL_AudioQueue *queue); +extern void SDL_PopAudioQueueHead(SDL_AudioQueue *queue); // Write data to the end of queue // REQUIRES: If the spec has changed, the last track must have been flushed -int SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const Uint8 *data, size_t len); +extern bool SDL_WriteToAudioQueue(SDL_AudioQueue *queue, const SDL_AudioSpec *spec, const int *chmap, const Uint8 *data, size_t len); -// Create a track without needing to hold any locks -SDL_AudioTrack *SDL_CreateChunkedAudioTrack(const SDL_AudioSpec *spec, const Uint8 *data, size_t len, size_t chunk_size); +// Create a track where the input data is owned by the caller +extern SDL_AudioTrack *SDL_CreateAudioTrack(SDL_AudioQueue *queue, + const SDL_AudioSpec *spec, const int *chmap, Uint8 *data, size_t len, size_t capacity, + SDL_ReleaseAudioBufferCallback callback, void *userdata); // Add a track to the end of the queue // REQUIRES: `track != NULL` -void SDL_AddTrackToAudioQueue(SDL_AudioQueue *queue, SDL_AudioTrack *track); +extern void SDL_AddTrackToAudioQueue(SDL_AudioQueue *queue, SDL_AudioTrack *track); // Iterate over the tracks in the queue -void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue); +extern void *SDL_BeginAudioQueueIter(SDL_AudioQueue *queue); // Query and update the track iterator // REQUIRES: `*inout_iter != NULL` (a valid iterator) -size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, SDL_bool *out_flushed); +extern size_t SDL_NextAudioQueueIter(SDL_AudioQueue *queue, void **inout_iter, SDL_AudioSpec *out_spec, int **out_chmap, bool *out_flushed); + +extern const Uint8 *SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, + Uint8 *dst, SDL_AudioFormat dst_format, int dst_channels, const int *dst_map, + int past_frames, int present_frames, int future_frames, + Uint8 *scratch, float gain); -// Read data from the start of the queue -// REQUIRES: There must be enough data in the queue -int SDL_ReadFromAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len); +// Get the total number of bytes currently queued +extern size_t SDL_GetAudioQueueQueued(SDL_AudioQueue *queue); -// Peek into the start of the queue -// REQUIRES: There must be enough data in the queue, unless it has been flushed, in which case missing data is filled with silence. -int SDL_PeekIntoAudioQueue(SDL_AudioQueue *queue, Uint8 *data, size_t len); +extern bool SDL_ResetAudioQueueHistory(SDL_AudioQueue *queue, int num_frames); #endif // SDL_audioqueue_h_ diff --git a/libs/SDL3/src/audio/SDL_audioresample.c b/libs/SDL3/src/audio/SDL_audioresample.c index 9ca6d0a22..07d0b4a63 100644 --- a/libs/SDL3/src/audio/SDL_audioresample.c +++ b/libs/SDL3/src/audio/SDL_audioresample.c @@ -21,208 +21,565 @@ #include "SDL_internal.h" #include "SDL_sysaudio.h" + #include "SDL_audioresample.h" // SDL's resampler uses a "bandlimited interpolation" algorithm: // https://ccrma.stanford.edu/~jos/resample/ -#include "SDL_audio_resampler_filter.h" +// TODO: Support changing this at runtime? +#if defined(SDL_SSE_INTRINSICS) || defined(SDL_NEON_INTRINSICS) +// In , SSE is basically mandatory anyway +// We want RESAMPLER_SAMPLES_PER_FRAME to be a multiple of 4, to make SIMD easier +#define RESAMPLER_ZERO_CROSSINGS 6 +#else +#define RESAMPLER_ZERO_CROSSINGS 5 +#endif + +#define RESAMPLER_SAMPLES_PER_FRAME (RESAMPLER_ZERO_CROSSINGS * 2) // For a given srcpos, `srcpos + frame` are sampled, where `-RESAMPLER_ZERO_CROSSINGS < frame <= RESAMPLER_ZERO_CROSSINGS`. // Note, when upsampling, it is also possible to start sampling from `srcpos = -1`. #define RESAMPLER_MAX_PADDING_FRAMES (RESAMPLER_ZERO_CROSSINGS + 1) -#define RESAMPLER_FILTER_INTERP_BITS (32 - RESAMPLER_BITS_PER_ZERO_CROSSING) -#define RESAMPLER_FILTER_INTERP_RANGE (1 << RESAMPLER_FILTER_INTERP_BITS) +// More bits gives more precision, at the cost of a larger table. +#define RESAMPLER_BITS_PER_ZERO_CROSSING 3 +#define RESAMPLER_SAMPLES_PER_ZERO_CROSSING (1 << RESAMPLER_BITS_PER_ZERO_CROSSING) +#define RESAMPLER_FILTER_INTERP_BITS (32 - RESAMPLER_BITS_PER_ZERO_CROSSING) +#define RESAMPLER_FILTER_INTERP_RANGE (1 << RESAMPLER_FILTER_INTERP_BITS) -#define RESAMPLER_SAMPLES_PER_FRAME (RESAMPLER_ZERO_CROSSINGS * 2) +// ResampleFrame is just a vector/matrix/matrix multiplication. +// It performs cubic interpolation of the filter, then multiplies that with the input. +// dst = [1, frac, frac^2, frac^3] * filter * src -#define RESAMPLER_FULL_FILTER_SIZE (RESAMPLER_SAMPLES_PER_FRAME * (RESAMPLER_SAMPLES_PER_ZERO_CROSSING + 1)) +// Cubic Polynomial +typedef union Cubic +{ + float v[4]; + +#ifdef SDL_SSE_INTRINSICS + // Aligned loads can be used directly as memory operands for mul/add + __m128 v128; +#endif -static void ResampleFrame_Scalar(const float *src, float *dst, const float *raw_filter, float interp, int chans) +#ifdef SDL_NEON_INTRINSICS + float32x4_t v128; +#endif + +} Cubic; + +static void ResampleFrame_Generic(const float *src, float *dst, const Cubic *filter, float frac, int chans) { + const float frac2 = frac * frac; + const float frac3 = frac * frac2; + int i, chan; + float scales[RESAMPLER_SAMPLES_PER_FRAME]; + + for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; ++i, ++filter) { + scales[i] = filter->v[0] + (filter->v[1] * frac) + (filter->v[2] * frac2) + (filter->v[3] * frac3); + } + + for (chan = 0; chan < chans; ++chan) { + float out = 0.0f; - float filter[RESAMPLER_SAMPLES_PER_FRAME]; + for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; ++i) { + out += src[i * chans + chan] * scales[i]; + } + + dst[chan] = out; + } +} + +static void ResampleFrame_Mono(const float *src, float *dst, const Cubic *filter, float frac, int chans) +{ + const float frac2 = frac * frac; + const float frac3 = frac * frac2; + + int i; + float out = 0.0f; + + for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; ++i, ++filter) { + // Interpolate between the nearest two filters + const float scale = filter->v[0] + (filter->v[1] * frac) + (filter->v[2] * frac2) + (filter->v[3] * frac3); - // Interpolate between the nearest two filters - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - filter[i] = (raw_filter[i] * (1.0f - interp)) + (raw_filter[i + RESAMPLER_SAMPLES_PER_FRAME] * interp); + out += src[i] * scale; + } + + dst[0] = out; +} + +static void ResampleFrame_Stereo(const float *src, float *dst, const Cubic *filter, float frac, int chans) +{ + const float frac2 = frac * frac; + const float frac3 = frac * frac2; + + int i; + float out0 = 0.0f; + float out1 = 0.0f; + + for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; ++i, ++filter) { + // Interpolate between the nearest two filters + const float scale = filter->v[0] + (filter->v[1] * frac) + (filter->v[2] * frac2) + (filter->v[3] * frac3); + + out0 += src[i * 2 + 0] * scale; + out1 += src[i * 2 + 1] * scale; + } + + dst[0] = out0; + dst[1] = out1; +} + +#ifdef SDL_SSE_INTRINSICS +#define sdl_madd_ps(a, b, c) _mm_add_ps(a, _mm_mul_ps(b, c)) // Not-so-fused multiply-add + +static void SDL_TARGETING("sse") ResampleFrame_Generic_SSE(const float *src, float *dst, const Cubic *filter, float frac, int chans) +{ +#if RESAMPLER_SAMPLES_PER_FRAME != 12 +#error Invalid samples per frame +#endif + + __m128 f0, f1, f2; + + { + const __m128 frac1 = _mm_set1_ps(frac); + const __m128 frac2 = _mm_mul_ps(frac1, frac1); + const __m128 frac3 = _mm_mul_ps(frac1, frac2); + +// Transposed in SetupAudioResampler +// Explicitly use _mm_load_ps to workaround ICE in GCC 4.9.4 accessing Cubic.v128 +#define X(out) \ + out = _mm_load_ps(filter[0].v); \ + out = sdl_madd_ps(out, frac1, _mm_load_ps(filter[1].v)); \ + out = sdl_madd_ps(out, frac2, _mm_load_ps(filter[2].v)); \ + out = sdl_madd_ps(out, frac3, _mm_load_ps(filter[3].v)); \ + filter += 4 + + X(f0); + X(f1); + X(f2); + +#undef X } if (chans == 2) { - float out[2]; - out[0] = 0.0f; - out[1] = 0.0f; - - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - const float scale = filter[i]; - out[0] += src[i * 2 + 0] * scale; - out[1] += src[i * 2 + 1] * scale; - } + // Duplicate each of the filter elements and multiply by the input + // Use two accumulators to improve throughput + __m128 out0 = _mm_mul_ps(_mm_loadu_ps(src + 0), _mm_unpacklo_ps(f0, f0)); + __m128 out1 = _mm_mul_ps(_mm_loadu_ps(src + 4), _mm_unpackhi_ps(f0, f0)); + out0 = sdl_madd_ps(out0, _mm_loadu_ps(src + 8), _mm_unpacklo_ps(f1, f1)); + out1 = sdl_madd_ps(out1, _mm_loadu_ps(src + 12), _mm_unpackhi_ps(f1, f1)); + out0 = sdl_madd_ps(out0, _mm_loadu_ps(src + 16), _mm_unpacklo_ps(f2, f2)); + out1 = sdl_madd_ps(out1, _mm_loadu_ps(src + 20), _mm_unpackhi_ps(f2, f2)); + + // Add the accumulators together + __m128 out = _mm_add_ps(out0, out1); - dst[0] = out[0]; - dst[1] = out[1]; + // Add the lower and upper pairs together + out = _mm_add_ps(out, _mm_movehl_ps(out, out)); + + // Store the result + _mm_storel_pi((__m64 *)dst, out); return; } if (chans == 1) { - float out = 0.0f; + // Multiply the filter by the input + __m128 out = _mm_mul_ps(f0, _mm_loadu_ps(src + 0)); + out = sdl_madd_ps(out, f1, _mm_loadu_ps(src + 4)); + out = sdl_madd_ps(out, f2, _mm_loadu_ps(src + 8)); - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - out += src[i] * filter[i]; - } + // Horizontal sum + __m128 shuf = _mm_shuffle_ps(out, out, _MM_SHUFFLE(2, 3, 0, 1)); + out = _mm_add_ps(out, shuf); + out = _mm_add_ss(out, _mm_movehl_ps(shuf, out)); - dst[0] = out; + _mm_store_ss(dst, out); return; } - for (chan = 0; chan < chans; chan++) { - float f = 0.0f; + int chan = 0; - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - f += src[i * chans + chan] * filter[i]; - } + // Process 4 channels at once + for (; chan + 4 <= chans; chan += 4) { + const float *in = &src[chan]; + __m128 out0 = _mm_setzero_ps(); + __m128 out1 = _mm_setzero_ps(); + +#define X(a, b, out) \ + out = sdl_madd_ps(out, _mm_loadu_ps(in), _mm_shuffle_ps(a, a, _MM_SHUFFLE(b, b, b, b))); \ + in += chans + +#define Y(a) \ + X(a, 0, out0); \ + X(a, 1, out1); \ + X(a, 2, out0); \ + X(a, 3, out1) + + Y(f0); + Y(f1); + Y(f2); + +#undef X +#undef Y + + // Add the accumulators together + __m128 out = _mm_add_ps(out0, out1); + + _mm_storeu_ps(&dst[chan], out); + } + + // Process the remaining channels one at a time. + // Channel counts 1,2,4,8 are already handled above, leaving 3,5,6,7 to deal with (looping 3,1,2,3 times). + // Without vgatherdps (AVX2), this gets quite messy. + for (; chan < chans; ++chan) { + const float *in = &src[chan]; + __m128 v0, v1, v2; + +#define X(x) \ + x = _mm_unpacklo_ps(_mm_load_ss(in), _mm_load_ss(in + chans)); \ + in += chans + chans; \ + x = _mm_movelh_ps(x, _mm_unpacklo_ps(_mm_load_ss(in), _mm_load_ss(in + chans))); \ + in += chans + chans - dst[chan] = f; + X(v0); + X(v1); + X(v2); + +#undef X + + __m128 out = _mm_mul_ps(f0, v0); + out = sdl_madd_ps(out, f1, v1); + out = sdl_madd_ps(out, f2, v2); + + // Horizontal sum + __m128 shuf = _mm_shuffle_ps(out, out, _MM_SHUFFLE(2, 3, 0, 1)); + out = _mm_add_ps(out, shuf); + out = _mm_add_ss(out, _mm_movehl_ps(shuf, out)); + + _mm_store_ss(&dst[chan], out); } } -#ifdef SDL_SSE_INTRINSICS -static void SDL_TARGETING("sse") ResampleFrame_SSE(const float *src, float *dst, const float *raw_filter, float interp, int chans) +#undef sdl_madd_ps +#endif + +#ifdef SDL_NEON_INTRINSICS +static void ResampleFrame_Generic_NEON(const float *src, float *dst, const Cubic *filter, float frac, int chans) { -#if RESAMPLER_SAMPLES_PER_FRAME != 10 +#if RESAMPLER_SAMPLES_PER_FRAME != 12 #error Invalid samples per frame #endif - // Load the filter - __m128 f0 = _mm_loadu_ps(raw_filter + 0); - __m128 f1 = _mm_loadu_ps(raw_filter + 4); - __m128 f2 = _mm_loadl_pi(_mm_setzero_ps(), (const __m64 *)(raw_filter + 8)); + float32x4_t f0, f1, f2; - __m128 g0 = _mm_loadu_ps(raw_filter + 10); - __m128 g1 = _mm_loadu_ps(raw_filter + 14); - __m128 g2 = _mm_loadl_pi(_mm_setzero_ps(), (const __m64 *)(raw_filter + 18)); + { + const float32x4_t frac1 = vdupq_n_f32(frac); + const float32x4_t frac2 = vmulq_f32(frac1, frac1); + const float32x4_t frac3 = vmulq_f32(frac1, frac2); - __m128 interp1 = _mm_set1_ps(interp); - __m128 interp2 = _mm_sub_ps(_mm_set1_ps(1.0f), _mm_set1_ps(interp)); +// Transposed in SetupAudioResampler +#define X(out) \ + out = vmlaq_f32(vmlaq_f32(vmlaq_f32(filter[0].v128, filter[1].v128, frac1), filter[2].v128, frac2), filter[3].v128, frac3); \ + filter += 4 - // Linear interpolate the filter - f0 = _mm_add_ps(_mm_mul_ps(f0, interp2), _mm_mul_ps(g0, interp1)); - f1 = _mm_add_ps(_mm_mul_ps(f1, interp2), _mm_mul_ps(g1, interp1)); - f2 = _mm_add_ps(_mm_mul_ps(f2, interp2), _mm_mul_ps(g2, interp1)); + X(f0); + X(f1); + X(f2); + +#undef X + } if (chans == 2) { - // Duplicate each of the filter elements - g0 = _mm_unpackhi_ps(f0, f0); - f0 = _mm_unpacklo_ps(f0, f0); - g1 = _mm_unpackhi_ps(f1, f1); - f1 = _mm_unpacklo_ps(f1, f1); - f2 = _mm_unpacklo_ps(f2, f2); + float32x4x2_t g0 = vzipq_f32(f0, f0); + float32x4x2_t g1 = vzipq_f32(f1, f1); + float32x4x2_t g2 = vzipq_f32(f2, f2); - // Multiply the filter by the input - f0 = _mm_mul_ps(f0, _mm_loadu_ps(src + 0)); - g0 = _mm_mul_ps(g0, _mm_loadu_ps(src + 4)); - f1 = _mm_mul_ps(f1, _mm_loadu_ps(src + 8)); - g1 = _mm_mul_ps(g1, _mm_loadu_ps(src + 12)); - f2 = _mm_mul_ps(f2, _mm_loadu_ps(src + 16)); + // Duplicate each of the filter elements and multiply by the input + // Use two accumulators to improve throughput + float32x4_t out0 = vmulq_f32(vld1q_f32(src + 0), g0.val[0]); + float32x4_t out1 = vmulq_f32(vld1q_f32(src + 4), g0.val[1]); + out0 = vmlaq_f32(out0, vld1q_f32(src + 8), g1.val[0]); + out1 = vmlaq_f32(out1, vld1q_f32(src + 12), g1.val[1]); + out0 = vmlaq_f32(out0, vld1q_f32(src + 16), g2.val[0]); + out1 = vmlaq_f32(out1, vld1q_f32(src + 20), g2.val[1]); + + // Add the accumulators together + out0 = vaddq_f32(out0, out1); - // Calculate the sum - f0 = _mm_add_ps(_mm_add_ps(_mm_add_ps(f0, g0), _mm_add_ps(f1, g1)), f2); - f0 = _mm_add_ps(f0, _mm_movehl_ps(f0, f0)); + // Add the lower and upper pairs together + float32x2_t out = vadd_f32(vget_low_f32(out0), vget_high_f32(out0)); // Store the result - _mm_storel_pi((__m64 *)dst, f0); + vst1_f32(dst, out); return; } if (chans == 1) { // Multiply the filter by the input - f0 = _mm_mul_ps(f0, _mm_loadu_ps(src + 0)); - f1 = _mm_mul_ps(f1, _mm_loadu_ps(src + 4)); - f2 = _mm_mul_ps(f2, _mm_loadl_pi(_mm_setzero_ps(), (const __m64 *)(src + 8))); + float32x4_t out = vmulq_f32(f0, vld1q_f32(src + 0)); + out = vmlaq_f32(out, f1, vld1q_f32(src + 4)); + out = vmlaq_f32(out, f2, vld1q_f32(src + 8)); - // Calculate the sum - f0 = _mm_add_ps(f0, f1); - f0 = _mm_add_ps(_mm_add_ps(f0, f2), _mm_movehl_ps(f0, f0)); - f0 = _mm_add_ss(f0, _mm_shuffle_ps(f0, f0, _MM_SHUFFLE(1, 1, 1, 1))); + // Horizontal sum + float32x2_t sum = vadd_f32(vget_low_f32(out), vget_high_f32(out)); + sum = vpadd_f32(sum, sum); - // Store the result - _mm_store_ss(dst, f0); + vst1_lane_f32(dst, sum, 0); return; } - float filter[RESAMPLER_SAMPLES_PER_FRAME]; - _mm_storeu_ps(filter + 0, f0); - _mm_storeu_ps(filter + 4, f1); - _mm_storel_pi((__m64 *)(filter + 8), f2); - - int i, chan = 0; + int chan = 0; + // Process 4 channels at once for (; chan + 4 <= chans; chan += 4) { - f0 = _mm_setzero_ps(); + const float *in = &src[chan]; + float32x4_t out0 = vdupq_n_f32(0); + float32x4_t out1 = vdupq_n_f32(0); - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - f0 = _mm_add_ps(f0, _mm_mul_ps(_mm_loadu_ps(&src[i * chans + chan]), _mm_load1_ps(&filter[i]))); - } +#define X(a, b, out) \ + out = vmlaq_f32(out, vld1q_f32(in), vdupq_lane_f32(a, b)); \ + in += chans - _mm_storeu_ps(&dst[chan], f0); - } +#define Y(a) \ + X(vget_low_f32(a), 0, out0); \ + X(vget_low_f32(a), 1, out1); \ + X(vget_high_f32(a), 0, out0); \ + X(vget_high_f32(a), 1, out1) - for (; chan < chans; chan++) { - f0 = _mm_setzero_ps(); + Y(f0); + Y(f1); + Y(f2); - for (i = 0; i < RESAMPLER_SAMPLES_PER_FRAME; i++) { - f0 = _mm_add_ss(f0, _mm_mul_ss(_mm_load_ss(&src[i * chans + chan]), _mm_load_ss(&filter[i]))); - } +#undef X +#undef Y + + // Add the accumulators together + float32x4_t out = vaddq_f32(out0, out1); - _mm_store_ss(&dst[chan], f0); + vst1q_f32(&dst[chan], out); + } + + // Process the remaining channels one at a time. + // Channel counts 1,2,4,8 are already handled above, leaving 3,5,6,7 to deal with (looping 3,1,2,3 times). + for (; chan < chans; ++chan) { + const float *in = &src[chan]; + float32x4_t v0, v1, v2; + +#define X(x) \ + x = vld1q_dup_f32(in); \ + in += chans; \ + x = vld1q_lane_f32(in, x, 1); \ + in += chans; \ + x = vld1q_lane_f32(in, x, 2); \ + in += chans; \ + x = vld1q_lane_f32(in, x, 3); \ + in += chans + + X(v0); + X(v1); + X(v2); + +#undef X + + float32x4_t out = vmulq_f32(f0, v0); + out = vmlaq_f32(out, f1, v1); + out = vmlaq_f32(out, f2, v2); + + // Horizontal sum + float32x2_t sum = vadd_f32(vget_low_f32(out), vget_high_f32(out)); + sum = vpadd_f32(sum, sum); + + vst1_lane_f32(&dst[chan], sum, 0); } } #endif -static void (*ResampleFrame)(const float *src, float *dst, const float *raw_filter, float interp, int chans); +// Calculate the cubic equation which passes through all four points. +// https://en.wikipedia.org/wiki/Ordinary_least_squares +// https://en.wikipedia.org/wiki/Polynomial_regression +static void CubicLeastSquares(Cubic *coeffs, float y0, float y1, float y2, float y3) +{ + // Least squares matrix for xs = [0, 1/3, 2/3, 1] + // [ 1.0 0.0 0.0 0.0 ] + // [ -5.5 9.0 -4.5 1.0 ] + // [ 9.0 -22.5 18.0 -4.5 ] + // [ -4.5 13.5 -13.5 4.5 ] + + coeffs->v[0] = y0; + coeffs->v[1] = -5.5f * y0 + 9.0f * y1 - 4.5f * y2 + y3; + coeffs->v[2] = 9.0f * y0 - 22.5f * y1 + 18.0f * y2 - 4.5f * y3; + coeffs->v[3] = -4.5f * y0 + 13.5f * y1 - 13.5f * y2 + 4.5f * y3; +} -static float FullResamplerFilter[RESAMPLER_FULL_FILTER_SIZE]; +// Zeroth-order modified Bessel function of the first kind +// https://mathworld.wolfram.com/ModifiedBesselFunctionoftheFirstKind.html +static float BesselI0(float x) +{ + float sum = 0.0f; + float i = 1.0f; + float t = 1.0f; + x *= x * 0.25f; + + while (t >= sum * SDL_FLT_EPSILON) { + sum += t; + t *= x / (i * i); + ++i; + } -void SDL_SetupAudioResampler(void) + return sum; +} + +// Pre-calculate 180 degrees of sin(pi * x) / pi +// The speedup from this isn't huge, but it also avoids precision issues. +// If sinf isn't available, SDL_sinf just calls SDL_sin. +// Know what SDL_sin(SDL_PI_F) equals? Not quite zero. +static void SincTable(float *table, int len) { - static SDL_bool setup = SDL_FALSE; - if (setup) { - return; + int i; + + for (i = 0; i < len; ++i) { + table[i] = SDL_sinf(i * (SDL_PI_F / len)) / SDL_PI_F; } +} + +// Calculate Sinc(x/y), using a lookup table +static float Sinc(float *table, int x, int y) +{ + float s = table[x % y]; + s = ((x / y) & 1) ? -s : s; + return (s * y) / x; +} + +static Cubic ResamplerFilter[RESAMPLER_SAMPLES_PER_ZERO_CROSSING][RESAMPLER_SAMPLES_PER_FRAME]; + +static void GenerateResamplerFilter(void) +{ + enum + { + // Generate samples at 3x the target resolution, so that we have samples at [0, 1/3, 2/3, 1] of each position + TABLE_SAMPLES_PER_ZERO_CROSSING = RESAMPLER_SAMPLES_PER_ZERO_CROSSING * 3, + TABLE_SIZE = RESAMPLER_ZERO_CROSSINGS * TABLE_SAMPLES_PER_ZERO_CROSSING, + }; + + // if dB > 50, beta=(0.1102 * (dB - 8.7)), according to Matlab. + const float dB = 80.0f; + const float beta = 0.1102f * (dB - 8.7f); + const float bessel_beta = BesselI0(beta); + const float lensqr = TABLE_SIZE * TABLE_SIZE; - // Build a table combining the left and right wings, for faster access int i, j; + float sinc[TABLE_SAMPLES_PER_ZERO_CROSSING]; + SincTable(sinc, TABLE_SAMPLES_PER_ZERO_CROSSING); + + // Generate one wing of the filter + // https://en.wikipedia.org/wiki/Kaiser_window + // https://en.wikipedia.org/wiki/Whittaker%E2%80%93Shannon_interpolation_formula + float filter[TABLE_SIZE + 1]; + filter[0] = 1.0f; + + for (i = 1; i <= TABLE_SIZE; ++i) { + float b = BesselI0(beta * SDL_sqrtf((lensqr - (i * i)) / lensqr)) / bessel_beta; + float s = Sinc(sinc, i, TABLE_SAMPLES_PER_ZERO_CROSSING); + filter[i] = b * s; + } + + // Generate the coefficients for each point + // When interpolating, the fraction represents how far we are between input samples, + // so we need to align the filter by "moving" it to the right. + // + // For the left wing, this means interpolating "forwards" (away from the center) + // For the right wing, this means interpolating "backwards" (towards the center) + // + // The center of the filter is at the end of the left wing (RESAMPLER_ZERO_CROSSINGS - 1) + // The left wing is the filter, but reversed + // The right wing is the filter, but offset by 1 + // + // Since the right wing is offset by 1, this just means we interpolate backwards + // between the same points, instead of forwards + // interp(p[n], p[n+1], t) = interp(p[n+1], p[n+1-1], 1 - t) = interp(p[n+1], p[n], 1 - t) for (i = 0; i < RESAMPLER_SAMPLES_PER_ZERO_CROSSING; ++i) { - for (j = 0; j < RESAMPLER_ZERO_CROSSINGS; j++) { - int lwing = (i * RESAMPLER_SAMPLES_PER_FRAME) + (RESAMPLER_ZERO_CROSSINGS - 1) - j; - int rwing = (RESAMPLER_FULL_FILTER_SIZE - 1) - lwing; + for (j = 0; j < RESAMPLER_ZERO_CROSSINGS; ++j) { + const float *ys = &filter[((j * RESAMPLER_SAMPLES_PER_ZERO_CROSSING) + i) * 3]; + + Cubic *fwd = &ResamplerFilter[i][RESAMPLER_ZERO_CROSSINGS - j - 1]; + Cubic *rev = &ResamplerFilter[RESAMPLER_SAMPLES_PER_ZERO_CROSSING - i - 1][RESAMPLER_ZERO_CROSSINGS + j]; - float value = ResamplerFilter[(i * RESAMPLER_ZERO_CROSSINGS) + j]; - FullResamplerFilter[lwing] = value; - FullResamplerFilter[rwing] = value; + // Calculate the cubic equation of the 4 points + CubicLeastSquares(fwd, ys[0], ys[1], ys[2], ys[3]); + CubicLeastSquares(rev, ys[3], ys[2], ys[1], ys[0]); } } +} - for (i = 0; i < RESAMPLER_ZERO_CROSSINGS; ++i) { - int rwing = i + RESAMPLER_ZERO_CROSSINGS; - int lwing = (RESAMPLER_FULL_FILTER_SIZE - 1) - rwing; +typedef void (*ResampleFrameFunc)(const float *src, float *dst, const Cubic *filter, float frac, int chans); +static ResampleFrameFunc ResampleFrame[8]; - FullResamplerFilter[lwing] = 0.0f; - FullResamplerFilter[rwing] = 0.0f; +// Transpose 4x4 floats +static void Transpose4x4(Cubic *data) +{ + int i, j; + + Cubic temp[4] = { data[0], data[1], data[2], data[3] }; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 4; ++j) { + data[i].v[j] = temp[j].v[i]; + } } +} + +static void SetupAudioResampler(void) +{ + int i, j; + bool transpose = false; - ResampleFrame = ResampleFrame_Scalar; + GenerateResamplerFilter(); #ifdef SDL_SSE_INTRINSICS if (SDL_HasSSE()) { - ResampleFrame = ResampleFrame_SSE; - } + for (i = 0; i < 8; ++i) { + ResampleFrame[i] = ResampleFrame_Generic_SSE; + } + transpose = true; + } else +#endif +#ifdef SDL_NEON_INTRINSICS + if (SDL_HasNEON()) { + for (i = 0; i < 8; ++i) { + ResampleFrame[i] = ResampleFrame_Generic_NEON; + } + transpose = true; + } else #endif + { + for (i = 0; i < 8; ++i) { + ResampleFrame[i] = ResampleFrame_Generic; + } + + ResampleFrame[0] = ResampleFrame_Mono; + ResampleFrame[1] = ResampleFrame_Stereo; + } + + if (transpose) { + // Transpose each set of 4 coefficients, to reduce work when resampling + for (i = 0; i < RESAMPLER_SAMPLES_PER_ZERO_CROSSING; ++i) { + for (j = 0; j + 4 <= RESAMPLER_SAMPLES_PER_FRAME; j += 4) { + Transpose4x4(&ResamplerFilter[i][j]); + } + } + } +} + +void SDL_SetupAudioResampler(void) +{ + static SDL_InitState init; - setup = SDL_TRUE; + if (SDL_ShouldInit(&init)) { + SetupAudioResampler(); + SDL_SetInitialized(&init, true); + } } Sint64 SDL_GetResampleRate(int src_rate, int dst_rate) @@ -251,24 +608,24 @@ int SDL_GetResamplerPaddingFrames(Sint64 resample_rate) } // These are not general purpose. They do not check for all possible underflow/overflow -SDL_FORCE_INLINE Sint64 ResamplerAdd(Sint64 a, Sint64 b, Sint64 *ret) +SDL_FORCE_INLINE bool ResamplerAdd(Sint64 a, Sint64 b, Sint64 *ret) { if ((b > 0) && (a > SDL_MAX_SINT64 - b)) { - return -1; + return false; } *ret = a + b; - return 0; + return true; } -SDL_FORCE_INLINE Sint64 ResamplerMul(Sint64 a, Sint64 b, Sint64 *ret) +SDL_FORCE_INLINE bool ResamplerMul(Sint64 a, Sint64 b, Sint64 *ret) { if ((b > 0) && (a > SDL_MAX_SINT64 / b)) { - return -1; + return false; } *ret = a * b; - return 0; + return true; } Sint64 SDL_GetResamplerInputFrames(Sint64 output_frames, Sint64 resample_rate, Sint64 resample_offset) @@ -277,8 +634,8 @@ Sint64 SDL_GetResamplerInputFrames(Sint64 output_frames, Sint64 resample_rate, S // ((((output_frames - 1) * resample_rate) + resample_offset) >> 32) + 1 Sint64 output_offset; - if (ResamplerMul(output_frames, resample_rate, &output_offset) || - ResamplerAdd(output_offset, -resample_rate + resample_offset + 0x100000000, &output_offset)) { + if (!ResamplerMul(output_frames, resample_rate, &output_offset) || + !ResamplerAdd(output_offset, -resample_rate + resample_offset + 0x100000000, &output_offset)) { output_offset = SDL_MAX_SINT64; } @@ -294,13 +651,13 @@ Sint64 SDL_GetResamplerOutputFrames(Sint64 input_frames, Sint64 resample_rate, S // input_offset = (input_frames << 32) - resample_offset; Sint64 input_offset; - if (ResamplerMul(input_frames, 0x100000000, &input_offset) || - ResamplerAdd(input_offset, -resample_offset, &input_offset)) { + if (!ResamplerMul(input_frames, 0x100000000, &input_offset) || + !ResamplerAdd(input_offset, -resample_offset, &input_offset)) { input_offset = SDL_MAX_SINT64; } // output_frames = div_ceil(input_offset, resample_rate) - Sint64 output_frames = (input_offset > 0) ? (((input_offset - 1) / resample_rate) + 1) : 0; + Sint64 output_frames = (input_offset > 0) ? ((input_offset + resample_rate * 3 / 4) / resample_rate) : 0; *inout_resample_offset = (output_frames * resample_rate) - input_offset; @@ -312,21 +669,24 @@ void SDL_ResampleAudio(int chans, const float *src, int inframes, float *dst, in { int i; Sint64 srcpos = *inout_resample_offset; + ResampleFrameFunc resample_frame = ResampleFrame[chans - 1]; SDL_assert(resample_rate > 0); - for (i = 0; i < outframes; i++) { + src -= (RESAMPLER_ZERO_CROSSINGS - 1) * chans; + + for (i = 0; i < outframes; ++i) { int srcindex = (int)(Sint32)(srcpos >> 32); Uint32 srcfraction = (Uint32)(srcpos & 0xFFFFFFFF); srcpos += resample_rate; SDL_assert(srcindex >= -1 && srcindex < inframes); - const float *filter = &FullResamplerFilter[(srcfraction >> RESAMPLER_FILTER_INTERP_BITS) * RESAMPLER_SAMPLES_PER_FRAME]; - const float interp = (float)(srcfraction & (RESAMPLER_FILTER_INTERP_RANGE - 1)) * (1.0f / RESAMPLER_FILTER_INTERP_RANGE); + const Cubic *filter = ResamplerFilter[srcfraction >> RESAMPLER_FILTER_INTERP_BITS]; + const float frac = (float)(srcfraction & (RESAMPLER_FILTER_INTERP_RANGE - 1)) * (1.0f / RESAMPLER_FILTER_INTERP_RANGE); - const float *frame = &src[(srcindex - (RESAMPLER_ZERO_CROSSINGS - 1)) * chans]; - ResampleFrame(frame, dst, filter, interp, chans); + const float *frame = &src[srcindex * chans]; + resample_frame(frame, dst, filter, frac, chans); dst += chans; } diff --git a/libs/SDL3/src/audio/SDL_audiotypecvt.c b/libs/SDL3/src/audio/SDL_audiotypecvt.c index 43cabd9b5..a2978ee1c 100644 --- a/libs/SDL3/src/audio/SDL_audiotypecvt.c +++ b/libs/SDL3/src/audio/SDL_audiotypecvt.c @@ -22,9 +22,6 @@ #include "SDL_sysaudio.h" -// TODO: NEON is disabled until https://github.com/libsdl-org/SDL/issues/8352 can be fixed -#undef SDL_NEON_INTRINSICS - #define DIVBY2147483648 0.0000000004656612873077392578125f // 0x1p-31f // start fallback scalar converters @@ -184,13 +181,47 @@ static void SDL_Convert_F32_to_S32_Scalar(Sint32 *dst, const float *src, int num #undef SIGNMASK +static void SDL_Convert_Swap16_Scalar(Uint16* dst, const Uint16* src, int num_samples) +{ + int i; + + for (i = 0; i < num_samples; ++i) { + dst[i] = SDL_Swap16(src[i]); + } +} + +static void SDL_Convert_Swap32_Scalar(Uint32* dst, const Uint32* src, int num_samples) +{ + int i; + + for (i = 0; i < num_samples; ++i) { + dst[i] = SDL_Swap32(src[i]); + } +} + // end fallback scalar converters +// Convert forwards, when sizeof(*src) >= sizeof(*dst) +#define CONVERT_16_FWD(CVT1, CVT16) \ + int i = 0; \ + if (num_samples >= 16) { \ + while ((uintptr_t)(&dst[i]) & 15) { CVT1 ++i; } \ + while ((i + 16) <= num_samples) { CVT16 i += 16; } \ + } \ + while (i < num_samples) { CVT1 ++i; } + +// Convert backwards, when sizeof(*src) <= sizeof(*dst) +#define CONVERT_16_REV(CVT1, CVT16) \ + int i = num_samples; \ + if (i >= 16) { \ + while ((uintptr_t)(&dst[i]) & 15) { --i; CVT1 } \ + while (i >= 16) { i -= 16; CVT16 } \ + } \ + while (i > 0) { --i; CVT1 } + #ifdef SDL_SSE2_INTRINSICS static void SDL_TARGETING("sse2") SDL_Convert_S8_to_F32_SSE2(float *dst, const Sint8 *src, int num_samples) { - int i = num_samples; - /* 1) Flip the sign bit to convert from S8 to U8 format * 2) Construct a float in the range [65536.0, 65538.0) * 3) Shift the float range to [-1.0, 1.0) @@ -202,35 +233,28 @@ static void SDL_TARGETING("sse2") SDL_Convert_S8_to_F32_SSE2(float *dst, const S LOG_DEBUG_AUDIO_CONVERT("S8", "F32 (using SSE2)"); - while (i >= 16) { - i -= 16; - + CONVERT_16_REV({ + _mm_store_ss(&dst[i], _mm_add_ss(_mm_castsi128_ps(_mm_cvtsi32_si128((Uint8)src[i] ^ 0x47800080u)), offset)); + }, { const __m128i bytes = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&src[i]), flipper); - const __m128i shorts1 = _mm_unpacklo_epi8(bytes, zero); - const __m128i shorts2 = _mm_unpackhi_epi8(bytes, zero); - - const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); - const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); - const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts2, caster)), offset); - const __m128 floats4 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts2, caster)), offset); + const __m128i shorts0 = _mm_unpacklo_epi8(bytes, zero); + const __m128i shorts1 = _mm_unpackhi_epi8(bytes, zero); - _mm_storeu_ps(&dst[i], floats1); - _mm_storeu_ps(&dst[i + 4], floats2); - _mm_storeu_ps(&dst[i + 8], floats3); - _mm_storeu_ps(&dst[i + 12], floats4); - } + const __m128 floats0 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts0, caster)), offset); + const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts0, caster)), offset); + const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); + const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); - while (i) { - --i; - _mm_store_ss(&dst[i], _mm_add_ss(_mm_castsi128_ps(_mm_cvtsi32_si128((Uint8)src[i] ^ 0x47800080u)), offset)); - } + _mm_store_ps(&dst[i], floats0); + _mm_store_ps(&dst[i + 4], floats1); + _mm_store_ps(&dst[i + 8], floats2); + _mm_store_ps(&dst[i + 12], floats3); + }) } static void SDL_TARGETING("sse2") SDL_Convert_U8_to_F32_SSE2(float *dst, const Uint8 *src, int num_samples) { - int i = num_samples; - /* 1) Construct a float in the range [65536.0, 65538.0) * 2) Shift the float range to [-1.0, 1.0) * dst[i] = i2f(src[i] | 0x47800000) - 65537.0 */ @@ -240,35 +264,28 @@ static void SDL_TARGETING("sse2") SDL_Convert_U8_to_F32_SSE2(float *dst, const U LOG_DEBUG_AUDIO_CONVERT("U8", "F32 (using SSE2)"); - while (i >= 16) { - i -= 16; - + CONVERT_16_REV({ + _mm_store_ss(&dst[i], _mm_add_ss(_mm_castsi128_ps(_mm_cvtsi32_si128((Uint8)src[i] ^ 0x47800000u)), offset)); + }, { const __m128i bytes = _mm_loadu_si128((const __m128i *)&src[i]); - const __m128i shorts1 = _mm_unpacklo_epi8(bytes, zero); - const __m128i shorts2 = _mm_unpackhi_epi8(bytes, zero); + const __m128i shorts0 = _mm_unpacklo_epi8(bytes, zero); + const __m128i shorts1 = _mm_unpackhi_epi8(bytes, zero); - const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); - const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); - const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts2, caster)), offset); - const __m128 floats4 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts2, caster)), offset); + const __m128 floats0 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts0, caster)), offset); + const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts0, caster)), offset); + const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); + const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); - _mm_storeu_ps(&dst[i], floats1); - _mm_storeu_ps(&dst[i + 4], floats2); - _mm_storeu_ps(&dst[i + 8], floats3); - _mm_storeu_ps(&dst[i + 12], floats4); - } - - while (i) { - --i; - _mm_store_ss(&dst[i], _mm_add_ss(_mm_castsi128_ps(_mm_cvtsi32_si128((Uint8)src[i] ^ 0x47800000u)), offset)); - } + _mm_store_ps(&dst[i], floats0); + _mm_store_ps(&dst[i + 4], floats1); + _mm_store_ps(&dst[i + 8], floats2); + _mm_store_ps(&dst[i + 12], floats3); + }) } static void SDL_TARGETING("sse2") SDL_Convert_S16_to_F32_SSE2(float *dst, const Sint16 *src, int num_samples) { - int i = num_samples; - /* 1) Flip the sign bit to convert from S16 to U16 format * 2) Construct a float in the range [256.0, 258.0) * 3) Shift the float range to [-1.0, 1.0) @@ -279,67 +296,53 @@ static void SDL_TARGETING("sse2") SDL_Convert_S16_to_F32_SSE2(float *dst, const LOG_DEBUG_AUDIO_CONVERT("S16", "F32 (using SSE2)"); - while (i >= 16) { - i -= 16; - - const __m128i shorts1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&src[i]), flipper); - const __m128i shorts2 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&src[i + 8]), flipper); - - const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); - const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); - const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts2, caster)), offset); - const __m128 floats4 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts2, caster)), offset); - - _mm_storeu_ps(&dst[i], floats1); - _mm_storeu_ps(&dst[i + 4], floats2); - _mm_storeu_ps(&dst[i + 8], floats3); - _mm_storeu_ps(&dst[i + 12], floats4); - } - - while (i) { - --i; + CONVERT_16_REV({ _mm_store_ss(&dst[i], _mm_add_ss(_mm_castsi128_ps(_mm_cvtsi32_si128((Uint16)src[i] ^ 0x43808000u)), offset)); - } + }, { + const __m128i shorts0 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&src[i]), flipper); + const __m128i shorts1 = _mm_xor_si128(_mm_loadu_si128((const __m128i *)&src[i + 8]), flipper); + + const __m128 floats0 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts0, caster)), offset); + const __m128 floats1 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts0, caster)), offset); + const __m128 floats2 = _mm_add_ps(_mm_castsi128_ps(_mm_unpacklo_epi16(shorts1, caster)), offset); + const __m128 floats3 = _mm_add_ps(_mm_castsi128_ps(_mm_unpackhi_epi16(shorts1, caster)), offset); + + _mm_store_ps(&dst[i], floats0); + _mm_store_ps(&dst[i + 4], floats1); + _mm_store_ps(&dst[i + 8], floats2); + _mm_store_ps(&dst[i + 12], floats3); + }) } static void SDL_TARGETING("sse2") SDL_Convert_S32_to_F32_SSE2(float *dst, const Sint32 *src, int num_samples) { - int i = num_samples; - // dst[i] = f32(src[i]) / f32(0x80000000) const __m128 scaler = _mm_set1_ps(DIVBY2147483648); LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using SSE2)"); - while (i >= 16) { - i -= 16; - - const __m128i ints1 = _mm_loadu_si128((const __m128i *)&src[i]); - const __m128i ints2 = _mm_loadu_si128((const __m128i *)&src[i + 4]); - const __m128i ints3 = _mm_loadu_si128((const __m128i *)&src[i + 8]); - const __m128i ints4 = _mm_loadu_si128((const __m128i *)&src[i + 12]); + CONVERT_16_FWD({ + _mm_store_ss(&dst[i], _mm_mul_ss(_mm_cvt_si2ss(_mm_setzero_ps(), src[i]), scaler)); + }, { + const __m128i ints0 = _mm_loadu_si128((const __m128i *)&src[i]); + const __m128i ints1 = _mm_loadu_si128((const __m128i *)&src[i + 4]); + const __m128i ints2 = _mm_loadu_si128((const __m128i *)&src[i + 8]); + const __m128i ints3 = _mm_loadu_si128((const __m128i *)&src[i + 12]); + const __m128 floats0 = _mm_mul_ps(_mm_cvtepi32_ps(ints0), scaler); const __m128 floats1 = _mm_mul_ps(_mm_cvtepi32_ps(ints1), scaler); const __m128 floats2 = _mm_mul_ps(_mm_cvtepi32_ps(ints2), scaler); const __m128 floats3 = _mm_mul_ps(_mm_cvtepi32_ps(ints3), scaler); - const __m128 floats4 = _mm_mul_ps(_mm_cvtepi32_ps(ints4), scaler); - _mm_storeu_ps(&dst[i], floats1); - _mm_storeu_ps(&dst[i + 4], floats2); - _mm_storeu_ps(&dst[i + 8], floats3); - _mm_storeu_ps(&dst[i + 12], floats4); - } - - while (i) { - --i; - _mm_store_ss(&dst[i], _mm_mul_ss(_mm_cvt_si2ss(_mm_setzero_ps(), src[i]), scaler)); - } + _mm_store_ps(&dst[i], floats0); + _mm_store_ps(&dst[i + 4], floats1); + _mm_store_ps(&dst[i + 8], floats2); + _mm_store_ps(&dst[i + 12], floats3); + }) } static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S8_SSE2(Sint8 *dst, const float *src, int num_samples) { - int i = num_samples; - /* 1) Shift the float range from [-1.0, 1.0] to [98303.0, 98305.0] * 2) Extract the lowest 16 bits and clamp to [-128, 127] * Overflow is correctly handled for inputs between roughly [-255.0, 255.0] @@ -349,43 +352,31 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S8_SSE2(Sint8 *dst, const f LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using SSE2)"); - while (i >= 16) { - const __m128 floats1 = _mm_loadu_ps(&src[0]); - const __m128 floats2 = _mm_loadu_ps(&src[4]); - const __m128 floats3 = _mm_loadu_ps(&src[8]); - const __m128 floats4 = _mm_loadu_ps(&src[12]); + CONVERT_16_FWD({ + const __m128i ints = _mm_castps_si128(_mm_add_ss(_mm_load_ss(&src[i]), offset)); + dst[i] = (Sint8)(_mm_cvtsi128_si32(_mm_packs_epi16(ints, ints)) & 0xFF); + }, { + const __m128 floats0 = _mm_loadu_ps(&src[i]); + const __m128 floats1 = _mm_loadu_ps(&src[i + 4]); + const __m128 floats2 = _mm_loadu_ps(&src[i + 8]); + const __m128 floats3 = _mm_loadu_ps(&src[i + 12]); + const __m128i ints0 = _mm_castps_si128(_mm_add_ps(floats0, offset)); const __m128i ints1 = _mm_castps_si128(_mm_add_ps(floats1, offset)); const __m128i ints2 = _mm_castps_si128(_mm_add_ps(floats2, offset)); const __m128i ints3 = _mm_castps_si128(_mm_add_ps(floats3, offset)); - const __m128i ints4 = _mm_castps_si128(_mm_add_ps(floats4, offset)); - const __m128i shorts1 = _mm_and_si128(_mm_packs_epi16(ints1, ints2), mask); - const __m128i shorts2 = _mm_and_si128(_mm_packs_epi16(ints3, ints4), mask); + const __m128i shorts0 = _mm_and_si128(_mm_packs_epi16(ints0, ints1), mask); + const __m128i shorts1 = _mm_and_si128(_mm_packs_epi16(ints2, ints3), mask); - const __m128i bytes = _mm_packus_epi16(shorts1, shorts2); + const __m128i bytes = _mm_packus_epi16(shorts0, shorts1); - _mm_storeu_si128((__m128i*)dst, bytes); - - i -= 16; - src += 16; - dst += 16; - } - - while (i) { - const __m128i ints = _mm_castps_si128(_mm_add_ss(_mm_load_ss(src), offset)); - *dst = (Sint8)(_mm_cvtsi128_si32(_mm_packs_epi16(ints, ints)) & 0xFF); - - --i; - ++src; - ++dst; - } + _mm_store_si128((__m128i*)&dst[i], bytes); + }) } static void SDL_TARGETING("sse2") SDL_Convert_F32_to_U8_SSE2(Uint8 *dst, const float *src, int num_samples) { - int i = num_samples; - /* 1) Shift the float range from [-1.0, 1.0] to [98304.0, 98306.0] * 2) Extract the lowest 16 bits and clamp to [0, 255] * Overflow is correctly handled for inputs between roughly [-254.0, 254.0] @@ -395,43 +386,31 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_U8_SSE2(Uint8 *dst, const f LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using SSE2)"); - while (i >= 16) { - const __m128 floats1 = _mm_loadu_ps(&src[0]); - const __m128 floats2 = _mm_loadu_ps(&src[4]); - const __m128 floats3 = _mm_loadu_ps(&src[8]); - const __m128 floats4 = _mm_loadu_ps(&src[12]); + CONVERT_16_FWD({ + const __m128i ints = _mm_castps_si128(_mm_add_ss(_mm_load_ss(&src[i]), offset)); + dst[i] = (Uint8)(_mm_cvtsi128_si32(_mm_packus_epi16(ints, ints)) & 0xFF); + }, { + const __m128 floats0 = _mm_loadu_ps(&src[i]); + const __m128 floats1 = _mm_loadu_ps(&src[i + 4]); + const __m128 floats2 = _mm_loadu_ps(&src[i + 8]); + const __m128 floats3 = _mm_loadu_ps(&src[i + 12]); + const __m128i ints0 = _mm_castps_si128(_mm_add_ps(floats0, offset)); const __m128i ints1 = _mm_castps_si128(_mm_add_ps(floats1, offset)); const __m128i ints2 = _mm_castps_si128(_mm_add_ps(floats2, offset)); const __m128i ints3 = _mm_castps_si128(_mm_add_ps(floats3, offset)); - const __m128i ints4 = _mm_castps_si128(_mm_add_ps(floats4, offset)); - const __m128i shorts1 = _mm_and_si128(_mm_packus_epi16(ints1, ints2), mask); - const __m128i shorts2 = _mm_and_si128(_mm_packus_epi16(ints3, ints4), mask); + const __m128i shorts0 = _mm_and_si128(_mm_packus_epi16(ints0, ints1), mask); + const __m128i shorts1 = _mm_and_si128(_mm_packus_epi16(ints2, ints3), mask); - const __m128i bytes = _mm_packus_epi16(shorts1, shorts2); + const __m128i bytes = _mm_packus_epi16(shorts0, shorts1); - _mm_storeu_si128((__m128i*)dst, bytes); - - i -= 16; - src += 16; - dst += 16; - } - - while (i) { - const __m128i ints = _mm_castps_si128(_mm_add_ss(_mm_load_ss(src), offset)); - *dst = (Uint8)(_mm_cvtsi128_si32(_mm_packus_epi16(ints, ints)) & 0xFF); - - --i; - ++src; - ++dst; - } + _mm_store_si128((__m128i*)&dst[i], bytes); + }) } static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S16_SSE2(Sint16 *dst, const float *src, int num_samples) { - int i = num_samples; - /* 1) Shift the float range from [-1.0, 1.0] to [256.0, 258.0] * 2) Shift the int range from [0x43800000, 0x43810000] to [-32768,32768] * 3) Clamp to range [-32768,32767] @@ -441,42 +420,30 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S16_SSE2(Sint16 *dst, const LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using SSE2)"); - while (i >= 16) { - const __m128 floats1 = _mm_loadu_ps(&src[0]); - const __m128 floats2 = _mm_loadu_ps(&src[4]); - const __m128 floats3 = _mm_loadu_ps(&src[8]); - const __m128 floats4 = _mm_loadu_ps(&src[12]); + CONVERT_16_FWD({ + const __m128i ints = _mm_sub_epi32(_mm_castps_si128(_mm_add_ss(_mm_load_ss(&src[i]), offset)), _mm_castps_si128(offset)); + dst[i] = (Sint16)(_mm_cvtsi128_si32(_mm_packs_epi32(ints, ints)) & 0xFFFF); + }, { + const __m128 floats0 = _mm_loadu_ps(&src[i]); + const __m128 floats1 = _mm_loadu_ps(&src[i + 4]); + const __m128 floats2 = _mm_loadu_ps(&src[i + 8]); + const __m128 floats3 = _mm_loadu_ps(&src[i + 12]); + const __m128i ints0 = _mm_sub_epi32(_mm_castps_si128(_mm_add_ps(floats0, offset)), _mm_castps_si128(offset)); const __m128i ints1 = _mm_sub_epi32(_mm_castps_si128(_mm_add_ps(floats1, offset)), _mm_castps_si128(offset)); const __m128i ints2 = _mm_sub_epi32(_mm_castps_si128(_mm_add_ps(floats2, offset)), _mm_castps_si128(offset)); const __m128i ints3 = _mm_sub_epi32(_mm_castps_si128(_mm_add_ps(floats3, offset)), _mm_castps_si128(offset)); - const __m128i ints4 = _mm_sub_epi32(_mm_castps_si128(_mm_add_ps(floats4, offset)), _mm_castps_si128(offset)); - - const __m128i shorts1 = _mm_packs_epi32(ints1, ints2); - const __m128i shorts2 = _mm_packs_epi32(ints3, ints4); - - _mm_storeu_si128((__m128i*)&dst[0], shorts1); - _mm_storeu_si128((__m128i*)&dst[8], shorts2); - i -= 16; - src += 16; - dst += 16; - } - - while (i) { - const __m128i ints = _mm_sub_epi32(_mm_castps_si128(_mm_add_ss(_mm_load_ss(src), offset)), _mm_castps_si128(offset)); - *dst = (Sint16)(_mm_cvtsi128_si32(_mm_packs_epi32(ints, ints)) & 0xFFFF); + const __m128i shorts0 = _mm_packs_epi32(ints0, ints1); + const __m128i shorts1 = _mm_packs_epi32(ints2, ints3); - --i; - ++src; - ++dst; - } + _mm_store_si128((__m128i*)&dst[i], shorts0); + _mm_store_si128((__m128i*)&dst[i + 8], shorts1); + }) } static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S32_SSE2(Sint32 *dst, const float *src, int num_samples) { - int i = num_samples; - /* 1) Scale the float range from [-1.0, 1.0] to [-2147483648.0, 2147483648.0] * 2) Convert to integer (values too small/large become 0x80000000 = -2147483648) * 3) Fixup values which were too large (0x80000000 ^ 0xFFFFFFFF = 2147483647) @@ -485,478 +452,449 @@ static void SDL_TARGETING("sse2") SDL_Convert_F32_to_S32_SSE2(Sint32 *dst, const LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using SSE2)"); - while (i >= 16) { - const __m128 floats1 = _mm_loadu_ps(&src[0]); - const __m128 floats2 = _mm_loadu_ps(&src[4]); - const __m128 floats3 = _mm_loadu_ps(&src[8]); - const __m128 floats4 = _mm_loadu_ps(&src[12]); - - const __m128 values1 = _mm_mul_ps(floats1, limit); - const __m128 values2 = _mm_mul_ps(floats2, limit); - const __m128 values3 = _mm_mul_ps(floats3, limit); - const __m128 values4 = _mm_mul_ps(floats4, limit); - - const __m128i ints1 = _mm_xor_si128(_mm_cvttps_epi32(values1), _mm_castps_si128(_mm_cmpge_ps(values1, limit))); - const __m128i ints2 = _mm_xor_si128(_mm_cvttps_epi32(values2), _mm_castps_si128(_mm_cmpge_ps(values2, limit))); - const __m128i ints3 = _mm_xor_si128(_mm_cvttps_epi32(values3), _mm_castps_si128(_mm_cmpge_ps(values3, limit))); - const __m128i ints4 = _mm_xor_si128(_mm_cvttps_epi32(values4), _mm_castps_si128(_mm_cmpge_ps(values4, limit))); - - _mm_storeu_si128((__m128i*)&dst[0], ints1); - _mm_storeu_si128((__m128i*)&dst[4], ints2); - _mm_storeu_si128((__m128i*)&dst[8], ints3); - _mm_storeu_si128((__m128i*)&dst[12], ints4); - - i -= 16; - src += 16; - dst += 16; - } - - while (i) { - const __m128 floats = _mm_load_ss(src); + CONVERT_16_FWD({ + const __m128 floats = _mm_load_ss(&src[i]); const __m128 values = _mm_mul_ss(floats, limit); const __m128i ints = _mm_xor_si128(_mm_cvttps_epi32(values), _mm_castps_si128(_mm_cmpge_ss(values, limit))); - *dst = (Sint32)_mm_cvtsi128_si32(ints); + dst[i] = (Sint32)_mm_cvtsi128_si32(ints); + }, { + const __m128 floats0 = _mm_loadu_ps(&src[i]); + const __m128 floats1 = _mm_loadu_ps(&src[i + 4]); + const __m128 floats2 = _mm_loadu_ps(&src[i + 8]); + const __m128 floats3 = _mm_loadu_ps(&src[i + 12]); + + const __m128 values1 = _mm_mul_ps(floats0, limit); + const __m128 values2 = _mm_mul_ps(floats1, limit); + const __m128 values3 = _mm_mul_ps(floats2, limit); + const __m128 values4 = _mm_mul_ps(floats3, limit); + + const __m128i ints0 = _mm_xor_si128(_mm_cvttps_epi32(values1), _mm_castps_si128(_mm_cmpge_ps(values1, limit))); + const __m128i ints1 = _mm_xor_si128(_mm_cvttps_epi32(values2), _mm_castps_si128(_mm_cmpge_ps(values2, limit))); + const __m128i ints2 = _mm_xor_si128(_mm_cvttps_epi32(values3), _mm_castps_si128(_mm_cmpge_ps(values3, limit))); + const __m128i ints3 = _mm_xor_si128(_mm_cvttps_epi32(values4), _mm_castps_si128(_mm_cmpge_ps(values4, limit))); + + _mm_store_si128((__m128i*)&dst[i], ints0); + _mm_store_si128((__m128i*)&dst[i + 4], ints1); + _mm_store_si128((__m128i*)&dst[i + 8], ints2); + _mm_store_si128((__m128i*)&dst[i + 12], ints3); + }) +} +#endif - --i; - ++src; - ++dst; - } +// FIXME: SDL doesn't have SSSE3 detection, so use the next one up +#ifdef SDL_SSE4_1_INTRINSICS +static void SDL_TARGETING("ssse3") SDL_Convert_Swap16_SSSE3(Uint16* dst, const Uint16* src, int num_samples) +{ + const __m128i shuffle = _mm_set_epi8(14, 15, 12, 13, 10, 11, 8, 9, 6, 7, 4, 5, 2, 3, 0, 1); + + CONVERT_16_FWD({ + dst[i] = SDL_Swap16(src[i]); + }, { + __m128i ints0 = _mm_loadu_si128((const __m128i*)&src[i]); + __m128i ints1 = _mm_loadu_si128((const __m128i*)&src[i + 8]); + + ints0 = _mm_shuffle_epi8(ints0, shuffle); + ints1 = _mm_shuffle_epi8(ints1, shuffle); + + _mm_store_si128((__m128i*)&dst[i], ints0); + _mm_store_si128((__m128i*)&dst[i + 8], ints1); + }) +} + +static void SDL_TARGETING("ssse3") SDL_Convert_Swap32_SSSE3(Uint32* dst, const Uint32* src, int num_samples) +{ + const __m128i shuffle = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3); + + CONVERT_16_FWD({ + dst[i] = SDL_Swap32(src[i]); + }, { + __m128i ints0 = _mm_loadu_si128((const __m128i*)&src[i]); + __m128i ints1 = _mm_loadu_si128((const __m128i*)&src[i + 4]); + __m128i ints2 = _mm_loadu_si128((const __m128i*)&src[i + 8]); + __m128i ints3 = _mm_loadu_si128((const __m128i*)&src[i + 12]); + + ints0 = _mm_shuffle_epi8(ints0, shuffle); + ints1 = _mm_shuffle_epi8(ints1, shuffle); + ints2 = _mm_shuffle_epi8(ints2, shuffle); + ints3 = _mm_shuffle_epi8(ints3, shuffle); + + _mm_store_si128((__m128i*)&dst[i], ints0); + _mm_store_si128((__m128i*)&dst[i + 4], ints1); + _mm_store_si128((__m128i*)&dst[i + 8], ints2); + _mm_store_si128((__m128i*)&dst[i + 12], ints3); + }) } #endif #ifdef SDL_NEON_INTRINSICS -#define DIVBY128 0.0078125f // 0x1p-7f -#define DIVBY32768 0.000030517578125f // 0x1p-15f -#define DIVBY8388607 0.00000011920930376163766f // 0x1.000002p-23f - static void SDL_Convert_S8_to_F32_NEON(float *dst, const Sint8 *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("S8", "F32 (using NEON)"); - src += num_samples - 1; - dst += num_samples - 1; + CONVERT_16_REV({ + vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 7), 0); + }, { + int8x16_t bytes = vld1q_s8(&src[i]); - // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) - for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) { - *dst = ((float)*src) * DIVBY128; - } - - src -= 15; - dst -= 15; // adjust to read NEON blocks from the start. - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const int8_t *mmsrc = (const int8_t *)src; - const float32x4_t divby128 = vdupq_n_f32(DIVBY128); - while (i >= 16) { // 16 * 8-bit - const int8x16_t bytes = vld1q_s8(mmsrc); // get 16 sint8 into a NEON register. - const int16x8_t int16hi = vmovl_s8(vget_high_s8(bytes)); // convert top 8 bytes to 8 int16 - const int16x8_t int16lo = vmovl_s8(vget_low_s8(bytes)); // convert bottom 8 bytes to 8 int16 - // split int16 to two int32, then convert to float, then multiply to normalize, store. - vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16lo))), divby128)); - vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16lo))), divby128)); - vst1q_f32(dst + 8, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(int16hi))), divby128)); - vst1q_f32(dst + 12, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(int16hi))), divby128)); - i -= 16; - mmsrc -= 16; - dst -= 16; - } - - src = (const Sint8 *)mmsrc; - } + int16x8_t shorts0 = vmovl_s8(vget_low_s8(bytes)); + int16x8_t shorts1 = vmovl_s8(vget_high_s8(bytes)); - src += 15; - dst += 15; // adjust for any scalar finishing. + float32x4_t floats0 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts0)), 7); + float32x4_t floats1 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts0)), 7); + float32x4_t floats2 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts1)), 7); + float32x4_t floats3 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts1)), 7); - // Finish off any leftovers with scalar operations. - while (i) { - *dst = ((float)*src) * DIVBY128; - i--; - src--; - dst--; - } + vst1q_f32(&dst[i], floats0); + vst1q_f32(&dst[i + 4], floats1); + vst1q_f32(&dst[i + 8], floats2); + vst1q_f32(&dst[i + 12], floats3); + }) } static void SDL_Convert_U8_to_F32_NEON(float *dst, const Uint8 *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("U8", "F32 (using NEON)"); - src += num_samples - 1; - dst += num_samples - 1; + uint8x16_t flipper = vdupq_n_u8(0x80); - // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) - for (i = num_samples; i && (((size_t)(dst - 15)) & 15); --i, --src, --dst) { - *dst = (((float)*src) * DIVBY128) - 1.0f; - } + CONVERT_16_REV({ + vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32((Sint8)(src[i] ^ 0x80)), 7), 0); + }, { + int8x16_t bytes = vreinterpretq_s8_u8(veorq_u8(vld1q_u8(&src[i]), flipper)); - src -= 15; - dst -= 15; // adjust to read NEON blocks from the start. - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const uint8_t *mmsrc = (const uint8_t *)src; - const float32x4_t divby128 = vdupq_n_f32(DIVBY128); - const float32x4_t negone = vdupq_n_f32(-1.0f); - while (i >= 16) { // 16 * 8-bit - const uint8x16_t bytes = vld1q_u8(mmsrc); // get 16 uint8 into a NEON register. - const uint16x8_t uint16hi = vmovl_u8(vget_high_u8(bytes)); // convert top 8 bytes to 8 uint16 - const uint16x8_t uint16lo = vmovl_u8(vget_low_u8(bytes)); // convert bottom 8 bytes to 8 uint16 - // split uint16 to two uint32, then convert to float, then multiply to normalize, subtract to adjust for sign, store. - vst1q_f32(dst, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16lo))), divby128)); - vst1q_f32(dst + 4, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16lo))), divby128)); - vst1q_f32(dst + 8, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_low_u16(uint16hi))), divby128)); - vst1q_f32(dst + 12, vmlaq_f32(negone, vcvtq_f32_u32(vmovl_u16(vget_high_u16(uint16hi))), divby128)); - i -= 16; - mmsrc -= 16; - dst -= 16; - } - - src = (const Uint8 *)mmsrc; - } + int16x8_t shorts0 = vmovl_s8(vget_low_s8(bytes)); + int16x8_t shorts1 = vmovl_s8(vget_high_s8(bytes)); - src += 15; - dst += 15; // adjust for any scalar finishing. + float32x4_t floats0 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts0)), 7); + float32x4_t floats1 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts0)), 7); + float32x4_t floats2 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts1)), 7); + float32x4_t floats3 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts1)), 7); - // Finish off any leftovers with scalar operations. - while (i) { - *dst = (((float)*src) * DIVBY128) - 1.0f; - i--; - src--; - dst--; - } + vst1q_f32(&dst[i], floats0); + vst1q_f32(&dst[i + 4], floats1); + vst1q_f32(&dst[i + 8], floats2); + vst1q_f32(&dst[i + 12], floats3); + }) } static void SDL_Convert_S16_to_F32_NEON(float *dst, const Sint16 *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("S16", "F32 (using NEON)"); - src += num_samples - 1; - dst += num_samples - 1; - - // Get dst aligned to 16 bytes (since buffer is growing, we don't have to worry about overreading from src) - for (i = num_samples; i && (((size_t)(dst - 7)) & 15); --i, --src, --dst) { - *dst = ((float)*src) * DIVBY32768; - } - - src -= 7; - dst -= 7; // adjust to read NEON blocks from the start. - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t divby32768 = vdupq_n_f32(DIVBY32768); - while (i >= 8) { // 8 * 16-bit - const int16x8_t ints = vld1q_s16((int16_t const *)src); // get 8 sint16 into a NEON register. - // split int16 to two int32, then convert to float, then multiply to normalize, store. - vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_low_s16(ints))), divby32768)); - vst1q_f32(dst + 4, vmulq_f32(vcvtq_f32_s32(vmovl_s16(vget_high_s16(ints))), divby32768)); - i -= 8; - src -= 8; - dst -= 8; - } - } - - src += 7; - dst += 7; // adjust for any scalar finishing. - - // Finish off any leftovers with scalar operations. - while (i) { - *dst = ((float)*src) * DIVBY32768; - i--; - src--; - dst--; - } + CONVERT_16_REV({ + vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vdup_n_s32(src[i]), 15), 0); + }, { + int16x8_t shorts0 = vld1q_s16(&src[i]); + int16x8_t shorts1 = vld1q_s16(&src[i + 8]); + + float32x4_t floats0 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts0)), 15); + float32x4_t floats1 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts0)), 15); + float32x4_t floats2 = vcvtq_n_f32_s32(vmovl_s16(vget_low_s16(shorts1)), 15); + float32x4_t floats3 = vcvtq_n_f32_s32(vmovl_s16(vget_high_s16(shorts1)), 15); + + vst1q_f32(&dst[i], floats0); + vst1q_f32(&dst[i + 4], floats1); + vst1q_f32(&dst[i + 8], floats2); + vst1q_f32(&dst[i + 12], floats3); + }) } static void SDL_Convert_S32_to_F32_NEON(float *dst, const Sint32 *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("S32", "F32 (using NEON)"); - // Get dst aligned to 16 bytes - for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { - *dst = ((float)(*src >> 8)) * DIVBY8388607; - } - - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t divby8388607 = vdupq_n_f32(DIVBY8388607); - const int32_t *mmsrc = (const int32_t *)src; - while (i >= 4) { // 4 * sint32 - // shift out lowest bits so int fits in a float32. Small precision loss, but much faster. - vst1q_f32(dst, vmulq_f32(vcvtq_f32_s32(vshrq_n_s32(vld1q_s32(mmsrc), 8)), divby8388607)); - i -= 4; - mmsrc += 4; - dst += 4; - } - src = (const Sint32 *)mmsrc; - } - - // Finish off any leftovers with scalar operations. - while (i) { - *dst = ((float)(*src >> 8)) * DIVBY8388607; - i--; - src++; - dst++; - } + CONVERT_16_FWD({ + vst1_lane_f32(&dst[i], vcvt_n_f32_s32(vld1_dup_s32(&src[i]), 31), 0); + }, { + int32x4_t ints0 = vld1q_s32(&src[i]); + int32x4_t ints1 = vld1q_s32(&src[i + 4]); + int32x4_t ints2 = vld1q_s32(&src[i + 8]); + int32x4_t ints3 = vld1q_s32(&src[i + 12]); + + float32x4_t floats0 = vcvtq_n_f32_s32(ints0, 31); + float32x4_t floats1 = vcvtq_n_f32_s32(ints1, 31); + float32x4_t floats2 = vcvtq_n_f32_s32(ints2, 31); + float32x4_t floats3 = vcvtq_n_f32_s32(ints3, 31); + + vst1q_f32(&dst[i], floats0); + vst1q_f32(&dst[i + 4], floats1); + vst1q_f32(&dst[i + 8], floats2); + vst1q_f32(&dst[i + 12], floats3); + }) } static void SDL_Convert_F32_to_S8_NEON(Sint8 *dst, const float *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("F32", "S8 (using NEON)"); - // Get dst aligned to 16 bytes - for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 127; - } else if (sample <= -1.0f) { - *dst = -128; - } else { - *dst = (Sint8)(sample * 127.0f); - } - } + CONVERT_16_FWD({ + vst1_lane_s8(&dst[i], vreinterpret_s8_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 3); + }, { + float32x4_t floats0 = vld1q_f32(&src[i]); + float32x4_t floats1 = vld1q_f32(&src[i + 4]); + float32x4_t floats2 = vld1q_f32(&src[i + 8]); + float32x4_t floats3 = vld1q_f32(&src[i + 12]); - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t one = vdupq_n_f32(1.0f); - const float32x4_t negone = vdupq_n_f32(-1.0f); - const float32x4_t mulby127 = vdupq_n_f32(127.0f); - int8_t *mmdst = (int8_t *)dst; - while (i >= 16) { // 16 * float32 - const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby127)); // load 4 floats, clamp, convert to sint32 - const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby127)); // load 4 floats, clamp, convert to sint32 - const int32x4_t ints3 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), mulby127)); // load 4 floats, clamp, convert to sint32 - const int32x4_t ints4 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), mulby127)); // load 4 floats, clamp, convert to sint32 - const int8x8_t i8lo = vmovn_s16(vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, narrow to sint8 - const int8x8_t i8hi = vmovn_s16(vcombine_s16(vmovn_s32(ints3), vmovn_s32(ints4))); // narrow to sint16, combine, narrow to sint8 - vst1q_s8(mmdst, vcombine_s8(i8lo, i8hi)); // combine to int8x16_t, store out - i -= 16; - src += 16; - mmdst += 16; - } - dst = (Sint8 *)mmdst; - } + int32x4_t ints0 = vcvtq_n_s32_f32(floats0, 31); + int32x4_t ints1 = vcvtq_n_s32_f32(floats1, 31); + int32x4_t ints2 = vcvtq_n_s32_f32(floats2, 31); + int32x4_t ints3 = vcvtq_n_s32_f32(floats3, 31); - // Finish off any leftovers with scalar operations. - while (i) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 127; - } else if (sample <= -1.0f) { - *dst = -128; - } else { - *dst = (Sint8)(sample * 127.0f); - } - i--; - src++; - dst++; - } + int16x8_t shorts0 = vcombine_s16(vshrn_n_s32(ints0, 16), vshrn_n_s32(ints1, 16)); + int16x8_t shorts1 = vcombine_s16(vshrn_n_s32(ints2, 16), vshrn_n_s32(ints3, 16)); + + int8x16_t bytes = vcombine_s8(vshrn_n_s16(shorts0, 8), vshrn_n_s16(shorts1, 8)); + + vst1q_s8(&dst[i], bytes); + }) } static void SDL_Convert_F32_to_U8_NEON(Uint8 *dst, const float *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("F32", "U8 (using NEON)"); - // Get dst aligned to 16 bytes - for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 255; - } else if (sample <= -1.0f) { - *dst = 0; - } else { - *dst = (Uint8)((sample + 1.0f) * 127.0f); - } - } + uint8x16_t flipper = vdupq_n_u8(0x80); - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t one = vdupq_n_f32(1.0f); - const float32x4_t negone = vdupq_n_f32(-1.0f); - const float32x4_t mulby127 = vdupq_n_f32(127.0f); - uint8_t *mmdst = (uint8_t *)dst; - while (i >= 16) { // 16 * float32 - const uint32x4_t uints1 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 - const uint32x4_t uints2 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 - const uint32x4_t uints3 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 8)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 - const uint32x4_t uints4 = vcvtq_u32_f32(vmulq_f32(vaddq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 12)), one), one), mulby127)); // load 4 floats, clamp, convert to uint32 - const uint8x8_t ui8lo = vmovn_u16(vcombine_u16(vmovn_u32(uints1), vmovn_u32(uints2))); // narrow to uint16, combine, narrow to uint8 - const uint8x8_t ui8hi = vmovn_u16(vcombine_u16(vmovn_u32(uints3), vmovn_u32(uints4))); // narrow to uint16, combine, narrow to uint8 - vst1q_u8(mmdst, vcombine_u8(ui8lo, ui8hi)); // combine to uint8x16_t, store out - i -= 16; - src += 16; - mmdst += 16; - } - - dst = (Uint8 *)mmdst; - } + CONVERT_16_FWD({ + vst1_lane_u8(&dst[i], + veor_u8(vreinterpret_u8_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), + vget_low_u8(flipper)), 3); + }, { + float32x4_t floats0 = vld1q_f32(&src[i]); + float32x4_t floats1 = vld1q_f32(&src[i + 4]); + float32x4_t floats2 = vld1q_f32(&src[i + 8]); + float32x4_t floats3 = vld1q_f32(&src[i + 12]); - // Finish off any leftovers with scalar operations. - while (i) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 255; - } else if (sample <= -1.0f) { - *dst = 0; - } else { - *dst = (Uint8)((sample + 1.0f) * 127.0f); - } - i--; - src++; - dst++; - } + int32x4_t ints0 = vcvtq_n_s32_f32(floats0, 31); + int32x4_t ints1 = vcvtq_n_s32_f32(floats1, 31); + int32x4_t ints2 = vcvtq_n_s32_f32(floats2, 31); + int32x4_t ints3 = vcvtq_n_s32_f32(floats3, 31); + + int16x8_t shorts0 = vcombine_s16(vshrn_n_s32(ints0, 16), vshrn_n_s32(ints1, 16)); + int16x8_t shorts1 = vcombine_s16(vshrn_n_s32(ints2, 16), vshrn_n_s32(ints3, 16)); + + uint8x16_t bytes = veorq_u8(vreinterpretq_u8_s8( + vcombine_s8(vshrn_n_s16(shorts0, 8), vshrn_n_s16(shorts1, 8))), + flipper); + + vst1q_u8(&dst[i], bytes); + }) } static void SDL_Convert_F32_to_S16_NEON(Sint16 *dst, const float *src, int num_samples) { - int i; - LOG_DEBUG_AUDIO_CONVERT("F32", "S16 (using NEON)"); - // Get dst aligned to 16 bytes - for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 32767; - } else if (sample <= -1.0f) { - *dst = -32768; - } else { - *dst = (Sint16)(sample * 32767.0f); - } - } + CONVERT_16_FWD({ + vst1_lane_s16(&dst[i], vreinterpret_s16_s32(vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31)), 1); + }, { + float32x4_t floats0 = vld1q_f32(&src[i]); + float32x4_t floats1 = vld1q_f32(&src[i + 4]); + float32x4_t floats2 = vld1q_f32(&src[i + 8]); + float32x4_t floats3 = vld1q_f32(&src[i + 12]); + + int32x4_t ints0 = vcvtq_n_s32_f32(floats0, 31); + int32x4_t ints1 = vcvtq_n_s32_f32(floats1, 31); + int32x4_t ints2 = vcvtq_n_s32_f32(floats2, 31); + int32x4_t ints3 = vcvtq_n_s32_f32(floats3, 31); + + int16x8_t shorts0 = vcombine_s16(vshrn_n_s32(ints0, 16), vshrn_n_s32(ints1, 16)); + int16x8_t shorts1 = vcombine_s16(vshrn_n_s32(ints2, 16), vshrn_n_s32(ints3, 16)); + + vst1q_s16(&dst[i], shorts0); + vst1q_s16(&dst[i + 8], shorts1); + }) +} - SDL_assert(!i || !(((size_t)dst) & 15)); - - // Make sure src is aligned too. - if (!(((size_t)src) & 15)) { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t one = vdupq_n_f32(1.0f); - const float32x4_t negone = vdupq_n_f32(-1.0f); - const float32x4_t mulby32767 = vdupq_n_f32(32767.0f); - int16_t *mmdst = (int16_t *)dst; - while (i >= 8) { // 8 * float32 - const int32x4_t ints1 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby32767)); // load 4 floats, clamp, convert to sint32 - const int32x4_t ints2 = vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src + 4)), one), mulby32767)); // load 4 floats, clamp, convert to sint32 - vst1q_s16(mmdst, vcombine_s16(vmovn_s32(ints1), vmovn_s32(ints2))); // narrow to sint16, combine, store out. - i -= 8; - src += 8; - mmdst += 8; - } - dst = (Sint16 *)mmdst; - } +static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_samples) +{ + LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)"); - // Finish off any leftovers with scalar operations. - while (i) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 32767; - } else if (sample <= -1.0f) { - *dst = -32768; - } else { - *dst = (Sint16)(sample * 32767.0f); - } - i--; - src++; - dst++; - } + CONVERT_16_FWD({ + vst1_lane_s32(&dst[i], vcvt_n_s32_f32(vld1_dup_f32(&src[i]), 31), 0); + }, { + float32x4_t floats0 = vld1q_f32(&src[i]); + float32x4_t floats1 = vld1q_f32(&src[i + 4]); + float32x4_t floats2 = vld1q_f32(&src[i + 8]); + float32x4_t floats3 = vld1q_f32(&src[i + 12]); + + int32x4_t ints0 = vcvtq_n_s32_f32(floats0, 31); + int32x4_t ints1 = vcvtq_n_s32_f32(floats1, 31); + int32x4_t ints2 = vcvtq_n_s32_f32(floats2, 31); + int32x4_t ints3 = vcvtq_n_s32_f32(floats3, 31); + + vst1q_s32(&dst[i], ints0); + vst1q_s32(&dst[i + 4], ints1); + vst1q_s32(&dst[i + 8], ints2); + vst1q_s32(&dst[i + 12], ints3); + }) } -static void SDL_Convert_F32_to_S32_NEON(Sint32 *dst, const float *src, int num_samples) +static void SDL_Convert_Swap16_NEON(Uint16* dst, const Uint16* src, int num_samples) { - int i; + CONVERT_16_FWD({ + dst[i] = SDL_Swap16(src[i]); + }, { + uint8x16_t ints0 = vld1q_u8((const Uint8*)&src[i]); + uint8x16_t ints1 = vld1q_u8((const Uint8*)&src[i + 8]); + + ints0 = vrev16q_u8(ints0); + ints1 = vrev16q_u8(ints1); + + vst1q_u8((Uint8*)&dst[i], ints0); + vst1q_u8((Uint8*)&dst[i + 8], ints1); + }) +} - LOG_DEBUG_AUDIO_CONVERT("F32", "S32 (using NEON)"); +static void SDL_Convert_Swap32_NEON(Uint32* dst, const Uint32* src, int num_samples) +{ + CONVERT_16_FWD({ + dst[i] = SDL_Swap32(src[i]); + }, { + uint8x16_t ints0 = vld1q_u8((const Uint8*)&src[i]); + uint8x16_t ints1 = vld1q_u8((const Uint8*)&src[i + 4]); + uint8x16_t ints2 = vld1q_u8((const Uint8*)&src[i + 8]); + uint8x16_t ints3 = vld1q_u8((const Uint8*)&src[i + 12]); + + ints0 = vrev32q_u8(ints0); + ints1 = vrev32q_u8(ints1); + ints2 = vrev32q_u8(ints2); + ints3 = vrev32q_u8(ints3); + + vst1q_u8((Uint8*)&dst[i], ints0); + vst1q_u8((Uint8*)&dst[i + 4], ints1); + vst1q_u8((Uint8*)&dst[i + 8], ints2); + vst1q_u8((Uint8*)&dst[i + 12], ints3); + }) +} +#endif - // Get dst aligned to 16 bytes - for (i = num_samples; i && (((size_t)dst) & 15); --i, ++src, ++dst) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 2147483647; - } else if (sample <= -1.0f) { - *dst = (-2147483647) - 1; - } else { - *dst = ((Sint32)(sample * 8388607.0f)) << 8; - } - } +#undef CONVERT_16_FWD +#undef CONVERT_16_REV + +// Function pointers set to a CPU-specific implementation. +static void (*SDL_Convert_S8_to_F32)(float *dst, const Sint8 *src, int num_samples) = NULL; +static void (*SDL_Convert_U8_to_F32)(float *dst, const Uint8 *src, int num_samples) = NULL; +static void (*SDL_Convert_S16_to_F32)(float *dst, const Sint16 *src, int num_samples) = NULL; +static void (*SDL_Convert_S32_to_F32)(float *dst, const Sint32 *src, int num_samples) = NULL; +static void (*SDL_Convert_F32_to_S8)(Sint8 *dst, const float *src, int num_samples) = NULL; +static void (*SDL_Convert_F32_to_U8)(Uint8 *dst, const float *src, int num_samples) = NULL; +static void (*SDL_Convert_F32_to_S16)(Sint16 *dst, const float *src, int num_samples) = NULL; +static void (*SDL_Convert_F32_to_S32)(Sint32 *dst, const float *src, int num_samples) = NULL; + +static void (*SDL_Convert_Swap16)(Uint16* dst, const Uint16* src, int num_samples) = NULL; +static void (*SDL_Convert_Swap32)(Uint32* dst, const Uint32* src, int num_samples) = NULL; + +void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt) +{ + switch (src_fmt) { + case SDL_AUDIO_S8: + SDL_Convert_S8_to_F32(dst, (const Sint8 *) src, num_samples); + break; - SDL_assert(!i || !(((size_t)dst) & 15)); - SDL_assert(!i || !(((size_t)src) & 15)); + case SDL_AUDIO_U8: + SDL_Convert_U8_to_F32(dst, (const Uint8 *) src, num_samples); + break; - { - // Aligned! Do NEON blocks as long as we have 16 bytes available. - const float32x4_t one = vdupq_n_f32(1.0f); - const float32x4_t negone = vdupq_n_f32(-1.0f); - const float32x4_t mulby8388607 = vdupq_n_f32(8388607.0f); - int32_t *mmdst = (int32_t *)dst; - while (i >= 4) { // 4 * float32 - vst1q_s32(mmdst, vshlq_n_s32(vcvtq_s32_f32(vmulq_f32(vminq_f32(vmaxq_f32(negone, vld1q_f32(src)), one), mulby8388607)), 8)); - i -= 4; - src += 4; - mmdst += 4; - } - dst = (Sint32 *)mmdst; + case SDL_AUDIO_S16: + SDL_Convert_S16_to_F32(dst, (const Sint16 *) src, num_samples); + break; + + case SDL_AUDIO_S16 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) src, num_samples); + SDL_Convert_S16_to_F32(dst, (const Sint16 *) dst, num_samples); + break; + + case SDL_AUDIO_S32: + SDL_Convert_S32_to_F32(dst, (const Sint32 *) src, num_samples); + break; + + case SDL_AUDIO_S32 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples); + SDL_Convert_S32_to_F32(dst, (const Sint32 *) dst, num_samples); + break; + + case SDL_AUDIO_F32 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples); + break; + + default: SDL_assert(!"Unexpected audio format!"); break; } +} - // Finish off any leftovers with scalar operations. - while (i) { - const float sample = *src; - if (sample >= 1.0f) { - *dst = 2147483647; - } else if (sample <= -1.0f) { - *dst = (-2147483647) - 1; - } else { - *dst = ((Sint32)(sample * 8388607.0f)) << 8; - } - i--; - src++; - dst++; +void ConvertAudioFromFloat(void *dst, const float *src, int num_samples, SDL_AudioFormat dst_fmt) +{ + switch (dst_fmt) { + case SDL_AUDIO_S8: + SDL_Convert_F32_to_S8((Sint8 *) dst, src, num_samples); + break; + + case SDL_AUDIO_U8: + SDL_Convert_F32_to_U8((Uint8 *) dst, src, num_samples); + break; + + case SDL_AUDIO_S16: + SDL_Convert_F32_to_S16((Sint16 *) dst, src, num_samples); + break; + + case SDL_AUDIO_S16 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_F32_to_S16((Sint16 *) dst, src, num_samples); + SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) dst, num_samples); + break; + + case SDL_AUDIO_S32: + SDL_Convert_F32_to_S32((Sint32 *) dst, src, num_samples); + break; + + case SDL_AUDIO_S32 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_F32_to_S32((Sint32 *) dst, src, num_samples); + SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) dst, num_samples); + break; + + case SDL_AUDIO_F32 ^ SDL_AUDIO_MASK_BIG_ENDIAN: + SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples); + break; + + default: SDL_assert(!"Unexpected audio format!"); break; } } -#endif -// Function pointers set to a CPU-specific implementation. -void (*SDL_Convert_S8_to_F32)(float *dst, const Sint8 *src, int num_samples) = NULL; -void (*SDL_Convert_U8_to_F32)(float *dst, const Uint8 *src, int num_samples) = NULL; -void (*SDL_Convert_S16_to_F32)(float *dst, const Sint16 *src, int num_samples) = NULL; -void (*SDL_Convert_S32_to_F32)(float *dst, const Sint32 *src, int num_samples) = NULL; -void (*SDL_Convert_F32_to_S8)(Sint8 *dst, const float *src, int num_samples) = NULL; -void (*SDL_Convert_F32_to_U8)(Uint8 *dst, const float *src, int num_samples) = NULL; -void (*SDL_Convert_F32_to_S16)(Sint16 *dst, const float *src, int num_samples) = NULL; -void (*SDL_Convert_F32_to_S32)(Sint32 *dst, const float *src, int num_samples) = NULL; +void ConvertAudioSwapEndian(void* dst, const void* src, int num_samples, int bitsize) +{ + switch (bitsize) { + case 16: SDL_Convert_Swap16((Uint16*) dst, (const Uint16*) src, num_samples); break; + case 32: SDL_Convert_Swap32((Uint32*) dst, (const Uint32*) src, num_samples); break; + default: SDL_assert(!"Unexpected audio format!"); break; + } +} void SDL_ChooseAudioConverters(void) { - static SDL_bool converters_chosen = SDL_FALSE; + static bool converters_chosen = false; if (converters_chosen) { return; } +#define SET_CONVERTER_FUNCS(fntype) \ + SDL_Convert_Swap16 = SDL_Convert_Swap16_##fntype; \ + SDL_Convert_Swap32 = SDL_Convert_Swap32_##fntype; + +#ifdef SDL_SSE4_1_INTRINSICS + if (SDL_HasSSE41()) { + SET_CONVERTER_FUNCS(SSSE3); + } else +#endif +#ifdef SDL_NEON_INTRINSICS + if (SDL_HasNEON()) { + SET_CONVERTER_FUNCS(NEON); + } else +#endif + { + SET_CONVERTER_FUNCS(Scalar); + } + +#undef SET_CONVERTER_FUNCS + #define SET_CONVERTER_FUNCS(fntype) \ SDL_Convert_S8_to_F32 = SDL_Convert_S8_to_F32_##fntype; \ SDL_Convert_U8_to_F32 = SDL_Convert_U8_to_F32_##fntype; \ @@ -966,25 +904,22 @@ void SDL_ChooseAudioConverters(void) SDL_Convert_F32_to_U8 = SDL_Convert_F32_to_U8_##fntype; \ SDL_Convert_F32_to_S16 = SDL_Convert_F32_to_S16_##fntype; \ SDL_Convert_F32_to_S32 = SDL_Convert_F32_to_S32_##fntype; \ - converters_chosen = SDL_TRUE #ifdef SDL_SSE2_INTRINSICS if (SDL_HasSSE2()) { SET_CONVERTER_FUNCS(SSE2); - return; - } + } else #endif - #ifdef SDL_NEON_INTRINSICS if (SDL_HasNEON()) { SET_CONVERTER_FUNCS(NEON); - return; - } + } else #endif - - SET_CONVERTER_FUNCS(Scalar); + { + SET_CONVERTER_FUNCS(Scalar); + } #undef SET_CONVERTER_FUNCS - SDL_assert(converters_chosen == SDL_TRUE); + converters_chosen = true; } diff --git a/libs/SDL3/src/audio/SDL_mixer.c b/libs/SDL3/src/audio/SDL_mixer.c index 4e71620b0..e6924ddc4 100644 --- a/libs/SDL3/src/audio/SDL_mixer.c +++ b/libs/SDL3/src/audio/SDL_mixer.c @@ -78,17 +78,20 @@ static const Uint8 mix8[] = { }; // The volume ranges from 0 - 128 -#define ADJUST_VOLUME(type, s, v) ((s) = (type)(((s) * (v)) / SDL_MIX_MAXVOLUME)) -#define ADJUST_VOLUME_U8(s, v) ((s) = (Uint8)(((((s) - 128) * (v)) / SDL_MIX_MAXVOLUME) + 128)) +#define MIX_MAXVOLUME 128 +#define ADJUST_VOLUME(type, s, v) ((s) = (type)(((s) * (v)) / MIX_MAXVOLUME)) +#define ADJUST_VOLUME_U8(s, v) ((s) = (Uint8)(((((s) - 128) * (v)) / MIX_MAXVOLUME) + 128)) +// !!! FIXME: This needs some SIMD magic. +// !!! FIXME: Add fast-path for volume = 1 +// !!! FIXME: Use larger scales for 16-bit/32-bit integers -// !!! FIXME: this needs some SIMD magic. - -int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, - Uint32 len, int volume) +bool SDL_MixAudio(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, Uint32 len, float fvolume) { + int volume = (int)SDL_roundf(fvolume * MIX_MAXVOLUME); + if (volume == 0) { - return 0; + return true; } switch (format) { @@ -140,9 +143,9 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, len /= 2; while (len--) { - src1 = SDL_SwapLE16(*(Sint16 *)src); + src1 = SDL_Swap16LE(*(Sint16 *)src); ADJUST_VOLUME(Sint16, src1, volume); - src2 = SDL_SwapLE16(*(Sint16 *)dst); + src2 = SDL_Swap16LE(*(Sint16 *)dst); src += 2; dst_sample = src1 + src2; if (dst_sample > max_audioval) { @@ -150,7 +153,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(Sint16 *)dst = SDL_SwapLE16((Sint16)dst_sample); + *(Sint16 *)dst = SDL_Swap16LE((Sint16)dst_sample); dst += 2; } } break; @@ -164,9 +167,9 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, len /= 2; while (len--) { - src1 = SDL_SwapBE16(*(Sint16 *)src); + src1 = SDL_Swap16BE(*(Sint16 *)src); ADJUST_VOLUME(Sint16, src1, volume); - src2 = SDL_SwapBE16(*(Sint16 *)dst); + src2 = SDL_Swap16BE(*(Sint16 *)dst); src += 2; dst_sample = src1 + src2; if (dst_sample > max_audioval) { @@ -174,7 +177,7 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(Sint16 *)dst = SDL_SwapBE16((Sint16)dst_sample); + *(Sint16 *)dst = SDL_Swap16BE((Sint16)dst_sample); dst += 2; } } break; @@ -190,17 +193,17 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, len /= 4; while (len--) { - src1 = (Sint64)((Sint32)SDL_SwapLE32(*src32)); + src1 = (Sint64)((Sint32)SDL_Swap32LE(*src32)); src32++; ADJUST_VOLUME(Sint64, src1, volume); - src2 = (Sint64)((Sint32)SDL_SwapLE32(*dst32)); + src2 = (Sint64)((Sint32)SDL_Swap32LE(*dst32)); dst_sample = src1 + src2; if (dst_sample > max_audioval) { dst_sample = max_audioval; } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(dst32++) = SDL_SwapLE32((Uint32)((Sint32)dst_sample)); + *(dst32++) = SDL_Swap32LE((Uint32)((Sint32)dst_sample)); } } break; @@ -215,79 +218,73 @@ int SDL_MixAudioFormat(Uint8 *dst, const Uint8 *src, SDL_AudioFormat format, len /= 4; while (len--) { - src1 = (Sint64)((Sint32)SDL_SwapBE32(*src32)); + src1 = (Sint64)((Sint32)SDL_Swap32BE(*src32)); src32++; ADJUST_VOLUME(Sint64, src1, volume); - src2 = (Sint64)((Sint32)SDL_SwapBE32(*dst32)); + src2 = (Sint64)((Sint32)SDL_Swap32BE(*dst32)); dst_sample = src1 + src2; if (dst_sample > max_audioval) { dst_sample = max_audioval; } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(dst32++) = SDL_SwapBE32((Uint32)((Sint32)dst_sample)); + *(dst32++) = SDL_Swap32BE((Uint32)((Sint32)dst_sample)); } } break; case SDL_AUDIO_F32LE: { - const float fmaxvolume = 1.0f / ((float)SDL_MIX_MAXVOLUME); - const float fvolume = (float)volume; const float *src32 = (float *)src; float *dst32 = (float *)dst; float src1, src2; - double dst_sample; - // !!! FIXME: are these right? - const double max_audioval = 3.402823466e+38F; - const double min_audioval = -3.402823466e+38F; + float dst_sample; + const float max_audioval = 1.0f; + const float min_audioval = -1.0f; len /= 4; while (len--) { - src1 = ((SDL_SwapFloatLE(*src32) * fvolume) * fmaxvolume); + src1 = SDL_SwapFloatLE(*src32) * fvolume; src2 = SDL_SwapFloatLE(*dst32); src32++; - dst_sample = ((double)src1) + ((double)src2); + dst_sample = src1 + src2; if (dst_sample > max_audioval) { dst_sample = max_audioval; } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(dst32++) = SDL_SwapFloatLE((float)dst_sample); + *(dst32++) = SDL_SwapFloatLE(dst_sample); } } break; case SDL_AUDIO_F32BE: { - const float fmaxvolume = 1.0f / ((float)SDL_MIX_MAXVOLUME); - const float fvolume = (float)volume; const float *src32 = (float *)src; float *dst32 = (float *)dst; float src1, src2; - double dst_sample; - // !!! FIXME: are these right? - const double max_audioval = 3.402823466e+38F; - const double min_audioval = -3.402823466e+38F; + float dst_sample; + const float max_audioval = 1.0f; + const float min_audioval = -1.0f; len /= 4; while (len--) { - src1 = ((SDL_SwapFloatBE(*src32) * fvolume) * fmaxvolume); + src1 = SDL_SwapFloatBE(*src32) * fvolume; src2 = SDL_SwapFloatBE(*dst32); src32++; - dst_sample = ((double)src1) + ((double)src2); + dst_sample = src1 + src2; if (dst_sample > max_audioval) { dst_sample = max_audioval; } else if (dst_sample < min_audioval) { dst_sample = min_audioval; } - *(dst32++) = SDL_SwapFloatBE((float)dst_sample); + *(dst32++) = SDL_SwapFloatBE(dst_sample); } } break; default: // If this happens... FIXME! - return SDL_SetError("SDL_MixAudioFormat(): unknown audio format"); + return SDL_SetError("SDL_MixAudio(): unknown audio format"); } - return 0; + return true; } diff --git a/libs/SDL3/src/audio/SDL_sysaudio.h b/libs/SDL3/src/audio/SDL_sysaudio.h index eb6b38bad..8adfe9ab8 100644 --- a/libs/SDL3/src/audio/SDL_sysaudio.h +++ b/libs/SDL3/src/audio/SDL_sysaudio.h @@ -24,8 +24,6 @@ #ifndef SDL_sysaudio_h_ #define SDL_sysaudio_h_ -#include "../SDL_hashtable.h" - #define DEBUG_AUDIOSTREAM 0 #define DEBUG_AUDIO_CONVERT 0 @@ -35,36 +33,26 @@ #define LOG_DEBUG_AUDIO_CONVERT(from, to) #endif -// These pointers get set during SDL_ChooseAudioConverters() to various SIMD implementations. -extern void (*SDL_Convert_S8_to_F32)(float *dst, const Sint8 *src, int num_samples); -extern void (*SDL_Convert_U8_to_F32)(float *dst, const Uint8 *src, int num_samples); -extern void (*SDL_Convert_S16_to_F32)(float *dst, const Sint16 *src, int num_samples); -extern void (*SDL_Convert_S32_to_F32)(float *dst, const Sint32 *src, int num_samples); -extern void (*SDL_Convert_F32_to_S8)(Sint8 *dst, const float *src, int num_samples); -extern void (*SDL_Convert_F32_to_U8)(Uint8 *dst, const float *src, int num_samples); -extern void (*SDL_Convert_F32_to_S16)(Sint16 *dst, const float *src, int num_samples); -extern void (*SDL_Convert_F32_to_S32)(Sint32 *dst, const float *src, int num_samples); - // !!! FIXME: These are wordy and unlocalized... -#define DEFAULT_OUTPUT_DEVNAME "System audio output device" -#define DEFAULT_INPUT_DEVNAME "System audio capture device" +#define DEFAULT_PLAYBACK_DEVNAME "System audio playback device" +#define DEFAULT_RECORDING_DEVNAME "System audio recording device" // these are used when no better specifics are known. We default to CD audio quality. -#define DEFAULT_AUDIO_OUTPUT_FORMAT SDL_AUDIO_S16 -#define DEFAULT_AUDIO_OUTPUT_CHANNELS 2 -#define DEFAULT_AUDIO_OUTPUT_FREQUENCY 44100 +#define DEFAULT_AUDIO_PLAYBACK_FORMAT SDL_AUDIO_S16 +#define DEFAULT_AUDIO_PLAYBACK_CHANNELS 2 +#define DEFAULT_AUDIO_PLAYBACK_FREQUENCY 44100 -#define DEFAULT_AUDIO_CAPTURE_FORMAT SDL_AUDIO_S16 -#define DEFAULT_AUDIO_CAPTURE_CHANNELS 1 -#define DEFAULT_AUDIO_CAPTURE_FREQUENCY 44100 +#define DEFAULT_AUDIO_RECORDING_FORMAT SDL_AUDIO_S16 +#define DEFAULT_AUDIO_RECORDING_CHANNELS 1 +#define DEFAULT_AUDIO_RECORDING_FREQUENCY 44100 -#define AUDIO_SPECS_EQUAL(x, y) (((x).format == (y).format) && ((x).channels == (y).channels) && ((x).freq == (y).freq)) +#define SDL_MAX_CHANNELMAP_CHANNELS 8 // !!! FIXME: if SDL ever supports more channels, clean this out and make those parts dynamic. typedef struct SDL_AudioDevice SDL_AudioDevice; typedef struct SDL_LogicalAudioDevice SDL_LogicalAudioDevice; // Used by src/SDL.c to initialize a particular audio driver. -extern int SDL_InitAudio(const char *driver_name); +extern bool SDL_InitAudio(const char *driver_name); // Used by src/SDL.c to shut down previously-initialized audio. extern void SDL_QuitAudio(void); @@ -79,7 +67,7 @@ extern void SDL_SetupAudioResampler(void); /* Backends should call this as devices are added to the system (such as a USB headset being plugged in), and should also be called for for every device found during DetectDevices(). */ -extern SDL_AudioDevice *SDL_AddAudioDevice(const SDL_bool iscapture, const char *name, const SDL_AudioSpec *spec, void *handle); +extern SDL_AudioDevice *SDL_AddAudioDevice(bool recording, const char *name, const SDL_AudioSpec *spec, void *handle); /* Backends should call this if an opened audio device is lost. This can happen due to i/o errors, or a device being unplugged, etc. */ @@ -89,16 +77,16 @@ extern void SDL_AudioDeviceDisconnected(SDL_AudioDevice *device); extern void SDL_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device); // Backends should call this if a device's format is changing (opened or not); SDL will update state and carry on with the new format. -extern int SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames); +extern bool SDL_AudioDeviceFormatChanged(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames); // Same as above, but assume the device is already locked. -extern int SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames); +extern bool SDL_AudioDeviceFormatChangedAlreadyLocked(SDL_AudioDevice *device, const SDL_AudioSpec *newspec, int new_sample_frames); // Find the SDL_AudioDevice associated with the handle supplied to SDL_AddAudioDevice. NULL if not found. DOES NOT LOCK THE DEVICE. extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByHandle(void *handle); // Find an SDL_AudioDevice, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. -extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(SDL_bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata); +extern SDL_AudioDevice *SDL_FindPhysicalAudioDeviceByCallback(bool (*callback)(SDL_AudioDevice *device, void *userdata), void *userdata); // Backends should call this if they change the device format, channels, freq, or sample_frames to keep other state correct. extern void SDL_UpdatedAudioDeviceFormat(SDL_AudioDevice *device); @@ -111,44 +99,68 @@ extern void RefPhysicalAudioDevice(SDL_AudioDevice *device); extern void UnrefPhysicalAudioDevice(SDL_AudioDevice *device); // These functions are the heart of the audio threads. Backends can call them directly if they aren't using the SDL-provided thread. -extern void SDL_OutputAudioThreadSetup(SDL_AudioDevice *device); -extern SDL_bool SDL_OutputAudioThreadIterate(SDL_AudioDevice *device); -extern void SDL_OutputAudioThreadShutdown(SDL_AudioDevice *device); -extern void SDL_CaptureAudioThreadSetup(SDL_AudioDevice *device); -extern SDL_bool SDL_CaptureAudioThreadIterate(SDL_AudioDevice *device); -extern void SDL_CaptureAudioThreadShutdown(SDL_AudioDevice *device); +extern void SDL_PlaybackAudioThreadSetup(SDL_AudioDevice *device); +extern bool SDL_PlaybackAudioThreadIterate(SDL_AudioDevice *device); +extern void SDL_PlaybackAudioThreadShutdown(SDL_AudioDevice *device); +extern void SDL_RecordingAudioThreadSetup(SDL_AudioDevice *device); +extern bool SDL_RecordingAudioThreadIterate(SDL_AudioDevice *device); +extern void SDL_RecordingAudioThreadShutdown(SDL_AudioDevice *device); extern void SDL_AudioThreadFinalize(SDL_AudioDevice *device); +extern void ConvertAudioToFloat(float *dst, const void *src, int num_samples, SDL_AudioFormat src_fmt); +extern void ConvertAudioFromFloat(void *dst, const float *src, int num_samples, SDL_AudioFormat dst_fmt); +extern void ConvertAudioSwapEndian(void* dst, const void* src, int num_samples, int bitsize); + +extern bool SDL_ChannelMapIsDefault(const int *map, int channels); +extern bool SDL_ChannelMapIsBogus(const int *map, int channels); + // this gets used from the audio device threads. It has rules, don't use this if you don't know how to use it! -extern void ConvertAudio(int num_frames, const void *src, SDL_AudioFormat src_format, int src_channels, - void *dst, SDL_AudioFormat dst_format, int dst_channels, void* scratch); +extern void ConvertAudio(int num_frames, + const void *src, SDL_AudioFormat src_format, int src_channels, const int *src_map, + void *dst, SDL_AudioFormat dst_format, int dst_channels, const int *dst_map, + void* scratch, float gain); + +// Compare two SDL_AudioSpecs, return true if they match exactly. +// Using SDL_memcmp directly isn't safe, since potential padding might not be initialized. +// either channel maps can be NULL for the default (and both should be if you don't care about them). +extern bool SDL_AudioSpecsEqual(const SDL_AudioSpec *a, const SDL_AudioSpec *b, const int *channel_map_a, const int *channel_map_b); + +// allocate+copy a channel map. +extern int *SDL_ChannelMapDup(const int *origchmap, int channels); // Special case to let something in SDL_audiocvt.c access something in SDL_audio.c. Don't use this. extern void OnAudioStreamCreated(SDL_AudioStream *stream); extern void OnAudioStreamDestroy(SDL_AudioStream *stream); +// This just lets audio playback apply logical device gain at the same time as audiostream gain, so it's one multiplication instead of thousands. +extern int SDL_GetAudioStreamDataAdjustGain(SDL_AudioStream *stream, void *voidbuf, int len, float extra_gain); + +// This is the bulk of `SDL_SetAudioStream*putChannelMap`'s work, but it lets you skip the check about changing the device end of a stream if isinput==-1. +extern bool SetAudioStreamChannelMap(SDL_AudioStream *stream, const SDL_AudioSpec *spec, int **stream_chmap, const int *chmap, int channels, int isinput); + + typedef struct SDL_AudioDriverImpl { - void (*DetectDevices)(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); - int (*OpenDevice)(SDL_AudioDevice *device); + void (*DetectDevices)(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording); + bool (*OpenDevice)(SDL_AudioDevice *device); void (*ThreadInit)(SDL_AudioDevice *device); // Called by audio thread at start void (*ThreadDeinit)(SDL_AudioDevice *device); // Called by audio thread at end - int (*WaitDevice)(SDL_AudioDevice *device); - int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience. + bool (*WaitDevice)(SDL_AudioDevice *device); + bool (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); // buffer and buflen are always from GetDeviceBuf, passed here for convenience. Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); - int (*WaitCaptureDevice)(SDL_AudioDevice *device); - int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); - void (*FlushCapture)(SDL_AudioDevice *device); + bool (*WaitRecordingDevice)(SDL_AudioDevice *device); + int (*RecordDevice)(SDL_AudioDevice *device, void *buffer, int buflen); + void (*FlushRecording)(SDL_AudioDevice *device); void (*CloseDevice)(SDL_AudioDevice *device); void (*FreeDeviceHandle)(SDL_AudioDevice *device); // SDL is done with this device; free the handle from SDL_AddAudioDevice() void (*DeinitializeStart)(void); // SDL calls this, then starts destroying objects, then calls Deinitialize. This is a good place to stop hotplug detection. void (*Deinitialize)(void); // Some flags to push duplicate code into the core and reduce #ifdefs. - SDL_bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore. - SDL_bool HasCaptureSupport; - SDL_bool OnlyHasDefaultOutputDevice; - SDL_bool OnlyHasDefaultCaptureDevice; // !!! FIXME: is there ever a time where you'd have a default output and not a default capture (or vice versa)? + bool ProvidesOwnCallbackThread; // !!! FIXME: rename this, it's not a callback thread anymore. + bool HasRecordingSupport; + bool OnlyHasDefaultPlaybackDevice; + bool OnlyHasDefaultRecordingDevice; // !!! FIXME: is there ever a time where you'd have a default playback and not a default recording (or vice versa)? } SDL_AudioDriverImpl; @@ -165,16 +177,16 @@ typedef struct SDL_AudioDriver const char *desc; // The description of this audio driver SDL_AudioDriverImpl impl; // the backend's interface SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash` - SDL_HashTable *device_hash; // the collection of currently-available audio devices (capture, playback, logical and physical!) + SDL_HashTable *device_hash; // the collection of currently-available audio devices (recording, playback, logical and physical!) SDL_AudioStream *existing_streams; // a list of all existing SDL_AudioStreams. - SDL_AudioDeviceID default_output_device_id; - SDL_AudioDeviceID default_capture_device_id; + SDL_AudioDeviceID default_playback_device_id; + SDL_AudioDeviceID default_recording_device_id; SDL_PendingAudioDeviceEvent pending_events; SDL_PendingAudioDeviceEvent *pending_events_tail; // !!! FIXME: most (all?) of these don't have to be atomic. - SDL_AtomicInt output_device_count; - SDL_AtomicInt capture_device_count; + SDL_AtomicInt playback_device_count; + SDL_AtomicInt recording_device_count; SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs. } SDL_AudioDriver; @@ -193,21 +205,22 @@ struct SDL_AudioStream SDL_AudioSpec src_spec; SDL_AudioSpec dst_spec; + int *src_chmap; + int *dst_chmap; float freq_ratio; + float gain; struct SDL_AudioQueue* queue; - Uint64 total_bytes_queued; SDL_AudioSpec input_spec; // The spec of input data currently being processed + int *input_chmap; + int input_chmap_storage[SDL_MAX_CHANNELMAP_CHANNELS]; // !!! FIXME: this needs to grow if SDL ever supports more channels. But if it grows, we should probably be more clever about allocations. Sint64 resample_offset; Uint8 *work_buffer; // used for scratch space during data conversion/resampling. size_t work_buffer_allocation; - Uint8 *history_buffer; // history for left padding and future sample rate changes. - size_t history_buffer_allocation; - - SDL_bool simplified; // SDL_TRUE if created via SDL_OpenAudioDeviceStream + bool simplified; // true if created via SDL_OpenAudioDeviceStream SDL_LogicalAudioDevice *bound_device; SDL_AudioStream *next_binding; @@ -232,14 +245,17 @@ struct SDL_LogicalAudioDevice // If whole logical device is paused (process no streams bound to this device). SDL_AtomicInt paused; + // Volume of the device output. + float gain; + // double-linked list of all audio streams currently bound to this opened device. SDL_AudioStream *bound_streams; - // SDL_TRUE if this was opened as a default device. - SDL_bool opened_as_default; + // true if this was opened as a default device. + bool opened_as_default; - // SDL_TRUE if device was opened with SDL_OpenAudioDeviceStream (so it forbids binding changes, etc). - SDL_bool simplified; + // true if device was opened with SDL_OpenAudioDeviceStream (so it forbids binding changes, etc). + bool simplified; // If non-NULL, callback into the app that lets them access the final postmix buffer. SDL_AudioPostmixCallback postmix; @@ -264,12 +280,12 @@ struct SDL_AudioDevice SDL_AtomicInt refcount; // These are, initially, set from current_audio, but we might swap them out with Zombie versions on disconnect/failure. - int (*WaitDevice)(SDL_AudioDevice *device); - int (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); + bool (*WaitDevice)(SDL_AudioDevice *device); + bool (*PlayDevice)(SDL_AudioDevice *device, const Uint8 *buffer, int buflen); Uint8 *(*GetDeviceBuf)(SDL_AudioDevice *device, int *buffer_size); - int (*WaitCaptureDevice)(SDL_AudioDevice *device); - int (*CaptureFromDevice)(SDL_AudioDevice *device, void *buffer, int buflen); - void (*FlushCapture)(SDL_AudioDevice *device); + bool (*WaitRecordingDevice)(SDL_AudioDevice *device); + int (*RecordDevice)(SDL_AudioDevice *device, void *buffer, int buflen); + void (*FlushRecording)(SDL_AudioDevice *device); // human-readable name of the device. ("SoundBlaster Pro 16") char *name; @@ -284,6 +300,8 @@ struct SDL_AudioDevice SDL_AudioSpec spec; int buffer_size; + int *chmap; + // The device's default audio specification SDL_AudioSpec default_spec; @@ -299,11 +317,11 @@ struct SDL_AudioDevice // non-zero if this was a disconnected device and we're waiting for it to be decommissioned. SDL_AtomicInt zombie; - // SDL_TRUE if this is a capture device instead of an output device - SDL_bool iscapture; + // true if this is a recording device instead of an playback device + bool recording; - // SDL_TRUE if audio thread can skip silence/mix/convert stages and just do a basic memcpy. - SDL_bool simple_copy; + // true if audio thread can skip silence/mix/convert stages and just do a basic memcpy. + bool simple_copy; // Scratch buffers used for mixing. Uint8 *work_buffer; @@ -316,8 +334,8 @@ struct SDL_AudioDevice // A thread to feed the audio device SDL_Thread *thread; - // SDL_TRUE if this physical device is currently opened by the backend. - SDL_bool currently_opened; + // true if this physical device is currently opened by the backend. + bool currently_opened; // Data private to this driver struct SDL_PrivateAudioData *hidden; @@ -330,11 +348,12 @@ typedef struct AudioBootStrap { const char *name; const char *desc; - SDL_bool (*init)(SDL_AudioDriverImpl *impl); - SDL_bool demand_only; // if SDL_TRUE: request explicitly, or it won't be available. + bool (*init)(SDL_AudioDriverImpl *impl); + bool demand_only; // if true: request explicitly, or it won't be available. } AudioBootStrap; // Not all of these are available in a given build. Use #ifdefs, etc. +extern AudioBootStrap PIPEWIRE_PREFERRED_bootstrap; extern AudioBootStrap PIPEWIRE_bootstrap; extern AudioBootStrap PULSEAUDIO_bootstrap; extern AudioBootStrap ALSA_bootstrap; @@ -351,7 +370,6 @@ extern AudioBootStrap DISKAUDIO_bootstrap; extern AudioBootStrap DUMMYAUDIO_bootstrap; extern AudioBootStrap AAUDIO_bootstrap; extern AudioBootStrap OPENSLES_bootstrap; -extern AudioBootStrap ANDROIDAUDIO_bootstrap; extern AudioBootStrap PS2AUDIO_bootstrap; extern AudioBootStrap PSPAUDIO_bootstrap; extern AudioBootStrap VITAAUD_bootstrap; diff --git a/libs/SDL3/src/audio/SDL_wave.c b/libs/SDL3/src/audio/SDL_wave.c index 280bd9a9b..9ce1c85b1 100644 --- a/libs/SDL3/src/audio/SDL_wave.c +++ b/libs/SDL3/src/audio/SDL_wave.c @@ -24,14 +24,14 @@ #include #endif #ifndef INT_MAX -/* Make a lucky guess. */ +SDL_COMPILE_TIME_ASSERT(int_size, sizeof(int) == sizeof(Sint32)); #define INT_MAX SDL_MAX_SINT32 #endif #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) #endif -/* Microsoft WAVE file loading routines */ +// Microsoft WAVE file loading routines #include "SDL_wave.h" #include "SDL_sysaudio.h" @@ -52,17 +52,17 @@ static int SafeMult(size_t *f1, size_t f2) typedef struct ADPCM_DecoderState { - Uint32 channels; /* Number of channels. */ - size_t blocksize; /* Size of an ADPCM block in bytes. */ - size_t blockheadersize; /* Size of an ADPCM block header in bytes. */ - size_t samplesperblock; /* Number of samples per channel in an ADPCM block. */ - size_t framesize; /* Size of a sample frame (16-bit PCM) in bytes. */ - Sint64 framestotal; /* Total number of sample frames. */ - Sint64 framesleft; /* Number of sample frames still to be decoded. */ - void *ddata; /* Decoder data from initialization. */ - void *cstate; /* Decoding state for each channel. */ - - /* ADPCM data. */ + Uint32 channels; // Number of channels. + size_t blocksize; // Size of an ADPCM block in bytes. + size_t blockheadersize; // Size of an ADPCM block header in bytes. + size_t samplesperblock; // Number of samples per channel in an ADPCM block. + size_t framesize; // Size of a sample frame (16-bit PCM) in bytes. + Sint64 framestotal; // Total number of sample frames. + Sint64 framesleft; // Number of sample frames still to be decoded. + void *ddata; // Decoder data from initialization. + void *cstate; // Decoding state for each channel. + + // ADPCM data. struct { Uint8 *data; @@ -70,7 +70,7 @@ typedef struct ADPCM_DecoderState size_t pos; } input; - /* Current ADPCM block in the ADPCM data above. */ + // Current ADPCM block in the ADPCM data above. struct { Uint8 *data; @@ -78,7 +78,7 @@ typedef struct ADPCM_DecoderState size_t pos; } block; - /* Decoded 16-bit PCM data. */ + // Decoded 16-bit PCM data. struct { Sint16 *data; @@ -91,7 +91,7 @@ typedef struct MS_ADPCM_CoeffData { Uint16 coeffcount; Sint16 *coeff; - Sint16 aligndummy; /* Has to be last member. */ + Sint16 aligndummy; // Has to be last member. } MS_ADPCM_CoeffData; typedef struct MS_ADPCM_ChannelState @@ -324,7 +324,8 @@ static Sint64 WaveAdjustToFactValue(WaveFile *file, Sint64 sampleframes) { if (file->fact.status == 2) { if (file->facthint == FactStrict && sampleframes < file->fact.samplelength) { - return SDL_SetError("Invalid number of sample frames in WAVE fact chunk (too many)"); + SDL_SetError("Invalid number of sample frames in WAVE fact chunk (too many)"); + return -1; } else if (sampleframes > file->fact.samplelength) { return file->fact.samplelength; } @@ -333,7 +334,7 @@ static Sint64 WaveAdjustToFactValue(WaveFile *file, Sint64 sampleframes) return sampleframes; } -static int MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) +static bool MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; const size_t blockheadersize = (size_t)file->format.channels * 7; @@ -342,18 +343,18 @@ static int MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) const size_t trailingdata = datalength % file->format.blockalign; if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) { - /* The size of the data chunk must be a multiple of the block size. */ + // The size of the data chunk must be a multiple of the block size. if (datalength < blockheadersize || trailingdata > 0) { return SDL_SetError("Truncated MS ADPCM block"); } } - /* Calculate number of sample frames that will be decoded. */ + // Calculate number of sample frames that will be decoded. file->sampleframes = (Sint64)availableblocks * format->samplesperblock; if (trailingdata > 0) { - /* The last block is truncated. Check if we can get any samples out of it. */ + // The last block is truncated. Check if we can get any samples out of it. if (file->trunchint == TruncDropFrame) { - /* Drop incomplete sample frame. */ + // Drop incomplete sample frame. if (trailingdata >= blockheadersize) { size_t trailingsamples = 2 + (trailingdata - blockheadersize) * 8 / blockframebitsize; if (trailingsamples > format->samplesperblock) { @@ -366,13 +367,13 @@ static int MS_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes); if (file->sampleframes < 0) { - return -1; + return false; } - return 0; + return true; } -static int MS_ADPCM_Init(WaveFile *file, size_t datalength) +static bool MS_ADPCM_Init(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; WaveChunk *chunk = &file->chunk; @@ -384,7 +385,7 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) size_t i, coeffcount; MS_ADPCM_CoeffData *coeffdata; - /* Sanity checks. */ + // Sanity checks. /* While it's clear how IMA ADPCM handles more than two channels, the nibble * order of MS ADPCM makes it awkward. The Standards Update does not talk @@ -398,7 +399,7 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) return SDL_SetError("Invalid MS ADPCM bits per sample of %u", (unsigned int)format->bitspersample); } - /* The block size must be big enough to contain the block header. */ + // The block size must be big enough to contain the block header. if (format->blockalign < blockheadersize) { return SDL_SetError("Invalid MS ADPCM block size (nBlockAlign)"); } @@ -419,7 +420,7 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) } format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8); - /* Number of coefficient pairs. A pair has two 16-bit integers. */ + // Number of coefficient pairs. A pair has two 16-bit integers. coeffcount = chunk->data[20] | ((size_t)chunk->data[21] << 8); /* bPredictor, the integer offset into the coefficients array, is only * 8 bits. It can only address the first 256 coefficients. Let's limit @@ -438,14 +439,14 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) } coeffdata = (MS_ADPCM_CoeffData *)SDL_malloc(sizeof(MS_ADPCM_CoeffData) + coeffcount * 4); - file->decoderdata = coeffdata; /* Freed in cleanup. */ + file->decoderdata = coeffdata; // Freed in cleanup. if (!coeffdata) { - return -1; + return false; } coeffdata->coeff = &coeffdata->aligndummy; coeffdata->coeffcount = (Uint16)coeffcount; - /* Copy the 16-bit pairs. */ + // Copy the 16-bit pairs. for (i = 0; i < coeffcount * 2; i++) { Sint32 c = chunk->data[22 + i * 2] | ((Sint32)chunk->data[23 + i * 2] << 8); if (c >= 0x8000) { @@ -483,11 +484,11 @@ static int MS_ADPCM_Init(WaveFile *file, size_t datalength) return SDL_SetError("Invalid number of samples per MS ADPCM block (wSamplesPerBlock)"); } - if (MS_ADPCM_CalculateSampleFrames(file, datalength) < 0) { - return -1; + if (!MS_ADPCM_CalculateSampleFrames(file, datalength)) { + return false; } - return 0; + return true; } static Sint16 MS_ADPCM_ProcessNibble(MS_ADPCM_ChannelState *cstate, Sint32 sample1, Sint32 sample2, Uint8 nybble) @@ -504,7 +505,7 @@ static Sint16 MS_ADPCM_ProcessNibble(MS_ADPCM_ChannelState *cstate, Sint32 sampl Uint32 delta = cstate->delta; new_sample = (sample1 * cstate->coeff1 + sample2 * cstate->coeff2) / 256; - /* The nibble is a signed 4-bit error delta. */ + // The nibble is a signed 4-bit error delta. errordelta = (Sint32)nybble - (nybble >= 0x08 ? 0x10 : 0); new_sample += (Sint32)delta * errordelta; if (new_sample < min_audioval) { @@ -526,7 +527,7 @@ static Sint16 MS_ADPCM_ProcessNibble(MS_ADPCM_ChannelState *cstate, Sint32 sampl return (Sint16)new_sample; } -static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) +static bool MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) { Uint8 coeffindex; const Uint32 channels = state->channels; @@ -538,7 +539,7 @@ static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) for (c = 0; c < channels; c++) { size_t o = c; - /* Load the coefficient pair into the channel state. */ + // Load the coefficient pair into the channel state. coeffindex = state->block.data[o]; if (coeffindex > ddata->coeffcount) { return SDL_SetError("Invalid MS ADPCM coefficient index in block header"); @@ -546,7 +547,7 @@ static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) cstate[c].coeff1 = ddata->coeff[coeffindex * 2]; cstate[c].coeff2 = ddata->coeff[coeffindex * 2 + 1]; - /* Initial delta value. */ + // Initial delta value. o = (size_t)channels + c * 2; cstate[c].delta = state->block.data[o] | ((Uint16)state->block.data[o + 1] << 8); @@ -572,13 +573,13 @@ static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) state->block.pos += state->blockheadersize; - /* Skip second sample frame that came from the header. */ + // Skip second sample frame that came from the header. state->output.pos += state->channels; - /* Header provided two sample frames. */ + // Header provided two sample frames. state->framesleft -= 2; - return 0; + return true; } /* Decodes the data of the MS ADPCM block. Decoding will stop if a block is too @@ -586,7 +587,7 @@ static int MS_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) * will always contain full sample frames (same sample count for each channel). * Incomplete sample frames are discarded. */ -static int MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) +static bool MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) { Uint16 nybble = 0; Sint16 sample1, sample2; @@ -611,12 +612,12 @@ static int MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) } else if (blockpos < blocksize) { nybble = state->block.data[blockpos++] | 0x4000; } else { - /* Out of input data. Drop the incomplete frame and return. */ + // Out of input data. Drop the incomplete frame and return. state->output.pos = outpos - c; - return -1; + return false; } - /* Load previous samples which may come from the block header. */ + // Load previous samples which may come from the block header. sample1 = state->output.data[outpos - channels]; sample2 = state->output.data[outpos - channels * 2]; @@ -630,12 +631,12 @@ static int MS_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) state->output.pos = outpos; - return 0; + return true; } -static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) +static bool MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) { - int result; + bool result; size_t bytesleft, outputsize; WaveChunk *chunk = &file->chunk; ADPCM_DecoderState state; @@ -645,17 +646,17 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) SDL_zeroa(cstate); if (chunk->size != chunk->length) { - /* Could not read everything. Recalculate number of sample frames. */ - if (MS_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) { - return -1; + // Could not read everything. Recalculate number of sample frames. + if (!MS_ADPCM_CalculateSampleFrames(file, chunk->size)) { + return false; } } - /* Nothing to decode, nothing to return. */ + // Nothing to decode, nothing to return. if (file->sampleframes == 0) { *audio_buf = NULL; *audio_len = 0; - return 0; + return true; } state.blocksize = file->format.blockalign; @@ -671,7 +672,7 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) state.input.size = chunk->size; state.input.pos = 0; - /* The output size in bytes. May get modified if data is truncated. */ + // The output size in bytes. May get modified if data is truncated. outputsize = (size_t)state.framestotal; if (SafeMult(&outputsize, state.framesize)) { return SDL_SetError("WAVE file too big"); @@ -683,12 +684,12 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_calloc(1, outputsize); if (!state.output.data) { - return -1; + return false; } state.cstate = cstate; - /* Decode block by block. A truncated block will stop the decoding. */ + // Decode block by block. A truncated block will stop the decoding. bytesleft = state.input.size - state.input.pos; while (state.framesleft > 0 && bytesleft >= state.blockheadersize) { state.block.data = state.input.data + state.input.pos; @@ -696,29 +697,29 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) state.block.pos = 0; if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) { - /* Somehow didn't allocate enough space for the output. */ + // Somehow didn't allocate enough space for the output. SDL_free(state.output.data); return SDL_SetError("Unexpected overflow in MS ADPCM decoder"); } - /* Initialize decoder with the values from the block header. */ + // Initialize decoder with the values from the block header. result = MS_ADPCM_DecodeBlockHeader(&state); - if (result == -1) { + if (!result) { SDL_free(state.output.data); - return -1; + return false; } - /* Decode the block data. It stores the samples directly in the output. */ + // Decode the block data. It stores the samples directly in the output. result = MS_ADPCM_DecodeBlockData(&state); - if (result == -1) { - /* Unexpected end. Stop decoding and return partial data if necessary. */ + if (!result) { + // Unexpected end. Stop decoding and return partial data if necessary. if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) { SDL_free(state.output.data); return SDL_SetError("Truncated data chunk"); } else if (file->trunchint != TruncDropFrame) { state.output.pos -= state.output.pos % (state.samplesperblock * state.channels); } - outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */ + outputsize = state.output.pos * sizeof(Sint16); // Can't overflow, is always smaller. break; } @@ -729,10 +730,10 @@ static int MS_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) *audio_buf = (Uint8 *)state.output.data; *audio_len = (Uint32)outputsize; - return 0; + return true; } -static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) +static bool IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; const size_t blockheadersize = (size_t)format->channels * 4; @@ -741,16 +742,16 @@ static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) const size_t trailingdata = datalength % format->blockalign; if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) { - /* The size of the data chunk must be a multiple of the block size. */ + // The size of the data chunk must be a multiple of the block size. if (datalength < blockheadersize || trailingdata > 0) { return SDL_SetError("Truncated IMA ADPCM block"); } } - /* Calculate number of sample frames that will be decoded. */ + // Calculate number of sample frames that will be decoded. file->sampleframes = (Uint64)availableblocks * format->samplesperblock; if (trailingdata > 0) { - /* The last block is truncated. Check if we can get any samples out of it. */ + // The last block is truncated. Check if we can get any samples out of it. if (file->trunchint == TruncDropFrame && trailingdata > blockheadersize - 2) { /* The sample frame in the header of the truncated block is present. * Drop incomplete sample frames. @@ -758,7 +759,7 @@ static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) size_t trailingsamples = 1; if (trailingdata > blockheadersize) { - /* More data following after the header. */ + // More data following after the header. const size_t trailingblockdata = trailingdata - blockheadersize; const size_t trailingsubblockdata = trailingblockdata % subblockframesize; trailingsamples += (trailingblockdata / subblockframesize) * 8; @@ -779,13 +780,13 @@ static int IMA_ADPCM_CalculateSampleFrames(WaveFile *file, size_t datalength) file->sampleframes = WaveAdjustToFactValue(file, file->sampleframes); if (file->sampleframes < 0) { - return -1; + return false; } - return 0; + return true; } -static int IMA_ADPCM_Init(WaveFile *file, size_t datalength) +static bool IMA_ADPCM_Init(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; WaveChunk *chunk = &file->chunk; @@ -794,9 +795,9 @@ static int IMA_ADPCM_Init(WaveFile *file, size_t datalength) const size_t blockframebitsize = (size_t)format->bitspersample * format->channels; const size_t blockdatasamples = (blockdatasize * 8) / blockframebitsize; - /* Sanity checks. */ + // Sanity checks. - /* IMA ADPCM can also have 3-bit samples, but it's not supported by SDL at this time. */ + // IMA ADPCM can also have 3-bit samples, but it's not supported by SDL at this time. if (format->bitspersample == 3) { return SDL_SetError("3-bit IMA ADPCM currently not supported"); } else if (format->bitspersample != 4) { @@ -815,7 +816,7 @@ static int IMA_ADPCM_Init(WaveFile *file, size_t datalength) * format because the extensible header has wSampePerBlocks too. */ } else { - /* The Standards Update says there 'should' be 2 bytes for wSamplesPerBlock. */ + // The Standards Update says there 'should' be 2 bytes for wSamplesPerBlock. if (chunk->size >= 20 && format->extsize >= 2) { format->samplesperblock = chunk->data[18] | ((Uint16)chunk->data[19] << 8); } @@ -843,11 +844,11 @@ static int IMA_ADPCM_Init(WaveFile *file, size_t datalength) return SDL_SetError("Invalid number of samples per IMA ADPCM block (wSamplesPerBlock)"); } - if (IMA_ADPCM_CalculateSampleFrames(file, datalength) < 0) { - return -1; + if (!IMA_ADPCM_CalculateSampleFrames(file, datalength)) { + return false; } - return 0; + return true; } static Sint16 IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 nybble) @@ -874,17 +875,17 @@ static Sint16 IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 ny Sint32 sample, delta; Sint8 index = *cindex; - /* Clamp index into valid range. */ + // Clamp index into valid range. if (index > 88) { index = 88; } else if (index < 0) { index = 0; } - /* explicit cast to avoid gcc warning about using 'char' as array index */ + // explicit cast to avoid gcc warning about using 'char' as array index step = step_table[(size_t)index]; - /* Update index value */ + // Update index value *cindex = index + index_table_4b[nybble]; /* This calculation uses shifts and additions because multiplications were @@ -909,7 +910,7 @@ static Sint16 IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 ny sample = lastsample + delta; - /* Clamp output sample */ + // Clamp output sample if (sample > max_audioval) { sample = max_audioval; } else if (sample < min_audioval) { @@ -919,7 +920,7 @@ static Sint16 IMA_ADPCM_ProcessNibble(Sint8 *cindex, Sint16 lastsample, Uint8 ny return (Sint16)sample; } -static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) +static bool IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) { Sint16 step; Uint32 c; @@ -928,18 +929,18 @@ static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) for (c = 0; c < state->channels; c++) { size_t o = state->block.pos + c * 4; - /* Extract the sample from the header. */ + // Extract the sample from the header. Sint32 sample = state->block.data[o] | ((Sint32)state->block.data[o + 1] << 8); if (sample >= 0x8000) { sample -= 0x10000; } state->output.data[state->output.pos++] = (Sint16)sample; - /* Channel step index. */ + // Channel step index. step = (Sint16)state->block.data[o + 2]; cstate[c] = (Sint8)(step > 0x80 ? step - 0x100 : step); - /* Reserved byte in block header, should be 0. */ + // Reserved byte in block header, should be 0. if (state->block.data[o + 3] != 0) { /* Uh oh, corrupt data? Buggy code? */; } @@ -947,10 +948,10 @@ static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) state->block.pos += state->blockheadersize; - /* Header provided one sample frame. */ + // Header provided one sample frame. state->framesleft--; - return 0; + return true; } /* Decodes the data of the IMA ADPCM block. Decoding will stop if a block is too @@ -958,14 +959,14 @@ static int IMA_ADPCM_DecodeBlockHeader(ADPCM_DecoderState *state) * contains full sample frames (same sample count for each channel). * Incomplete sample frames are discarded. */ -static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) +static bool IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) { size_t i; - int retval = 0; const Uint32 channels = state->channels; const size_t subblockframesize = (size_t)channels * 4; Uint64 bytesrequired; Uint32 c; + bool result = true; size_t blockpos = state->block.pos; size_t blocksize = state->block.size; @@ -980,15 +981,15 @@ static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) bytesrequired = (blockframesleft + 7) / 8 * subblockframesize; if (blockleft < bytesrequired) { - /* Data truncated. Calculate how many samples we can get out if it. */ + // Data truncated. Calculate how many samples we can get out if it. const size_t guaranteedframes = blockleft / subblockframesize; const size_t remainingbytes = blockleft % subblockframesize; blockframesleft = guaranteedframes; if (remainingbytes > subblockframesize - 4) { blockframesleft += (Sint64)(remainingbytes % 4) * 2; } - /* Signal the truncation. */ - retval = -1; + // Signal the truncation. + result = false; } /* Each channel has their nibbles packed into 32-bit blocks. These blocks @@ -1001,7 +1002,7 @@ static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) for (c = 0; c < channels; c++) { Uint8 nybble = 0; - /* Load previous sample which may come from the block header. */ + // Load previous sample which may come from the block header. Sint16 sample = state->output.data[outpos + c - channels]; for (i = 0; i < subblocksamples; i++) { @@ -1024,29 +1025,29 @@ static int IMA_ADPCM_DecodeBlockData(ADPCM_DecoderState *state) state->block.pos = blockpos; state->output.pos = outpos; - return retval; + return result; } -static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) +static bool IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) { - int result; + bool result; size_t bytesleft, outputsize; WaveChunk *chunk = &file->chunk; ADPCM_DecoderState state; Sint8 *cstate; if (chunk->size != chunk->length) { - /* Could not read everything. Recalculate number of sample frames. */ - if (IMA_ADPCM_CalculateSampleFrames(file, chunk->size) < 0) { - return -1; + // Could not read everything. Recalculate number of sample frames. + if (!IMA_ADPCM_CalculateSampleFrames(file, chunk->size)) { + return false; } } - /* Nothing to decode, nothing to return. */ + // Nothing to decode, nothing to return. if (file->sampleframes == 0) { *audio_buf = NULL; *audio_len = 0; - return 0; + return true; } SDL_zero(state); @@ -1062,7 +1063,7 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len state.input.size = chunk->size; state.input.pos = 0; - /* The output size in bytes. May get modified if data is truncated. */ + // The output size in bytes. May get modified if data is truncated. outputsize = (size_t)state.framestotal; if (SafeMult(&outputsize, state.framesize)) { return SDL_SetError("WAVE file too big"); @@ -1074,17 +1075,17 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len state.output.size = outputsize / sizeof(Sint16); state.output.data = (Sint16 *)SDL_malloc(outputsize); if (!state.output.data) { - return -1; + return false; } cstate = (Sint8 *)SDL_calloc(state.channels, sizeof(Sint8)); if (!cstate) { SDL_free(state.output.data); - return -1; + return false; } state.cstate = cstate; - /* Decode block by block. A truncated block will stop the decoding. */ + // Decode block by block. A truncated block will stop the decoding. bytesleft = state.input.size - state.input.pos; while (state.framesleft > 0 && bytesleft >= state.blockheadersize) { state.block.data = state.input.data + state.input.pos; @@ -1092,21 +1093,21 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len state.block.pos = 0; if (state.output.size - state.output.pos < (Uint64)state.framesleft * state.channels) { - /* Somehow didn't allocate enough space for the output. */ + // Somehow didn't allocate enough space for the output. SDL_free(state.output.data); SDL_free(cstate); return SDL_SetError("Unexpected overflow in IMA ADPCM decoder"); } - /* Initialize decoder with the values from the block header. */ + // Initialize decoder with the values from the block header. result = IMA_ADPCM_DecodeBlockHeader(&state); - if (result == 0) { - /* Decode the block data. It stores the samples directly in the output. */ + if (result) { + // Decode the block data. It stores the samples directly in the output. result = IMA_ADPCM_DecodeBlockData(&state); } - if (result == -1) { - /* Unexpected end. Stop decoding and return partial data if necessary. */ + if (!result) { + // Unexpected end. Stop decoding and return partial data if necessary. if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) { SDL_free(state.output.data); SDL_free(cstate); @@ -1114,7 +1115,7 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len } else if (file->trunchint != TruncDropFrame) { state.output.pos -= state.output.pos % (state.samplesperblock * state.channels); } - outputsize = state.output.pos * sizeof(Sint16); /* Can't overflow, is always smaller. */ + outputsize = state.output.pos * sizeof(Sint16); // Can't overflow, is always smaller. break; } @@ -1127,19 +1128,19 @@ static int IMA_ADPCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len SDL_free(cstate); - return 0; + return true; } -static int LAW_Init(WaveFile *file, size_t datalength) +static bool LAW_Init(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; - /* Standards Update requires this to be 8. */ + // Standards Update requires this to be 8. if (format->bitspersample != 8) { return SDL_SetError("Invalid companded bits per sample of %u", (unsigned int)format->bitspersample); } - /* Not going to bother with weird padding. */ + // Not going to bother with weird padding. if (format->blockalign != format->channels) { return SDL_SetError("Unsupported block alignment"); } @@ -1152,13 +1153,13 @@ static int LAW_Init(WaveFile *file, size_t datalength) file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign); if (file->sampleframes < 0) { - return -1; + return false; } - return 0; + return true; } -static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) +static bool LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) { #ifdef SDL_WAVE_LAW_LUT const Sint16 alaw_lut[256] = { @@ -1208,15 +1209,15 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) if (chunk->length != chunk->size) { file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign); if (file->sampleframes < 0) { - return -1; + return false; } } - /* Nothing to decode, nothing to return. */ + // Nothing to decode, nothing to return. if (file->sampleframes == 0) { *audio_buf = NULL; *audio_len = 0; - return 0; + return true; } sample_count = (size_t)file->sampleframes; @@ -1231,10 +1232,10 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) return SDL_SetError("WAVE file too big"); } - /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ + // 1 to avoid allocating zero bytes, to keep static analysis happy. src = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); if (!src) { - return -1; + return false; } chunk->data = NULL; chunk->size = 0; @@ -1297,10 +1298,10 @@ static int LAW_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) *audio_buf = src; *audio_len = (Uint32)expanded_len; - return 0; + return true; } -static int PCM_Init(WaveFile *file, size_t datalength) +static bool PCM_Init(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; @@ -1310,7 +1311,7 @@ static int PCM_Init(WaveFile *file, size_t datalength) case 16: case 24: case 32: - /* These are supported. */ + // These are supported. break; default: return SDL_SetError("%u-bit PCM format not supported", (unsigned int)format->bitspersample); @@ -1324,7 +1325,7 @@ static int PCM_Init(WaveFile *file, size_t datalength) /* It wouldn't be that hard to support more exotic block sizes, but * the most common formats should do for now. */ - /* Make sure we're a multiple of the blockalign, at least. */ + // Make sure we're a multiple of the blockalign, at least. if ((format->channels * format->bitspersample) % (format->blockalign * 8)) { return SDL_SetError("Unsupported block alignment"); } @@ -1337,13 +1338,13 @@ static int PCM_Init(WaveFile *file, size_t datalength) file->sampleframes = WaveAdjustToFactValue(file, datalength / format->blockalign); if (file->sampleframes < 0) { - return -1; + return false; } - return 0; + return true; } -static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) +static bool PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) { WaveFormat *format = &file->format; WaveChunk *chunk = &file->chunk; @@ -1362,20 +1363,20 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 * return SDL_SetError("WAVE file too big"); } - /* 1 to avoid allocating zero bytes, to keep static analysis happy. */ + // 1 to avoid allocating zero bytes, to keep static analysis happy. ptr = (Uint8 *)SDL_realloc(chunk->data, expanded_len ? expanded_len : 1); if (!ptr) { - return -1; + return false; } - /* This pointer is now invalid. */ + // This pointer is now invalid. chunk->data = NULL; chunk->size = 0; *audio_buf = ptr; *audio_len = (Uint32)expanded_len; - /* work from end to start, since we're expanding in-place. */ + // work from end to start, since we're expanding in-place. for (i = sample_count; i > 0; i--) { const size_t o = i - 1; uint8_t b[4]; @@ -1391,10 +1392,10 @@ static int PCM_ConvertSint24ToSint32(WaveFile *file, Uint8 **audio_buf, Uint32 * ptr[o * 4 + 3] = b[3]; } - return 0; + return true; } -static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) +static bool PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) { WaveFormat *format = &file->format; WaveChunk *chunk = &file->chunk; @@ -1403,18 +1404,18 @@ static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) if (chunk->length != chunk->size) { file->sampleframes = WaveAdjustToFactValue(file, chunk->size / format->blockalign); if (file->sampleframes < 0) { - return -1; + return false; } } - /* Nothing to decode, nothing to return. */ + // Nothing to decode, nothing to return. if (file->sampleframes == 0) { *audio_buf = NULL; *audio_len = 0; - return 0; + return true; } - /* 24-bit samples get shifted to 32 bits. */ + // 24-bit samples get shifted to 32 bits. if (format->encoding == PCM_CODE && format->bitspersample == 24) { return PCM_ConvertSint24ToSint32(file, audio_buf, audio_len); } @@ -1429,11 +1430,11 @@ static int PCM_Decode(WaveFile *file, Uint8 **audio_buf, Uint32 *audio_len) *audio_buf = chunk->data; *audio_len = (Uint32)outputsize; - /* This pointer is going to be returned to the caller. Prevent free in cleanup. */ + // This pointer is going to be returned to the caller. Prevent free in cleanup. chunk->data = NULL; chunk->size = 0; - return 0; + return true; } static WaveRiffSizeHint WaveGetRiffSizeHint(void) @@ -1507,28 +1508,28 @@ static int WaveNextChunk(SDL_IOStream *src, WaveChunk *chunk) Uint32 chunkheader[2]; Sint64 nextposition = chunk->position + chunk->length; - /* Data is no longer valid after this function returns. */ + // Data is no longer valid after this function returns. WaveFreeChunkData(chunk); - /* Error on overflows. */ + // Error on overflows. if (SDL_MAX_SINT64 - chunk->length < chunk->position || SDL_MAX_SINT64 - 8 < nextposition) { return -1; } - /* RIFF chunks have a 2-byte alignment. Skip padding byte. */ + // RIFF chunks have a 2-byte alignment. Skip padding byte. if (chunk->length & 1) { nextposition++; } if (SDL_SeekIO(src, nextposition, SDL_IO_SEEK_SET) != nextposition) { - /* Not sure how we ended up here. Just abort. */ + // Not sure how we ended up here. Just abort. return -2; } else if (SDL_ReadIO(src, chunkheader, sizeof(Uint32) * 2) != (sizeof(Uint32) * 2)) { return -1; } - chunk->fourcc = SDL_SwapLE32(chunkheader[0]); - chunk->length = SDL_SwapLE32(chunkheader[1]); + chunk->fourcc = SDL_Swap32LE(chunkheader[0]); + chunk->length = SDL_Swap32LE(chunkheader[1]); chunk->position = nextposition + 8; return 0; @@ -1549,13 +1550,13 @@ static int WaveReadPartialChunkData(SDL_IOStream *src, WaveChunk *chunk, size_t } if (SDL_SeekIO(src, chunk->position, SDL_IO_SEEK_SET) != chunk->position) { - /* Not sure how we ended up here. Just abort. */ + // Not sure how we ended up here. Just abort. return -2; } chunk->size = SDL_ReadIO(src, chunk->data, length); if (chunk->size != length) { - /* Expected to be handled by the caller. */ + // Expected to be handled by the caller. } } @@ -1573,7 +1574,7 @@ typedef struct WaveExtensibleGUID Uint8 guid[16]; } WaveExtensibleGUID; -/* Some of the GUIDs that are used by WAVEFORMATEXTENSIBLE. */ +// Some of the GUIDs that are used by WAVEFORMATEXTENSIBLE. #define WAVE_FORMATTAG_GUID(tag) \ { \ (tag) & 0xff, (tag) >> 8, 0, 0, 0, 0, 16, 0, 128, 0, 0, 170, 0, 56, 155, 113 \ @@ -1598,7 +1599,7 @@ static Uint16 WaveGetFormatGUIDEncoding(WaveFormat *format) return UNKNOWN_CODE; } -static int WaveReadFormat(WaveFile *file) +static bool WaveReadFormat(WaveFile *file) { WaveChunk *chunk = &file->chunk; WaveFormat *format = &file->format; @@ -1606,12 +1607,12 @@ static int WaveReadFormat(WaveFile *file) size_t fmtlen = chunk->size; if (fmtlen > SDL_MAX_SINT32) { - /* Limit given by SDL_IOFromConstMem. */ + // Limit given by SDL_IOFromConstMem. return SDL_SetError("Data of WAVE fmt chunk too big"); } fmtsrc = SDL_IOFromConstMem(chunk->data, (int)chunk->size); if (!fmtsrc) { - return -1; + return false; } if (!SDL_ReadU16LE(fmtsrc, &format->formattag) || @@ -1619,24 +1620,24 @@ static int WaveReadFormat(WaveFile *file) !SDL_ReadU32LE(fmtsrc, &format->frequency) || !SDL_ReadU32LE(fmtsrc, &format->byterate) || !SDL_ReadU16LE(fmtsrc, &format->blockalign)) { - return -1; + return false; } format->encoding = format->formattag; - /* This is PCM specific in the first version of the specification. */ + // This is PCM specific in the first version of the specification. if (fmtlen >= 16) { if (!SDL_ReadU16LE(fmtsrc, &format->bitspersample)) { - return -1; + return false; } } else if (format->encoding == PCM_CODE) { SDL_CloseIO(fmtsrc); return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk"); } - /* The earlier versions also don't have this field. */ + // The earlier versions also don't have this field. if (fmtlen >= 18) { if (!SDL_ReadU16LE(fmtsrc, &format->extsize)) { - return -1; + return false; } } @@ -1647,7 +1648,7 @@ static int WaveReadFormat(WaveFile *file) * to be useful working when they use this format flag. */ - /* Extensible header must be at least 22 bytes. */ + // Extensible header must be at least 22 bytes. if (fmtlen < 40 || format->extsize < 22) { SDL_CloseIO(fmtsrc); return SDL_SetError("Extensible WAVE header too small"); @@ -1663,14 +1664,14 @@ static int WaveReadFormat(WaveFile *file) SDL_CloseIO(fmtsrc); - return 0; + return true; } -static int WaveCheckFormat(WaveFile *file, size_t datalength) +static bool WaveCheckFormat(WaveFile *file, size_t datalength) { WaveFormat *format = &file->format; - /* Check for some obvious issues. */ + // Check for some obvious issues. if (format->channels == 0) { return SDL_SetError("Invalid number of channels"); @@ -1682,7 +1683,7 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength) return SDL_SetError("Sample rate exceeds limit of %d", INT_MAX); } - /* Reject invalid fact chunks in strict mode. */ + // Reject invalid fact chunks in strict mode. if (file->facthint == FactStrict && file->fact.status == -1) { return SDL_SetError("Invalid fact chunk in WAVE file"); } @@ -1697,22 +1698,22 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength) case MULAW_CODE: case MS_ADPCM_CODE: case IMA_ADPCM_CODE: - /* These formats require a fact chunk. */ + // These formats require a fact chunk. if (file->facthint == FactStrict && file->fact.status <= 0) { return SDL_SetError("Missing fact chunk in WAVE file"); } SDL_FALLTHROUGH; case PCM_CODE: - /* All supported formats require a non-zero bit depth. */ + // All supported formats require a non-zero bit depth. if (file->chunk.size < 16) { return SDL_SetError("Missing wBitsPerSample field in WAVE fmt chunk"); } else if (format->bitspersample == 0) { return SDL_SetError("Invalid bits per sample"); } - /* All supported formats must have a proper block size. */ + // All supported formats must have a proper block size. if (format->blockalign == 0) { - format->blockalign = 1; /* force it to 1 if it was unset. */ + format->blockalign = 1; // force it to 1 if it was unset. } /* If the fact chunk is valid and the appropriate hint is set, the @@ -1727,28 +1728,28 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength) } } - /* Check the format for encoding specific issues and initialize decoders. */ + // Check the format for encoding specific issues and initialize decoders. switch (format->encoding) { case PCM_CODE: case IEEE_FLOAT_CODE: - if (PCM_Init(file, datalength) < 0) { - return -1; + if (!PCM_Init(file, datalength)) { + return false; } break; case ALAW_CODE: case MULAW_CODE: - if (LAW_Init(file, datalength) < 0) { - return -1; + if (!LAW_Init(file, datalength)) { + return false; } break; case MS_ADPCM_CODE: - if (MS_ADPCM_Init(file, datalength) < 0) { - return -1; + if (!MS_ADPCM_Init(file, datalength)) { + return false; } break; case IMA_ADPCM_CODE: - if (IMA_ADPCM_Init(file, datalength) < 0) { - return -1; + if (!IMA_ADPCM_Init(file, datalength)) { + return false; } break; case MPEG_CODE: @@ -1766,17 +1767,17 @@ static int WaveCheckFormat(WaveFile *file, size_t datalength) return SDL_SetError("Unknown WAVE format tag: 0x%04x", (unsigned int)format->encoding); } - return 0; + return true; } -static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +static bool WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { int result; Uint32 chunkcount = 0; Uint32 chunkcountlimit = 10000; - char *envchunkcountlimit; + const char *hint; Sint64 RIFFstart, RIFFend, lastchunkpos; - SDL_bool RIFFlengthknown = SDL_FALSE; + bool RIFFlengthknown = false; WaveFormat *format = &file->format; WaveChunk *chunk = &file->chunk; WaveChunk RIFFchunk; @@ -1787,10 +1788,10 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint SDL_zero(fmtchunk); SDL_zero(datachunk); - envchunkcountlimit = SDL_getenv("SDL_WAVE_CHUNK_LIMIT"); - if (envchunkcountlimit) { + hint = SDL_GetHint(SDL_HINT_WAVE_CHUNK_LIMIT); + if (hint) { unsigned int count; - if (SDL_sscanf(envchunkcountlimit, "%u", &count) == 1) { + if (SDL_sscanf(hint, "%u", &count) == 1) { chunkcountlimit = count <= SDL_MAX_UINT32 ? count : SDL_MAX_UINT32; } } @@ -1805,24 +1806,24 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint return SDL_SetError("Could not read RIFF header"); } - /* Check main WAVE file identifiers. */ + // Check main WAVE file identifiers. if (RIFFchunk.fourcc == RIFF) { Uint32 formtype; - /* Read the form type. "WAVE" expected. */ + // Read the form type. "WAVE" expected. if (!SDL_ReadU32LE(src, &formtype)) { return SDL_SetError("Could not read RIFF form type"); } else if (formtype != WAVE) { return SDL_SetError("RIFF form type is not WAVE (not a Waveform file)"); } } else if (RIFFchunk.fourcc == WAVE) { - /* RIFF chunk missing or skipped. Length unknown. */ + // RIFF chunk missing or skipped. Length unknown. RIFFchunk.position = 0; RIFFchunk.length = 0; } else { return SDL_SetError("Could not find RIFF or WAVE identifiers (not a Waveform file)"); } - /* The 4-byte form type is immediately followed by the first chunk.*/ + // The 4-byte form type is immediately followed by the first chunk. chunk->position = RIFFchunk.position + 4; /* Use the RIFF chunk size to limit the search for the chunks. This is not @@ -1842,7 +1843,7 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint SDL_FALLTHROUGH; case RiffSizeForce: RIFFend = RIFFchunk.position + RIFFchunk.length; - RIFFlengthknown = SDL_TRUE; + RIFFlengthknown = true; break; case RiffSizeMaximum: RIFFend = SDL_MAX_SINT64; @@ -1854,18 +1855,18 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint * currently also ignores cue, list, and slnt chunks. */ while ((Uint64)RIFFend > (Uint64)chunk->position + chunk->length + (chunk->length & 1)) { - /* Abort after too many chunks or else corrupt files may waste time. */ + // Abort after too many chunks or else corrupt files may waste time. if (chunkcount++ >= chunkcountlimit) { return SDL_SetError("Chunk count in WAVE file exceeds limit of %" SDL_PRIu32, chunkcountlimit); } result = WaveNextChunk(src, chunk); - if (result == -1) { - /* Unexpected EOF. Corrupt file or I/O issues. */ + if (result < 0) { + // Unexpected EOF. Corrupt file or I/O issues. if (file->trunchint == TruncVeryStrict) { return SDL_SetError("Unexpected end of WAVE file"); } - /* Let the checks after this loop sort this issue out. */ + // Let the checks after this loop sort this issue out. break; } else if (result == -2) { return SDL_SetError("Could not seek to WAVE chunk header"); @@ -1873,9 +1874,9 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint if (chunk->fourcc == FMT) { if (fmtchunk.fourcc == FMT) { - /* Multiple fmt chunks. Ignore or error? */ + // Multiple fmt chunks. Ignore or error? } else { - /* The fmt chunk must occur before the data chunk. */ + // The fmt chunk must occur before the data chunk. if (datachunk.fourcc == DATA) { return SDL_SetError("fmt chunk after data chunk in WAVE file"); } @@ -1896,7 +1897,7 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint if (chunk->length < 4) { file->fact.status = -1; } else { - /* Let's use src directly, it's just too convenient. */ + // Let's use src directly, it's just too convenient. Sint64 position = SDL_SeekIO(src, chunk->position, SDL_IO_SEEK_SET); if (position == chunk->position && SDL_ReadU32LE(src, &file->fact.samplelength)) { file->fact.status = 1; @@ -1926,17 +1927,17 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint */ lastchunkpos = chunk->position + chunk->length; - /* The fmt chunk is mandatory. */ + // The fmt chunk is mandatory. if (fmtchunk.fourcc != FMT) { return SDL_SetError("Missing fmt chunk in WAVE file"); } - /* A data chunk must be present. */ + // A data chunk must be present. if (datachunk.fourcc != DATA) { return SDL_SetError("Missing data chunk in WAVE file"); } - /* Check if the last chunk has all of its data in verystrict mode. */ + // Check if the last chunk has all of its data in verystrict mode. if (file->trunchint == TruncVeryStrict) { - /* data chunk is handled later. */ + // data chunk is handled later. if (chunk->fourcc != DATA && chunk->length > 0) { Uint8 tmp; Uint64 position = (Uint64)chunk->position + chunk->length - 1; @@ -1948,7 +1949,7 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint } } - /* Process fmt chunk. */ + // Process fmt chunk. *chunk = fmtchunk; /* No need to read more than 1046 bytes of the fmt chunk data with the @@ -1965,10 +1966,10 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint return SDL_SetError("Invalid WAVE fmt chunk length (too small)"); } else if (chunk->size < 14) { return SDL_SetError("Could not read data of WAVE fmt chunk"); - } else if (WaveReadFormat(file) < 0) { - return -1; - } else if (WaveCheckFormat(file, (size_t)datachunk.length) < 0) { - return -1; + } else if (!WaveReadFormat(file)) { + return false; + } else if (!WaveCheckFormat(file, (size_t)datachunk.length)) { + return false; } #ifdef SDL_WAVE_DEBUG_LOG_FORMAT @@ -1980,48 +1981,48 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint WaveFreeChunkData(chunk); - /* Process data chunk. */ + // Process data chunk. *chunk = datachunk; if (chunk->length > 0) { result = WaveReadChunkData(src, chunk); - if (result == -1) { - return -1; + if (result < 0) { + return false; } else if (result == -2) { return SDL_SetError("Could not seek data of WAVE data chunk"); } } if (chunk->length != chunk->size) { - /* I/O issues or corrupt file. */ + // I/O issues or corrupt file. if (file->trunchint == TruncVeryStrict || file->trunchint == TruncStrict) { return SDL_SetError("Could not read data of WAVE data chunk"); } - /* The decoders handle this truncation. */ + // The decoders handle this truncation. } - /* Decode or convert the data if necessary. */ + // Decode or convert the data if necessary. switch (format->encoding) { case PCM_CODE: case IEEE_FLOAT_CODE: - if (PCM_Decode(file, audio_buf, audio_len) < 0) { - return -1; + if (!PCM_Decode(file, audio_buf, audio_len)) { + return false; } break; case ALAW_CODE: case MULAW_CODE: - if (LAW_Decode(file, audio_buf, audio_len) < 0) { - return -1; + if (!LAW_Decode(file, audio_buf, audio_len)) { + return false; } break; case MS_ADPCM_CODE: - if (MS_ADPCM_Decode(file, audio_buf, audio_len) < 0) { - return -1; + if (!MS_ADPCM_Decode(file, audio_buf, audio_len)) { + return false; } break; case IMA_ADPCM_CODE: - if (IMA_ADPCM_Decode(file, audio_buf, audio_len) < 0) { - return -1; + if (!IMA_ADPCM_Decode(file, audio_buf, audio_len)) { + return false; } break; } @@ -2031,14 +2032,14 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint */ spec->freq = format->frequency; spec->channels = (Uint8)format->channels; - spec->format = 0; + spec->format = SDL_AUDIO_UNKNOWN; switch (format->encoding) { case MS_ADPCM_CODE: case IMA_ADPCM_CODE: case ALAW_CODE: case MULAW_CODE: - /* These can be easily stored in the byte order of the system. */ + // These can be easily stored in the byte order of the system. spec->format = SDL_AUDIO_S16; break; case IEEE_FLOAT_CODE: @@ -2052,12 +2053,12 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint case 16: spec->format = SDL_AUDIO_S16LE; break; - case 24: /* Has been shifted to 32 bits. */ + case 24: // Has been shifted to 32 bits. case 32: spec->format = SDL_AUDIO_S32LE; break; default: - /* Just in case something unexpected happened in the checks. */ + // Just in case something unexpected happened in the checks. return SDL_SetError("Unexpected %u-bit PCM data format", (unsigned int)format->bitspersample); } break; @@ -2065,24 +2066,34 @@ static int WaveLoad(SDL_IOStream *src, WaveFile *file, SDL_AudioSpec *spec, Uint return SDL_SetError("Unexpected data format"); } - /* Report the end position back to the cleanup code. */ + // Report the end position back to the cleanup code. if (RIFFlengthknown) { chunk->position = RIFFend; } else { chunk->position = lastchunkpos; } - return 0; + return true; } -int SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +bool SDL_LoadWAV_IO(SDL_IOStream *src, bool closeio, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { - int result = -1; + bool result = false; WaveFile file; - /* Make sure we are passed a valid data source */ + if (spec) { + SDL_zerop(spec); + } + if (audio_buf) { + *audio_buf = NULL; + } + if (audio_len) { + *audio_len = 0; + } + + // Make sure we are passed a valid data source if (!src) { - goto done; /* Error may come from SDL_IOStream. */ + goto done; // Error may come from SDL_IOStream. } else if (!spec) { SDL_InvalidParamError("spec"); goto done; @@ -2094,22 +2105,19 @@ int SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uin goto done; } - *audio_buf = NULL; - *audio_len = 0; - SDL_zero(file); file.riffhint = WaveGetRiffSizeHint(); file.trunchint = WaveGetTruncationHint(); file.facthint = WaveGetFactChunkHint(); result = WaveLoad(src, &file, spec, audio_buf, audio_len); - if (result < 0) { + if (!result) { SDL_free(*audio_buf); audio_buf = NULL; audio_len = 0; } - /* Cleanup */ + // Cleanup if (!closeio) { SDL_SeekIO(src, file.chunk.position, SDL_IO_SEEK_SET); } @@ -2122,7 +2130,7 @@ int SDL_LoadWAV_IO(SDL_IOStream *src, SDL_bool closeio, SDL_AudioSpec *spec, Uin return result; } -int SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) +bool SDL_LoadWAV(const char *path, SDL_AudioSpec *spec, Uint8 **audio_buf, Uint32 *audio_len) { return SDL_LoadWAV_IO(SDL_IOFromFile(path, "rb"), 1, spec, audio_buf, audio_len); } diff --git a/libs/SDL3/src/audio/SDL_wave.h b/libs/SDL3/src/audio/SDL_wave.h index 66128f752..47fe2b514 100644 --- a/libs/SDL3/src/audio/SDL_wave.h +++ b/libs/SDL3/src/audio/SDL_wave.h @@ -20,21 +20,21 @@ */ #include "SDL_internal.h" -/* RIFF WAVE files are little-endian */ +// RIFF WAVE files are little-endian /*******************************************/ -/* Define values for Microsoft WAVE format */ +// Define values for Microsoft WAVE format /*******************************************/ -/* FOURCC */ -#define RIFF 0x46464952 /* "RIFF" */ -#define WAVE 0x45564157 /* "WAVE" */ -#define FACT 0x74636166 /* "fact" */ -#define LIST 0x5453494c /* "LIST" */ -#define BEXT 0x74786562 /* "bext" */ -#define JUNK 0x4B4E554A /* "JUNK" */ -#define FMT 0x20746D66 /* "fmt " */ -#define DATA 0x61746164 /* "data" */ -/* Format tags */ +// FOURCC +#define RIFF 0x46464952 // "RIFF" +#define WAVE 0x45564157 // "WAVE" +#define FACT 0x74636166 // "fact" +#define LIST 0x5453494c // "LIST" +#define BEXT 0x74786562 // "bext" +#define JUNK 0x4B4E554A // "JUNK" +#define FMT 0x20746D66 // "fmt " +#define DATA 0x61746164 // "data" +// Format tags #define UNKNOWN_CODE 0x0000 #define PCM_CODE 0x0001 #define MS_ADPCM_CODE 0x0002 @@ -46,30 +46,30 @@ #define MPEGLAYER3_CODE 0x0055 #define EXTENSIBLE_CODE 0xFFFE -/* Stores the WAVE format information. */ +// Stores the WAVE format information. typedef struct WaveFormat { - Uint16 formattag; /* Raw value of the first field in the fmt chunk data. */ - Uint16 encoding; /* Actual encoding, possibly from the extensible header. */ - Uint16 channels; /* Number of channels. */ - Uint32 frequency; /* Sampling rate in Hz. */ - Uint32 byterate; /* Average bytes per second. */ - Uint16 blockalign; /* Bytes per block. */ - Uint16 bitspersample; /* Currently supported are 8, 16, 24, 32, and 4 for ADPCM. */ + Uint16 formattag; // Raw value of the first field in the fmt chunk data. + Uint16 encoding; // Actual encoding, possibly from the extensible header. + Uint16 channels; // Number of channels. + Uint32 frequency; // Sampling rate in Hz. + Uint32 byterate; // Average bytes per second. + Uint16 blockalign; // Bytes per block. + Uint16 bitspersample; // Currently supported are 8, 16, 24, 32, and 4 for ADPCM. /* Extra information size. Number of extra bytes starting at byte 18 in the * fmt chunk data. This is at least 22 for the extensible header. */ Uint16 extsize; - /* Extensible WAVE header fields */ + // Extensible WAVE header fields Uint16 validsamplebits; - Uint32 samplesperblock; /* For compressed formats. Can be zero. Actually 16 bits in the header. */ + Uint32 samplesperblock; // For compressed formats. Can be zero. Actually 16 bits in the header. Uint32 channelmask; - Uint8 subformat[16]; /* A format GUID. */ + Uint8 subformat[16]; // A format GUID. } WaveFormat; -/* Stores information on the fact chunk. */ +// Stores information on the fact chunk. typedef struct WaveFact { /* Represents the state of the fact chunk in the WAVE file. @@ -88,20 +88,20 @@ typedef struct WaveFact * because a compressed block is usually decoded to a fixed number of * sample frames. */ - Uint32 samplelength; /* Raw sample length value from the fact chunk. */ + Uint32 samplelength; // Raw sample length value from the fact chunk. } WaveFact; -/* Generic struct for the chunks in the WAVE file. */ +// Generic struct for the chunks in the WAVE file. typedef struct WaveChunk { - Uint32 fourcc; /* FOURCC of the chunk. */ - Uint32 length; /* Size of the chunk data. */ - Sint64 position; /* Position of the data in the stream. */ - Uint8 *data; /* When allocated, this points to the chunk data. length is used for the memory allocation size. */ - size_t size; /* Number of bytes in data that could be read from the stream. Can be smaller than length. */ + Uint32 fourcc; // FOURCC of the chunk. + Uint32 length; // Size of the chunk data. + Sint64 position; // Position of the data in the stream. + Uint8 *data; // When allocated, this points to the chunk data. length is used for the memory allocation size. + size_t size; // Number of bytes in data that could be read from the stream. Can be smaller than length. } WaveChunk; -/* Controls how the size of the RIFF chunk affects the loading of a WAVE file. */ +// Controls how the size of the RIFF chunk affects the loading of a WAVE file. typedef enum WaveRiffSizeHint { RiffSizeNoHint, @@ -111,7 +111,7 @@ typedef enum WaveRiffSizeHint RiffSizeMaximum } WaveRiffSizeHint; -/* Controls how a truncated WAVE file is handled. */ +// Controls how a truncated WAVE file is handled. typedef enum WaveTruncationHint { TruncNoHint, @@ -121,7 +121,7 @@ typedef enum WaveTruncationHint TruncDropBlock } WaveTruncationHint; -/* Controls how the fact chunk affects the loading of a WAVE file. */ +// Controls how the fact chunk affects the loading of a WAVE file. typedef enum WaveFactChunkHint { FactNoHint, @@ -143,7 +143,7 @@ typedef struct WaveFile */ Sint64 sampleframes; - void *decoderdata; /* Some decoders require extra data for a state. */ + void *decoderdata; // Some decoders require extra data for a state. WaveRiffSizeHint riffhint; WaveTruncationHint trunchint; diff --git a/libs/SDL3/src/audio/aaudio/SDL_aaudio.c b/libs/SDL3/src/audio/aaudio/SDL_aaudio.c index 265eaacaf..c53157ee0 100644 --- a/libs/SDL3/src/audio/aaudio/SDL_aaudio.c +++ b/libs/SDL3/src/audio/aaudio/SDL_aaudio.c @@ -26,7 +26,6 @@ #include "SDL_aaudio.h" #include "../../core/android/SDL_android.h" -#include #include #if __ANDROID_API__ < 31 @@ -43,7 +42,6 @@ struct SDL_PrivateAudioData size_t processed_bytes; SDL_Semaphore *semaphore; SDL_AtomicInt error_callback_triggered; - SDL_bool resume; // Resume device if it was paused automatically }; // Debug @@ -57,13 +55,13 @@ struct SDL_PrivateAudioData typedef struct AAUDIO_Data { - void *handle; + SDL_SharedObject *handle; #define SDL_PROC(ret, func, params) ret (*func) params; #include "SDL_aaudiofuncs.h" } AAUDIO_Data; static AAUDIO_Data ctx; -static int AAUDIO_LoadFunctions(AAUDIO_Data *data) +static bool AAUDIO_LoadFunctions(AAUDIO_Data *data) { #define SDL_PROC(ret, func, params) \ do { \ @@ -73,7 +71,7 @@ static int AAUDIO_LoadFunctions(AAUDIO_Data *data) } \ } while (0); #include "SDL_aaudiofuncs.h" - return 0; + return true; } @@ -84,8 +82,8 @@ static void AAUDIO_errorCallback(AAudioStream *stream, void *userData, aaudio_re // You MUST NOT close the audio stream from this callback, so we cannot call SDL_AudioDeviceDisconnected here. // Just flag the device so we can kill it in PlayDevice instead. SDL_AudioDevice *device = (SDL_AudioDevice *) userData; - SDL_AtomicSet(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error. - SDL_PostSemaphore(device->hidden->semaphore); // in case we're blocking in WaitDevice. + SDL_SetAtomicInt(&device->hidden->error_callback_triggered, (int) error); // AAUDIO_OK is zero, so !triggered means no error. + SDL_SignalSemaphore(device->hidden->semaphore); // in case we're blocking in WaitDevice. } static aaudio_data_callback_result_t AAUDIO_dataCallback(AAudioStream *stream, void *userData, void *audioData, int32_t numFrames) @@ -96,7 +94,7 @@ static aaudio_data_callback_result_t AAUDIO_dataCallback(AAudioStream *stream, v size_t callback_bytes = numFrames * framesize; size_t old_buffer_index = hidden->callback_bytes / device->buffer_size; - if (device->iscapture) { + if (device->recording) { const Uint8 *input = (const Uint8 *)audioData; size_t available_bytes = hidden->mixbuf_bytes - (hidden->callback_bytes - hidden->processed_bytes); size_t size = SDL_min(available_bytes, callback_bytes); @@ -149,7 +147,7 @@ static aaudio_data_callback_result_t AAUDIO_dataCallback(AAudioStream *stream, v size_t new_buffer_index = hidden->callback_bytes / device->buffer_size; while (old_buffer_index < new_buffer_index) { // Trigger audio processing - SDL_PostSemaphore(hidden->semaphore); + SDL_SignalSemaphore(hidden->semaphore); ++old_buffer_index; } @@ -163,15 +161,21 @@ static Uint8 *AAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) return &hidden->mixbuf[offset]; } -static int AAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool AAUDIO_WaitDevice(SDL_AudioDevice *device) { - SDL_WaitSemaphore(device->hidden->semaphore); - return 0; + while (!SDL_GetAtomicInt(&device->shutdown)) { + // this semaphore won't fire when the app is in the background (AAUDIO_PauseDevices was called). + if (SDL_WaitSemaphoreTimeout(device->hidden->semaphore, 100)) { + return true; // semaphore was signaled, let's go! + } + // Still waiting on the semaphore (or the system), check other things then wait again. + } + return true; } -static int BuildAAudioStream(SDL_AudioDevice *device); +static bool BuildAAudioStream(SDL_AudioDevice *device); -static int RecoverAAudioDevice(SDL_AudioDevice *device) +static bool RecoverAAudioDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *hidden = device->hidden; @@ -190,8 +194,8 @@ static int RecoverAAudioDevice(SDL_AudioDevice *device) SDL_AudioSpec prevspec; SDL_copyp(&prevspec, &device->spec); - if (BuildAAudioStream(device) < 0) { - return -1; // oh well, we tried. + if (!BuildAAudioStream(device)) { + return false; // oh well, we tried. } // we don't know the new device spec until we open the new device, so we saved off the old one and force it back @@ -202,39 +206,39 @@ static int RecoverAAudioDevice(SDL_AudioDevice *device) device->sample_frames = prev_sample_frames; SDL_copyp(&device->spec, &prevspec); - if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) { - return -1; // ugh + if (!SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames)) { + return false; // ugh } - return 0; + return true; } -static int AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool AAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { struct SDL_PrivateAudioData *hidden = device->hidden; // AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here. - const aaudio_result_t err = (aaudio_result_t) SDL_AtomicGet(&hidden->error_callback_triggered); + const aaudio_result_t err = (aaudio_result_t) SDL_GetAtomicInt(&hidden->error_callback_triggered); if (err) { SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "aaudio: Audio device triggered error %d (%s)", (int) err, ctx.AAudio_convertResultToText(err)); - if (RecoverAAudioDevice(device) < 0) { - return -1; // oh well, we went down hard. + if (!RecoverAAudioDevice(device)) { + return false; // oh well, we went down hard. } } else { SDL_MemoryBarrierRelease(); hidden->processed_bytes += buflen; } - return 0; + return true; } -static int AAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int AAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *hidden = device->hidden; // AAUDIO_dataCallback picks up our work and unblocks AAUDIO_WaitDevice. But make sure we didn't fail here. - if (SDL_AtomicGet(&hidden->error_callback_triggered)) { - SDL_AtomicSet(&hidden->error_callback_triggered, 0); + if (SDL_GetAtomicInt(&hidden->error_callback_triggered)) { + SDL_SetAtomicInt(&hidden->error_callback_triggered, 0); return -1; } @@ -269,13 +273,13 @@ static void AAUDIO_CloseDevice(SDL_AudioDevice *device) } } -static int BuildAAudioStream(SDL_AudioDevice *device) +static bool BuildAAudioStream(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *hidden = device->hidden; - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; aaudio_result_t res; - SDL_AtomicSet(&hidden->error_callback_triggered, 0); + SDL_SetAtomicInt(&hidden->error_callback_triggered, 0); AAudioStreamBuilder *builder = NULL; res = ctx.AAudio_createStreamBuilder(&builder); @@ -304,19 +308,19 @@ static int BuildAAudioStream(SDL_AudioDevice *device) } ctx.AAudioStreamBuilder_setFormat(builder, format); ctx.AAudioStreamBuilder_setSampleRate(builder, device->spec.freq); - ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels); #endif + ctx.AAudioStreamBuilder_setChannelCount(builder, device->spec.channels); - const aaudio_direction_t direction = (iscapture ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT); + const aaudio_direction_t direction = (recording ? AAUDIO_DIRECTION_INPUT : AAUDIO_DIRECTION_OUTPUT); ctx.AAudioStreamBuilder_setDirection(builder, direction); ctx.AAudioStreamBuilder_setErrorCallback(builder, AAUDIO_errorCallback, device); ctx.AAudioStreamBuilder_setDataCallback(builder, AAUDIO_dataCallback, device); // Some devices have flat sounding audio when low latency mode is enabled, but this is a better experience for most people - if (SDL_GetHintBoolean("SDL_ANDROID_LOW_LATENCY_AUDIO", SDL_TRUE)) { + if (SDL_GetHintBoolean("SDL_ANDROID_LOW_LATENCY_AUDIO", true)) { ctx.AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY); } - LOGI("AAudio Try to open %u hz %u bit chan %u %s samples %u", + LOGI("AAudio Try to open %u hz %u bit %u channels %s samples %u", device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames); @@ -353,41 +357,41 @@ static int BuildAAudioStream(SDL_AudioDevice *device) // Allocate a double buffered mixing buffer hidden->num_buffers = 2; hidden->mixbuf_bytes = (hidden->num_buffers * device->buffer_size); - hidden->mixbuf = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), hidden->mixbuf_bytes); + hidden->mixbuf = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), hidden->mixbuf_bytes); if (!hidden->mixbuf) { - return -1; + return false; } hidden->processed_bytes = 0; hidden->callback_bytes = 0; - hidden->semaphore = SDL_CreateSemaphore(iscapture ? 0 : hidden->num_buffers); + hidden->semaphore = SDL_CreateSemaphore(recording ? 0 : hidden->num_buffers); if (!hidden->semaphore) { - LOGI("SDL Failed SDL_CreateSemaphore %s iscapture:%d", SDL_GetError(), iscapture); - return -1; + LOGI("SDL Failed SDL_CreateSemaphore %s recording:%d", SDL_GetError(), recording); + return false; } - LOGI("AAudio Actually opened %u hz %u bit chan %u %s samples %u, buffers %d", + LOGI("AAudio Actually opened %u hz %u bit %u channels %s samples %u, buffers %d", device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), device->spec.channels, SDL_AUDIO_ISBIGENDIAN(device->spec.format) ? "BE" : "LE", device->sample_frames, hidden->num_buffers); res = ctx.AAudioStream_requestStart(hidden->stream); if (res != AAUDIO_OK) { - LOGI("SDL Failed AAudioStream_requestStart %d iscapture:%d", res, iscapture); + LOGI("SDL Failed AAudioStream_requestStart %d recording:%d", res, recording); return SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res)); } LOGI("SDL AAudioStream_requestStart OK"); - return 0; + return true; } // !!! FIXME: make this non-blocking! -static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted) +static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted) { - SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1); + SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1); } -static int AAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool AAUDIO_OpenDevice(SDL_AudioDevice *device) { #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES SDL_assert(device->handle); // AAUDIO_UNSPECIFIED is zero, so legit devices should all be non-zero. @@ -395,19 +399,19 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) LOGI(__func__); - if (device->iscapture) { + if (device->recording) { // !!! FIXME: make this non-blocking! SDL_AtomicInt permission_response; - SDL_AtomicSet(&permission_response, 0); - if (SDL_AndroidRequestPermission("android.permission.RECORD_AUDIO", AndroidRequestPermissionBlockingCallback, &permission_response) == -1) { - return -1; + SDL_SetAtomicInt(&permission_response, 0); + if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) { + return false; } - while (SDL_AtomicGet(&permission_response) == 0) { + while (SDL_GetAtomicInt(&permission_response) == 0) { SDL_Delay(10); } - if (SDL_AtomicGet(&permission_response) < 0) { + if (SDL_GetAtomicInt(&permission_response) < 0) { LOGI("This app doesn't have RECORD_AUDIO permission"); return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); } @@ -415,21 +419,21 @@ static int AAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } return BuildAAudioStream(device); } -static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata) +static bool PauseOneDevice(SDL_AudioDevice *device, void *userdata) { struct SDL_PrivateAudioData *hidden = (struct SDL_PrivateAudioData *)device->hidden; if (hidden) { if (hidden->stream) { aaudio_result_t res; - if (device->iscapture) { - // Pause() isn't implemented for 'capture', use Stop() + if (device->recording) { + // Pause() isn't implemented for recording, use Stop() res = ctx.AAudioStream_requestStop(hidden->stream); } else { res = ctx.AAudioStream_requestPause(hidden->stream); @@ -439,12 +443,9 @@ static SDL_bool PauseOneDevice(SDL_AudioDevice *device, void *userdata) LOGI("SDL Failed AAudioStream_requestPause %d", res); SDL_SetError("%s : %s", __func__, ctx.AAudio_convertResultToText(res)); } - - SDL_LockMutex(device->lock); - hidden->resume = SDL_TRUE; } } - return SDL_FALSE; // keep enumerating. + return false; // keep enumerating. } // Pause (block) all non already paused audio devices by taking their mixer lock @@ -456,15 +457,10 @@ void AAUDIO_PauseDevices(void) } // Resume (unblock) all non already paused audio devices by releasing their mixer lock -static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata) +static bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata) { struct SDL_PrivateAudioData *hidden = device->hidden; if (hidden) { - if (hidden->resume) { - hidden->resume = SDL_FALSE; - SDL_UnlockMutex(device->lock); - } - if (hidden->stream) { aaudio_result_t res = ctx.AAudioStream_requestStart(hidden->stream); if (res != AAUDIO_OK) { @@ -473,7 +469,7 @@ static SDL_bool ResumeOneDevice(SDL_AudioDevice *device, void *userdata) } } } - return SDL_FALSE; // keep enumerating. + return false; // keep enumerating. } void AAUDIO_ResumeDevices(void) @@ -496,7 +492,7 @@ static void AAUDIO_Deinitialize(void) } -static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool AAUDIO_Init(SDL_AudioDriverImpl *impl) { LOGI(__func__); @@ -506,7 +502,7 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl) * See https://github.com/google/oboe/issues/40 for more information. */ if (SDL_GetAndroidSDKVersion() < 27) { - return SDL_FALSE; + return false; } SDL_zero(ctx); @@ -514,13 +510,13 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl) ctx.handle = SDL_LoadObject(LIB_AAUDIO_SO); if (!ctx.handle) { LOGI("SDL couldn't find " LIB_AAUDIO_SO); - return SDL_FALSE; + return false; } - if (AAUDIO_LoadFunctions(&ctx) < 0) { + if (!AAUDIO_LoadFunctions(&ctx)) { SDL_UnloadObject(ctx.handle); SDL_zero(ctx); - return SDL_FALSE; + return false; } impl->ThreadInit = Android_AudioThreadInit; @@ -530,24 +526,24 @@ static SDL_bool AAUDIO_Init(SDL_AudioDriverImpl *impl) impl->WaitDevice = AAUDIO_WaitDevice; impl->PlayDevice = AAUDIO_PlayDevice; impl->GetDeviceBuf = AAUDIO_GetDeviceBuf; - impl->WaitCaptureDevice = AAUDIO_WaitDevice; - impl->CaptureFromDevice = AAUDIO_CaptureFromDevice; + impl->WaitRecordingDevice = AAUDIO_WaitDevice; + impl->RecordDevice = AAUDIO_RecordDevice; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES impl->DetectDevices = Android_StartAudioHotplug; #else - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; #endif LOGI("SDL AAUDIO_Init OK"); - return SDL_TRUE; + return true; } AudioBootStrap AAUDIO_bootstrap = { - "AAudio", "AAudio audio driver", AAUDIO_Init, SDL_FALSE + "AAudio", "AAudio audio driver", AAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_AAUDIO diff --git a/libs/SDL3/src/audio/aaudio/SDL_aaudio.h b/libs/SDL3/src/audio/aaudio/SDL_aaudio.h index 3354304a1..1047c9873 100644 --- a/libs/SDL3/src/audio/aaudio/SDL_aaudio.h +++ b/libs/SDL3/src/audio/aaudio/SDL_aaudio.h @@ -25,8 +25,8 @@ #ifdef SDL_AUDIO_DRIVER_AAUDIO -void AAUDIO_ResumeDevices(void); -void AAUDIO_PauseDevices(void); +extern void AAUDIO_ResumeDevices(void); +extern void AAUDIO_PauseDevices(void); #else diff --git a/libs/SDL3/src/audio/alsa/SDL_alsa_audio.c b/libs/SDL3/src/audio/alsa/SDL_alsa_audio.c index c0f696b9c..827b54de4 100644 --- a/libs/SDL3/src/audio/alsa/SDL_alsa_audio.c +++ b/libs/SDL3/src/audio/alsa/SDL_alsa_audio.c @@ -91,28 +91,28 @@ static int (*ALSA_snd_pcm_chmap_print)(const snd_pcm_chmap_t *map, size_t maxlen #define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof static const char *alsa_library = SDL_AUDIO_DRIVER_ALSA_DYNAMIC; -static void *alsa_handle = NULL; +static SDL_SharedObject *alsa_handle = NULL; -static int load_alsa_sym(const char *fn, void **addr) +static bool load_alsa_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(alsa_handle, fn); if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. - return 0; + return false; } - return 1; + return true; } // cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_ALSA_SYM(x) \ if (!load_alsa_sym(#x, (void **)(char *)&ALSA_##x)) \ - return -1 + return false #else #define SDL_ALSA_SYM(x) ALSA_##x = x #endif -static int load_alsa_syms(void) +static bool load_alsa_syms(void) { SDL_ALSA_SYM(snd_pcm_open); SDL_ALSA_SYM(snd_pcm_close); @@ -156,7 +156,7 @@ static int load_alsa_syms(void) SDL_ALSA_SYM(snd_pcm_chmap_print); #endif - return 0; + return true; } #undef SDL_ALSA_SYM @@ -171,17 +171,17 @@ static void UnloadALSALibrary(void) } } -static int LoadALSALibrary(void) +static bool LoadALSALibrary(void) { - int retval = 0; + bool retval = true; if (!alsa_handle) { alsa_handle = SDL_LoadObject(alsa_library); if (!alsa_handle) { - retval = -1; + retval = false; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { retval = load_alsa_syms(); - if (retval < 0) { + if (!retval) { UnloadALSALibrary(); } } @@ -195,10 +195,10 @@ static void UnloadALSALibrary(void) { } -static int LoadALSALibrary(void) +static bool LoadALSALibrary(void) { load_alsa_syms(); - return 0; + return true; } #endif // SDL_AUDIO_DRIVER_ALSA_DYNAMIC @@ -206,19 +206,19 @@ static int LoadALSALibrary(void) typedef struct ALSA_Device { char *name; - SDL_bool iscapture; + bool recording; struct ALSA_Device *next; } ALSA_Device; -static const ALSA_Device default_output_handle = { +static const ALSA_Device default_playback_handle = { "default", - SDL_FALSE, + false, NULL }; -static const ALSA_Device default_capture_handle = { +static const ALSA_Device default_recording_handle = { "default", - SDL_TRUE, + true, NULL }; @@ -228,7 +228,7 @@ static const char *get_audio_device(void *handle, const int channels) ALSA_Device *dev = (ALSA_Device *)handle; if (SDL_strcmp(dev->name, "default") == 0) { - const char *device = SDL_getenv("AUDIODEV"); // Is there a standard variable name? + const char *device = SDL_GetHint(SDL_HINT_AUDIO_ALSA_DEFAULT_DEVICE); if (device) { return device; } else if (channels == 6) { @@ -242,123 +242,37 @@ static const char *get_audio_device(void *handle, const int channels) return dev->name; } -// !!! FIXME: is there a channel swizzler in alsalib instead? +// Swizzle channels to match SDL defaults. +// These are swizzles _from_ SDL's layouts to what ALSA wants. +// 5.1 swizzle: // https://bugzilla.libsdl.org/show_bug.cgi?id=110 // "For Linux ALSA, this is FL-FR-RL-RR-C-LFE // and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR" -#define SWIZ6(T) \ - static void swizzle_alsa_channels_6_##T(void *buffer, const Uint32 bufferlen) \ - { \ - T *ptr = (T *)buffer; \ - Uint32 i; \ - for (i = 0; i < bufferlen; i++, ptr += 6) { \ - T tmp; \ - tmp = ptr[2]; \ - ptr[2] = ptr[4]; \ - ptr[4] = tmp; \ - tmp = ptr[3]; \ - ptr[3] = ptr[5]; \ - ptr[5] = tmp; \ - } \ - } - - -// !!! FIXME: is there a channel swizzler in alsalib instead? -// !!! FIXME: this screams for a SIMD shuffle operation. +static const int swizzle_alsa_channels_6[6] = { 0, 1, 4, 5, 2, 3 }; +// 7.1 swizzle: // https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/mapping-stream-formats-to-speaker-configurations // For Linux ALSA, this appears to be FL-FR-RL-RR-C-LFE-SL-SR // and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-SL-SR-RL-RR" -#define SWIZ8(T) \ - static void swizzle_alsa_channels_8_##T(void *buffer, const Uint32 bufferlen) \ - { \ - T *ptr = (T *)buffer; \ - Uint32 i; \ - for (i = 0; i < bufferlen; i++, ptr += 6) { \ - const T center = ptr[2]; \ - const T subwoofer = ptr[3]; \ - const T side_left = ptr[4]; \ - const T side_right = ptr[5]; \ - const T rear_left = ptr[6]; \ - const T rear_right = ptr[7]; \ - ptr[2] = rear_left; \ - ptr[3] = rear_right; \ - ptr[4] = center; \ - ptr[5] = subwoofer; \ - ptr[6] = side_left; \ - ptr[7] = side_right; \ - } \ - } - -#define CHANNEL_SWIZZLE(x) \ - x(Uint64) \ - x(Uint32) \ - x(Uint16) \ - x(Uint8) - -CHANNEL_SWIZZLE(SWIZ6) -CHANNEL_SWIZZLE(SWIZ8) - -#undef CHANNEL_SWIZZLE -#undef SWIZ6 -#undef SWIZ8 - -// Called right before feeding device->hidden->mixbuf to the hardware. Swizzle -// channels from Windows/Mac order to the format alsalib will want. -static void swizzle_alsa_channels(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen) -{ - switch (device->spec.channels) { -#define CHANSWIZ(chans) \ - case chans: \ - switch ((device->spec.format & (0xFF))) { \ - case 8: \ - swizzle_alsa_channels_##chans##_Uint8(buffer, bufferlen); \ - break; \ - case 16: \ - swizzle_alsa_channels_##chans##_Uint16(buffer, bufferlen); \ - break; \ - case 32: \ - swizzle_alsa_channels_##chans##_Uint32(buffer, bufferlen); \ - break; \ - case 64: \ - swizzle_alsa_channels_##chans##_Uint64(buffer, bufferlen); \ - break; \ - default: \ - SDL_assert(!"unhandled bitsize"); \ - break; \ - } \ - return; +static const int swizzle_alsa_channels_8[8] = { 0, 1, 6, 7, 2, 3, 4, 5 }; - CHANSWIZ(6); - CHANSWIZ(8); -#undef CHANSWIZ - default: - break; - } -} -#ifdef SND_CHMAP_API_VERSION -// Some devices have the right channel map, no swizzling necessary -static void no_swizzle(SDL_AudioDevice *device, void *buffer, Uint32 bufferlen) -{ -} -#endif // SND_CHMAP_API_VERSION // This function waits until it is possible to write a full sound buffer -static int ALSA_WaitDevice(SDL_AudioDevice *device) +static bool ALSA_WaitDevice(SDL_AudioDevice *device) { const int fulldelay = (int) ((((Uint64) device->sample_frames) * 1000) / device->spec.freq); const int delay = SDL_max(fulldelay, 10); - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { const int rc = ALSA_snd_pcm_wait(device->hidden->pcm_handle, delay); if (rc < 0 && (rc != -EAGAIN)) { const int status = ALSA_snd_pcm_recover(device->hidden->pcm_handle, rc, 0); if (status < 0) { // Hmm, not much we can do - abort SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA: snd_pcm_wait failed (unrecoverable): %s", ALSA_snd_strerror(rc)); - return -1; + return false; } continue; } @@ -370,19 +284,17 @@ static int ALSA_WaitDevice(SDL_AudioDevice *device) // Timed out! Make sure we aren't shutting down and then wait again. } - return 0; + return true; } -static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { SDL_assert(buffer == device->hidden->mixbuf); Uint8 *sample_buf = (Uint8 *) buffer; // !!! FIXME: deal with this without casting away constness const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec); snd_pcm_uframes_t frames_left = (snd_pcm_uframes_t) (buflen / frame_size); - device->hidden->swizzle_func(device, sample_buf, frames_left); - - while ((frames_left > 0) && !SDL_AtomicGet(&device->shutdown)) { + while ((frames_left > 0) && !SDL_GetAtomicInt(&device->shutdown)) { const int rc = ALSA_snd_pcm_writei(device->hidden->pcm_handle, sample_buf, frames_left); //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA PLAYDEVICE: WROTE %d of %d bytes", (rc >= 0) ? ((int) (rc * frame_size)) : rc, (int) (frames_left * frame_size)); SDL_assert(rc != 0); // assuming this can't happen if we used snd_pcm_wait and queried for available space. @@ -392,7 +304,7 @@ static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buf if (status < 0) { // Hmm, not much we can do - abort SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "ALSA write failed (unrecoverable): %s", ALSA_snd_strerror(rc)); - return -1; + return false; } continue; } @@ -401,7 +313,7 @@ static int ALSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buf frames_left -= rc; } - return 0; + return true; } static Uint8 *ALSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -427,7 +339,7 @@ static Uint8 *ALSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->mixbuf; } -static int ALSA_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int ALSA_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { const int frame_size = SDL_AUDIO_FRAMESIZE(device->spec); SDL_assert((buflen % frame_size) == 0); @@ -447,16 +359,14 @@ static int ALSA_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buf return -1; } return 0; // go back to WaitDevice and try again. - } else if (rc > 0) { - device->hidden->swizzle_func(device, buffer, total_frames - rc); } - //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: captured %d bytes", rc * frame_size); + //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: recorded %d bytes", rc * frame_size); return rc * frame_size; } -static void ALSA_FlushCapture(SDL_AudioDevice *device) +static void ALSA_FlushRecording(SDL_AudioDevice *device) { ALSA_snd_pcm_reset(device->hidden->pcm_handle); } @@ -516,28 +426,23 @@ static int ALSA_set_buffer_size(SDL_AudioDevice *device, snd_pcm_hw_params_t *pa device->sample_frames = persize; // This is useful for debugging - if (SDL_getenv("SDL_AUDIO_ALSA_DEBUG")) { - snd_pcm_uframes_t bufsize; - - ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize); - - SDL_LogError(SDL_LOG_CATEGORY_AUDIO, - "ALSA: period size = %ld, periods = %u, buffer size = %lu", - persize, periods, bufsize); - } - + snd_pcm_uframes_t bufsize; + ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize); + SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, + "ALSA: period size = %ld, periods = %u, buffer size = %lu", + persize, periods, bufsize); return 0; } -static int ALSA_OpenDevice(SDL_AudioDevice *device) +static bool ALSA_OpenDevice(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; int status = 0; // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Open the audio device @@ -545,7 +450,7 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) snd_pcm_t *pcm_handle = NULL; status = ALSA_snd_pcm_open(&pcm_handle, get_audio_device(device->handle, device->spec.channels), - iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, + recording ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (status < 0) { @@ -611,23 +516,6 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) } device->spec.format = test_format; - // Validate number of channels and determine if swizzling is necessary. - // Assume original swizzling, until proven otherwise. - device->hidden->swizzle_func = swizzle_alsa_channels; -#ifdef SND_CHMAP_API_VERSION - snd_pcm_chmap_t *chmap = ALSA_snd_pcm_get_chmap(pcm_handle); - if (chmap) { - char chmap_str[64]; - if (ALSA_snd_pcm_chmap_print(chmap, sizeof(chmap_str), chmap_str) > 0) { - if (SDL_strcmp("FL FR FC LFE RL RR", chmap_str) == 0 || - SDL_strcmp("FL FR FC LFE SL SR", chmap_str) == 0) { - device->hidden->swizzle_func = no_swizzle; - } - } - free(chmap); // This should NOT be SDL_free() - } -#endif // SND_CHMAP_API_VERSION - // Set the number of channels status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams, device->spec.channels); @@ -640,6 +528,41 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) device->spec.channels = channels; } + const int *swizmap = NULL; + if (channels == 6) { + swizmap = swizzle_alsa_channels_6; + } else if (channels == 8) { + swizmap = swizzle_alsa_channels_8; + } + +#ifdef SND_CHMAP_API_VERSION + if (swizmap) { + snd_pcm_chmap_t *chmap = ALSA_snd_pcm_get_chmap(pcm_handle); + if (chmap) { + char chmap_str[64]; + if (ALSA_snd_pcm_chmap_print(chmap, sizeof(chmap_str), chmap_str) > 0) { + if ( (channels == 6) && + ((SDL_strcmp("FL FR FC LFE RL RR", chmap_str) == 0) || + (SDL_strcmp("FL FR FC LFE SL SR", chmap_str) == 0)) ) { + swizmap = NULL; + } else if ((channels == 8) && (SDL_strcmp("FL FR FC LFE SL SR RL RR", chmap_str) == 0)) { + swizmap = NULL; + } + } + free(chmap); // This should NOT be SDL_free() + } + } +#endif // SND_CHMAP_API_VERSION + + // Validate number of channels and determine if swizzling is necessary. + // Assume original swizzling, until proven otherwise. + if (swizmap) { + device->chmap = SDL_ChannelMapDup(swizmap, channels); + if (!device->chmap) { + return false; + } + } + // Set the audio rate unsigned int rate = device->spec.freq; status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, @@ -680,26 +603,26 @@ static int ALSA_OpenDevice(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); // Allocate mixing buffer - if (!iscapture) { + if (!recording) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } #if !SDL_ALSA_NON_BLOCKING - if (!iscapture) { + if (!recording) { ALSA_snd_pcm_nonblock(pcm_handle, 0); } #endif ALSA_snd_pcm_start(pcm_handle); - return 0; // We're ready to rock and roll. :-) + return true; // We're ready to rock and roll. :-) } -static void add_device(const SDL_bool iscapture, const char *name, void *hint, ALSA_Device **pSeen) +static void add_device(const bool recording, const char *name, void *hint, ALSA_Device **pSeen) { ALSA_Device *dev = SDL_malloc(sizeof(ALSA_Device)); char *desc; @@ -733,7 +656,7 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A *ptr = '\0'; } - //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", iscapture ? "capture" : "output", name, desc); + //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: adding %s device '%s' (%s)", recording ? "recording" : "playback", name, desc); dev->name = SDL_strdup(name); if (!dev->name) { @@ -748,19 +671,19 @@ static void add_device(const SDL_bool iscapture, const char *name, void *hint, A // Note that spec is NULL, because we are required to open the device before // acquiring the mix format, making this information inaccessible at // enumeration time - SDL_AddAudioDevice(iscapture, desc, NULL, dev); + SDL_AddAudioDevice(recording, desc, NULL, dev); if (hint) { free(desc); // This should NOT be SDL_free() } - dev->iscapture = iscapture; + dev->recording = recording; dev->next = *pSeen; *pSeen = dev; } static ALSA_Device *hotplug_devices = NULL; -static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_default_capture) +static void ALSA_HotplugIteration(bool *has_default_playback, bool *has_default_recording) { void **hints = NULL; ALSA_Device *unseen = NULL; @@ -818,13 +741,13 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de } // only want physical hardware interfaces - const SDL_bool is_default = (has_default == i); + const bool is_default = (has_default == i); if (is_default || (match && SDL_strncmp(name, match, match_len) == 0)) { char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID"); - const SDL_bool isoutput = (!ioid) || (SDL_strcmp(ioid, "Output") == 0); - const SDL_bool isinput = (!ioid) || (SDL_strcmp(ioid, "Input") == 0); - SDL_bool have_output = SDL_FALSE; - SDL_bool have_input = SDL_FALSE; + const bool isoutput = (!ioid) || (SDL_strcmp(ioid, "Output") == 0); + const bool isinput = (!ioid) || (SDL_strcmp(ioid, "Input") == 0); + bool have_output = false; + bool have_input = false; free(ioid); // This should NOT be SDL_free() @@ -834,10 +757,10 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de } if (is_default) { - if (has_default_output && isoutput) { - *has_default_output = SDL_TRUE; - } else if (has_default_capture && isinput) { - *has_default_capture = SDL_TRUE; + if (has_default_playback && isoutput) { + *has_default_playback = true; + } else if (has_default_recording && isinput) { + *has_default_recording = true; } free(name); // This should NOT be SDL_free() continue; @@ -847,7 +770,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de ALSA_Device *next; for (ALSA_Device *dev = unseen; dev; dev = next) { next = dev->next; - if ((SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->iscapture) || ((isoutput) && !dev->iscapture))) { + if ((SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->recording) || ((isoutput) && !dev->recording))) { if (prev) { prev->next = next; } else { @@ -856,10 +779,10 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de dev->next = seen; seen = dev; if (isinput) { - have_input = SDL_TRUE; + have_input = true; } if (isoutput) { - have_output = SDL_TRUE; + have_output = true; } } else { prev = dev; @@ -867,10 +790,10 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de } if (isinput && !have_input) { - add_device(SDL_TRUE, name, hints[i], &seen); + add_device(true, name, hints[i], &seen); } if (isoutput && !have_output) { - add_device(SDL_FALSE, name, hints[i], &seen); + add_device(false, name, hints[i], &seen); } } @@ -885,7 +808,7 @@ static void ALSA_HotplugIteration(SDL_bool *has_default_output, SDL_bool *has_de // report anything still in unseen as removed. ALSA_Device *next = NULL; for (ALSA_Device *dev = unseen; dev; dev = next) { - //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); + //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: removing %s device '%s'", dev->recording ? "recording" : "playback", dev->name); next = dev->next; SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle(dev)); SDL_free(dev->name); @@ -900,12 +823,12 @@ static SDL_Thread *ALSA_hotplug_thread; static int SDLCALL ALSA_HotplugThread(void *arg) { - SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); + SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_LOW); - while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) { + while (!SDL_GetAtomicInt(&ALSA_hotplug_shutdown)) { // Block awhile before checking again, unless we're told to stop. const Uint64 ticks = SDL_GetTicks() + 5000; - while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) { + while (!SDL_GetAtomicInt(&ALSA_hotplug_shutdown) && SDL_GetTicks() < ticks) { SDL_Delay(100); } @@ -916,21 +839,21 @@ static int SDLCALL ALSA_HotplugThread(void *arg) } #endif -static void ALSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void ALSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { // ALSA doesn't have a concept of a changeable default device, afaik, so we expose a generic default // device here. It's the best we can do at this level. - SDL_bool has_default_output = SDL_FALSE, has_default_capture = SDL_FALSE; - ALSA_HotplugIteration(&has_default_output, &has_default_capture); // run once now before a thread continues to check. - if (has_default_output) { - *default_output = SDL_AddAudioDevice(/*iscapture=*/SDL_FALSE, "ALSA default output device", NULL, (void*)&default_output_handle); + bool has_default_playback = false, has_default_recording = false; + ALSA_HotplugIteration(&has_default_playback, &has_default_recording); // run once now before a thread continues to check. + if (has_default_playback) { + *default_playback = SDL_AddAudioDevice(/*recording=*/false, "ALSA default playback device", NULL, (void*)&default_playback_handle); } - if (has_default_capture) { - *default_capture = SDL_AddAudioDevice(/*iscapture=*/SDL_TRUE, "ALSA default capture device", NULL, (void*)&default_capture_handle); + if (has_default_recording) { + *default_recording = SDL_AddAudioDevice(/*recording=*/true, "ALSA default recording device", NULL, (void*)&default_recording_handle); } #if SDL_ALSA_HOTPLUG_THREAD - SDL_AtomicSet(&ALSA_hotplug_shutdown, 0); + SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 0); ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", NULL); // if the thread doesn't spin, oh well, you just don't get further hotplug events. #endif @@ -943,7 +866,7 @@ static void ALSA_DeinitializeStart(void) #if SDL_ALSA_HOTPLUG_THREAD if (ALSA_hotplug_thread) { - SDL_AtomicSet(&ALSA_hotplug_shutdown, 1); + SDL_SetAtomicInt(&ALSA_hotplug_shutdown, 1); SDL_WaitThread(ALSA_hotplug_thread, NULL); ALSA_hotplug_thread = NULL; } @@ -951,7 +874,7 @@ static void ALSA_DeinitializeStart(void) // Shutting down! Clean up any data we've gathered. for (dev = hotplug_devices; dev; dev = next) { - //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->iscapture ? "capture" : "output", dev->name); + //SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "ALSA: at shutdown, removing %s device '%s'", dev->recording ? "recording" : "playback", dev->name); next = dev->next; SDL_free(dev->name); SDL_free(dev); @@ -964,10 +887,10 @@ static void ALSA_Deinitialize(void) UnloadALSALibrary(); } -static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl) +static bool ALSA_Init(SDL_AudioDriverImpl *impl) { - if (LoadALSALibrary() < 0) { - return SDL_FALSE; + if (!LoadALSALibrary()) { + return false; } impl->DetectDevices = ALSA_DetectDevices; @@ -978,17 +901,17 @@ static SDL_bool ALSA_Init(SDL_AudioDriverImpl *impl) impl->CloseDevice = ALSA_CloseDevice; impl->DeinitializeStart = ALSA_DeinitializeStart; impl->Deinitialize = ALSA_Deinitialize; - impl->WaitCaptureDevice = ALSA_WaitDevice; - impl->CaptureFromDevice = ALSA_CaptureFromDevice; - impl->FlushCapture = ALSA_FlushCapture; + impl->WaitRecordingDevice = ALSA_WaitDevice; + impl->RecordDevice = ALSA_RecordDevice; + impl->FlushRecording = ALSA_FlushRecording; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap ALSA_bootstrap = { - "alsa", "ALSA PCM audio", ALSA_Init, SDL_FALSE + "alsa", "ALSA PCM audio", ALSA_Init, false }; #endif // SDL_AUDIO_DRIVER_ALSA diff --git a/libs/SDL3/src/audio/android/SDL_androidaudio.c b/libs/SDL3/src/audio/android/SDL_androidaudio.c deleted file mode 100644 index 0c8713ee7..000000000 --- a/libs/SDL3/src/audio/android/SDL_androidaudio.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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_AUDIO_DRIVER_ANDROID - -// Output audio to Android (legacy interface) - -#include "../SDL_sysaudio.h" -#include "SDL_androidaudio.h" - -#include "../../core/android/SDL_android.h" -#include - - -struct SDL_PrivateAudioData -{ - int resume; // Resume device if it was paused automatically -}; - -static SDL_AudioDevice *audioDevice = NULL; -static SDL_AudioDevice *captureDevice = NULL; - -static int ANDROIDAUDIO_OpenDevice(SDL_AudioDevice *device) -{ - device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); - if (!device->hidden) { - return -1; - } - - const SDL_bool iscapture = device->iscapture; - - if (iscapture) { - if (captureDevice) { - return SDL_SetError("An audio capture device is already opened"); - } - captureDevice = device; - } else { - if (audioDevice) { - return SDL_SetError("An audio playback device is already opened"); - } - audioDevice = device; - } - - SDL_AudioFormat test_format; - const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); - while ((test_format = *(closefmts++)) != 0) { - if ((test_format == SDL_AUDIO_U8) || - (test_format == SDL_AUDIO_S16) || - (test_format == SDL_AUDIO_F32)) { - device->spec.format = test_format; - break; - } - } - - if (!test_format) { - return SDL_SetError("android: Unsupported audio format"); - } - - if (Android_JNI_OpenAudioDevice(device) < 0) { - return -1; - } - - SDL_UpdatedAudioDeviceFormat(device); - - return 0; -} - -// !!! FIXME: this needs a WaitDevice implementation. - -static int ANDROIDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) -{ - Android_JNI_WriteAudioBuffer(); - return 0; -} - -static Uint8 *ANDROIDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) -{ - return Android_JNI_GetAudioBuffer(); -} - -static int ANDROIDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) -{ - return Android_JNI_CaptureAudioBuffer(buffer, buflen); -} - -static void ANDROIDAUDIO_FlushCapture(SDL_AudioDevice *device) -{ - Android_JNI_FlushCapturedAudio(); -} - -static void ANDROIDAUDIO_CloseDevice(SDL_AudioDevice *device) -{ - /* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread - so it's safe to terminate the Java side buffer and AudioTrack - */ - if (device->hidden) { - Android_JNI_CloseAudioDevice(device->iscapture); - if (device->iscapture) { - SDL_assert(captureDevice == device); - captureDevice = NULL; - } else { - SDL_assert(audioDevice == device); - audioDevice = NULL; - } - SDL_free(device->hidden); - device->hidden = NULL; - } -} - -// Pause (block) all non already paused audio devices by taking their mixer lock -void ANDROIDAUDIO_PauseDevices(void) -{ - // TODO: Handle multiple devices? - struct SDL_PrivateAudioData *hidden; - if (audioDevice && audioDevice->hidden) { - hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; - SDL_LockMutex(audioDevice->lock); - hidden->resume = SDL_TRUE; - } - - if (captureDevice && captureDevice->hidden) { - hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; - SDL_LockMutex(captureDevice->lock); - hidden->resume = SDL_TRUE; - } -} - -// Resume (unblock) all non already paused audio devices by releasing their mixer lock -void ANDROIDAUDIO_ResumeDevices(void) -{ - // TODO: Handle multiple devices? - struct SDL_PrivateAudioData *hidden; - if (audioDevice && audioDevice->hidden) { - hidden = (struct SDL_PrivateAudioData *)audioDevice->hidden; - if (hidden->resume) { - hidden->resume = SDL_FALSE; - SDL_UnlockMutex(audioDevice->lock); - } - } - - if (captureDevice && captureDevice->hidden) { - hidden = (struct SDL_PrivateAudioData *)captureDevice->hidden; - if (hidden->resume) { - hidden->resume = SDL_FALSE; - SDL_UnlockMutex(captureDevice->lock); - } - } -} - -static SDL_bool ANDROIDAUDIO_Init(SDL_AudioDriverImpl *impl) -{ - // !!! FIXME: if on Android API < 24, DetectDevices and Deinitialize should be NULL and OnlyHasDefaultOutputDevice and OnlyHasDefaultCaptureDevice should be SDL_TRUE, since audio device enum and hotplug appears to require Android 7.0+. - impl->ThreadInit = Android_AudioThreadInit; - impl->DetectDevices = Android_StartAudioHotplug; - impl->DeinitializeStart = Android_StopAudioHotplug; - impl->OpenDevice = ANDROIDAUDIO_OpenDevice; - impl->PlayDevice = ANDROIDAUDIO_PlayDevice; - impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf; - impl->CloseDevice = ANDROIDAUDIO_CloseDevice; - impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice; - impl->FlushCapture = ANDROIDAUDIO_FlushCapture; - - impl->HasCaptureSupport = SDL_TRUE; - - return SDL_TRUE; -} - -AudioBootStrap ANDROIDAUDIO_bootstrap = { - "android", "SDL Android audio driver", ANDROIDAUDIO_Init, SDL_FALSE -}; - -#endif // SDL_AUDIO_DRIVER_ANDROID diff --git a/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.h b/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.h index cd64e3038..e00d835b0 100644 --- a/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.h +++ b/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.h @@ -60,7 +60,7 @@ struct SDL_PrivateAudioData #ifdef MACOSX_COREAUDIO AudioDeviceID deviceID; #else - SDL_bool interrupted; + bool interrupted; CFTypeRef interruption_listener; #endif }; diff --git a/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.m b/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.m index 8de8d96c0..9b6b81984 100644 --- a/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.m +++ b/libs/SDL3/src/audio/coreaudio/SDL_coreaudio.m @@ -48,19 +48,19 @@ typedef struct SDLCoreAudioHandle { AudioDeviceID devid; - SDL_bool iscapture; + bool recording; } SDLCoreAudioHandle; -static SDL_bool TestCoreAudioDeviceHandleCallback(SDL_AudioDevice *device, void *handle) +static bool TestCoreAudioDeviceHandleCallback(SDL_AudioDevice *device, void *handle) { const SDLCoreAudioHandle *a = (const SDLCoreAudioHandle *) device->handle; const SDLCoreAudioHandle *b = (const SDLCoreAudioHandle *) handle; - return (a->devid == b->devid) && (!!a->iscapture == !!b->iscapture); + return (a->devid == b->devid) && (!!a->recording == !!b->recording); } -static SDL_AudioDevice *FindCoreAudioDeviceByHandle(const AudioDeviceID devid, const SDL_bool iscapture) +static SDL_AudioDevice *FindCoreAudioDeviceByHandle(const AudioDeviceID devid, const bool recording) { - SDLCoreAudioHandle handle = { devid, iscapture }; + SDLCoreAudioHandle handle = { devid, recording }; return SDL_FindPhysicalAudioDeviceByCallback(TestCoreAudioDeviceHandleCallback, &handle); } @@ -70,13 +70,13 @@ static SDL_bool TestCoreAudioDeviceHandleCallback(SDL_AudioDevice *device, void kAudioObjectPropertyElementMain }; -static const AudioObjectPropertyAddress default_output_device_address = { +static const AudioObjectPropertyAddress default_playback_device_address = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain }; -static const AudioObjectPropertyAddress default_input_device_address = { +static const AudioObjectPropertyAddress default_recording_device_address = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain @@ -98,11 +98,11 @@ static OSStatus DeviceAliveNotification(AudioObjectID devid, UInt32 num_addr, co UInt32 size = sizeof(alive); const OSStatus error = AudioObjectGetPropertyData(devid, addrs, 0, NULL, &size, &alive); - SDL_bool dead = SDL_FALSE; + bool dead = false; if (error == kAudioHardwareBadDeviceError) { - dead = SDL_TRUE; // device was unplugged. + dead = true; // device was unplugged. } else if ((error == kAudioHardwareNoError) && (!alive)) { - dead = SDL_TRUE; // device died in some other way. + dead = true; // device died in some other way. } if (dead) { @@ -127,7 +127,7 @@ static void RefreshPhysicalDevices(void) { UInt32 size = 0; AudioDeviceID *devs = NULL; - SDL_bool isstack; + bool isstack; if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &devlist_address, 0, NULL, &size) != kAudioHardwareNoError) { return; @@ -140,26 +140,26 @@ static void RefreshPhysicalDevices(void) const UInt32 total_devices = (UInt32) (size / sizeof(AudioDeviceID)); for (UInt32 i = 0; i < total_devices; i++) { - if (FindCoreAudioDeviceByHandle(devs[i], SDL_TRUE) || FindCoreAudioDeviceByHandle(devs[i], SDL_FALSE)) { + if (FindCoreAudioDeviceByHandle(devs[i], true) || FindCoreAudioDeviceByHandle(devs[i], false)) { devs[i] = 0; // The system and SDL both agree it's already here, don't check it again. } } // any non-zero items remaining in `devs` are new devices to be added. - for (int iscapture = 0; iscapture < 2; iscapture++) { + for (int recording = 0; recording < 2; recording++) { const AudioObjectPropertyAddress addr = { kAudioDevicePropertyStreamConfiguration, - iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; const AudioObjectPropertyAddress nameaddr = { kAudioObjectPropertyName, - iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; const AudioObjectPropertyAddress freqaddr = { kAudioDevicePropertyNominalSampleRate, - iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; @@ -207,7 +207,7 @@ static void RefreshPhysicalDevices(void) CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8); char *name = (char *)SDL_malloc(len + 1); - SDL_bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8))); + bool usable = ((name != NULL) && (CFStringGetCString(cfstr, name, len + 1, kCFStringEncodingUTF8))); CFRelease(cfstr); @@ -224,15 +224,13 @@ static void RefreshPhysicalDevices(void) name[len] = '\0'; #if DEBUG_COREAUDIO - SDL_Log("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n", - ((iscapture) ? "capture" : "output"), - (int)i, name, (int)dev); + SDL_Log("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n", ((recording) ? "recording" : "playback"), (int)i, name, (int)dev); #endif SDLCoreAudioHandle *newhandle = (SDLCoreAudioHandle *) SDL_calloc(1, sizeof (*newhandle)); if (newhandle) { newhandle->devid = dev; - newhandle->iscapture = iscapture ? SDL_TRUE : SDL_FALSE; - SDL_AudioDevice *device = SDL_AddAudioDevice(newhandle->iscapture, name, &spec, newhandle); + newhandle->recording = recording ? true : false; + SDL_AudioDevice *device = SDL_AddAudioDevice(newhandle->recording, name, &spec, newhandle); if (device) { AudioObjectAddPropertyListener(dev, &alive_address, DeviceAliveNotification, device); } else { @@ -254,35 +252,35 @@ static OSStatus DeviceListChangedNotification(AudioObjectID systemObj, UInt32 nu return noErr; } -static OSStatus DefaultAudioDeviceChangedNotification(const SDL_bool iscapture, AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr) +static OSStatus DefaultAudioDeviceChangedNotification(const bool recording, AudioObjectID inObjectID, const AudioObjectPropertyAddress *addr) { AudioDeviceID devid; UInt32 size = sizeof(devid); if (AudioObjectGetPropertyData(inObjectID, addr, 0, NULL, &size, &devid) == noErr) { - SDL_DefaultAudioDeviceChanged(FindCoreAudioDeviceByHandle(devid, iscapture)); + SDL_DefaultAudioDeviceChanged(FindCoreAudioDeviceByHandle(devid, recording)); } return noErr; } -static OSStatus DefaultOutputDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) +static OSStatus DefaultPlaybackDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) { #if DEBUG_COREAUDIO - SDL_Log("COREAUDIO: default output device changed!"); + SDL_Log("COREAUDIO: default playback device changed!"); #endif SDL_assert(inNumberAddresses == 1); - return DefaultAudioDeviceChangedNotification(SDL_FALSE, inObjectID, inAddresses); + return DefaultAudioDeviceChangedNotification(false, inObjectID, inAddresses); } -static OSStatus DefaultInputDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) +static OSStatus DefaultRecordingDeviceChangedNotification(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *inUserData) { #if DEBUG_COREAUDIO - SDL_Log("COREAUDIO: default input device changed!"); + SDL_Log("COREAUDIO: default recording device changed!"); #endif SDL_assert(inNumberAddresses == 1); - return DefaultAudioDeviceChangedNotification(SDL_TRUE, inObjectID, inAddresses); + return DefaultAudioDeviceChangedNotification(true, inObjectID, inAddresses); } -static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { RefreshPhysicalDevices(); @@ -293,34 +291,34 @@ static void COREAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioD AudioDeviceID devid; size = sizeof(AudioDeviceID); - if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_output_device_address, 0, NULL, &size, &devid) == noErr) { - SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_FALSE); + if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_playback_device_address, 0, NULL, &size, &devid) == noErr) { + SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, false); if (device) { - *default_output = device; + *default_playback = device; } } - AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_output_device_address, DefaultOutputDeviceChangedNotification, NULL); + AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_playback_device_address, DefaultPlaybackDeviceChangedNotification, NULL); size = sizeof(AudioDeviceID); - if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_input_device_address, 0, NULL, &size, &devid) == noErr) { - SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, SDL_TRUE); + if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_recording_device_address, 0, NULL, &size, &devid) == noErr) { + SDL_AudioDevice *device = FindCoreAudioDeviceByHandle(devid, true); if (device) { - *default_capture = device; + *default_recording = device; } } - AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_input_device_address, DefaultInputDeviceChangedNotification, NULL); + AudioObjectAddPropertyListener(kAudioObjectSystemObject, &default_recording_device_address, DefaultRecordingDeviceChangedNotification, NULL); } #else // iOS-specific section follows. -static SDL_bool session_active = SDL_FALSE; +static bool session_active = false; -static SDL_bool PauseOneAudioDevice(SDL_AudioDevice *device, void *userdata) +static bool PauseOneAudioDevice(SDL_AudioDevice *device, void *userdata) { if (device->hidden && device->hidden->audioQueue && !device->hidden->interrupted) { AudioQueuePause(device->hidden->audioQueue); } - return SDL_FALSE; // keep enumerating devices until we've paused them all. + return false; // keep enumerating devices until we've paused them all. } static void PauseAudioDevices(void) @@ -328,12 +326,12 @@ static void PauseAudioDevices(void) (void) SDL_FindPhysicalAudioDeviceByCallback(PauseOneAudioDevice, NULL); } -static SDL_bool ResumeOneAudioDevice(SDL_AudioDevice *device, void *userdata) +static bool ResumeOneAudioDevice(SDL_AudioDevice *device, void *userdata) { if (device->hidden && device->hidden->audioQueue && !device->hidden->interrupted) { AudioQueueStart(device->hidden->audioQueue, NULL); } - return SDL_FALSE; // keep enumerating devices until we've resumed them all. + return false; // keep enumerating devices until we've resumed them all. } static void ResumeAudioDevices(void) @@ -344,7 +342,7 @@ static void ResumeAudioDevices(void) static void InterruptionBegin(SDL_AudioDevice *device) { if (device != NULL && device->hidden->audioQueue != NULL) { - device->hidden->interrupted = SDL_TRUE; + device->hidden->interrupted = true; AudioQueuePause(device->hidden->audioQueue); } } @@ -352,7 +350,7 @@ static void InterruptionBegin(SDL_AudioDevice *device) static void InterruptionEnd(SDL_AudioDevice *device) { if (device != NULL && device->hidden != NULL && device->hidden->audioQueue != NULL && device->hidden->interrupted && AudioQueueStart(device->hidden->audioQueue, NULL) == AVAudioSessionErrorCodeNone) { - device->hidden->interrupted = SDL_FALSE; + device->hidden->interrupted = false; } } @@ -387,24 +385,24 @@ - (void)applicationBecameActive:(NSNotification *)note typedef struct { - int output; - int capture; + int playback; + int recording; } CountOpenAudioDevicesData; -static SDL_bool CountOpenAudioDevices(SDL_AudioDevice *device, void *userdata) +static bool CountOpenAudioDevices(SDL_AudioDevice *device, void *userdata) { CountOpenAudioDevicesData *data = (CountOpenAudioDevicesData *) userdata; if (device->hidden != NULL) { // assume it's open if hidden != NULL - if (device->iscapture) { - data->capture++; + if (device->recording) { + data->recording++; } else { - data->output++; + data->playback++; } } - return SDL_FALSE; // keep enumerating until all devices have been checked. + return false; // keep enumerating until all devices have been checked. } -static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_bool allow_playandrecord) +static bool UpdateAudioSession(SDL_AudioDevice *device, bool open, bool allow_playandrecord) { @autoreleasepool { AVAudioSession *session = [AVAudioSession sharedInstance]; @@ -437,9 +435,9 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b category = AVAudioSessionCategoryPlayAndRecord; } } - } else if (data.output && data.capture) { + } else if (data.playback && data.recording) { category = AVAudioSessionCategoryPlayAndRecord; - } else if (data.capture) { + } else if (data.recording) { category = AVAudioSessionCategoryRecord; } @@ -469,12 +467,12 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b // Stop the current session so we don't interrupt other application audio PauseAudioDevices(); [session setActive:NO error:nil]; - session_active = SDL_FALSE; + session_active = false; if (![session setCategory:category mode:mode options:options error:&err]) { NSString *desc = err.description; SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String); - return SDL_FALSE; + return false; } } } else { @@ -482,33 +480,33 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b // Stop the current session so we don't interrupt other application audio PauseAudioDevices(); [session setActive:NO error:nil]; - session_active = SDL_FALSE; + session_active = false; if (![session setCategory:category error:&err]) { NSString *desc = err.description; SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String); - return SDL_FALSE; + return false; } } } - if ((data.output || data.capture) && !session_active) { + if ((data.playback || data.recording) && !session_active) { if (![session setActive:YES error:&err]) { if ([err code] == AVAudioSessionErrorCodeResourceNotAvailable && category == AVAudioSessionCategoryPlayAndRecord) { - return UpdateAudioSession(device, open, SDL_FALSE); + return UpdateAudioSession(device, open, false); } NSString *desc = err.description; SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String); - return SDL_FALSE; + return false; } - session_active = SDL_TRUE; + session_active = true; ResumeAudioDevices(); - } else if (!data.output && !data.capture && session_active) { + } else if (!data.playback && !data.recording && session_active) { PauseAudioDevices(); [session setActive:NO error:nil]; - session_active = SDL_FALSE; + session_active = false; } if (open) { @@ -545,38 +543,38 @@ static SDL_bool UpdateAudioSession(SDL_AudioDevice *device, SDL_bool open, SDL_b } } - return SDL_TRUE; + return true; } #endif -static int COREAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool COREAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { AudioQueueBufferRef current_buffer = device->hidden->current_buffer; - SDL_assert(current_buffer != NULL); // should have been called from OutputBufferReadyCallback + SDL_assert(current_buffer != NULL); // should have been called from PlaybackBufferReadyCallback SDL_assert(buffer == (Uint8 *) current_buffer->mAudioData); current_buffer->mAudioDataByteSize = current_buffer->mAudioDataBytesCapacity; device->hidden->current_buffer = NULL; AudioQueueEnqueueBuffer(device->hidden->audioQueue, current_buffer, 0, NULL); - return 0; + return true; } static Uint8 *COREAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { AudioQueueBufferRef current_buffer = device->hidden->current_buffer; - SDL_assert(current_buffer != NULL); // should have been called from OutputBufferReadyCallback + SDL_assert(current_buffer != NULL); // should have been called from PlaybackBufferReadyCallback SDL_assert(current_buffer->mAudioData != NULL); *buffer_size = (int) current_buffer->mAudioDataBytesCapacity; return (Uint8 *) current_buffer->mAudioData; } -static void OutputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) +static void PlaybackBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { SDL_AudioDevice *device = (SDL_AudioDevice *)inUserData; SDL_assert(inBuffer != NULL); // ...right? SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending device->hidden->current_buffer = inBuffer; - const SDL_bool okay = SDL_OutputAudioThreadIterate(device); + const bool okay = SDL_PlaybackAudioThreadIterate(device); SDL_assert((device->hidden->current_buffer == NULL) || !okay); // PlayDevice should have enqueued and cleaned it out, unless we failed or shutdown. // buffer is unexpectedly here? We're probably dying, but try to requeue this buffer with silence. @@ -588,10 +586,10 @@ static void OutputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Audi } } -static int COREAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int COREAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { AudioQueueBufferRef current_buffer = device->hidden->current_buffer; - SDL_assert(current_buffer != NULL); // should have been called from InputBufferReadyCallback + SDL_assert(current_buffer != NULL); // should have been called from RecordingBufferReadyCallback SDL_assert(current_buffer->mAudioData != NULL); SDL_assert(buflen >= (int) current_buffer->mAudioDataByteSize); // `cpy` makes sure this won't overflow a buffer, but we _will_ drop samples if this assertion fails! const int cpy = SDL_min(buflen, (int) current_buffer->mAudioDataByteSize); @@ -601,7 +599,7 @@ static int COREAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in return cpy; } -static void COREAUDIO_FlushCapture(SDL_AudioDevice *device) +static void COREAUDIO_FlushRecording(SDL_AudioDevice *device) { AudioQueueBufferRef current_buffer = device->hidden->current_buffer; if (current_buffer != NULL) { // also gets called at shutdown, when no buffer is available. @@ -611,7 +609,7 @@ static void COREAUDIO_FlushCapture(SDL_AudioDevice *device) } } -static void InputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, +static void RecordingBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription *inPacketDescs) { @@ -620,12 +618,12 @@ static void InputBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Audio SDL_assert(inBuffer != NULL); // ...right? SDL_assert(device->hidden->current_buffer == NULL); // shouldn't have anything pending device->hidden->current_buffer = inBuffer; - SDL_CaptureAudioThreadIterate(device); + SDL_RecordingAudioThreadIterate(device); // buffer is unexpectedly here? We're probably dying, but try to requeue this buffer anyhow. if (device->hidden->current_buffer != NULL) { - SDL_assert(SDL_AtomicGet(&device->shutdown) != 0); - COREAUDIO_FlushCapture(device); // just flush it manually, which will requeue it. + SDL_assert(SDL_GetAtomicInt(&device->shutdown) != 0); + COREAUDIO_FlushRecording(device); // just flush it manually, which will requeue it. } } @@ -643,12 +641,12 @@ static void COREAUDIO_CloseDevice(SDL_AudioDevice *device) } if (device->hidden->thread) { - SDL_assert(SDL_AtomicGet(&device->shutdown) != 0); // should have been set by SDL_audio.c + SDL_assert(SDL_GetAtomicInt(&device->shutdown) != 0); // should have been set by SDL_audio.c SDL_WaitThread(device->hidden->thread, NULL); } #ifndef MACOSX_COREAUDIO - UpdateAudioSession(device, SDL_FALSE, SDL_TRUE); + UpdateAudioSession(device, false, true); #endif if (device->hidden->ready_semaphore) { @@ -662,7 +660,7 @@ static void COREAUDIO_CloseDevice(SDL_AudioDevice *device) } #ifdef MACOSX_COREAUDIO -static int PrepareDevice(SDL_AudioDevice *device) +static bool PrepareDevice(SDL_AudioDevice *device) { SDL_assert(device->handle != NULL); // this meant "system default" in SDL2, but doesn't anymore @@ -680,7 +678,7 @@ static int PrepareDevice(SDL_AudioDevice *device) UInt32 alive = 0; size = sizeof(alive); addr.mSelector = kAudioDevicePropertyDeviceIsAlive; - addr.mScope = device->iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; + addr.mScope = device->recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput; result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive); CHECK_RESULT("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)"); if (!alive) { @@ -698,14 +696,14 @@ static int PrepareDevice(SDL_AudioDevice *device) device->hidden->deviceID = devid; - return 0; + return true; } -static int AssignDeviceToAudioQueue(SDL_AudioDevice *device) +static bool AssignDeviceToAudioQueue(SDL_AudioDevice *device) { const AudioObjectPropertyAddress prop = { kAudioDevicePropertyDeviceUID, - device->iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, + device->recording ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMain }; @@ -715,33 +713,31 @@ static int AssignDeviceToAudioQueue(SDL_AudioDevice *device) result = AudioObjectGetPropertyData(device->hidden->deviceID, &prop, 0, NULL, &devuidsize, &devuid); CHECK_RESULT("AudioObjectGetPropertyData (kAudioDevicePropertyDeviceUID)"); result = AudioQueueSetProperty(device->hidden->audioQueue, kAudioQueueProperty_CurrentDevice, &devuid, devuidsize); + CFRelease(devuid); // Release devuid; we're done with it and AudioQueueSetProperty should have retained if it wants to keep it. CHECK_RESULT("AudioQueueSetProperty (kAudioQueueProperty_CurrentDevice)"); - - // !!! FIXME: do we need to CFRelease(devuid)? - - return 0; + return true; } #endif -static int PrepareAudioQueue(SDL_AudioDevice *device) +static bool PrepareAudioQueue(SDL_AudioDevice *device) { const AudioStreamBasicDescription *strdesc = &device->hidden->strdesc; - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; OSStatus result; SDL_assert(CFRunLoopGetCurrent() != NULL); - if (iscapture) { - result = AudioQueueNewInput(strdesc, InputBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); + if (recording) { + result = AudioQueueNewInput(strdesc, RecordingBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); CHECK_RESULT("AudioQueueNewInput"); } else { - result = AudioQueueNewOutput(strdesc, OutputBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); + result = AudioQueueNewOutput(strdesc, PlaybackBufferReadyCallback, device, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &device->hidden->audioQueue); CHECK_RESULT("AudioQueueNewOutput"); } #ifdef MACOSX_COREAUDIO - if (AssignDeviceToAudioQueue(device) < 0) { - return -1; + if (!AssignDeviceToAudioQueue(device)) { + return false; } #endif @@ -800,7 +796,7 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) device->hidden->numAudioBuffers = numAudioBuffers; device->hidden->audioBuffer = SDL_calloc(numAudioBuffers, sizeof(AudioQueueBufferRef)); if (device->hidden->audioBuffer == NULL) { - return -1; + return false; } #if DEBUG_COREAUDIO @@ -820,56 +816,56 @@ static int PrepareAudioQueue(SDL_AudioDevice *device) result = AudioQueueStart(device->hidden->audioQueue, NULL); CHECK_RESULT("AudioQueueStart"); - return 0; // We're running! + return true; // We're running! } static int AudioQueueThreadEntry(void *arg) { SDL_AudioDevice *device = (SDL_AudioDevice *)arg; - if (device->iscapture) { - SDL_CaptureAudioThreadSetup(device); + if (device->recording) { + SDL_RecordingAudioThreadSetup(device); } else { - SDL_OutputAudioThreadSetup(device); + SDL_PlaybackAudioThreadSetup(device); } - if (PrepareAudioQueue(device) < 0) { + if (!PrepareAudioQueue(device)) { device->hidden->thread_error = SDL_strdup(SDL_GetError()); - SDL_PostSemaphore(device->hidden->ready_semaphore); + SDL_SignalSemaphore(device->hidden->ready_semaphore); return 0; } // init was successful, alert parent thread and start running... - SDL_PostSemaphore(device->hidden->ready_semaphore); + SDL_SignalSemaphore(device->hidden->ready_semaphore); - // This would be WaitDevice/WaitCaptureDevice in the normal SDL audio thread, but we get *BufferReadyCallback calls here to know when to iterate. - while (!SDL_AtomicGet(&device->shutdown)) { + // This would be WaitDevice/WaitRecordingDevice in the normal SDL audio thread, but we get *BufferReadyCallback calls here to know when to iterate. + while (!SDL_GetAtomicInt(&device->shutdown)) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1); } - if (device->iscapture) { - SDL_CaptureAudioThreadShutdown(device); + if (device->recording) { + SDL_RecordingAudioThreadShutdown(device); } else { // Drain off any pending playback. const CFTimeInterval secs = (((CFTimeInterval)device->sample_frames) / ((CFTimeInterval)device->spec.freq)) * 2.0; CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0); - SDL_OutputAudioThreadShutdown(device); + SDL_PlaybackAudioThreadShutdown(device); } return 0; } -static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool COREAUDIO_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (device->hidden == NULL) { - return -1; + return false; } #ifndef MACOSX_COREAUDIO - if (!UpdateAudioSession(device, SDL_TRUE, SDL_TRUE)) { - return -1; + if (!UpdateAudioSession(device, true, true)) { + return false; } // Stop CoreAudio from doing expensive audio rate conversion @@ -878,7 +874,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) [session setPreferredSampleRate:device->spec.freq error:nil]; device->spec.freq = (int)session.sampleRate; #ifdef SDL_PLATFORM_TVOS - if (device->iscapture) { + if (device->recording) { [session setPreferredInputNumberOfChannels:device->spec.channels error:nil]; device->spec.channels = (int)session.preferredInputNumberOfChannels; } else { @@ -887,7 +883,7 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) } #else // Calling setPreferredOutputNumberOfChannels seems to break audio output on iOS - #endif /* SDL_PLATFORM_TVOS */ + #endif // SDL_PLATFORM_TVOS } #endif @@ -939,22 +935,22 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) strdesc->mBytesPerPacket = strdesc->mBytesPerFrame * strdesc->mFramesPerPacket; #ifdef MACOSX_COREAUDIO - if (PrepareDevice(device) < 0) { - return -1; + if (!PrepareDevice(device)) { + return false; } #endif // This has to init in a new thread so it can get its own CFRunLoop. :/ device->hidden->ready_semaphore = SDL_CreateSemaphore(0); if (!device->hidden->ready_semaphore) { - return -1; // oh well. + return false; // oh well. } char threadname[64]; SDL_GetAudioThreadName(device, threadname, sizeof(threadname)); - device->hidden->thread = SDL_CreateThreadInternal(AudioQueueThreadEntry, threadname, 0, device); + device->hidden->thread = SDL_CreateThread(AudioQueueThreadEntry, threadname, device); if (!device->hidden->thread) { - return -1; + return false; } SDL_WaitSemaphore(device->hidden->ready_semaphore); @@ -967,25 +963,25 @@ static int COREAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("%s", device->hidden->thread_error); } - return (device->hidden->thread != NULL) ? 0 : -1; + return (device->hidden->thread != NULL); } static void COREAUDIO_DeinitializeStart(void) { #ifdef MACOSX_COREAUDIO AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, DeviceListChangedNotification, NULL); - AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_output_device_address, DefaultOutputDeviceChangedNotification, NULL); - AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_input_device_address, DefaultInputDeviceChangedNotification, NULL); + AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_playback_device_address, DefaultPlaybackDeviceChangedNotification, NULL); + AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &default_recording_device_address, DefaultRecordingDeviceChangedNotification, NULL); #endif } -static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = COREAUDIO_OpenDevice; impl->PlayDevice = COREAUDIO_PlayDevice; impl->GetDeviceBuf = COREAUDIO_GetDeviceBuf; - impl->CaptureFromDevice = COREAUDIO_CaptureFromDevice; - impl->FlushCapture = COREAUDIO_FlushCapture; + impl->RecordDevice = COREAUDIO_RecordDevice; + impl->FlushRecording = COREAUDIO_FlushRecording; impl->CloseDevice = COREAUDIO_CloseDevice; impl->DeinitializeStart = COREAUDIO_DeinitializeStart; @@ -993,18 +989,18 @@ static SDL_bool COREAUDIO_Init(SDL_AudioDriverImpl *impl) impl->DetectDevices = COREAUDIO_DetectDevices; impl->FreeDeviceHandle = COREAUDIO_FreeDeviceHandle; #else - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; #endif - impl->ProvidesOwnCallbackThread = SDL_TRUE; - impl->HasCaptureSupport = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap COREAUDIO_bootstrap = { - "coreaudio", "CoreAudio", COREAUDIO_Init, SDL_FALSE + "coreaudio", "CoreAudio", COREAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_COREAUDIO diff --git a/libs/SDL3/src/audio/directsound/SDL_directsound.c b/libs/SDL3/src/audio/directsound/SDL_directsound.c index 2d8101120..609e1b37a 100644 --- a/libs/SDL3/src/audio/directsound/SDL_directsound.c +++ b/libs/SDL3/src/audio/directsound/SDL_directsound.c @@ -35,11 +35,11 @@ // For Vista+, we can enumerate DSound devices with IMMDevice #ifdef HAVE_MMDEVICEAPI_H -static SDL_bool SupportsIMMDevice = SDL_FALSE; +static bool SupportsIMMDevice = false; #endif // DirectX function pointers for audio -static void *DSoundDLL = NULL; +static SDL_SharedObject *DSoundDLL = NULL; typedef HRESULT(WINAPI *fnDirectSoundCreate8)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); typedef HRESULT(WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID); typedef HRESULT(WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID, LPDIRECTSOUNDCAPTURE8 *, LPUNKNOWN); @@ -72,9 +72,9 @@ static void DSOUND_Unload(void) } } -static int DSOUND_Load(void) +static bool DSOUND_Load(void) { - int loaded = 0; + bool loaded = false; DSOUND_Unload(); @@ -87,9 +87,9 @@ static int DSOUND_Load(void) { \ p##f = (fn##f)SDL_LoadFunction(DSoundDLL, #f); \ if (!p##f) \ - loaded = 0; \ + loaded = false; \ } - loaded = 1; // will reset if necessary. + loaded = true; // will reset if necessary. DSOUNDLOAD(DirectSoundCreate8); DSOUNDLOAD(DirectSoundEnumerateW); DSOUNDLOAD(DirectSoundCaptureCreate8); @@ -109,7 +109,7 @@ static int DSOUND_Load(void) return loaded; } -static int SetDSerror(const char *function, int code) +static bool SetDSerror(const char *function, int code) { const char *error; @@ -170,7 +170,7 @@ static void DSOUND_FreeDeviceHandle(SDL_AudioDevice *device) // FindAllDevs is presumably only used on WinXP; Vista and later can use IMMDevice for better results. typedef struct FindAllDevsData { - SDL_bool iscapture; + bool recording; SDL_AudioDevice **default_device; LPCGUID default_device_guid; } FindAllDevsData; @@ -189,7 +189,7 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO * device before getting the channel mask and output format, making * this information inaccessible at enumeration time */ - SDL_AudioDevice *device = SDL_AddAudioDevice(data->iscapture, str, NULL, cpyguid); + SDL_AudioDevice *device = SDL_AddAudioDevice(data->recording, str, NULL, cpyguid); if (device && data->default_device && data->default_device_guid) { if (SDL_memcmp(cpyguid, data->default_device_guid, sizeof (GUID)) == 0) { *data->default_device = device; @@ -202,11 +202,11 @@ static BOOL CALLBACK FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVO return TRUE; // keep enumerating. } -static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void DSOUND_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { #ifdef HAVE_MMDEVICEAPI_H if (SupportsIMMDevice) { - SDL_IMMDevice_EnumerateEndpoints(default_output, default_capture); + SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording); } else #endif { @@ -216,25 +216,25 @@ static void DSOUND_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevi FindAllDevsData data; GUID guid; - data.iscapture = SDL_TRUE; - data.default_device = default_capture; + data.recording = true; + data.default_device = default_recording; data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultCapture, &guid) == DS_OK) ? &guid : NULL; pDirectSoundCaptureEnumerateW(FindAllDevs, &data); - data.iscapture = SDL_FALSE; - data.default_device = default_output; + data.recording = false; + data.default_device = default_playback; data.default_device_guid = (pGetDeviceID(&SDL_DSDEVID_DefaultPlayback, &guid) == DS_OK) ? &guid : NULL; pDirectSoundEnumerateW(FindAllDevs, &data); } } -static int DSOUND_WaitDevice(SDL_AudioDevice *device) +static bool DSOUND_WaitDevice(SDL_AudioDevice *device) { /* Semi-busy wait, since we have no way of getting play notification on a primary mixing buffer located in hardware (DirectX 5.0) */ - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { DWORD status = 0; DWORD cursor = 0; DWORD junk = 0; @@ -255,23 +255,23 @@ static int DSOUND_WaitDevice(SDL_AudioDevice *device) } if ((result != DS_OK) && (result != DSERR_BUFFERLOST)) { - return -1; + return false; } SDL_Delay(1); // not ready yet; sleep a bit. } - return 0; + return true; } -static int DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool DSOUND_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { // Unlock the buffer, allowing it to play SDL_assert(buflen == device->buffer_size); if (IDirectSoundBuffer_Unlock(device->hidden->mixbuf, (LPVOID) buffer, buflen, NULL, 0) != DS_OK) { - return -1; + return false; } - return 0; + return true; } static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -333,23 +333,23 @@ static Uint8 *DSOUND_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->locked_buf; } -static int DSOUND_WaitCaptureDevice(SDL_AudioDevice *device) +static bool DSOUND_WaitRecordingDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { DWORD junk, cursor; if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) { - return -1; + return false; } else if ((cursor / device->buffer_size) != h->lastchunk) { break; } SDL_Delay(1); } - return 0; + return true; } -static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int DSOUND_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *h = device->hidden; DWORD ptr1len, ptr2len; @@ -376,7 +376,7 @@ static int DSOUND_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b return (int) ptr1len; } -static void DSOUND_FlushCapture(SDL_AudioDevice *device) +static void DSOUND_FlushRecording(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; DWORD junk, cursor; @@ -409,9 +409,9 @@ static void DSOUND_CloseDevice(SDL_AudioDevice *device) /* This function tries to create a secondary audio buffer, and returns the number of audio chunks available in the created buffer. This is for - playback devices, not capture. + playback devices, not recording. */ -static int CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) +static bool CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) { LPDIRECTSOUND sndObj = device->hidden->sound; LPDIRECTSOUNDBUFFER *sndbuf = &device->hidden->mixbuf; @@ -445,14 +445,14 @@ static int CreateSecondary(SDL_AudioDevice *device, const DWORD bufsize, WAVEFOR (LPVOID)pvAudioPtr2, dwAudioBytes2); } - return 0; // We're ready to go + return true; // We're ready to go } /* This function tries to create a capture buffer, and returns the number of audio chunks available in the created buffer. This is for - capture devices, not playback. + recording devices, not playback. */ -static int CreateCaptureBuffer(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) +static bool CreateCaptureBuffer(SDL_AudioDevice *device, const DWORD bufsize, WAVEFORMATEX *wfmt) { LPDIRECTSOUNDCAPTURE capture = device->hidden->capture; LPDIRECTSOUNDCAPTUREBUFFER *capturebuf = &device->hidden->capturebuf; @@ -488,15 +488,15 @@ static int CreateCaptureBuffer(SDL_AudioDevice *device, const DWORD bufsize, WAV device->hidden->lastchunk = cursor / device->buffer_size; #endif - return 0; + return true; } -static int DSOUND_OpenDevice(SDL_AudioDevice *device) +static bool DSOUND_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Open the audio device @@ -513,7 +513,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) SDL_assert(guid != NULL); HRESULT result; - if (device->iscapture) { + if (device->recording) { result = pDirectSoundCaptureCreate8(guid, &device->hidden->capture, NULL); if (result != DS_OK) { return SetDSerror("DirectSoundCaptureCreate8", result); @@ -533,7 +533,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) const DWORD numchunks = 8; DWORD bufsize; - SDL_bool tried_format = SDL_FALSE; + bool tried_format = false; SDL_AudioFormat test_format; const SDL_AudioFormat *closefmts = SDL_ClosestAudioFormats(device->spec.format); while ((test_format = *(closefmts++)) != 0) { @@ -542,7 +542,7 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) case SDL_AUDIO_S16: case SDL_AUDIO_S32: case SDL_AUDIO_F32: - tried_format = SDL_TRUE; + tried_format = true; device->spec.format = test_format; @@ -603,8 +603,8 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) wfmt.Format.nBlockAlign = wfmt.Format.nChannels * (wfmt.Format.wBitsPerSample / 8); wfmt.Format.nAvgBytesPerSec = wfmt.Format.nSamplesPerSec * wfmt.Format.nBlockAlign; - const int rc = device->iscapture ? CreateCaptureBuffer(device, bufsize, (WAVEFORMATEX *)&wfmt) : CreateSecondary(device, bufsize, (WAVEFORMATEX *)&wfmt); - if (rc == 0) { + const bool rc = device->recording ? CreateCaptureBuffer(device, bufsize, (WAVEFORMATEX *)&wfmt) : CreateSecondary(device, bufsize, (WAVEFORMATEX *)&wfmt); + if (rc) { device->hidden->num_buffers = numchunks; break; } @@ -618,14 +618,14 @@ static int DSOUND_OpenDevice(SDL_AudioDevice *device) if (!test_format) { if (tried_format) { - return -1; // CreateSecondary() should have called SDL_SetError(). + return false; // CreateSecondary() should have called SDL_SetError(). } return SDL_SetError("%s: Unsupported audio format", "directsound"); } // Playback buffers will auto-start playing in DSOUND_WaitDevice() - return 0; // good to go. + return true; // good to go. } static void DSOUND_DeinitializeStart(void) @@ -641,18 +641,18 @@ static void DSOUND_Deinitialize(void) { DSOUND_Unload(); #ifdef HAVE_MMDEVICEAPI_H - SupportsIMMDevice = SDL_FALSE; + SupportsIMMDevice = false; #endif } -static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl) +static bool DSOUND_Init(SDL_AudioDriverImpl *impl) { if (!DSOUND_Load()) { - return SDL_FALSE; + return false; } #ifdef HAVE_MMDEVICEAPI_H - SupportsIMMDevice = !(SDL_IMMDevice_Init(NULL) < 0); + SupportsIMMDevice = SDL_IMMDevice_Init(NULL); #endif impl->DetectDevices = DSOUND_DetectDevices; @@ -660,21 +660,21 @@ static SDL_bool DSOUND_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = DSOUND_PlayDevice; impl->WaitDevice = DSOUND_WaitDevice; impl->GetDeviceBuf = DSOUND_GetDeviceBuf; - impl->WaitCaptureDevice = DSOUND_WaitCaptureDevice; - impl->CaptureFromDevice = DSOUND_CaptureFromDevice; - impl->FlushCapture = DSOUND_FlushCapture; + impl->WaitRecordingDevice = DSOUND_WaitRecordingDevice; + impl->RecordDevice = DSOUND_RecordDevice; + impl->FlushRecording = DSOUND_FlushRecording; impl->CloseDevice = DSOUND_CloseDevice; impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle; impl->DeinitializeStart = DSOUND_DeinitializeStart; impl->Deinitialize = DSOUND_Deinitialize; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap DSOUND_bootstrap = { - "directsound", "DirectSound", DSOUND_Init, SDL_FALSE + "directsound", "DirectSound", DSOUND_Init, false }; #endif // SDL_AUDIO_DRIVER_DSOUND diff --git a/libs/SDL3/src/audio/disk/SDL_diskaudio.c b/libs/SDL3/src/audio/disk/SDL_diskaudio.c index c68f8a24d..bf1e3d4f4 100644 --- a/libs/SDL3/src/audio/disk/SDL_diskaudio.c +++ b/libs/SDL3/src/audio/disk/SDL_diskaudio.c @@ -27,30 +27,25 @@ #include "../SDL_sysaudio.h" #include "SDL_diskaudio.h" -// !!! FIXME: these should be SDL hints, not environment variables. -// environment variables and defaults. -#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE" #define DISKDEFAULT_OUTFILE "sdlaudio.raw" -#define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN" #define DISKDEFAULT_INFILE "sdlaudio-in.raw" -#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY" -static int DISKAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool DISKAUDIO_WaitDevice(SDL_AudioDevice *device) { SDL_Delay(device->hidden->io_delay); - return 0; + return true; } -static int DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool DISKAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { const int written = (int)SDL_WriteIO(device->hidden->io, buffer, (size_t)buffer_size); if (written != buffer_size) { // If we couldn't write, assume fatal error for now - return -1; + return false; } #ifdef DEBUG_AUDIO SDL_Log("DISKAUDIO: Wrote %d bytes of audio data", (int) written); #endif - return 0; + return true; } static Uint8 *DISKAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -58,7 +53,7 @@ static Uint8 *DISKAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->mixbuf; } -static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int DISKAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *h = device->hidden; const int origbuflen = buflen; @@ -79,7 +74,7 @@ static int DISKAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, in return origbuflen; } -static void DISKAUDIO_FlushCapture(SDL_AudioDevice *device) +static void DISKAUDIO_FlushRecording(SDL_AudioDevice *device) { // no op...we don't advance the file pointer or anything. } @@ -96,78 +91,81 @@ static void DISKAUDIO_CloseDevice(SDL_AudioDevice *device) } } -static const char *get_filename(const SDL_bool iscapture) +static const char *get_filename(const bool recording) { - const char *devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE); + const char *devname = SDL_GetHint(recording ? SDL_HINT_AUDIO_DISK_INPUT_FILE : SDL_HINT_AUDIO_DISK_OUTPUT_FILE); if (!devname) { - devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE; + devname = recording ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE; } return devname; } -static int DISKAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool DISKAUDIO_OpenDevice(SDL_AudioDevice *device) { - SDL_bool iscapture = device->iscapture; - const char *fname = get_filename(iscapture); - const char *envr = SDL_getenv(DISKENVR_IODELAY); + bool recording = device->recording; + const char *fname = get_filename(recording); device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } - if (envr) { - device->hidden->io_delay = SDL_atoi(envr); - } else { - device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq); + device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq); + + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DISK_TIMESCALE); + if (hint) { + double scale = SDL_atof(hint); + if (scale >= 0.0) { + device->hidden->io_delay = (Uint32)SDL_round(device->hidden->io_delay * scale); + } } // Open the "audio device" - device->hidden->io = SDL_IOFromFile(fname, iscapture ? "rb" : "wb"); + device->hidden->io = SDL_IOFromFile(fname, recording ? "rb" : "wb"); if (!device->hidden->io) { - return -1; + return false; } // Allocate mixing buffer - if (!iscapture) { + if (!recording) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, "You are using the SDL disk i/o audio driver!"); - SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, " %s file [%s].\n", iscapture ? "Reading from" : "Writing to", fname); + SDL_LogCritical(SDL_LOG_CATEGORY_AUDIO, " %s file [%s].\n", recording ? "Reading from" : "Writing to", fname); - return 0; // We're ready to rock and roll. :-) + return true; // We're ready to rock and roll. :-) } -static void DISKAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void DISKAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - *default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)0x1); - *default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)0x2); + *default_playback = SDL_AddAudioDevice(false, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)0x1); + *default_recording = SDL_AddAudioDevice(true, DEFAULT_RECORDING_DEVNAME, NULL, (void *)0x2); } -static SDL_bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool DISKAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = DISKAUDIO_OpenDevice; impl->WaitDevice = DISKAUDIO_WaitDevice; - impl->WaitCaptureDevice = DISKAUDIO_WaitDevice; + impl->WaitRecordingDevice = DISKAUDIO_WaitDevice; impl->PlayDevice = DISKAUDIO_PlayDevice; impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf; - impl->CaptureFromDevice = DISKAUDIO_CaptureFromDevice; - impl->FlushCapture = DISKAUDIO_FlushCapture; + impl->RecordDevice = DISKAUDIO_RecordDevice; + impl->FlushRecording = DISKAUDIO_FlushRecording; impl->CloseDevice = DISKAUDIO_CloseDevice; impl->DetectDevices = DISKAUDIO_DetectDevices; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap DISKAUDIO_bootstrap = { - "disk", "direct-to-disk audio", DISKAUDIO_Init, SDL_TRUE + "disk", "direct-to-disk audio", DISKAUDIO_Init, true }; #endif // SDL_AUDIO_DRIVER_DISK diff --git a/libs/SDL3/src/audio/dsp/SDL_dspaudio.c b/libs/SDL3/src/audio/dsp/SDL_dspaudio.c index e9412e083..62e2f4c45 100644 --- a/libs/SDL3/src/audio/dsp/SDL_dspaudio.c +++ b/libs/SDL3/src/audio/dsp/SDL_dspaudio.c @@ -37,12 +37,11 @@ #include #include "../SDL_audiodev_c.h" -#include "../../SDL_utils_c.h" #include "SDL_dspaudio.h" -static void DSP_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void DSP_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - SDL_EnumUnixAudioDevices(SDL_FALSE, NULL); + SDL_EnumUnixAudioDevices(false, NULL); } static void DSP_CloseDevice(SDL_AudioDevice *device) @@ -56,7 +55,7 @@ static void DSP_CloseDevice(SDL_AudioDevice *device) } } -static int DSP_OpenDevice(SDL_AudioDevice *device) +static bool DSP_OpenDevice(SDL_AudioDevice *device) { // Make sure fragment size stays a power of 2, or OSS fails. // (I don't know which of these are actually legal values, though...) @@ -71,11 +70,11 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. - const int flags = ((device->iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); + const int flags = ((device->recording) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC, 0); if (device->hidden->audio_fd < 0) { return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno)); @@ -189,23 +188,23 @@ static int DSP_OpenDevice(SDL_AudioDevice *device) #endif // Allocate mixing buffer - if (!device->iscapture) { + if (!device->recording) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } - return 0; // We're ready to rock and roll. :-) + return true; // We're ready to rock and roll. :-) } -static int DSP_WaitDevice(SDL_AudioDevice *device) +static bool DSP_WaitDevice(SDL_AudioDevice *device) { - const unsigned long ioctlreq = device->iscapture ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE; + const unsigned long ioctlreq = device->recording ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE; struct SDL_PrivateAudioData *h = device->hidden; - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { audio_buf_info info; const int rc = ioctl(h->audio_fd, ioctlreq, &info); if (rc < 0) { @@ -214,7 +213,7 @@ static int DSP_WaitDevice(SDL_AudioDevice *device) } // Hmm, not much we can do - abort fprintf(stderr, "dsp WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); - return -1; + return false; } else if (info.bytes < device->buffer_size) { SDL_Delay(10); } else { @@ -222,20 +221,20 @@ static int DSP_WaitDevice(SDL_AudioDevice *device) } } - return 0; + return true; } -static int DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool DSP_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { struct SDL_PrivateAudioData *h = device->hidden; if (write(h->audio_fd, buffer, buflen) == -1) { perror("Audio write"); - return -1; + return false; } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", h->mixlen); #endif - return 0; + return true; } static Uint8 *DSP_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -243,12 +242,12 @@ static Uint8 *DSP_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->mixbuf; } -static int DSP_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int DSP_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { return (int)read(device->hidden->audio_fd, buffer, buflen); } -static void DSP_FlushCapture(SDL_AudioDevice *device) +static void DSP_FlushRecording(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; audio_buf_info info; @@ -265,21 +264,21 @@ static void DSP_FlushCapture(SDL_AudioDevice *device) } } -static SDL_bool InitTimeDevicesExist = SDL_FALSE; -static SDL_bool look_for_devices_test(int fd) +static bool InitTimeDevicesExist = false; +static bool look_for_devices_test(int fd) { - InitTimeDevicesExist = SDL_TRUE; // note that _something_ exists. + InitTimeDevicesExist = true; // note that _something_ exists. // Don't add to the device list, we're just seeing if any devices exist. - return SDL_FALSE; + return false; } -static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl) +static bool DSP_Init(SDL_AudioDriverImpl *impl) { - InitTimeDevicesExist = SDL_FALSE; - SDL_EnumUnixAudioDevices(SDL_FALSE, look_for_devices_test); + InitTimeDevicesExist = false; + SDL_EnumUnixAudioDevices(false, look_for_devices_test); if (!InitTimeDevicesExist) { SDL_SetError("dsp: No such audio device"); - return SDL_FALSE; // maybe try a different backend. + return false; // maybe try a different backend. } impl->DetectDevices = DSP_DetectDevices; @@ -288,17 +287,17 @@ static SDL_bool DSP_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = DSP_PlayDevice; impl->GetDeviceBuf = DSP_GetDeviceBuf; impl->CloseDevice = DSP_CloseDevice; - impl->WaitCaptureDevice = DSP_WaitDevice; - impl->CaptureFromDevice = DSP_CaptureFromDevice; - impl->FlushCapture = DSP_FlushCapture; + impl->WaitRecordingDevice = DSP_WaitDevice; + impl->RecordDevice = DSP_RecordDevice; + impl->FlushRecording = DSP_FlushRecording; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap DSP_bootstrap = { - "dsp", "Open Sound System (/dev/dsp)", DSP_Init, SDL_FALSE + "dsp", "Open Sound System (/dev/dsp)", DSP_Init, false }; #endif // SDL_AUDIO_DRIVER_OSS diff --git a/libs/SDL3/src/audio/dummy/SDL_dummyaudio.c b/libs/SDL3/src/audio/dummy/SDL_dummyaudio.c index 19c4b4f09..c3b01f200 100644 --- a/libs/SDL3/src/audio/dummy/SDL_dummyaudio.c +++ b/libs/SDL3/src/audio/dummy/SDL_dummyaudio.c @@ -25,39 +25,63 @@ #include "../SDL_sysaudio.h" #include "SDL_dummyaudio.h" -// !!! FIXME: this should be an SDL hint, not an environment variable. -#define DUMMYENVR_IODELAY "SDL_DUMMYAUDIODELAY" +#if defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) +#include +#endif -static int DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool DUMMYAUDIO_WaitDevice(SDL_AudioDevice *device) { SDL_Delay(device->hidden->io_delay); - return 0; + return true; } -static int DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool DUMMYAUDIO_OpenDevice(SDL_AudioDevice *device) { - const char *envr = SDL_getenv(DUMMYENVR_IODELAY); - device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } - if (!device->iscapture) { + if (!device->recording) { device->hidden->mixbuf = (Uint8 *) SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; + } + } + + device->hidden->io_delay = ((device->sample_frames * 1000) / device->spec.freq); + + const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DUMMY_TIMESCALE); + if (hint) { + double scale = SDL_atof(hint); + if (scale >= 0.0) { + device->hidden->io_delay = (Uint32)SDL_round(device->hidden->io_delay * scale); } } - device->hidden->io_delay = (Uint32) (envr ? SDL_atoi(envr) : ((device->sample_frames * 1000) / device->spec.freq)); + // on Emscripten without threads, we just fire a repeating timer to consume audio. + #if defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) + MAIN_THREAD_EM_ASM({ + var a = Module['SDL3'].dummy_audio; + if (a.timers[$0] !== undefined) { clearInterval(a.timers[$0]); } + a.timers[$0] = setInterval(function() { dynCall('vi', $3, [$4]); }, ($1 / $2) * 1000); + }, device->recording ? 1 : 0, device->sample_frames, device->spec.freq, device->recording ? SDL_RecordingAudioThreadIterate : SDL_PlaybackAudioThreadIterate, device); + #endif - return 0; // we're good; don't change reported device format. + return true; // we're good; don't change reported device format. } static void DUMMYAUDIO_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { + // on Emscripten without threads, we just fire a repeating timer to consume audio. + #if defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) + MAIN_THREAD_EM_ASM({ + var a = Module['SDL3'].dummy_audio; + if (a.timers[$0] !== undefined) { clearInterval(a.timers[$0]); } + a.timers[$0] = undefined; + }, device->recording ? 1 : 0); + #endif SDL_free(device->hidden->mixbuf); SDL_free(device->hidden); device->hidden = NULL; @@ -69,29 +93,43 @@ static Uint8 *DUMMYAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->mixbuf; } -static int DUMMYAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int DUMMYAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { // always return a full buffer of silence. SDL_memset(buffer, device->silence_value, buflen); return buflen; } -static SDL_bool DUMMYAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool DUMMYAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = DUMMYAUDIO_OpenDevice; impl->CloseDevice = DUMMYAUDIO_CloseDevice; impl->WaitDevice = DUMMYAUDIO_WaitDevice; impl->GetDeviceBuf = DUMMYAUDIO_GetDeviceBuf; - impl->WaitCaptureDevice = DUMMYAUDIO_WaitDevice; - impl->CaptureFromDevice = DUMMYAUDIO_CaptureFromDevice; - - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; - impl->HasCaptureSupport = SDL_TRUE; - - return SDL_TRUE; + impl->WaitRecordingDevice = DUMMYAUDIO_WaitDevice; + impl->RecordDevice = DUMMYAUDIO_RecordDevice; + + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; + impl->HasRecordingSupport = true; + + // on Emscripten without threads, we just fire a repeating timer to consume audio. + #if defined(SDL_PLATFORM_EMSCRIPTEN) && !defined(__EMSCRIPTEN_PTHREADS__) + MAIN_THREAD_EM_ASM({ + if (typeof(Module['SDL3']) === 'undefined') { + Module['SDL3'] = {}; + } + Module['SDL3'].dummy_audio = {}; + Module['SDL3'].dummy_audio.timers = []; + Module['SDL3'].dummy_audio.timers[0] = undefined; + Module['SDL3'].dummy_audio.timers[1] = undefined; + }); + impl->ProvidesOwnCallbackThread = true; + #endif + + return true; } AudioBootStrap DUMMYAUDIO_bootstrap = { - "dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, SDL_TRUE + "dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, true }; diff --git a/libs/SDL3/src/audio/dummy/SDL_dummyaudio.h b/libs/SDL3/src/audio/dummy/SDL_dummyaudio.h index 6f4c31c97..fd46c3a8f 100644 --- a/libs/SDL3/src/audio/dummy/SDL_dummyaudio.h +++ b/libs/SDL3/src/audio/dummy/SDL_dummyaudio.h @@ -28,7 +28,7 @@ struct SDL_PrivateAudioData { Uint8 *mixbuf; // The file descriptor for the audio device - Uint32 io_delay; // miliseconds to sleep in WaitDevice. + Uint32 io_delay; // milliseconds to sleep in WaitDevice. }; #endif // SDL_dummyaudio_h_ diff --git a/libs/SDL3/src/audio/emscripten/SDL_emscriptenaudio.c b/libs/SDL3/src/audio/emscripten/SDL_emscriptenaudio.c index 764f0b559..89ddbcd23 100644 --- a/libs/SDL3/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/libs/SDL3/src/audio/emscripten/SDL_emscriptenaudio.c @@ -29,23 +29,23 @@ // just turn off clang-format for this whole file, this INDENT_OFF stuff on // each EM_ASM section is ugly. -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static Uint8 *EMSCRIPTENAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { return device->hidden->mixbuf; } -static int EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { const int framelen = SDL_AUDIO_FRAMESIZE(device->spec); MAIN_THREAD_EM_ASM({ var SDL3 = Module['SDL3']; - var numChannels = SDL3.audio.currentOutputBuffer['numberOfChannels']; + var numChannels = SDL3.audio_playback.currentPlaybackBuffer['numberOfChannels']; for (var c = 0; c < numChannels; ++c) { - var channelData = SDL3.audio.currentOutputBuffer['getChannelData'](c); + var channelData = SDL3.audio_playback.currentPlaybackBuffer['getChannelData'](c); if (channelData.length != $1) { - throw 'Web Audio output buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; + throw 'Web Audio playback buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } for (var j = 0; j < $1; ++j) { @@ -53,24 +53,24 @@ static int EMSCRIPTENAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buff } } }, buffer, buffer_size / framelen); - return 0; + return true; } -static void EMSCRIPTENAUDIO_FlushCapture(SDL_AudioDevice *device) +static void EMSCRIPTENAUDIO_FlushRecording(SDL_AudioDevice *device) { // Do nothing, the new data will just be dropped. } -static int EMSCRIPTENAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int EMSCRIPTENAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { MAIN_THREAD_EM_ASM({ var SDL3 = Module['SDL3']; - var numChannels = SDL3.capture.currentCaptureBuffer.numberOfChannels; + var numChannels = SDL3.audio_recording.currentRecordingBuffer.numberOfChannels; for (var c = 0; c < numChannels; ++c) { - var channelData = SDL3.capture.currentCaptureBuffer.getChannelData(c); + var channelData = SDL3.audio_recording.currentRecordingBuffer.getChannelData(c); if (channelData.length != $1) { - throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; + throw 'Web Audio recording buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!'; } if (numChannels == 1) { // fastpath this a little for the common (mono) case. @@ -97,37 +97,37 @@ static void EMSCRIPTENAUDIO_CloseDevice(SDL_AudioDevice *device) MAIN_THREAD_EM_ASM({ var SDL3 = Module['SDL3']; if ($0) { - if (SDL3.capture.silenceTimer !== undefined) { - clearInterval(SDL3.capture.silenceTimer); + if (SDL3.audio_recording.silenceTimer !== undefined) { + clearInterval(SDL3.audio_recording.silenceTimer); } - if (SDL3.capture.stream !== undefined) { - var tracks = SDL3.capture.stream.getAudioTracks(); + if (SDL3.audio_recording.stream !== undefined) { + var tracks = SDL3.audio_recording.stream.getAudioTracks(); for (var i = 0; i < tracks.length; i++) { - SDL3.capture.stream.removeTrack(tracks[i]); + SDL3.audio_recording.stream.removeTrack(tracks[i]); } } - if (SDL3.capture.scriptProcessorNode !== undefined) { - SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; - SDL3.capture.scriptProcessorNode.disconnect(); + if (SDL3.audio_recording.scriptProcessorNode !== undefined) { + SDL3.audio_recording.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {}; + SDL3.audio_recording.scriptProcessorNode.disconnect(); } - if (SDL3.capture.mediaStreamNode !== undefined) { - SDL3.capture.mediaStreamNode.disconnect(); + if (SDL3.audio_recording.mediaStreamNode !== undefined) { + SDL3.audio_recording.mediaStreamNode.disconnect(); } - SDL3.capture = undefined; + SDL3.audio_recording = undefined; } else { - if (SDL3.audio.scriptProcessorNode != undefined) { - SDL3.audio.scriptProcessorNode.disconnect(); + if (SDL3.audio_playback.scriptProcessorNode != undefined) { + SDL3.audio_playback.scriptProcessorNode.disconnect(); } - if (SDL3.audio.silenceTimer !== undefined) { - clearInterval(SDL3.audio.silenceTimer); + if (SDL3.audio_playback.silenceTimer !== undefined) { + clearInterval(SDL3.audio_playback.silenceTimer); } - SDL3.audio = undefined; + SDL3.audio_playback = undefined; } - if ((SDL3.audioContext !== undefined) && (SDL3.audio === undefined) && (SDL3.capture === undefined)) { + if ((SDL3.audioContext !== undefined) && (SDL3.audio_playback === undefined) && (SDL3.audio_recording === undefined)) { SDL3.audioContext.close(); SDL3.audioContext = undefined; } - }, device->iscapture); + }, device->recording); SDL_free(device->hidden->mixbuf); SDL_free(device->hidden); @@ -138,20 +138,20 @@ static void EMSCRIPTENAUDIO_CloseDevice(SDL_AudioDevice *device) EM_JS_DEPS(sdlaudio, "$autoResumeAudioContext,$dynCall"); -static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) { // based on parts of library_sdl.js // create context - const int result = MAIN_THREAD_EM_ASM_INT({ + const bool result = MAIN_THREAD_EM_ASM_INT({ if (typeof(Module['SDL3']) === 'undefined') { Module['SDL3'] = {}; } var SDL3 = Module['SDL3']; if (!$0) { - SDL3.audio = {}; + SDL3.audio_playback = {}; } else { - SDL3.capture = {}; + SDL3.audio_recording = {}; } if (!SDL3.audioContext) { @@ -166,10 +166,10 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) } } } - return SDL3.audioContext === undefined ? -1 : 0; - }, device->iscapture); + return (SDL3.audioContext !== undefined); + }, device->recording); - if (result < 0) { + if (!result) { return SDL_SetError("Web Audio API is not available!"); } @@ -178,7 +178,7 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // limit to native freq @@ -186,26 +186,26 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); - if (!device->iscapture) { + if (!device->recording) { device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } - if (device->iscapture) { - /* The idea is to take the capture media stream, hook it up to an + if (device->recording) { + /* The idea is to take the recording media stream, hook it up to an audio graph where we can pass it through a ScriptProcessorNode to access the raw PCM samples and push them to the SDL app's callback. From there, we "process" the audio data into silence and forget about it. - This should, strictly speaking, use MediaRecorder for capture, but + This should, strictly speaking, use MediaRecorder for recording, but this API is cleaner to use and better supported, and fires a callback whenever there's enough data to fire down into the app. The downside is that we are spending CPU time silencing a buffer - that the audiocontext uselessly mixes into any output. On the + that the audiocontext uselessly mixes into any playback. On the upside, both of those things are not only run in native code in the browser, they're probably SIMD code, too. MediaRecorder feels like it's a pretty inefficient tapdance in similar ways, @@ -214,67 +214,67 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) MAIN_THREAD_EM_ASM({ var SDL3 = Module['SDL3']; var have_microphone = function(stream) { - //console.log('SDL audio capture: we have a microphone! Replacing silence callback.'); - if (SDL3.capture.silenceTimer !== undefined) { - clearInterval(SDL3.capture.silenceTimer); - SDL3.capture.silenceTimer = undefined; - SDL3.capture.silenceBuffer = undefined + //console.log('SDL audio recording: we have a microphone! Replacing silence callback.'); + if (SDL3.audio_recording.silenceTimer !== undefined) { + clearInterval(SDL3.audio_recording.silenceTimer); + SDL3.audio_recording.silenceTimer = undefined; + SDL3.audio_recording.silenceBuffer = undefined } - SDL3.capture.mediaStreamNode = SDL3.audioContext.createMediaStreamSource(stream); - SDL3.capture.scriptProcessorNode = SDL3.audioContext.createScriptProcessor($1, $0, 1); - SDL3.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { - if ((SDL3 === undefined) || (SDL3.capture === undefined)) { return; } + SDL3.audio_recording.mediaStreamNode = SDL3.audioContext.createMediaStreamSource(stream); + SDL3.audio_recording.scriptProcessorNode = SDL3.audioContext.createScriptProcessor($1, $0, 1); + SDL3.audio_recording.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) { + if ((SDL3 === undefined) || (SDL3.audio_recording === undefined)) { return; } audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0); - SDL3.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer; + SDL3.audio_recording.currentRecordingBuffer = audioProcessingEvent.inputBuffer; dynCall('vi', $2, [$3]); }; - SDL3.capture.mediaStreamNode.connect(SDL3.capture.scriptProcessorNode); - SDL3.capture.scriptProcessorNode.connect(SDL3.audioContext.destination); - SDL3.capture.stream = stream; + SDL3.audio_recording.mediaStreamNode.connect(SDL3.audio_recording.scriptProcessorNode); + SDL3.audio_recording.scriptProcessorNode.connect(SDL3.audioContext.destination); + SDL3.audio_recording.stream = stream; }; var no_microphone = function(error) { - //console.log('SDL audio capture: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.'); + //console.log('SDL audio recording: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.'); }; // we write silence to the audio callback until the microphone is available (user approves use, etc). - SDL3.capture.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); - SDL3.capture.silenceBuffer.getChannelData(0).fill(0.0); + SDL3.audio_recording.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); + SDL3.audio_recording.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { - SDL3.capture.currentCaptureBuffer = SDL3.capture.silenceBuffer; + SDL3.audio_recording.currentRecordingBuffer = SDL3.audio_recording.silenceBuffer; dynCall('vi', $2, [$3]); }; - SDL3.capture.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); + SDL3.audio_recording.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) { navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone); } else if (navigator.webkitGetUserMedia !== undefined) { navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone); } - }, device->spec.channels, device->sample_frames, SDL_CaptureAudioThreadIterate, device); + }, device->spec.channels, device->sample_frames, SDL_RecordingAudioThreadIterate, device); } else { // setup a ScriptProcessorNode MAIN_THREAD_EM_ASM({ var SDL3 = Module['SDL3']; - SDL3.audio.scriptProcessorNode = SDL3.audioContext['createScriptProcessor']($1, 0, $0); - SDL3.audio.scriptProcessorNode['onaudioprocess'] = function (e) { - if ((SDL3 === undefined) || (SDL3.audio === undefined)) { return; } + SDL3.audio_playback.scriptProcessorNode = SDL3.audioContext['createScriptProcessor']($1, 0, $0); + SDL3.audio_playback.scriptProcessorNode['onaudioprocess'] = function (e) { + if ((SDL3 === undefined) || (SDL3.audio_playback === undefined)) { return; } // if we're actually running the node, we don't need the fake callback anymore, so kill it. - if (SDL3.audio.silenceTimer !== undefined) { - clearInterval(SDL3.audio.silenceTimer); - SDL3.audio.silenceTimer = undefined; - SDL3.audio.silenceBuffer = undefined; + if (SDL3.audio_playback.silenceTimer !== undefined) { + clearInterval(SDL3.audio_playback.silenceTimer); + SDL3.audio_playback.silenceTimer = undefined; + SDL3.audio_playback.silenceBuffer = undefined; } - SDL3.audio.currentOutputBuffer = e['outputBuffer']; + SDL3.audio_playback.currentPlaybackBuffer = e['outputBuffer']; dynCall('vi', $2, [$3]); }; - SDL3.audio.scriptProcessorNode['connect'](SDL3.audioContext['destination']); + SDL3.audio_playback.scriptProcessorNode['connect'](SDL3.audioContext['destination']); if (SDL3.audioContext.state === 'suspended') { // uhoh, autoplay is blocked. - SDL3.audio.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); - SDL3.audio.silenceBuffer.getChannelData(0).fill(0.0); + SDL3.audio_playback.silenceBuffer = SDL3.audioContext.createBuffer($0, $1, SDL3.audioContext.sampleRate); + SDL3.audio_playback.silenceBuffer.getChannelData(0).fill(0.0); var silence_callback = function() { if ((typeof navigator.userActivation) !== 'undefined') { // Almost everything modern except Firefox (as of August 2023) if (navigator.userActivation.hasBeenActive) { @@ -284,34 +284,34 @@ static int EMSCRIPTENAUDIO_OpenDevice(SDL_AudioDevice *device) // the buffer that gets filled here just gets ignored, so the app can make progress // and/or avoid flooding audio queues until we can actually play audio. - SDL3.audio.currentOutputBuffer = SDL3.audio.silenceBuffer; + SDL3.audio_playback.currentPlaybackBuffer = SDL3.audio_playback.silenceBuffer; dynCall('vi', $2, [$3]); - SDL3.audio.currentOutputBuffer = undefined; + SDL3.audio_playback.currentPlaybackBuffer = undefined; }; - SDL3.audio.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); + SDL3.audio_playback.silenceTimer = setInterval(silence_callback, ($1 / SDL3.audioContext.sampleRate) * 1000); } - }, device->spec.channels, device->sample_frames, SDL_OutputAudioThreadIterate, device); + }, device->spec.channels, device->sample_frames, SDL_PlaybackAudioThreadIterate, device); } - return 0; + return true; } -static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) { - SDL_bool available, capture_available; + bool available, recording_available; impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice; impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice; impl->GetDeviceBuf = EMSCRIPTENAUDIO_GetDeviceBuf; impl->PlayDevice = EMSCRIPTENAUDIO_PlayDevice; - impl->FlushCapture = EMSCRIPTENAUDIO_FlushCapture; - impl->CaptureFromDevice = EMSCRIPTENAUDIO_CaptureFromDevice; + impl->FlushRecording = EMSCRIPTENAUDIO_FlushRecording; + impl->RecordDevice = EMSCRIPTENAUDIO_RecordDevice; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; + impl->OnlyHasDefaultPlaybackDevice = true; // technically, this is just runs in idle time in the main thread, but it's close enough to a "thread" for our purposes. - impl->ProvidesOwnCallbackThread = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; // check availability available = MAIN_THREAD_EM_ASM_INT({ @@ -327,7 +327,7 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) SDL_SetError("No audio context available"); } - capture_available = available && MAIN_THREAD_EM_ASM_INT({ + recording_available = available && MAIN_THREAD_EM_ASM_INT({ if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) { return true; } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') { @@ -336,16 +336,16 @@ static SDL_bool EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl *impl) return false; }); - impl->HasCaptureSupport = capture_available; - impl->OnlyHasDefaultCaptureDevice = capture_available; + impl->HasRecordingSupport = recording_available; + impl->OnlyHasDefaultRecordingDevice = recording_available; return available; } AudioBootStrap EMSCRIPTENAUDIO_bootstrap = { - "emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, SDL_FALSE + "emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, false }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on #endif // SDL_AUDIO_DRIVER_EMSCRIPTEN diff --git a/libs/SDL3/src/audio/haiku/SDL_haikuaudio.cc b/libs/SDL3/src/audio/haiku/SDL_haikuaudio.cc index ed234d01f..5fe653811 100644 --- a/libs/SDL3/src/audio/haiku/SDL_haikuaudio.cc +++ b/libs/SDL3/src/audio/haiku/SDL_haikuaudio.cc @@ -45,14 +45,14 @@ static Uint8 *HAIKUAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return device->hidden->current_buffer; } -static int HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool HAIKUAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { // We already wrote our output right into the BSoundPlayer's callback's stream. Just clean up our stuff. SDL_assert(device->hidden->current_buffer != NULL); SDL_assert(device->hidden->current_buffer_len > 0); device->hidden->current_buffer = NULL; device->hidden->current_buffer_len = 0; - return 0; + return true; } // The Haiku callback for handling the audio buffer @@ -63,7 +63,7 @@ static void FillSound(void *data, void *stream, size_t len, const media_raw_audi SDL_assert(device->hidden->current_buffer_len == 0); device->hidden->current_buffer = (Uint8 *) stream; device->hidden->current_buffer_len = (int) len; - SDL_OutputAudioThreadIterate(device); + SDL_PlaybackAudioThreadIterate(device); } static void HAIKUAUDIO_CloseDevice(SDL_AudioDevice *device) @@ -102,12 +102,12 @@ static inline void UnmaskSignals(sigset_t * omask) } -static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = new SDL_PrivateAudioData; - if (device->hidden == NULL) { - return SDL_OutOfMemory(); + if (!device->hidden) { + return false; } SDL_zerop(device->hidden); @@ -186,7 +186,7 @@ static int HAIKUAUDIO_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Unable to start Haiku audio"); } - return 0; // We're running! + return true; // We're running! } static void HAIKUAUDIO_Deinitialize(void) @@ -194,10 +194,10 @@ static void HAIKUAUDIO_Deinitialize(void) SDL_QuitBeApp(); } -static SDL_bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl) { - if (SDL_InitBeApp() < 0) { - return SDL_FALSE; + if (!SDL_InitBeApp()) { + return false; } // Set the function pointers @@ -206,17 +206,17 @@ static SDL_bool HAIKUAUDIO_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = HAIKUAUDIO_PlayDevice; impl->CloseDevice = HAIKUAUDIO_CloseDevice; impl->Deinitialize = HAIKUAUDIO_Deinitialize; - impl->ProvidesOwnCallbackThread = SDL_TRUE; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; + impl->OnlyHasDefaultPlaybackDevice = true; - return SDL_TRUE; + return true; } extern "C" { extern AudioBootStrap HAIKUAUDIO_bootstrap; } AudioBootStrap HAIKUAUDIO_bootstrap = { - "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, SDL_FALSE + "haiku", "Haiku BSoundPlayer", HAIKUAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_HAIKU diff --git a/libs/SDL3/src/audio/jack/SDL_jackaudio.c b/libs/SDL3/src/audio/jack/SDL_jackaudio.c index 726b22d91..b590386e9 100644 --- a/libs/SDL3/src/audio/jack/SDL_jackaudio.c +++ b/libs/SDL3/src/audio/jack/SDL_jackaudio.c @@ -46,29 +46,29 @@ static int (*JACK_jack_set_process_callback)(jack_client_t *, JackProcessCallbac static int (*JACK_jack_set_sample_rate_callback)(jack_client_t *, JackSampleRateCallback, void *); static int (*JACK_jack_set_buffer_size_callback)(jack_client_t *, JackBufferSizeCallback, void *); -static int load_jack_syms(void); +static bool load_jack_syms(void); #ifdef SDL_AUDIO_DRIVER_JACK_DYNAMIC static const char *jack_library = SDL_AUDIO_DRIVER_JACK_DYNAMIC; -static void *jack_handle = NULL; +static SDL_SharedObject *jack_handle = NULL; // !!! FIXME: this is copy/pasted in several places now -static int load_jack_sym(const char *fn, void **addr) +static bool load_jack_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(jack_handle, fn); if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. - return 0; + return false; } - return 1; + return true; } // cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_JACK_SYM(x) \ if (!load_jack_sym(#x, (void **)(char *)&JACK_##x)) \ - return -1 + return false static void UnloadJackLibrary(void) { @@ -78,22 +78,22 @@ static void UnloadJackLibrary(void) } } -static int LoadJackLibrary(void) +static bool LoadJackLibrary(void) { - int retval = 0; + bool result = true; if (!jack_handle) { jack_handle = SDL_LoadObject(jack_library); if (!jack_handle) { - retval = -1; + result = false; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { - retval = load_jack_syms(); - if (retval < 0) { + result = load_jack_syms(); + if (!result) { UnloadJackLibrary(); } } } - return retval; + return result; } #else @@ -104,15 +104,15 @@ static void UnloadJackLibrary(void) { } -static int LoadJackLibrary(void) +static bool LoadJackLibrary(void) { load_jack_syms(); - return 0; + return true; } #endif // SDL_AUDIO_DRIVER_JACK_DYNAMIC -static int load_jack_syms(void) +static bool load_jack_syms(void) { SDL_JACK_SYM(jack_client_open); SDL_JACK_SYM(jack_client_close); @@ -134,7 +134,7 @@ static int load_jack_syms(void) SDL_JACK_SYM(jack_set_sample_rate_callback); SDL_JACK_SYM(jack_set_buffer_size_callback); - return 0; + return true; } static void jackShutdownCallback(void *arg) // JACK went away; device is lost. @@ -149,7 +149,7 @@ static int jackSampleRateCallback(jack_nframes_t nframes, void *arg) SDL_AudioSpec newspec; SDL_copyp(&newspec, &device->spec); newspec.freq = (int) nframes; - if (SDL_AudioDeviceFormatChanged(device, &newspec, device->sample_frames) < 0) { + if (!SDL_AudioDeviceFormatChanged(device, &newspec, device->sample_frames)) { SDL_AudioDeviceDisconnected(device); } return 0; @@ -161,7 +161,7 @@ static int jackBufferSizeCallback(jack_nframes_t nframes, void *arg) SDL_AudioDevice *device = (SDL_AudioDevice *) arg; SDL_AudioSpec newspec; SDL_copyp(&newspec, &device->spec); - if (SDL_AudioDeviceFormatChanged(device, &newspec, (int) nframes) < 0) { + if (!SDL_AudioDeviceFormatChanged(device, &newspec, (int) nframes)) { SDL_AudioDeviceDisconnected(device); } return 0; @@ -170,11 +170,11 @@ static int jackBufferSizeCallback(jack_nframes_t nframes, void *arg) static int jackProcessPlaybackCallback(jack_nframes_t nframes, void *arg) { SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames); - SDL_OutputAudioThreadIterate((SDL_AudioDevice *)arg); + SDL_PlaybackAudioThreadIterate((SDL_AudioDevice *)arg); return 0; } -static int JACK_PlayDevice(SDL_AudioDevice *device, const Uint8 *ui8buffer, int buflen) +static bool JACK_PlayDevice(SDL_AudioDevice *device, const Uint8 *ui8buffer, int buflen) { const float *buffer = (float *) ui8buffer; jack_port_t **ports = device->hidden->sdlports; @@ -193,7 +193,7 @@ static int JACK_PlayDevice(SDL_AudioDevice *device, const Uint8 *ui8buffer, int } } - return 0; + return true; } static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -201,14 +201,14 @@ static Uint8 *JACK_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return (Uint8 *)device->hidden->iobuffer; } -static int jackProcessCaptureCallback(jack_nframes_t nframes, void *arg) +static int jackProcessRecordingCallback(jack_nframes_t nframes, void *arg) { SDL_assert(nframes == ((SDL_AudioDevice *)arg)->sample_frames); - SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)arg); + SDL_RecordingAudioThreadIterate((SDL_AudioDevice *)arg); return 0; } -static int JACK_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) +static int JACK_RecordDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) { float *buffer = (float *) vbuffer; jack_port_t **ports = device->hidden->sdlports; @@ -230,7 +230,7 @@ static int JACK_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int bu return buflen; } -static void JACK_FlushCapture(SDL_AudioDevice *device) +static void JACK_FlushRecording(SDL_AudioDevice *device) { // do nothing, the data will just be replaced next callback. } @@ -261,31 +261,23 @@ static void JACK_CloseDevice(SDL_AudioDevice *device) } } -// !!! FIXME: unify this (PulseAudio has a getAppName, Pipewire has a thing, etc +// !!! FIXME: unify this (PulseAudio has a getAppName, Pipewire has a thing, etc) static const char *GetJackAppName(void) { - const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); - if (retval && *retval) { - return retval; - } - retval = SDL_GetHint(SDL_HINT_APP_NAME); - if (retval && *retval) { - return retval; - } - return "SDL Application"; + return SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); } -static int JACK_OpenDevice(SDL_AudioDevice *device) +static bool JACK_OpenDevice(SDL_AudioDevice *device) { - /* Note that JACK uses "output" for capture devices (they output audio + /* Note that JACK uses "output" for recording devices (they output audio data to us) and "input" for playback (we input audio data to them). Likewise, SDL's playback port will be "output" (we write data out) - and capture will be "input" (we read data in). */ - SDL_bool iscapture = device->iscapture; - const unsigned long sysportflags = iscapture ? JackPortIsOutput : JackPortIsInput; - const unsigned long sdlportflags = iscapture ? JackPortIsInput : JackPortIsOutput; - const JackProcessCallback callback = iscapture ? jackProcessCaptureCallback : jackProcessPlaybackCallback; - const char *sdlportstr = iscapture ? "input" : "output"; + and recording will be "input" (we read data in). */ + const bool recording = device->recording; + const unsigned long sysportflags = recording ? JackPortIsOutput : JackPortIsInput; + const unsigned long sdlportflags = recording ? JackPortIsInput : JackPortIsOutput; + const JackProcessCallback callback = recording ? jackProcessRecordingCallback : jackProcessPlaybackCallback; + const char *sdlportstr = recording ? "input" : "output"; const char **devports = NULL; int *audio_ports; jack_client_t *client = NULL; @@ -297,7 +289,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } client = JACK_jack_client_open(GetJackAppName(), JackNoStartServer, &status, NULL); @@ -339,11 +331,11 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); - if (!device->iscapture) { + if (!recording) { device->hidden->iobuffer = (float *)SDL_calloc(1, device->buffer_size); if (!device->hidden->iobuffer) { SDL_free(audio_ports); - return -1; + return false; } } @@ -351,7 +343,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) device->hidden->sdlports = (jack_port_t **)SDL_calloc(channels, sizeof(jack_port_t *)); if (!device->hidden->sdlports) { SDL_free(audio_ports); - return -1; + return false; } for (i = 0; i < channels; i++) { @@ -385,8 +377,8 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) // once activated, we can connect all the ports. for (i = 0; i < channels; i++) { const char *sdlport = JACK_jack_port_name(device->hidden->sdlports[i]); - const char *srcport = iscapture ? devports[audio_ports[i]] : sdlport; - const char *dstport = iscapture ? sdlport : devports[audio_ports[i]]; + const char *srcport = recording ? devports[audio_ports[i]] : sdlport; + const char *dstport = recording ? sdlport : devports[audio_ports[i]]; if (JACK_jack_connect(client, srcport, dstport) != 0) { SDL_free(audio_ports); return SDL_SetError("Couldn't connect JACK ports: %s => %s", srcport, dstport); @@ -398,7 +390,7 @@ static int JACK_OpenDevice(SDL_AudioDevice *device) SDL_free(audio_ports); // We're ready to rock and roll. :-) - return 0; + return true; } static void JACK_Deinitialize(void) @@ -406,18 +398,17 @@ static void JACK_Deinitialize(void) UnloadJackLibrary(); } -static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) +static bool JACK_Init(SDL_AudioDriverImpl *impl) { - if (LoadJackLibrary() < 0) { - return SDL_FALSE; + if (!LoadJackLibrary()) { + return false; } else { // Make sure a JACK server is running and available. jack_status_t status; jack_client_t *client = JACK_jack_client_open("SDL", JackNoStartServer, &status, NULL); if (!client) { UnloadJackLibrary(); - SDL_SetError("Can't open JACK client"); - return SDL_FALSE; + return SDL_SetError("Can't open JACK client"); } JACK_jack_client_close(client); } @@ -427,18 +418,18 @@ static SDL_bool JACK_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = JACK_PlayDevice; impl->CloseDevice = JACK_CloseDevice; impl->Deinitialize = JACK_Deinitialize; - impl->CaptureFromDevice = JACK_CaptureFromDevice; - impl->FlushCapture = JACK_FlushCapture; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; - impl->HasCaptureSupport = SDL_TRUE; - impl->ProvidesOwnCallbackThread = SDL_TRUE; - - return SDL_TRUE; + impl->RecordDevice = JACK_RecordDevice; + impl->FlushRecording = JACK_FlushRecording; + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; + impl->HasRecordingSupport = true; + impl->ProvidesOwnCallbackThread = true; + + return true; } AudioBootStrap JACK_bootstrap = { - "jack", "JACK Audio Connection Kit", JACK_Init, SDL_FALSE + "jack", "JACK Audio Connection Kit", JACK_Init, false }; #endif // SDL_AUDIO_DRIVER_JACK diff --git a/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.c b/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.c index 35f9a3196..900969ea4 100644 --- a/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.c +++ b/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.c @@ -47,7 +47,7 @@ static void N3DSAUD_DspHook(DSP_HookType hook) { if (hook == DSPHOOK_ONCANCEL) { contextLock(audio_device); - audio_device->hidden->isCancelled = SDL_TRUE; + audio_device->hidden->isCancelled = true; SDL_AudioDeviceDisconnected(audio_device); CondVar_Broadcast(&audio_device->hidden->cv); contextUnlock(audio_device); @@ -65,7 +65,7 @@ static void AudioFrameFinished(void *vdevice) for (i = 0; i < NUM_BUFFERS; i++) { if (device->hidden->waveBuf[i].status == NDSP_WBUF_DONE) { device->hidden->waveBuf[i].status = NDSP_WBUF_FREE; - shouldBroadcast = SDL_TRUE; + shouldBroadcast = true; } } @@ -76,7 +76,7 @@ static void AudioFrameFinished(void *vdevice) contextUnlock(device); } -static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) { Result ndsp_init_res; Uint8 *data_vaddr; @@ -84,18 +84,17 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Initialise the DSP service ndsp_init_res = ndspInit(); if (R_FAILED(ndsp_init_res)) { if ((R_SUMMARY(ndsp_init_res) == RS_NOTFOUND) && (R_MODULE(ndsp_init_res) == RM_DSP)) { - SDL_SetError("DSP init failed: dspfirm.cdc missing!"); + return SDL_SetError("DSP init failed: dspfirm.cdc missing!"); } else { - SDL_SetError("DSP init failed. Error code: 0x%lX", ndsp_init_res); + return SDL_SetError("DSP init failed. Error code: 0x%lX", ndsp_init_res); } - return -1; } // Initialise internal state @@ -135,7 +134,7 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); @@ -174,10 +173,10 @@ static int N3DSAUDIO_OpenDevice(SDL_AudioDevice *device) ndspSetCallback(AudioFrameFinished, device); dspHook(&dsp_hook, N3DSAUD_DspHook); - return 0; + return true; } -static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { contextLock(device); @@ -186,7 +185,7 @@ static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in if (device->hidden->isCancelled || device->hidden->waveBuf[nextbuf].status != NDSP_WBUF_FREE) { contextUnlock(device); - return 0; // !!! FIXME: is this a fatal error? If so, this should return -1. + return true; // !!! FIXME: is this a fatal error? If so, this should return false. } device->hidden->nextbuf = (nextbuf + 1) % NUM_BUFFERS; @@ -198,18 +197,18 @@ static int N3DSAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, in ndspChnWaveBufAdd(0, &device->hidden->waveBuf[nextbuf]); - return 0; + return true; } -static int N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool N3DSAUDIO_WaitDevice(SDL_AudioDevice *device) { contextLock(device); - while (!device->hidden->isCancelled && !SDL_AtomicGet(&device->shutdown) && + while (!device->hidden->isCancelled && !SDL_GetAtomicInt(&device->shutdown) && device->hidden->waveBuf[device->hidden->nextbuf].status != NDSP_WBUF_FREE) { CondVar_Wait(&device->hidden->cv, &device->hidden->lock); } contextUnlock(device); - return 0; + return true; } static Uint8 *N3DSAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -261,7 +260,7 @@ static void N3DSAUDIO_ThreadInit(SDL_AudioDevice *device) svcSetThreadPriority(CUR_THREAD_HANDLE, current_priority); } -static SDL_bool N3DSAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool N3DSAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = N3DSAUDIO_OpenDevice; impl->PlayDevice = N3DSAUDIO_PlayDevice; @@ -269,12 +268,12 @@ static SDL_bool N3DSAUDIO_Init(SDL_AudioDriverImpl *impl) impl->GetDeviceBuf = N3DSAUDIO_GetDeviceBuf; impl->CloseDevice = N3DSAUDIO_CloseDevice; impl->ThreadInit = N3DSAUDIO_ThreadInit; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; + impl->OnlyHasDefaultPlaybackDevice = true; // Should be possible, but micInit would fail - impl->HasCaptureSupport = SDL_FALSE; + impl->HasRecordingSupport = false; - return SDL_TRUE; + return true; } AudioBootStrap N3DSAUDIO_bootstrap = { diff --git a/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.h b/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.h index 932944d37..115ccc932 100644 --- a/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.h +++ b/libs/SDL3/src/audio/n3ds/SDL_n3dsaudio.h @@ -34,7 +34,7 @@ struct SDL_PrivateAudioData ndspWaveBuf waveBuf[NUM_BUFFERS]; LightLock lock; CondVar cv; - SDL_bool isCancelled; + bool isCancelled; }; #endif // SDL_n3dsaudio_h diff --git a/libs/SDL3/src/audio/netbsd/SDL_netbsdaudio.c b/libs/SDL3/src/audio/netbsd/SDL_netbsdaudio.c index f0de69482..7e105007b 100644 --- a/libs/SDL3/src/audio/netbsd/SDL_netbsdaudio.c +++ b/libs/SDL3/src/audio/netbsd/SDL_netbsdaudio.c @@ -39,15 +39,15 @@ //#define DEBUG_AUDIO -static void NETBSDAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void NETBSDAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - SDL_EnumUnixAudioDevices(SDL_FALSE, NULL); + SDL_EnumUnixAudioDevices(false, NULL); } static void NETBSDAUDIO_Status(SDL_AudioDevice *device) { #ifdef DEBUG_AUDIO - /* *INDENT-OFF* */ /* clang-format off */ + /* *INDENT-OFF* */ // clang-format off audio_info_t info; const struct audio_prinfo *prinfo; @@ -56,7 +56,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device) return; } - prinfo = device->iscapture ? &info.record : &info.play; + prinfo = device->recording ? &info.record : &info.play; fprintf(stderr, "\n" "[%s info]\n" @@ -73,7 +73,7 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device) "waiting : %s\n" "active : %s\n" "", - device->iscapture ? "record" : "play", + device->recording ? "record" : "play", prinfo->buffer_size, prinfo->sample_rate, prinfo->channels, @@ -109,15 +109,15 @@ static void NETBSDAUDIO_Status(SDL_AudioDevice *device) "", device->spec.format, device->buffer_size); - /* *INDENT-ON* */ /* clang-format on */ + /* *INDENT-ON* */ // clang-format on #endif // DEBUG_AUDIO } -static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; - while (!SDL_AtomicGet(&device->shutdown)) { + const bool recording = device->recording; + while (!SDL_GetAtomicInt(&device->shutdown)) { audio_info_t info; const int rc = ioctl(device->hidden->audio_fd, AUDIO_GETINFO, &info); if (rc < 0) { @@ -126,33 +126,33 @@ static int NETBSDAUDIO_WaitDevice(SDL_AudioDevice *device) } // Hmm, not much we can do - abort fprintf(stderr, "netbsdaudio WaitDevice ioctl failed (unrecoverable): %s\n", strerror(errno)); - return -1; + return false; } - const size_t remain = (size_t)((iscapture ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format)); - if (!iscapture && (remain >= device->buffer_size)) { + const size_t remain = (size_t)((recording ? info.record.seek : info.play.seek) * SDL_AUDIO_BYTESIZE(device->spec.format)); + if (!recording && (remain >= device->buffer_size)) { SDL_Delay(10); - } else if (iscapture && (remain < device->buffer_size)) { + } else if (recording && (remain < device->buffer_size)) { SDL_Delay(10); } else { break; // ready to go! } } - return 0; + return true; } -static int NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool NETBSDAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { struct SDL_PrivateAudioData *h = device->hidden; const int written = write(h->audio_fd, buffer, buflen); if (written != buflen) { // Treat even partial writes as fatal errors. - return -1; + return false; } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); #endif - return 0; + return true; } static Uint8 *NETBSDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -160,7 +160,7 @@ static Uint8 *NETBSDAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size return device->hidden->mixbuf; } -static int NETBSDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) +static int NETBSDAUDIO_RecordDevice(SDL_AudioDevice *device, void *vbuffer, int buflen) { Uint8 *buffer = (Uint8 *)vbuffer; const int br = read(device->hidden->audio_fd, buffer, buflen); @@ -171,12 +171,12 @@ static int NETBSDAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *vbuffer, } #ifdef DEBUG_AUDIO - fprintf(stderr, "Captured %d bytes of audio data\n", br); + fprintf(stderr, "Recorded %d bytes of audio data\n", br); #endif return br; } -static void NETBSDAUDIO_FlushCapture(SDL_AudioDevice *device) +static void NETBSDAUDIO_FlushRecording(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; audio_info_t info; @@ -206,21 +206,21 @@ static void NETBSDAUDIO_CloseDevice(SDL_AudioDevice *device) } } -static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; int encoding = AUDIO_ENCODING_NONE; audio_info_t info, hwinfo; - struct audio_prinfo *prinfo = iscapture ? &info.record : &info.play; + struct audio_prinfo *prinfo = recording ? &info.record : &info.play; // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Open the audio device; we hardcode the device path in `device->name` for lack of better info, so use that. - const int flags = ((device->iscapture) ? O_RDONLY : O_WRONLY); + const int flags = ((device->recording) ? O_RDONLY : O_WRONLY); device->hidden->audio_fd = open(device->name, flags | O_CLOEXEC); if (device->hidden->audio_fd < 0) { return SDL_SetError("Couldn't open %s: %s", device->name, strerror(errno)); @@ -231,7 +231,7 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) #ifdef AUDIO_GETFORMAT // Introduced in NetBSD 9.0 if (ioctl(device->hidden->audio_fd, AUDIO_GETFORMAT, &hwinfo) != -1) { // Use the device's native sample rate so the kernel doesn't have to resample. - device->spec.freq = iscapture ? hwinfo.record.sample_rate : hwinfo.play.sample_rate; + device->spec.freq = recording ? hwinfo.record.sample_rate : hwinfo.play.sample_rate; } #endif @@ -289,22 +289,22 @@ static int NETBSDAUDIO_OpenDevice(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); - if (!iscapture) { + if (!recording) { // Allocate mixing buffer device->hidden->mixlen = device->buffer_size; device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->hidden->mixlen); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); } NETBSDAUDIO_Status(device); - return 0; // We're ready to rock and roll. :-) + return true; // We're ready to rock and roll. :-) } -static SDL_bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->DetectDevices = NETBSDAUDIO_DetectDevices; impl->OpenDevice = NETBSDAUDIO_OpenDevice; @@ -312,17 +312,17 @@ static SDL_bool NETBSDAUDIO_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = NETBSDAUDIO_PlayDevice; impl->GetDeviceBuf = NETBSDAUDIO_GetDeviceBuf; impl->CloseDevice = NETBSDAUDIO_CloseDevice; - impl->WaitCaptureDevice = NETBSDAUDIO_WaitDevice; - impl->CaptureFromDevice = NETBSDAUDIO_CaptureFromDevice; - impl->FlushCapture = NETBSDAUDIO_FlushCapture; + impl->WaitRecordingDevice = NETBSDAUDIO_WaitDevice; + impl->RecordDevice = NETBSDAUDIO_RecordDevice; + impl->FlushRecording = NETBSDAUDIO_FlushRecording; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap NETBSDAUDIO_bootstrap = { - "netbsd", "NetBSD audio", NETBSDAUDIO_Init, SDL_FALSE + "netbsd", "NetBSD audio", NETBSDAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_NETBSD diff --git a/libs/SDL3/src/audio/openslES/SDL_openslES.c b/libs/SDL3/src/audio/openslES/SDL_openslES.c index bda1b91c9..2ab0de0e0 100644 --- a/libs/SDL3/src/audio/openslES/SDL_openslES.c +++ b/libs/SDL3/src/audio/openslES/SDL_openslES.c @@ -107,10 +107,10 @@ static const char *sldevaudioplayerstr = "SLES Audio Player"; #define SLES_DEV_AUDIO_RECORDER sldevaudiorecorderstr #define SLES_DEV_AUDIO_PLAYER sldevaudioplayerstr -static void OPENSLES_DetectDevices( int iscapture ) +static void OPENSLES_DetectDevices( int recording ) { LOGI( "openSLES_DetectDevices()" ); - if ( iscapture ) + if ( recording ) addfn( SLES_DEV_AUDIO_RECORDER ); else addfn( SLES_DEV_AUDIO_PLAYER ); @@ -135,7 +135,7 @@ static void OPENSLES_DestroyEngine(void) } } -static int OPENSLES_CreateEngine(void) +static bool OPENSLES_CreateEngine(void) { const SLInterfaceID ids[1] = { SL_IID_VOLUME }; const SLboolean req[1] = { SL_BOOLEAN_FALSE }; @@ -181,11 +181,11 @@ static int OPENSLES_CreateEngine(void) LOGE("RealizeOutputMix failed: %d", result); goto error; } - return 1; + return true; error: OPENSLES_DestroyEngine(); - return 0; + return false; } // this callback handler is called every time a buffer finishes recording @@ -194,7 +194,7 @@ static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context) struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *)context; LOGV("SLES: Recording Callback"); - SDL_PostSemaphore(audiodata->playsem); + SDL_SignalSemaphore(audiodata->playsem); } static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device) @@ -229,12 +229,12 @@ static void OPENSLES_DestroyPCMRecorder(SDL_AudioDevice *device) } // !!! FIXME: make this non-blocking! -static void SDLCALL AndroidRequestPermissionBlockingCallback(void *userdata, const char *permission, SDL_bool granted) +static void SDLCALL RequestAndroidPermissionBlockingCallback(void *userdata, const char *permission, bool granted) { - SDL_AtomicSet((SDL_AtomicInt *) userdata, granted ? 1 : -1); + SDL_SetAtomicInt((SDL_AtomicInt *) userdata, granted ? 1 : -1); } -static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) +static bool OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; SLDataFormat_PCM format_pcm; @@ -250,16 +250,16 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) // !!! FIXME: make this non-blocking! { SDL_AtomicInt permission_response; - SDL_AtomicSet(&permission_response, 0); - if (SDL_AndroidRequestPermission("android.permission.RECORD_AUDIO", AndroidRequestPermissionBlockingCallback, &permission_response) == -1) { - return -1; + SDL_SetAtomicInt(&permission_response, 0); + if (!SDL_RequestAndroidPermission("android.permission.RECORD_AUDIO", RequestAndroidPermissionBlockingCallback, &permission_response)) { + return false; } - while (SDL_AtomicGet(&permission_response) == 0) { + while (SDL_GetAtomicInt(&permission_response) == 0) { SDL_Delay(10); } - if (SDL_AtomicGet(&permission_response) < 0) { + if (SDL_GetAtomicInt(&permission_response) < 0) { LOGE("This app doesn't have RECORD_AUDIO permission"); return SDL_SetError("This app doesn't have RECORD_AUDIO permission"); } @@ -273,7 +273,7 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) // Update the fragment size as size in bytes SDL_UpdatedAudioDeviceFormat(device); - LOGI("Try to open %u hz %u bit chan %u %s samples %u", + LOGI("Try to open %u hz %u bit %u channels %s samples %u", device->spec.freq, SDL_AUDIO_BITSIZE(device->spec.format), device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); @@ -378,7 +378,7 @@ static int OPENSLES_CreatePCMRecorder(SDL_AudioDevice *device) goto failed; } - return 0; + return true; failed: return SDL_SetError("Open device failed!"); @@ -390,7 +390,7 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *)context; LOGV("SLES: Playback Callback"); - SDL_PostSemaphore(audiodata->playsem); + SDL_SignalSemaphore(audiodata->playsem); } static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device) @@ -424,7 +424,7 @@ static void OPENSLES_DestroyPCMPlayer(SDL_AudioDevice *device) } } -static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) +static bool OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) { /* If we want to add floating point audio support (requires API level 21) it can be done as described here: @@ -453,7 +453,7 @@ static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) // Update the fragment size as size in bytes SDL_UpdatedAudioDeviceFormat(device); - LOGI("Try to open %u hz %s %u bit chan %u %s samples %u", + LOGI("Try to open %u hz %s %u bit %u channels %s samples %u", device->spec.freq, SDL_AUDIO_ISFLOAT(device->spec.format) ? "float" : "pcm", SDL_AUDIO_BITSIZE(device->spec.format), device->spec.channels, (device->spec.format & 0x1000) ? "BE" : "LE", device->sample_frames); @@ -609,27 +609,27 @@ static int OPENSLES_CreatePCMPlayer(SDL_AudioDevice *device) goto failed; } - return 0; + return true; failed: - return -1; + return false; } -static int OPENSLES_OpenDevice(SDL_AudioDevice *device) +static bool OPENSLES_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } - if (device->iscapture) { - LOGI("OPENSLES_OpenDevice() for capture"); + if (device->recording) { + LOGI("OPENSLES_OpenDevice() for recording"); return OPENSLES_CreatePCMRecorder(device); } else { - int ret; - LOGI("OPENSLES_OpenDevice() for playing"); + bool ret; + LOGI("OPENSLES_OpenDevice() for playback"); ret = OPENSLES_CreatePCMPlayer(device); - if (ret < 0) { + if (!ret) { // Another attempt to open the device with a lower frequency if (device->spec.freq > 48000) { OPENSLES_DestroyPCMPlayer(device); @@ -638,25 +638,31 @@ static int OPENSLES_OpenDevice(SDL_AudioDevice *device) } } - if (ret != 0) { + if (!ret) { return SDL_SetError("Open device failed!"); } } - return 0; + return true; } -static int OPENSLES_WaitDevice(SDL_AudioDevice *device) +static bool OPENSLES_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *audiodata = device->hidden; LOGV("OPENSLES_WaitDevice()"); - // Wait for an audio chunk to finish - return SDL_WaitSemaphore(audiodata->playsem); + while (!SDL_GetAtomicInt(&device->shutdown)) { + // this semaphore won't fire when the app is in the background (OPENSLES_PauseDevices was called). + if (SDL_WaitSemaphoreTimeout(audiodata->playsem, 100)) { + return true; // semaphore was signaled, let's go! + } + // Still waiting on the semaphore (or the system), check other things then wait again. + } + return true; } -static int OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { struct SDL_PrivateAudioData *audiodata = device->hidden; @@ -673,10 +679,10 @@ static int OPENSLES_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int // If Enqueue fails, callback won't be called. // Post the semaphore, not to run out of buffer if (SL_RESULT_SUCCESS != result) { - SDL_PostSemaphore(audiodata->playsem); + SDL_SignalSemaphore(audiodata->playsem); } - return 0; + return true; } /// n playn sem @@ -699,7 +705,7 @@ static Uint8 *OPENSLES_GetDeviceBuf(SDL_AudioDevice *device, int *bufsize) return audiodata->pmixbuff[audiodata->next_buffer]; } -static int OPENSLES_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int OPENSLES_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *audiodata = device->hidden; @@ -726,8 +732,8 @@ static void OPENSLES_CloseDevice(SDL_AudioDevice *device) { // struct SDL_PrivateAudioData *audiodata = device->hidden; if (device->hidden) { - if (device->iscapture) { - LOGI("OPENSLES_CloseDevice() for capture"); + if (device->recording) { + LOGI("OPENSLES_CloseDevice() for recording"); OPENSLES_DestroyPCMRecorder(device); } else { LOGI("OPENSLES_CloseDevice() for playing"); @@ -739,12 +745,12 @@ static void OPENSLES_CloseDevice(SDL_AudioDevice *device) } } -static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl) +static bool OPENSLES_Init(SDL_AudioDriverImpl *impl) { LOGI("OPENSLES_Init() called"); if (!OPENSLES_CreateEngine()) { - return SDL_FALSE; + return false; } LOGI("OPENSLES_Init() - set pointers"); @@ -756,24 +762,24 @@ static SDL_bool OPENSLES_Init(SDL_AudioDriverImpl *impl) impl->WaitDevice = OPENSLES_WaitDevice; impl->PlayDevice = OPENSLES_PlayDevice; impl->GetDeviceBuf = OPENSLES_GetDeviceBuf; - impl->WaitCaptureDevice = OPENSLES_WaitDevice; - impl->CaptureFromDevice = OPENSLES_CaptureFromDevice; + impl->WaitRecordingDevice = OPENSLES_WaitDevice; + impl->RecordDevice = OPENSLES_RecordDevice; impl->CloseDevice = OPENSLES_CloseDevice; impl->Deinitialize = OPENSLES_DestroyEngine; // and the capabilities - impl->HasCaptureSupport = SDL_TRUE; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; + impl->HasRecordingSupport = true; + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; LOGI("OPENSLES_Init() - success"); // this audio target is available. - return SDL_TRUE; + return true; } AudioBootStrap OPENSLES_bootstrap = { - "openslES", "OpenSL ES audio driver", OPENSLES_Init, SDL_FALSE + "openslES", "OpenSL ES audio driver", OPENSLES_Init, false }; void OPENSLES_ResumeDevices(void) diff --git a/libs/SDL3/src/audio/openslES/SDL_openslES.h b/libs/SDL3/src/audio/openslES/SDL_openslES.h index 9d65a7dab..9148c7909 100644 --- a/libs/SDL3/src/audio/openslES/SDL_openslES.h +++ b/libs/SDL3/src/audio/openslES/SDL_openslES.h @@ -25,13 +25,13 @@ #ifdef SDL_AUDIO_DRIVER_OPENSLES -void OPENSLES_ResumeDevices(void); -void OPENSLES_PauseDevices(void); +extern void OPENSLES_ResumeDevices(void); +extern void OPENSLES_PauseDevices(void); #else -static void OPENSLES_ResumeDevices(void) {} -static void OPENSLES_PauseDevices(void) {} +#define OPENSLES_ResumeDevices() +#define OPENSLES_PauseDevices() #endif diff --git a/libs/SDL3/src/audio/pipewire/SDL_pipewire.c b/libs/SDL3/src/audio/pipewire/SDL_pipewire.c index 9941f17d1..d803c8d73 100644 --- a/libs/SDL3/src/audio/pipewire/SDL_pipewire.c +++ b/libs/SDL3/src/audio/pipewire/SDL_pipewire.c @@ -29,36 +29,6 @@ #include #include -/* - * The following keys are defined for compatibility when building against older versions of Pipewire - * prior to their introduction and can be removed if the minimum required Pipewire build version is - * increased to or beyond their point of introduction. - */ - -/* - * Introduced in 0.3.22 - * Taken from /src/pipewire/keys.h - */ -#ifndef PW_KEY_CONFIG_NAME -#define PW_KEY_CONFIG_NAME "config.name" -#endif - -/* - * Introduced in 0.3.33 - * Taken from src/pipewire/keys.h - */ -#ifndef PW_KEY_NODE_RATE -#define PW_KEY_NODE_RATE "node.rate" -#endif - -/* - * Introduced in 0.3.44 - * Taken from src/pipewire/keys.h - */ -#ifndef PW_KEY_TARGET_OBJECT -#define PW_KEY_TARGET_OBJECT "target.object" -#endif - /* * This seems to be a sane lower limit as Pipewire * uses it in several of it's own modules. @@ -80,12 +50,17 @@ enum PW_READY_FLAGS #define PW_ID_TO_HANDLE(x) (void *)((uintptr_t)x) #define PW_HANDLE_TO_ID(x) (uint32_t)((uintptr_t)x) -static SDL_bool pipewire_initialized = SDL_FALSE; +static bool pipewire_initialized = false; // Pipewire entry points static const char *(*PIPEWIRE_pw_get_library_version)(void); static void (*PIPEWIRE_pw_init)(int *, char ***); static void (*PIPEWIRE_pw_deinit)(void); +static struct pw_main_loop *(*PIPEWIRE_pw_main_loop_new)(const struct spa_dict *loop); +static struct pw_loop *(*PIPEWIRE_pw_main_loop_get_loop)(struct pw_main_loop *loop); +static int (*PIPEWIRE_pw_main_loop_run)(struct pw_main_loop *loop); +static int (*PIPEWIRE_pw_main_loop_quit)(struct pw_main_loop *loop); +static void(*PIPEWIRE_pw_main_loop_destroy)(struct pw_main_loop *loop); static struct pw_thread_loop *(*PIPEWIRE_pw_thread_loop_new)(const char *, const struct spa_dict *); static void (*PIPEWIRE_pw_thread_loop_destroy)(struct pw_thread_loop *); static void (*PIPEWIRE_pw_thread_loop_stop)(struct pw_thread_loop *); @@ -114,35 +89,30 @@ static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *); static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4); -static int pipewire_version_major; -static int pipewire_version_minor; -static int pipewire_version_patch; - #ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC; -static void *pipewire_handle = NULL; +static SDL_SharedObject *pipewire_handle = NULL; -static int pipewire_dlsym(const char *fn, void **addr) +static bool pipewire_dlsym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pipewire_handle, fn); if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. - return 0; + return false; } - return 1; + return true; } #define SDL_PIPEWIRE_SYM(x) \ - if (!pipewire_dlsym(#x, (void **)(char *)&PIPEWIRE_##x)) { \ - return -1; \ - } + if (!pipewire_dlsym(#x, (void **)(char *)&PIPEWIRE_##x)) \ + return false -static int load_pipewire_library(void) +static bool load_pipewire_library(void) { pipewire_handle = SDL_LoadObject(pipewire_library); - return pipewire_handle ? 0 : -1; + return pipewire_handle ? true : false; } static void unload_pipewire_library(void) @@ -157,9 +127,9 @@ static void unload_pipewire_library(void) #define SDL_PIPEWIRE_SYM(x) PIPEWIRE_##x = x -static int load_pipewire_library(void) +static bool load_pipewire_library(void) { - return 0; + return true; } static void unload_pipewire_library(void) @@ -169,11 +139,16 @@ static void unload_pipewire_library(void) #endif // SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC -static int load_pipewire_syms(void) +static bool load_pipewire_syms(void) { SDL_PIPEWIRE_SYM(pw_get_library_version); SDL_PIPEWIRE_SYM(pw_init); SDL_PIPEWIRE_SYM(pw_deinit); + SDL_PIPEWIRE_SYM(pw_main_loop_new); + SDL_PIPEWIRE_SYM(pw_main_loop_get_loop); + SDL_PIPEWIRE_SYM(pw_main_loop_run); + SDL_PIPEWIRE_SYM(pw_main_loop_quit); + SDL_PIPEWIRE_SYM(pw_main_loop_destroy); SDL_PIPEWIRE_SYM(pw_thread_loop_new); SDL_PIPEWIRE_SYM(pw_thread_loop_destroy); SDL_PIPEWIRE_SYM(pw_thread_loop_stop); @@ -200,36 +175,19 @@ static int load_pipewire_syms(void) SDL_PIPEWIRE_SYM(pw_properties_set); SDL_PIPEWIRE_SYM(pw_properties_setf); - return 0; -} - -static SDL_bool pipewire_version_at_least(int major, int minor, int patch) -{ - return (pipewire_version_major >= major) && - (pipewire_version_major > major || pipewire_version_minor >= minor) && - (pipewire_version_major > major || pipewire_version_minor > minor || pipewire_version_patch >= patch); + return true; } -static int init_pipewire_library(void) +static bool init_pipewire_library(void) { - if (!load_pipewire_library()) { - if (!load_pipewire_syms()) { - int nargs; - const char *version = PIPEWIRE_pw_get_library_version(); - nargs = SDL_sscanf(version, "%d.%d.%d", &pipewire_version_major, &pipewire_version_minor, &pipewire_version_patch); - if (nargs < 3) { - return -1; - } - - // SDL can build against 0.3.20, but requires 0.3.24 - if (pipewire_version_at_least(0, 3, 24)) { - PIPEWIRE_pw_init(NULL, NULL); - return 0; - } + if (load_pipewire_library()) { + if (load_pipewire_syms()) { + PIPEWIRE_pw_init(NULL, NULL); + return true; } } - return -1; + return false; } static void deinit_pipewire_library(void) @@ -245,7 +203,7 @@ struct node_object Uint32 id; int seq; - SDL_bool persist; + bool persist; /* * NOTE: If used, this is *must* be allocated with SDL_malloc() or similar @@ -267,7 +225,7 @@ struct io_node struct spa_list link; Uint32 id; - SDL_bool is_capture; + bool recording; SDL_AudioSpec spec; const char *name; // Friendly name @@ -286,22 +244,32 @@ static struct spa_hook hotplug_core_listener; static struct spa_list hotplug_pending_list; static struct spa_list hotplug_io_list; static int hotplug_init_seq_val; -static SDL_bool hotplug_init_complete; -static SDL_bool hotplug_events_enabled; +static bool hotplug_init_complete; +static bool hotplug_events_enabled; +static int pipewire_version_major; +static int pipewire_version_minor; +static int pipewire_version_patch; static char *pipewire_default_sink_id = NULL; static char *pipewire_default_source_id = NULL; +static bool pipewire_core_version_at_least(int major, int minor, int patch) +{ + return (pipewire_version_major >= major) && + (pipewire_version_major > major || pipewire_version_minor >= minor) && + (pipewire_version_major > major || pipewire_version_minor > minor || pipewire_version_patch >= patch); +} + // The active node list -static SDL_bool io_list_check_add(struct io_node *node) +static bool io_list_check_add(struct io_node *node) { struct io_node *n; - SDL_bool ret = SDL_TRUE; + bool ret = true; // See if the node is already in the list spa_list_for_each (n, &hotplug_io_list, link) { if (n->id == node->id) { - ret = SDL_FALSE; + ret = false; goto dup_found; } } @@ -310,7 +278,7 @@ static SDL_bool io_list_check_add(struct io_node *node) spa_list_append(&hotplug_io_list, &node->link); if (hotplug_events_enabled) { - SDL_AddAudioDevice(node->is_capture, node->name, &node->spec, PW_ID_TO_HANDLE(node->id)); + SDL_AddAudioDevice(node->recording, node->name, &node->spec, PW_ID_TO_HANDLE(node->id)); } dup_found: @@ -433,11 +401,20 @@ static void core_events_hotplug_init_callback(void *object, uint32_t id, int seq spa_hook_remove(&hotplug_core_listener); // Signal that the initial I/O list is populated - hotplug_init_complete = SDL_TRUE; + hotplug_init_complete = true; PIPEWIRE_pw_thread_loop_signal(hotplug_loop, false); } } +static void core_events_hotplug_info_callback(void *data, const struct pw_core_info *info) +{ + if (SDL_sscanf(info->version, "%d.%d.%d", &pipewire_version_major, &pipewire_version_minor, &pipewire_version_patch) < 3) { + pipewire_version_major = 0; + pipewire_version_minor = 0; + pipewire_version_patch = 0; + } +} + static void core_events_interface_callback(void *object, uint32_t id, int seq) { struct node_object *node = object; @@ -465,7 +442,7 @@ static void core_events_metadata_callback(void *object, uint32_t id, int seq) } } -static const struct pw_core_events hotplug_init_core_events = { PW_VERSION_CORE_EVENTS, .done = core_events_hotplug_init_callback }; +static const struct pw_core_events hotplug_init_core_events = { PW_VERSION_CORE_EVENTS, .info = core_events_hotplug_info_callback, .done = core_events_hotplug_init_callback }; static const struct pw_core_events interface_core_events = { PW_VERSION_CORE_EVENTS, .done = core_events_interface_callback }; static const struct pw_core_events metadata_core_events = { PW_VERSION_CORE_EVENTS, .done = core_events_metadata_callback }; @@ -485,7 +462,7 @@ static void hotplug_core_sync(struct node_object *node) } // Helpers for retrieving values from params -static SDL_bool get_range_param(const struct spa_pod *param, Uint32 key, int *def, int *min, int *max) +static bool get_range_param(const struct spa_pod *param, Uint32 key, int *def, int *min, int *max) { const struct spa_pod_prop *prop; struct spa_pod *value; @@ -510,15 +487,15 @@ static SDL_bool get_range_param(const struct spa_pod *param, Uint32 key, int *de *max = (int)v[2]; } - return SDL_TRUE; + return true; } } } - return SDL_FALSE; + return false; } -static SDL_bool get_int_param(const struct spa_pod *param, Uint32 key, int *val) +static bool get_int_param(const struct spa_pod *param, Uint32 key, int *val) { const struct spa_pod_prop *prop; Sint32 v; @@ -530,10 +507,10 @@ static SDL_bool get_int_param(const struct spa_pod *param, Uint32 key, int *val) *val = (int)v; } - return SDL_TRUE; + return true; } - return SDL_FALSE; + return false; } // Interface node callbacks @@ -629,14 +606,14 @@ static int metadata_property(void *object, Uint32 subject, const char *key, cons SDL_free(pipewire_default_sink_id); } pipewire_default_sink_id = get_name_from_json(value); - node->persist = SDL_TRUE; + node->persist = true; change_default_device(pipewire_default_sink_id); } else if (!SDL_strcmp(key, "default.audio.source")) { if (pipewire_default_source_id) { SDL_free(pipewire_default_source_id); } pipewire_default_source_id = get_name_from_json(value); - node->persist = SDL_TRUE; + node->persist = true; change_default_device(pipewire_default_source_id); } } @@ -660,15 +637,15 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p const char *node_desc; const char *node_path; struct io_node *io; - SDL_bool is_capture; + bool recording; int desc_buffer_len; int path_buffer_len; - // Just want sink and capture + // Just want sink and source if (!SDL_strcasecmp(media_class, "Audio/Sink")) { - is_capture = SDL_FALSE; + recording = false; } else if (!SDL_strcasecmp(media_class, "Audio/Source")) { - is_capture = SDL_TRUE; + recording = true; } else { return; } @@ -694,7 +671,7 @@ static void registry_event_global_callback(void *object, uint32_t id, uint32_t p // Begin setting the node properties io->id = id; - io->is_capture = is_capture; + io->recording = recording; io->spec.format = SDL_AUDIO_F32; // Pipewire uses floats internally, other formats require conversion. io->name = io->buf; io->path = io->buf + desc_buffer_len; @@ -727,14 +704,14 @@ static const struct pw_registry_events registry_events = { PW_VERSION_REGISTRY_E .global_remove = registry_event_remove_callback }; // The hotplug thread -static int hotplug_loop_init(void) +static bool hotplug_loop_init(void) { int res; spa_list_init(&hotplug_pending_list); spa_list_init(&hotplug_io_list); - hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLAudioHotplug", NULL); + hotplug_loop = PIPEWIRE_pw_thread_loop_new("SDLPwAudioPlug", NULL); if (!hotplug_loop) { return SDL_SetError("Pipewire: Failed to create hotplug detection loop (%i)", errno); } @@ -767,7 +744,7 @@ static int hotplug_loop_init(void) return SDL_SetError("Pipewire: Failed to start hotplug detection loop"); } - return 0; + return true; } static void hotplug_loop_destroy(void) @@ -779,8 +756,8 @@ static void hotplug_loop_destroy(void) pending_list_clear(); io_list_clear(); - hotplug_init_complete = SDL_FALSE; - hotplug_events_enabled = SDL_FALSE; + hotplug_init_complete = false; + hotplug_events_enabled = false; if (pipewire_default_sink_id) { SDL_free(pipewire_default_sink_id); @@ -812,7 +789,7 @@ static void hotplug_loop_destroy(void) } } -static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { struct io_node *io; @@ -824,19 +801,19 @@ static void PIPEWIRE_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDe } spa_list_for_each (io, &hotplug_io_list, link) { - SDL_AudioDevice *device = SDL_AddAudioDevice(io->is_capture, io->name, &io->spec, PW_ID_TO_HANDLE(io->id)); + SDL_AudioDevice *device = SDL_AddAudioDevice(io->recording, io->name, &io->spec, PW_ID_TO_HANDLE(io->id)); if (pipewire_default_sink_id && SDL_strcmp(io->path, pipewire_default_sink_id) == 0) { - if (!io->is_capture) { - *default_output = device; + if (!io->recording) { + *default_playback = device; } } else if (pipewire_default_source_id && SDL_strcmp(io->path, pipewire_default_source_id) == 0) { - if (io->is_capture) { - *default_capture = device; + if (io->recording) { + *default_recording = device; } } } - hotplug_events_enabled = SDL_TRUE; + hotplug_events_enabled = true; PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); } @@ -918,12 +895,15 @@ static void initialize_spa_info(const SDL_AudioSpec *spec, struct spa_audio_info case SDL_AUDIO_F32BE: info->format = SPA_AUDIO_FORMAT_F32_BE; break; + default: + info->format = SPA_AUDIO_FORMAT_UNKNOWN; + break; } } static Uint8 *PIPEWIRE_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { - // See if a buffer is available. If this returns NULL, SDL_OutputAudioThreadIterate will return SDL_FALSE, but since we own the thread, it won't kill playback. + // See if a buffer is available. If this returns NULL, SDL_PlaybackAudioThreadIterate will return false, but since we own the thread, it won't kill playback. // !!! FIXME: It's not clear to me if this ever returns NULL or if this was just defensive coding. struct pw_stream *stream = device->hidden->stream; @@ -942,7 +922,7 @@ static Uint8 *PIPEWIRE_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return (Uint8 *) spa_buf->datas[0].data; } -static int PIPEWIRE_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool PIPEWIRE_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { struct pw_stream *stream = device->hidden->stream; struct pw_buffer *pw_buf = device->hidden->pw_buf; @@ -954,15 +934,15 @@ static int PIPEWIRE_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int PIPEWIRE_pw_stream_queue_buffer(stream, pw_buf); device->hidden->pw_buf = NULL; - return 0; + return true; } static void output_callback(void *data) { - SDL_OutputAudioThreadIterate((SDL_AudioDevice *)data); + SDL_PlaybackAudioThreadIterate((SDL_AudioDevice *)data); } -static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device) +static void PIPEWIRE_FlushRecording(SDL_AudioDevice *device) { struct pw_stream *stream = device->hidden->stream; struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream); @@ -971,7 +951,7 @@ static void PIPEWIRE_FlushCapture(SDL_AudioDevice *device) } } -static int PIPEWIRE_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int PIPEWIRE_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct pw_stream *stream = device->hidden->stream; struct pw_buffer *pw_buf = PIPEWIRE_pw_stream_dequeue_buffer(stream); @@ -1000,14 +980,14 @@ static int PIPEWIRE_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int static void input_callback(void *data) { - SDL_CaptureAudioThreadIterate((SDL_AudioDevice *)data); + SDL_RecordingAudioThreadIterate((SDL_AudioDevice *)data); } static void stream_add_buffer_callback(void *data, struct pw_buffer *buffer) { SDL_AudioDevice *device = (SDL_AudioDevice *) data; - if (device->iscapture == SDL_FALSE) { + if (device->recording == false) { /* Clamp the output spec samples and size to the max size of the Pipewire buffer. If they exceed the maximum size of the Pipewire buffer, double buffering will be used. */ if (device->buffer_size > buffer->buffer->datas[0].maxsize) { @@ -1044,7 +1024,7 @@ static const struct pw_stream_events stream_input_events = { PW_VERSION_STREAM_E .add_buffer = stream_add_buffer_callback, .process = input_callback }; -static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) +static bool PIPEWIRE_OpenDevice(SDL_AudioDevice *device) { /* * NOTE: The PW_STREAM_FLAG_RT_PROCESS flag can be set to call the stream @@ -1062,25 +1042,24 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) const struct spa_pod *params = NULL; struct SDL_PrivateAudioData *priv; struct pw_properties *props; - const char *app_name, *app_id, *stream_name, *stream_role, *error; + const char *app_name, *icon_name, *app_id, *stream_name, *stream_role, *error; Uint32 node_id = !device->handle ? PW_ID_ANY : PW_HANDLE_TO_ID(device->handle); - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; int res; // Clamp the period size to sane values const int min_period = PW_MIN_SAMPLES * SPA_MAX(device->spec.freq / PW_BASE_CLOCK_RATE, 1); - // Get the hints for the application name, stream name and role - app_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); - if (!app_name || *app_name == '\0') { - app_name = SDL_GetHint(SDL_HINT_APP_NAME); - if (!app_name || *app_name == '\0') { - app_name = "SDL Application"; - } + // Get the hints for the application name, icon name, stream name and role + app_name = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); + + icon_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_ICON_NAME); + if (!icon_name || *icon_name == '\0') { + icon_name = "applications-games"; } // App ID. Default to NULL if not available. - app_id = SDL_GetHint(SDL_HINT_APP_ID); + app_id = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING); stream_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_STREAM_NAME); if (!stream_name || *stream_name == '\0') { @@ -1106,7 +1085,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) priv = SDL_calloc(1, sizeof(struct SDL_PrivateAudioData)); device->hidden = priv; if (!priv) { - return -1; + return false; } // Size of a single audio frame in bytes @@ -1141,9 +1120,10 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) } PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_TYPE, "Audio"); - PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, iscapture ? "Capture" : "Playback"); + PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_CATEGORY, recording ? "Capture" : "Playback"); PIPEWIRE_pw_properties_set(props, PW_KEY_MEDIA_ROLE, stream_role); PIPEWIRE_pw_properties_set(props, PW_KEY_APP_NAME, app_name); + PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ICON_NAME, icon_name); if (app_id) { PIPEWIRE_pw_properties_set(props, PW_KEY_APP_ID, app_id); } @@ -1154,35 +1134,24 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_ALWAYS_PROCESS, "true"); PIPEWIRE_pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); // Requesting a specific device, don't migrate to new default hardware. - /* - * Pipewire 0.3.44 introduced PW_KEY_TARGET_OBJECT that takes either a path - * (PW_KEY_NODE_NAME) or node serial number (PE_KEY_OBJECT_SERIAL) to connect - * the stream to its target. The target_id parameter in pw_stream_connect() is - * now deprecated and should always be PW_ID_ANY. - */ - if (pipewire_version_at_least(0, 3, 44)) { - if (node_id != PW_ID_ANY) { - const struct io_node *node; - - PIPEWIRE_pw_thread_loop_lock(hotplug_loop); - node = io_list_get_by_id(node_id); - if (node) { - PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path); - } - PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); - - node_id = PW_ID_ANY; + if (node_id != PW_ID_ANY) { + PIPEWIRE_pw_thread_loop_lock(hotplug_loop); + const struct io_node *node = io_list_get_by_id(node_id); + if (node) { + PIPEWIRE_pw_properties_set(props, PW_KEY_TARGET_OBJECT, node->path); } + PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); } // Create the new stream priv->stream = PIPEWIRE_pw_stream_new_simple(PIPEWIRE_pw_thread_loop_get_loop(priv->loop), stream_name, props, - iscapture ? &stream_input_events : &stream_output_events, device); + recording ? &stream_input_events : &stream_output_events, device); if (!priv->stream) { return SDL_SetError("Pipewire: Failed to create stream (%i)", errno); } - res = PIPEWIRE_pw_stream_connect(priv->stream, iscapture ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, node_id, STREAM_FLAGS, + // The target node is passed via PW_KEY_TARGET_OBJECT; target_id is a legacy parameter and must be PW_ID_ANY. + res = PIPEWIRE_pw_stream_connect(priv->stream, recording ? PW_DIRECTION_INPUT : PW_DIRECTION_OUTPUT, PW_ID_ANY, STREAM_FLAGS, ¶ms, 1); if (res != 0) { return SDL_SetError("Pipewire: Failed to connect stream"); @@ -1205,7 +1174,7 @@ static int PIPEWIRE_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Pipewire: Stream error: %s", error); } - return 0; + return true; } static void PIPEWIRE_CloseDevice(SDL_AudioDevice *device) @@ -1246,23 +1215,24 @@ static void PIPEWIRE_DeinitializeStart(void) static void PIPEWIRE_Deinitialize(void) { if (pipewire_initialized) { + hotplug_loop_destroy(); deinit_pipewire_library(); - pipewire_initialized = SDL_FALSE; + pipewire_initialized = false; } } -static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) +static bool PipewireInitialize(SDL_AudioDriverImpl *impl) { if (!pipewire_initialized) { - if (init_pipewire_library() < 0) { - return SDL_FALSE; + if (!init_pipewire_library()) { + return false; } - pipewire_initialized = SDL_TRUE; + pipewire_initialized = true; - if (hotplug_loop_init() < 0) { + if (!hotplug_loop_init()) { PIPEWIRE_Deinitialize(); - return SDL_FALSE; + return false; } } @@ -1272,16 +1242,52 @@ static SDL_bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) impl->Deinitialize = PIPEWIRE_Deinitialize; impl->PlayDevice = PIPEWIRE_PlayDevice; impl->GetDeviceBuf = PIPEWIRE_GetDeviceBuf; - impl->CaptureFromDevice = PIPEWIRE_CaptureFromDevice; - impl->FlushCapture = PIPEWIRE_FlushCapture; + impl->RecordDevice = PIPEWIRE_RecordDevice; + impl->FlushRecording = PIPEWIRE_FlushRecording; impl->CloseDevice = PIPEWIRE_CloseDevice; - impl->HasCaptureSupport = SDL_TRUE; - impl->ProvidesOwnCallbackThread = SDL_TRUE; + impl->HasRecordingSupport = true; + impl->ProvidesOwnCallbackThread = true; - return SDL_TRUE; + return true; } -AudioBootStrap PIPEWIRE_bootstrap = { "pipewire", "Pipewire", PIPEWIRE_Init, SDL_FALSE }; +static bool PIPEWIRE_PREFERRED_Init(SDL_AudioDriverImpl *impl) +{ + if (!PipewireInitialize(impl)) { + return false; + } + + // run device detection but don't add any devices to SDL; we're just waiting to see if PipeWire sees any devices. If not, fall back to the next backend. + PIPEWIRE_pw_thread_loop_lock(hotplug_loop); + + // Wait until the initial registry enumeration is complete + if (!hotplug_init_complete) { + PIPEWIRE_pw_thread_loop_wait(hotplug_loop); + } + + const bool no_devices = spa_list_is_empty(&hotplug_io_list); + + PIPEWIRE_pw_thread_loop_unlock(hotplug_loop); + + if (no_devices || !pipewire_core_version_at_least(1, 0, 0)) { + PIPEWIRE_Deinitialize(); + return false; + } + + return true; // this will move on to PIPEWIRE_DetectDevices and reuse hotplug_io_list. +} + +static bool PIPEWIRE_Init(SDL_AudioDriverImpl *impl) +{ + return PipewireInitialize(impl); +} + +AudioBootStrap PIPEWIRE_PREFERRED_bootstrap = { + "pipewire", "Pipewire", PIPEWIRE_PREFERRED_Init, false +}; +AudioBootStrap PIPEWIRE_bootstrap = { + "pipewire", "Pipewire", PIPEWIRE_Init, false +}; #endif // SDL_AUDIO_DRIVER_PIPEWIRE diff --git a/libs/SDL3/src/audio/ps2/SDL_ps2audio.c b/libs/SDL3/src/audio/ps2/SDL_ps2audio.c index a8230715d..8396b265a 100644 --- a/libs/SDL3/src/audio/ps2/SDL_ps2audio.c +++ b/libs/SDL3/src/audio/ps2/SDL_ps2audio.c @@ -27,11 +27,11 @@ #include #include -static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device) +static bool PS2AUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // These are the native supported audio PS2 configs @@ -82,19 +82,19 @@ static int PS2AUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->mixbufs[i] = &device->hidden->rawbuf[i * device->buffer_size]; } - return 0; + return true; } -static int PS2AUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool PS2AUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { // this returns number of bytes accepted or a negative error. We assume anything other than buflen is a fatal error. - return (audsrv_play_audio((char *)buffer, buflen) != buflen) ? -1 : 0; + return (audsrv_play_audio((char *)buffer, buflen) == buflen); } -static int PS2AUDIO_WaitDevice(SDL_AudioDevice *device) +static bool PS2AUDIO_WaitDevice(SDL_AudioDevice *device) { audsrv_wait_audio(device->buffer_size); - return 0; + return true; } static Uint8 *PS2AUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -137,10 +137,10 @@ static void PS2AUDIO_Deinitialize(void) deinit_audio_driver(); } -static SDL_bool PS2AUDIO_Init(SDL_AudioDriverImpl *impl) +static bool PS2AUDIO_Init(SDL_AudioDriverImpl *impl) { if (init_audio_driver() < 0) { - return SDL_FALSE; + return false; } impl->OpenDevice = PS2AUDIO_OpenDevice; @@ -150,10 +150,10 @@ static SDL_bool PS2AUDIO_Init(SDL_AudioDriverImpl *impl) impl->CloseDevice = PS2AUDIO_CloseDevice; impl->ThreadInit = PS2AUDIO_ThreadInit; impl->Deinitialize = PS2AUDIO_Deinitialize; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - return SDL_TRUE; // this audio target is available. + impl->OnlyHasDefaultPlaybackDevice = true; + return true; // this audio target is available. } AudioBootStrap PS2AUDIO_bootstrap = { - "ps2", "PS2 audio driver", PS2AUDIO_Init, SDL_FALSE + "ps2", "PS2 audio driver", PS2AUDIO_Init, false }; diff --git a/libs/SDL3/src/audio/psp/SDL_pspaudio.c b/libs/SDL3/src/audio/psp/SDL_pspaudio.c index 5783e7df0..9eb793b0d 100644 --- a/libs/SDL3/src/audio/psp/SDL_pspaudio.c +++ b/libs/SDL3/src/audio/psp/SDL_pspaudio.c @@ -33,16 +33,16 @@ #include #include -static inline SDL_bool isBasicAudioConfig(const SDL_AudioSpec *spec) +static bool isBasicAudioConfig(const SDL_AudioSpec *spec) { return spec->freq == 44100; } -static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool PSPAUDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // device only natively supports S16LSB @@ -102,10 +102,10 @@ static int PSPAUDIO_OpenDevice(SDL_AudioDevice *device) device->hidden->mixbufs[i] = &device->hidden->rawbuf[i * device->buffer_size]; } - return 0; + return true; } -static int PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { int rc; if (!isBasicAudioConfig(&device->spec)) { @@ -114,12 +114,12 @@ static int PSPAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int } else { rc = sceAudioOutputPannedBlocking(device->hidden->channel, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, (void *) buffer); } - return (rc == 0) ? 0 : -1; + return (rc == 0); } -static int PSPAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool PSPAUDIO_WaitDevice(SDL_AudioDevice *device) { - return 0; // Because we block when sending audio, there's no need for this function to do anything. + return true; // Because we block when sending audio, there's no need for this function to do anything. } static Uint8 *PSPAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -162,7 +162,7 @@ static void PSPAUDIO_ThreadInit(SDL_AudioDevice *device) } } -static SDL_bool PSPAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool PSPAUDIO_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = PSPAUDIO_OpenDevice; impl->PlayDevice = PSPAUDIO_PlayDevice; @@ -170,14 +170,14 @@ static SDL_bool PSPAUDIO_Init(SDL_AudioDriverImpl *impl) impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf; impl->CloseDevice = PSPAUDIO_CloseDevice; impl->ThreadInit = PSPAUDIO_ThreadInit; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - //impl->HasCaptureSupport = SDL_TRUE; - //impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; - return SDL_TRUE; + impl->OnlyHasDefaultPlaybackDevice = true; + //impl->HasRecordingSupport = true; + //impl->OnlyHasDefaultRecordingDevice = true; + return true; } AudioBootStrap PSPAUDIO_bootstrap = { - "psp", "PSP audio driver", PSPAUDIO_Init, SDL_FALSE + "psp", "PSP audio driver", PSPAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_PSP diff --git a/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.c b/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.c index 2d0ca1009..240b11e35 100644 --- a/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.c @@ -46,7 +46,7 @@ typedef struct PulseDeviceHandle } PulseDeviceHandle; // should we include monitors in the device list? Set at SDL_Init time -static SDL_bool include_monitors = SDL_FALSE; +static bool include_monitors = false; static pa_threaded_mainloop *pulseaudio_threaded_mainloop = NULL; static pa_context *pulseaudio_context = NULL; @@ -58,14 +58,17 @@ static SDL_AtomicInt pulseaudio_hotplug_thread_active; // to the change. static char *default_sink_path = NULL; static char *default_source_path = NULL; -static SDL_bool default_sink_changed = SDL_FALSE; -static SDL_bool default_source_changed = SDL_FALSE; +static bool default_sink_changed = false; +static bool default_source_changed = false; static const char *(*PULSEAUDIO_pa_get_library_version)(void); static pa_channel_map *(*PULSEAUDIO_pa_channel_map_init_auto)( pa_channel_map *, unsigned, pa_channel_map_def_t); static const char *(*PULSEAUDIO_pa_strerror)(int); +static pa_proplist *(*PULSEAUDIO_pa_proplist_new)(void); +static void (*PULSEAUDIO_pa_proplist_free)(pa_proplist *); +static int (*PULSEAUDIO_pa_proplist_sets)(pa_proplist *, const char *, const char *); static pa_threaded_mainloop *(*PULSEAUDIO_pa_threaded_mainloop_new)(void); static void (*PULSEAUDIO_pa_threaded_mainloop_set_name)(pa_threaded_mainloop *, const char *); @@ -84,8 +87,9 @@ static void (*PULSEAUDIO_pa_operation_set_state_callback)(pa_operation *, pa_ope static void (*PULSEAUDIO_pa_operation_cancel)(pa_operation *); static void (*PULSEAUDIO_pa_operation_unref)(pa_operation *); -static pa_context *(*PULSEAUDIO_pa_context_new)(pa_mainloop_api *, - const char *); +static pa_context *(*PULSEAUDIO_pa_context_new_with_proplist)(pa_mainloop_api *, + const char *, + const pa_proplist *); static void (*PULSEAUDIO_pa_context_set_state_callback)(pa_context *, pa_context_notify_cb_t, void *); static int (*PULSEAUDIO_pa_context_connect)(pa_context *, const char *, pa_context_flags_t, const pa_spawn_api *); @@ -125,28 +129,28 @@ static void (*PULSEAUDIO_pa_stream_set_write_callback)(pa_stream *, pa_stream_re static void (*PULSEAUDIO_pa_stream_set_read_callback)(pa_stream *, pa_stream_request_cb_t, void *); static pa_operation *(*PULSEAUDIO_pa_context_get_server_info)(pa_context *, pa_server_info_cb_t, void *); -static int load_pulseaudio_syms(void); +static bool load_pulseaudio_syms(void); #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC static const char *pulseaudio_library = SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC; -static void *pulseaudio_handle = NULL; +static SDL_SharedObject *pulseaudio_handle = NULL; -static int load_pulseaudio_sym(const char *fn, void **addr) +static bool load_pulseaudio_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(pulseaudio_handle, fn); if (!*addr) { // Don't call SDL_SetError(): SDL_LoadFunction already did. - return 0; + return false; } - return 1; + return true; } // cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_PULSEAUDIO_SYM(x) \ if (!load_pulseaudio_sym(#x, (void **)(char *)&PULSEAUDIO_##x)) \ - return -1 + return false static void UnloadPulseAudioLibrary(void) { @@ -156,22 +160,22 @@ static void UnloadPulseAudioLibrary(void) } } -static int LoadPulseAudioLibrary(void) +static bool LoadPulseAudioLibrary(void) { - int retval = 0; + bool result = true; if (!pulseaudio_handle) { pulseaudio_handle = SDL_LoadObject(pulseaudio_library); if (!pulseaudio_handle) { - retval = -1; + result = false; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { - retval = load_pulseaudio_syms(); - if (retval < 0) { + result = load_pulseaudio_syms(); + if (!result) { UnloadPulseAudioLibrary(); } } } - return retval; + return result; } #else @@ -182,15 +186,15 @@ static void UnloadPulseAudioLibrary(void) { } -static int LoadPulseAudioLibrary(void) +static bool LoadPulseAudioLibrary(void) { load_pulseaudio_syms(); - return 0; + return true; } #endif // SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC -static int load_pulseaudio_syms(void) +static bool load_pulseaudio_syms(void) { SDL_PULSEAUDIO_SYM(pa_get_library_version); SDL_PULSEAUDIO_SYM(pa_threaded_mainloop_new); @@ -205,7 +209,7 @@ static int load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_operation_get_state); SDL_PULSEAUDIO_SYM(pa_operation_cancel); SDL_PULSEAUDIO_SYM(pa_operation_unref); - SDL_PULSEAUDIO_SYM(pa_context_new); + SDL_PULSEAUDIO_SYM(pa_context_new_with_proplist); SDL_PULSEAUDIO_SYM(pa_context_set_state_callback); SDL_PULSEAUDIO_SYM(pa_context_connect); SDL_PULSEAUDIO_SYM(pa_context_get_sink_info_list); @@ -238,6 +242,9 @@ static int load_pulseaudio_syms(void) SDL_PULSEAUDIO_SYM(pa_stream_set_write_callback); SDL_PULSEAUDIO_SYM(pa_stream_set_read_callback); SDL_PULSEAUDIO_SYM(pa_context_get_server_info); + SDL_PULSEAUDIO_SYM(pa_proplist_new); + SDL_PULSEAUDIO_SYM(pa_proplist_free); + SDL_PULSEAUDIO_SYM(pa_proplist_sets); // optional #ifdef SDL_AUDIO_DRIVER_PULSEAUDIO_DYNAMIC @@ -254,37 +261,12 @@ static int load_pulseaudio_syms(void) PULSEAUDIO_pa_threaded_mainloop_set_name = NULL; #endif - return 0; -} - -static SDL_INLINE int squashVersion(const int major, const int minor, const int patch) -{ - return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF); + return true; } -// Workaround for older pulse: pa_context_new() must have non-NULL appname static const char *getAppName(void) { - const char *retval = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME); - if (retval && *retval) { - return retval; - } - retval = SDL_GetHint(SDL_HINT_APP_NAME); - if (retval && *retval) { - return retval; - } else { - const char *verstr = PULSEAUDIO_pa_get_library_version(); - retval = "SDL Application"; // the "oh well" default. - if (verstr) { - int maj, min, patch; - if (SDL_sscanf(verstr, "%d.%d.%d", &maj, &min, &patch) == 3) { - if (squashVersion(maj, min, patch) >= squashVersion(0, 9, 15)) { - retval = NULL; // 0.9.15+ handles NULL correctly. - } - } - } - } - return retval; + return SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); } static void OperationStateChangeCallback(pa_operation *o, void *userdata) @@ -334,16 +316,19 @@ static void PulseContextStateChangeCallback(pa_context *context, void *userdata) PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details. } -static int ConnectToPulseServer(void) +static bool ConnectToPulseServer(void) { pa_mainloop_api *mainloop_api = NULL; + pa_proplist *proplist = NULL; + const char *icon_name; int state = 0; SDL_assert(pulseaudio_threaded_mainloop == NULL); SDL_assert(pulseaudio_context == NULL); // Set up a new main loop - if (!(pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new())) { + pulseaudio_threaded_mainloop = PULSEAUDIO_pa_threaded_mainloop_new(); + if (!pulseaudio_threaded_mainloop) { return SDL_SetError("pa_threaded_mainloop_new() failed"); } @@ -362,11 +347,24 @@ static int ConnectToPulseServer(void) mainloop_api = PULSEAUDIO_pa_threaded_mainloop_get_api(pulseaudio_threaded_mainloop); SDL_assert(mainloop_api != NULL); // this never fails, right? - pulseaudio_context = PULSEAUDIO_pa_context_new(mainloop_api, getAppName()); + proplist = PULSEAUDIO_pa_proplist_new(); + if (!proplist) { + SDL_SetError("pa_proplist_new() failed"); + goto failed; + } + + icon_name = SDL_GetHint(SDL_HINT_AUDIO_DEVICE_APP_ICON_NAME); + if (!icon_name || *icon_name == '\0') { + icon_name = "applications-games"; + } + PULSEAUDIO_pa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, icon_name); + + pulseaudio_context = PULSEAUDIO_pa_context_new_with_proplist(mainloop_api, getAppName(), proplist); if (!pulseaudio_context) { - SDL_SetError("pa_context_new() failed"); + SDL_SetError("pa_context_new_with_proplist() failed"); goto failed; } + PULSEAUDIO_pa_proplist_free(proplist); PULSEAUDIO_pa_context_set_state_callback(pulseaudio_context, PulseContextStateChangeCallback, NULL); @@ -383,18 +381,18 @@ static int ConnectToPulseServer(void) } if (state != PA_CONTEXT_READY) { - return SDL_SetError("Could not connect to PulseAudio"); + SDL_SetError("Could not connect to PulseAudio"); goto failed; } PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - return 0; // connected and ready! + return true; // connected and ready! failed: PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); DisconnectFromPulseServer(); - return -1; + return false; } static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata) @@ -406,32 +404,32 @@ static void WriteCallback(pa_stream *p, size_t nbytes, void *userdata) } // This function waits until it is possible to write a full sound buffer -static int PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) +static bool PULSEAUDIO_WaitDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; - int retval = 0; + bool result = true; //SDL_Log("PULSEAUDIO PLAYDEVICE START! mixlen=%d", available); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - while (!SDL_AtomicGet(&device->shutdown) && (h->bytes_requested == 0)) { + while (!SDL_GetAtomicInt(&device->shutdown) && (h->bytes_requested == 0)) { //SDL_Log("PULSEAUDIO WAIT IN WAITDEVICE!"); PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITDEVICE!"); - retval = -1; + result = false; break; } } PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - return retval; + return result; } -static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { struct SDL_PrivateAudioData *h = device->hidden; @@ -444,14 +442,14 @@ static int PULSEAUDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, i PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); if (rc < 0) { - return -1; + return false; } //SDL_Log("PULSEAUDIO FEED! nbytes=%d", buffer_size); h->bytes_requested -= buffer_size; //SDL_Log("PULSEAUDIO PLAYDEVICE END! written=%d", written); - return 0; + return true; } static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -473,26 +471,26 @@ static Uint8 *PULSEAUDIO_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) static void ReadCallback(pa_stream *p, size_t nbytes, void *userdata) { //SDL_Log("PULSEAUDIO READ CALLBACK! nbytes=%u", (unsigned int) nbytes); - PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the capture code queries what it needs, we just need to signal to end any wait + PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // the recording code queries what it needs, we just need to signal to end any wait } -static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) +static bool PULSEAUDIO_WaitRecordingDevice(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; - if (h->capturebuf) { - return 0; // there's still data available to read. + if (h->recordingbuf) { + return true; // there's still data available to read. } - int retval = 0; + bool result = true; PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITCAPTUREDEVICE!"); - retval = -1; + //SDL_Log("PULSEAUDIO DEVICE FAILURE IN WAITRECORDINGDEVICE!"); + result = false; break; } else if (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0) { // a new fragment is available! @@ -503,10 +501,10 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) if (!data) { // If NULL, then the buffer had a hole, ignore that PULSEAUDIO_pa_stream_drop(h->stream); // drop this fragment. } else { - // store this fragment's data for use with CaptureFromDevice - //SDL_Log("PULSEAUDIO: captured %d new bytes", (int) nbytes); - h->capturebuf = (const Uint8 *)data; - h->capturelen = nbytes; + // store this fragment's data for use with RecordDevice + //SDL_Log("PULSEAUDIO: recorded %d new bytes", (int) nbytes); + h->recordingbuf = (const Uint8 *)data; + h->recordinglen = nbytes; break; } } @@ -514,23 +512,23 @@ static int PULSEAUDIO_WaitCaptureDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); - return retval; + return result; } -static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int PULSEAUDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { struct SDL_PrivateAudioData *h = device->hidden; - if (h->capturebuf) { - const int cpy = SDL_min(buflen, h->capturelen); + if (h->recordingbuf) { + const int cpy = SDL_min(buflen, h->recordinglen); if (cpy > 0) { - //SDL_Log("PULSEAUDIO: fed %d captured bytes", cpy); - SDL_memcpy(buffer, h->capturebuf, cpy); - h->capturebuf += cpy; - h->capturelen -= cpy; + //SDL_Log("PULSEAUDIO: fed %d recorded bytes", cpy); + SDL_memcpy(buffer, h->recordingbuf, cpy); + h->recordingbuf += cpy; + h->recordinglen -= cpy; } - if (h->capturelen == 0) { - h->capturebuf = NULL; + if (h->recordinglen == 0) { + h->recordingbuf = NULL; PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); // don't know if you _have_ to lock for this, but just in case. PULSEAUDIO_pa_stream_drop(h->stream); // done with this fragment. PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); @@ -541,7 +539,7 @@ static int PULSEAUDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, i return 0; } -static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) +static void PULSEAUDIO_FlushRecording(SDL_AudioDevice *device) { struct SDL_PrivateAudioData *h = device->hidden; const void *data = NULL; @@ -549,16 +547,16 @@ static void PULSEAUDIO_FlushCapture(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - if (h->capturebuf) { + if (h->recordingbuf) { PULSEAUDIO_pa_stream_drop(h->stream); - h->capturebuf = NULL; - h->capturelen = 0; + h->recordingbuf = NULL; + h->recordinglen = 0; } - while (!SDL_AtomicGet(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) { + while (!SDL_GetAtomicInt(&device->shutdown) && (PULSEAUDIO_pa_stream_readable_size(h->stream) > 0)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if ((PULSEAUDIO_pa_context_get_state(pulseaudio_context) != PA_CONTEXT_READY) || (PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY)) { - //SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHCAPTURE!"); + //SDL_Log("PULSEAUDIO DEVICE FAILURE IN FLUSHRECORDING!"); SDL_AudioDeviceDisconnected(device); break; } @@ -578,7 +576,7 @@ static void PULSEAUDIO_CloseDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); if (device->hidden->stream) { - if (device->hidden->capturebuf) { + if (device->hidden->recordingbuf) { PULSEAUDIO_pa_stream_drop(device->hidden->stream); } PULSEAUDIO_pa_stream_disconnect(device->hidden->stream); @@ -596,9 +594,9 @@ static void PulseStreamStateChangeCallback(pa_stream *stream, void *userdata) PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); // just signal any waiting code, it can look up the details. } -static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) +static bool PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; struct SDL_PrivateAudioData *h = NULL; SDL_AudioFormat test_format; const SDL_AudioFormat *closefmts; @@ -607,7 +605,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) pa_channel_map pacmap; pa_stream_flags_t flags = 0; int format = PA_SAMPLE_INVALID; - int retval = 0; + bool result = true; SDL_assert(pulseaudio_threaded_mainloop != NULL); SDL_assert(pulseaudio_context != NULL); @@ -615,7 +613,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) // Initialize all variables that we clean on shutdown h = device->hidden = (struct SDL_PrivateAudioData *)SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } // Try for a closest match on audio format @@ -661,10 +659,10 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) SDL_UpdatedAudioDeviceFormat(device); // Allocate mixing buffer - if (!iscapture) { + if (!recording) { h->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!h->mixbuf) { - return -1; + return false; } SDL_memset(h->mixbuf, device->silence_value, device->buffer_size); } @@ -673,7 +671,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) paspec.rate = device->spec.freq; // Reduced prebuffering compared to the defaults. - paattr.fragsize = device->buffer_size; // despite the name, this is only used for capture devices, according to PulseAudio docs! + paattr.fragsize = device->buffer_size; // despite the name, this is only used for recording devices, according to PulseAudio docs! paattr.tlength = device->buffer_size; paattr.prebuf = -1; paattr.maxlength = -1; @@ -695,7 +693,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) ); if (!h->stream) { - retval = SDL_SetError("Could not set up PulseAudio stream"); + result = SDL_SetError("Could not set up PulseAudio stream"); } else { int rc; @@ -705,7 +703,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) flags |= PA_STREAM_DONT_MOVE; const char *device_path = ((PulseDeviceHandle *) device->handle)->device_path; - if (iscapture) { + if (recording) { PULSEAUDIO_pa_stream_set_read_callback(h->stream, ReadCallback, h); rc = PULSEAUDIO_pa_stream_connect_record(h->stream, device_path, &paattr, flags); } else { @@ -714,7 +712,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) } if (rc < 0) { - retval = SDL_SetError("Could not connect PulseAudio stream"); + result = SDL_SetError("Could not connect PulseAudio stream"); } else { int state = PULSEAUDIO_pa_stream_get_state(h->stream); while (PA_STREAM_IS_GOOD(state) && (state != PA_STREAM_READY)) { @@ -723,13 +721,13 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) } if (!PA_STREAM_IS_GOOD(state)) { - retval = SDL_SetError("Could not connect PulseAudio stream"); + result = SDL_SetError("Could not connect PulseAudio stream"); } else { const pa_buffer_attr *actual_bufattr = PULSEAUDIO_pa_stream_get_buffer_attr(h->stream); if (!actual_bufattr) { - retval = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes"); + result = SDL_SetError("Could not determine connected PulseAudio stream's buffer attributes"); } else { - device->buffer_size = (int) iscapture ? actual_bufattr->tlength : actual_bufattr->fragsize; + device->buffer_size = (int) recording ? actual_bufattr->tlength : actual_bufattr->fragsize; device->sample_frames = device->buffer_size / SDL_AUDIO_FRAMESIZE(device->spec); } } @@ -739,7 +737,7 @@ static int PULSEAUDIO_OpenDevice(SDL_AudioDevice *device) PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); // We're (hopefully) ready to rock and roll. :-) - return retval; + return result; } // device handles are device index + 1, cast to void*, so we never pass a NULL. @@ -766,9 +764,10 @@ static SDL_AudioFormat PulseFormatToSDLFormat(pa_sample_format_t format) } } -static void AddPulseAudioDevice(const SDL_bool iscapture, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec) +static void AddPulseAudioDevice(const bool recording, const char *description, const char *name, const uint32_t index, const pa_sample_spec *sample_spec) { SDL_AudioSpec spec; + SDL_zero(spec); spec.format = PulseFormatToSDLFormat(sample_spec->format); spec.channels = sample_spec->channels; spec.freq = sample_spec->rate; @@ -780,25 +779,25 @@ static void AddPulseAudioDevice(const SDL_bool iscapture, const char *descriptio } else { handle->device_index = index; } - SDL_AddAudioDevice(iscapture, description, &spec, handle); + SDL_AddAudioDevice(recording, description, &spec, handle); } } -// This is called when PulseAudio adds an output ("sink") device. +// This is called when PulseAudio adds an playback ("sink") device. static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data) { if (i) { - AddPulseAudioDevice(SDL_FALSE, i->description, i->name, i->index, &i->sample_spec); + AddPulseAudioDevice(false, i->description, i->name, i->index, &i->sample_spec); } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -// This is called when PulseAudio adds a capture ("source") device. +// This is called when PulseAudio adds a recording ("source") device. static void SourceInfoCallback(pa_context *c, const pa_source_info *i, int is_last, void *data) { // Maybe skip "monitor" sources. These are just output from other sinks. if (i && (include_monitors || (i->monitor_of_sink == PA_INVALID_INDEX))) { - AddPulseAudioDevice(SDL_TRUE, i->description, i->name, i->index, &i->sample_spec); + AddPulseAudioDevice(true, i->description, i->name, i->index, &i->sample_spec); } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } @@ -812,7 +811,7 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat if (str) { SDL_free(default_sink_path); default_sink_path = str; - default_sink_changed = SDL_TRUE; + default_sink_changed = true; } } @@ -821,21 +820,21 @@ static void ServerInfoCallback(pa_context *c, const pa_server_info *i, void *dat if (str) { SDL_free(default_source_path); default_source_path = str; - default_source_changed = SDL_TRUE; + default_source_changed = true; } } PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -static SDL_bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata) +static bool FindAudioDeviceByIndex(SDL_AudioDevice *device, void *userdata) { const uint32_t idx = (uint32_t) (uintptr_t) userdata; const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; return (handle->device_index == idx); } -static SDL_bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata) +static bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata) { const char *path = (const char *) userdata; const PulseDeviceHandle *handle = (const PulseDeviceHandle *) device->handle; @@ -845,13 +844,13 @@ static SDL_bool FindAudioDeviceByPath(SDL_AudioDevice *device, void *userdata) // This is called when PulseAudio has a device connected/removed/changed. static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *data) { - const SDL_bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW); - const SDL_bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE); - const SDL_bool changed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE); + const bool added = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW); + const bool removed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE); + const bool changed = ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE); if (added || removed || changed) { // we only care about add/remove events. - const SDL_bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK); - const SDL_bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE); + const bool sink = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK); + const bool source = ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE); if (changed) { PULSEAUDIO_pa_operation_unref(PULSEAUDIO_pa_context_get_server_info(pulseaudio_context, ServerInfoCallback, NULL)); @@ -872,20 +871,20 @@ static void HotplugCallback(pa_context *c, pa_subscription_event_type_t t, uint3 PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); } -static SDL_bool CheckDefaultDevice(const SDL_bool changed, char *device_path) +static bool CheckDefaultDevice(const bool changed, char *device_path) { if (!changed) { - return SDL_FALSE; // nothing's happening, leave the flag marked as unchanged. + return false; // nothing's happening, leave the flag marked as unchanged. } else if (!device_path) { - return SDL_TRUE; // check again later, we don't have a device name... + return true; // check again later, we don't have a device name... } SDL_AudioDevice *device = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, device_path); if (device) { // if NULL, we might still be waiting for a SinkInfoCallback or something, we'll try later. SDL_DefaultAudioDeviceChanged(device); - return SDL_FALSE; // changing complete, set flag to unchanged for future tests. + return false; // changing complete, set flag to unchanged for future tests. } - return SDL_TRUE; // couldn't find the changed device, leave it marked as changed to try again later. + return true; // couldn't find the changed device, leave it marked as changed to try again later. } // this runs as a thread while the Pulse target is initialized to catch hotplug events. @@ -893,16 +892,16 @@ static int SDLCALL HotplugThread(void *data) { pa_operation *op; - SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW); + SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_LOW); PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); PULSEAUDIO_pa_context_set_subscribe_callback(pulseaudio_context, HotplugCallback, NULL); // don't WaitForPulseOperation on the subscription; when it's done we'll be able to get hotplug events, but waiting doesn't changing anything. op = PULSEAUDIO_pa_context_subscribe(pulseaudio_context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE | PA_SUBSCRIPTION_MASK_SERVER, NULL, NULL); - SDL_PostSemaphore((SDL_Semaphore *) data); + SDL_SignalSemaphore((SDL_Semaphore *) data); - while (SDL_AtomicGet(&pulseaudio_hotplug_thread_active)) { + while (SDL_GetAtomicInt(&pulseaudio_hotplug_thread_active)) { PULSEAUDIO_pa_threaded_mainloop_wait(pulseaudio_threaded_mainloop); if (op && PULSEAUDIO_pa_operation_get_state(op) != PA_OPERATION_RUNNING) { PULSEAUDIO_pa_operation_unref(op); @@ -910,11 +909,11 @@ static int SDLCALL HotplugThread(void *data) } // Update default devices; don't hold the pulse lock during this, since it could deadlock vs a playing device that we're about to lock here. - SDL_bool check_default_sink = default_sink_changed; - SDL_bool check_default_source = default_source_changed; + bool check_default_sink = default_sink_changed; + bool check_default_source = default_source_changed; char *current_default_sink = check_default_sink ? SDL_strdup(default_sink_path) : NULL; char *current_default_source = check_default_source ? SDL_strdup(default_source_path) : NULL; - default_sink_changed = default_source_changed = SDL_FALSE; + default_sink_changed = default_source_changed = false; PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); check_default_sink = CheckDefaultDevice(check_default_sink, current_default_sink); check_default_source = CheckDefaultDevice(check_default_source, current_default_source); @@ -938,7 +937,7 @@ static int SDLCALL HotplugThread(void *data) return 0; } -static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { SDL_Semaphore *ready_sem = SDL_CreateSemaphore(0); @@ -949,17 +948,22 @@ static void PULSEAUDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_Audio PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); if (default_sink_path) { - *default_output = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); + *default_playback = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_sink_path); } if (default_source_path) { - *default_capture = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); + *default_recording = SDL_FindPhysicalAudioDeviceByCallback(FindAudioDeviceByPath, default_source_path); } // ok, we have a sane list, let's set up hotplug notifications now... - SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 1); - pulseaudio_hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, ready_sem); // !!! FIXME: this can probably survive in significantly less stack space. - SDL_WaitSemaphore(ready_sem); + SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 1); + pulseaudio_hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", ready_sem); + if (pulseaudio_hotplug_thread) { + SDL_WaitSemaphore(ready_sem); // wait until the thread hits it's main loop. + } else { + SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 0); // thread failed to start, we'll go on without hotplug. + } + SDL_DestroySemaphore(ready_sem); } @@ -974,7 +978,7 @@ static void PULSEAUDIO_DeinitializeStart(void) { if (pulseaudio_hotplug_thread) { PULSEAUDIO_pa_threaded_mainloop_lock(pulseaudio_threaded_mainloop); - SDL_AtomicSet(&pulseaudio_hotplug_thread_active, 0); + SDL_SetAtomicInt(&pulseaudio_hotplug_thread_active, 0); PULSEAUDIO_pa_threaded_mainloop_signal(pulseaudio_threaded_mainloop, 0); PULSEAUDIO_pa_threaded_mainloop_unlock(pulseaudio_threaded_mainloop); SDL_WaitThread(pulseaudio_hotplug_thread, NULL); @@ -988,24 +992,24 @@ static void PULSEAUDIO_Deinitialize(void) SDL_free(default_sink_path); default_sink_path = NULL; - default_sink_changed = SDL_FALSE; + default_sink_changed = false; SDL_free(default_source_path); default_source_path = NULL; - default_source_changed = SDL_FALSE; + default_source_changed = false; UnloadPulseAudioLibrary(); } -static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) +static bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) { - if (LoadPulseAudioLibrary() < 0) { - return SDL_FALSE; - } else if (ConnectToPulseServer() < 0) { + if (!LoadPulseAudioLibrary()) { + return false; + } else if (!ConnectToPulseServer()) { UnloadPulseAudioLibrary(); - return SDL_FALSE; + return false; } - include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, SDL_FALSE); + include_monitors = SDL_GetHintBoolean(SDL_HINT_AUDIO_INCLUDE_MONITORS, false); impl->DetectDevices = PULSEAUDIO_DetectDevices; impl->OpenDevice = PULSEAUDIO_OpenDevice; @@ -1015,18 +1019,18 @@ static SDL_bool PULSEAUDIO_Init(SDL_AudioDriverImpl *impl) impl->CloseDevice = PULSEAUDIO_CloseDevice; impl->DeinitializeStart = PULSEAUDIO_DeinitializeStart; impl->Deinitialize = PULSEAUDIO_Deinitialize; - impl->WaitCaptureDevice = PULSEAUDIO_WaitCaptureDevice; - impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice; - impl->FlushCapture = PULSEAUDIO_FlushCapture; + impl->WaitRecordingDevice = PULSEAUDIO_WaitRecordingDevice; + impl->RecordDevice = PULSEAUDIO_RecordDevice; + impl->FlushRecording = PULSEAUDIO_FlushRecording; impl->FreeDeviceHandle = PULSEAUDIO_FreeDeviceHandle; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap PULSEAUDIO_bootstrap = { - "pulseaudio", "PulseAudio", PULSEAUDIO_Init, SDL_FALSE + "pulseaudio", "PulseAudio", PULSEAUDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_PULSEAUDIO diff --git a/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.h b/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.h index 1d209cb1e..62b0d4eac 100644 --- a/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.h +++ b/libs/SDL3/src/audio/pulseaudio/SDL_pulseaudio.h @@ -37,8 +37,8 @@ struct SDL_PrivateAudioData int bytes_requested; // bytes of data the hardware wants _now_. - const Uint8 *capturebuf; - int capturelen; + const Uint8 *recordingbuf; + int recordinglen; }; #endif // SDL_pulseaudio_h_ diff --git a/libs/SDL3/src/audio/qnx/SDL_qsa_audio.c b/libs/SDL3/src/audio/qnx/SDL_qsa_audio.c index 6b69670cf..3a549b87d 100644 --- a/libs/SDL3/src/audio/qnx/SDL_qsa_audio.c +++ b/libs/SDL3/src/audio/qnx/SDL_qsa_audio.c @@ -52,7 +52,7 @@ #define QSA_MAX_NAME_LENGTH 81+16 // Hardcoded in QSA, can't be changed -static int QSA_SetError(const char *fn, int status) +static bool QSA_SetError(const char *fn, int status) { return SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status)); } @@ -86,46 +86,46 @@ static void QSA_InitAudioParams(snd_pcm_channel_params_t * cpars) } // This function waits until it is possible to write a full sound buffer -static int QSA_WaitDevice(SDL_AudioDevice *device) +static bool QSA_WaitDevice(SDL_AudioDevice *device) { // Setup timeout for playing one fragment equal to 2 seconds // If timeout occurred than something wrong with hardware or driver // For example, Vortex 8820 audio driver stucks on second DAC because // it doesn't exist ! const int result = SDL_IOReady(device->hidden->audio_fd, - device->iscapture ? SDL_IOR_READ : SDL_IOR_WRITE, + device->recording ? SDL_IOR_READ : SDL_IOR_WRITE, 2 * 1000); switch (result) { case -1: SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "QSA: SDL_IOReady() failed: %s", strerror(errno)); - return -1; + return false; case 0: - device->hidden->timeout_on_wait = SDL_TRUE; // !!! FIXME: Should we just disconnect the device in this case? + device->hidden->timeout_on_wait = true; // !!! FIXME: Should we just disconnect the device in this case? break; default: - device->hidden->timeout_on_wait = SDL_FALSE; + device->hidden->timeout_on_wait = false; break; } - return 0; + return true; } -static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { - if (SDL_AtomicGet(&device->shutdown) || !device->hidden) { - return 0; + if (SDL_GetAtomicInt(&device->shutdown) || !device->hidden) { + return true; } int towrite = buflen; // Write the audio data, checking for EAGAIN (buffer full) and underrun - while ((towrite > 0) && !SDL_AtomicGet(&device->shutdown)); + while ((towrite > 0) && !SDL_GetAtomicInt(&device->shutdown)); const int bw = snd_pcm_plugin_write(device->hidden->audio_handle, buffer, towrite); if (bw != towrite) { // Check if samples playback got stuck somewhere in hardware or in the audio device driver if ((errno == EAGAIN) && (bw == 0)) { if (device->hidden->timeout_on_wait) { - return 0; // oh well, try again next time. !!! FIXME: Should we just disconnect the device in this case? + return true; // oh well, try again next time. !!! FIXME: Should we just disconnect the device in this case? } } @@ -140,22 +140,22 @@ static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int bufl } else if ((errno == EINVAL) || (errno == EIO)) { snd_pcm_channel_status_t cstatus; SDL_zero(cstatus); - cstatus.channel = device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; + cstatus.channel = device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; int status = snd_pcm_plugin_status(device->hidden->audio_handle, &cstatus); if (status < 0) { QSA_SetError("snd_pcm_plugin_status", status); - return -1; + return false; } else if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) { - status = snd_pcm_plugin_prepare(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); + status = snd_pcm_plugin_prepare(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); if (status < 0) { QSA_SetError("snd_pcm_plugin_prepare", status); - return -1; + return false; } } continue; } else { - return -1; + return false; } } else { // we wrote all remaining data @@ -165,7 +165,7 @@ static int QSA_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int bufl } // If we couldn't write, assume fatal error for now - return (towrite != 0) ? -1 : 0; + return (towrite == 0); } static Uint8 *QSA_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -178,8 +178,8 @@ static void QSA_CloseDevice(SDL_AudioDevice *device) if (device->hidden) { if (device->hidden->audio_handle) { #if _NTO_VERSION < 710 - // Finish playing available samples or cancel unread samples during capture - snd_pcm_plugin_flush(device->hidden->audio_handle, device->iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); + // Finish playing available samples or cancel unread samples during recording + snd_pcm_plugin_flush(device->hidden->audio_handle, device->recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK); #endif snd_pcm_close(device->hidden->audio_handle); } @@ -190,23 +190,23 @@ static void QSA_CloseDevice(SDL_AudioDevice *device) } } -static int QSA_OpenDevice(SDL_AudioDevice *device) +static bool QSA_OpenDevice(SDL_AudioDevice *device) { - if (device->iscapture) { - return SDL_SetError("SDL capture support isn't available on QNX atm"); // !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! + if (device->recording) { + return SDL_SetError("SDL recording support isn't available on QNX atm"); // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! } SDL_assert(device->handle != NULL); // NULL used to mean "system default device" in SDL2; it does not mean that in SDL3. const Uint32 sdlhandle = (Uint32) ((size_t) device->handle); const uint32_t cardno = (uint32_t) (sdlhandle & 0xFFFF); const uint32_t deviceno = (uint32_t) ((sdlhandle >> 16) & 0xFFFF); - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; int status = 0; // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof (struct SDL_PrivateAudioData))); if (device->hidden == NULL) { - return -1; + return false; } // Initialize channel transfer parameters to default @@ -214,7 +214,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) QSA_InitAudioParams(&cparams); // Open requested audio device - status = snd_pcm_open(&device->hidden->audio_handle, cardno, deviceno, iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK); + status = snd_pcm_open(&device->hidden->audio_handle, cardno, deviceno, recording ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK); if (status < 0) { device->hidden->audio_handle = NULL; return QSA_SetError("snd_pcm_open", status); @@ -263,7 +263,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) // Make sure channel is setup right one last time snd_pcm_channel_setup_t csetup; SDL_zero(csetup); - csetup.channel = iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; + csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { return SDL_SetError("QSA: Unable to setup channel"); } @@ -275,7 +275,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) device->hidden->pcm_buf = (Uint8 *) SDL_malloc(device->buffer_size); if (device->hidden->pcm_buf == NULL) { - return -1; + return false; } SDL_memset(device->hidden->pcm_buf, device->silence_value, device->buffer_size); @@ -291,7 +291,7 @@ static int QSA_OpenDevice(SDL_AudioDevice *device) return QSA_SetError("snd_pcm_plugin_prepare", status); } - return 0; // We're really ready to rock and roll. :-) + return true; // We're really ready to rock and roll. :-) } static SDL_AudioFormat QnxFormatToSDLFormat(const int32_t qnxfmt) @@ -312,13 +312,13 @@ static SDL_AudioFormat QnxFormatToSDLFormat(const int32_t qnxfmt) return SDL_AUDIO_S16; // oh well. } -static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void QSA_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { // Detect amount of available devices // this value can be changed in the runtime int num_cards = 0; (void) snd_cards_list(NULL, 0, &alloc_num_cards); - SDL_bool isstack = SDL_FALSE; + bool isstack = false; int *cards = SDL_small_alloc(int, num_cards, &isstack); if (!cards) { return; // we're in trouble. @@ -350,23 +350,24 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_snprintf(fullname, sizeof (fullname), "%s d%d", name, (int) deviceno); // Check if this device id could play anything - SDL_bool iscapture = SDL_FALSE; + bool recording = false; status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_PLAYBACK); - if (status != EOK) { // no? See if it's a capture device instead. - #if 0 // !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! + if (status != EOK) { // no? See if it's a recording device instead. + #if 0 // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! status = snd_pcm_open(&handle, card, deviceno, SND_PCM_OPEN_CAPTURE); if (status == EOK) { - iscapture = SDL_TRUE; + recording = true; } #endif } if (status == EOK) { SDL_AudioSpec spec; + SDL_zero(spec); SDL_AudioSpec *pspec = &spec; snd_pcm_channel_setup_t csetup; SDL_zero(csetup); - csetup.channel = iscapture ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; + csetup.channel = recording ? SND_PCM_CHANNEL_CAPTURE : SND_PCM_CHANNEL_PLAYBACK; if (snd_pcm_plugin_setup(device->hidden->audio_handle, &csetup) < 0) { pspec = NULL; // go on without spec info. @@ -382,7 +383,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_assert(card <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); - SDL_AddAudioDevice(iscapture, fullname, pspec, (void *) ((size_t) sdlhandle)); + SDL_AddAudioDevice(recording, fullname, pspec, (void *) ((size_t) sdlhandle)); } } else { // Check if we got end of devices list @@ -407,7 +408,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_assert(cardno <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); - *default_output = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); + *default_playback = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); } if (snd_pcm_open_preferred(&handle, &cardno, &deviceno, SND_PCM_OPEN_CAPTURE) == 0) { @@ -416,7 +417,7 @@ static void QSA_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice SDL_assert(cardno <= 0xFFFF); SDL_assert(deviceno <= 0xFFFF); const Uint32 sdlhandle = ((Uint32) card) | (((Uint32) deviceno) << 16); - *default_capture = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); + *default_recording = SDL_FindPhysicalAudioDeviceByHandle((void *) ((size_t) sdlhandle)); } } @@ -425,7 +426,7 @@ static void QSA_Deinitialize(void) // nothing to do here atm. } -static SDL_bool QSA_Init(SDL_AudioDriverImpl * impl) +static bool QSA_Init(SDL_AudioDriverImpl * impl) { impl->DetectDevices = QSA_DetectDevices; impl->OpenDevice = QSA_OpenDevice; @@ -436,10 +437,10 @@ static SDL_bool QSA_Init(SDL_AudioDriverImpl * impl) impl->CloseDevice = QSA_CloseDevice; impl->Deinitialize = QSA_Deinitialize; - // !!! FIXME: most of this code has support for capture devices, but there's no CaptureFromDevice, etc functions. Fill them in! - //impl->HasCaptureSupport = SDL_TRUE; + // !!! FIXME: most of this code has support for recording devices, but there's no RecordDevice, etc functions. Fill them in! + //impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap QSAAUDIO_bootstrap = { diff --git a/libs/SDL3/src/audio/qnx/SDL_qsa_audio.h b/libs/SDL3/src/audio/qnx/SDL_qsa_audio.h index ea5375209..3bb0b6f78 100644 --- a/libs/SDL3/src/audio/qnx/SDL_qsa_audio.h +++ b/libs/SDL3/src/audio/qnx/SDL_qsa_audio.h @@ -32,7 +32,7 @@ struct SDL_PrivateAudioData { snd_pcm_t *audio_handle; // The audio device handle int audio_fd; // The audio file descriptor, for selecting on - SDL_bool timeout_on_wait; // Select timeout status + bool timeout_on_wait; // Select timeout status Uint8 *pcm_buf; // Raw mixing buffer }; diff --git a/libs/SDL3/src/audio/sndio/SDL_sndioaudio.c b/libs/SDL3/src/audio/sndio/SDL_sndioaudio.c index ee35d3f39..0776a4529 100644 --- a/libs/SDL3/src/audio/sndio/SDL_sndioaudio.c +++ b/libs/SDL3/src/audio/sndio/SDL_sndioaudio.c @@ -66,27 +66,27 @@ static void (*SNDIO_sio_initpar)(struct sio_par *); #ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC static const char *sndio_library = SDL_AUDIO_DRIVER_SNDIO_DYNAMIC; -static void *sndio_handle = NULL; +static SDL_SharedObject *sndio_handle = NULL; -static int load_sndio_sym(const char *fn, void **addr) +static bool load_sndio_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(sndio_handle, fn); if (!*addr) { - return 0; // Don't call SDL_SetError(): SDL_LoadFunction already did. + return false; // Don't call SDL_SetError(): SDL_LoadFunction already did. } - return 1; + return true; } // cast funcs to char* first, to please GCC's strict aliasing rules. #define SDL_SNDIO_SYM(x) \ if (!load_sndio_sym(#x, (void **)(char *)&SNDIO_##x)) \ - return -1 + return false #else #define SDL_SNDIO_SYM(x) SNDIO_##x = x #endif -static int load_sndio_syms(void) +static bool load_sndio_syms(void) { SDL_SNDIO_SYM(sio_open); SDL_SNDIO_SYM(sio_close); @@ -101,7 +101,7 @@ static int load_sndio_syms(void) SDL_SNDIO_SYM(sio_revents); SDL_SNDIO_SYM(sio_eof); SDL_SNDIO_SYM(sio_initpar); - return 0; + return true; } #undef SDL_SNDIO_SYM @@ -116,21 +116,21 @@ static void UnloadSNDIOLibrary(void) } } -static int LoadSNDIOLibrary(void) +static bool LoadSNDIOLibrary(void) { - int retval = 0; + bool result = true; if (!sndio_handle) { sndio_handle = SDL_LoadObject(sndio_library); if (!sndio_handle) { - retval = -1; // Don't call SDL_SetError(): SDL_LoadObject already did. + result = false; // Don't call SDL_SetError(): SDL_LoadObject already did. } else { - retval = load_sndio_syms(); - if (retval < 0) { + result = load_sndio_syms(); + if (!result) { UnloadSNDIOLibrary(); } } } - return retval; + return result; } #else @@ -139,57 +139,57 @@ static void UnloadSNDIOLibrary(void) { } -static int LoadSNDIOLibrary(void) +static bool LoadSNDIOLibrary(void) { load_sndio_syms(); - return 0; + return true; } #endif // SDL_AUDIO_DRIVER_SNDIO_DYNAMIC -static int SNDIO_WaitDevice(SDL_AudioDevice *device) +static bool SNDIO_WaitDevice(SDL_AudioDevice *device) { - const SDL_bool iscapture = device->iscapture; + const bool recording = device->recording; - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { if (SNDIO_sio_eof(device->hidden->dev)) { - return -1; + return false; } - const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, iscapture ? POLLIN : POLLOUT); + const int nfds = SNDIO_sio_pollfd(device->hidden->dev, device->hidden->pfd, recording ? POLLIN : POLLOUT); if (nfds <= 0 || poll(device->hidden->pfd, nfds, 10) < 0) { - return -1; + return false; } const int revents = SNDIO_sio_revents(device->hidden->dev, device->hidden->pfd); - if (iscapture && (revents & POLLIN)) { + if (recording && (revents & POLLIN)) { break; - } else if (!iscapture && (revents & POLLOUT)) { + } else if (!recording && (revents & POLLOUT)) { break; } else if (revents & POLLHUP) { - return -1; + return false; } } - return 0; + return true; } -static int SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool SNDIO_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { // !!! FIXME: this should be non-blocking so we can check device->shutdown. // this is set to blocking, because we _have_ to send the entire buffer down, but hopefully WaitDevice took most of the delay time. if (SNDIO_sio_write(device->hidden->dev, buffer, buflen) != buflen) { - return -1; // If we couldn't write, assume fatal error for now + return false; // If we couldn't write, assume fatal error for now } #ifdef DEBUG_AUDIO fprintf(stderr, "Wrote %d bytes of audio data\n", written); #endif - return 0; + return true; } -static int SNDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int SNDIO_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { - // We set capture devices non-blocking; this can safely return 0 in SDL3, but we'll check for EOF to cause a device disconnect. + // We set recording devices non-blocking; this can safely return 0 in SDL3, but we'll check for EOF to cause a device disconnect. const size_t br = SNDIO_sio_read(device->hidden->dev, buffer, buflen); if ((br == 0) && SNDIO_sio_eof(device->hidden->dev)) { return -1; @@ -197,10 +197,10 @@ static int SNDIO_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int bu return (int) br; } -static void SNDIO_FlushCapture(SDL_AudioDevice *device) +static void SNDIO_FlushRecording(SDL_AudioDevice *device) { char buf[512]; - while (!SDL_AtomicGet(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) { + while (!SDL_GetAtomicInt(&device->shutdown) && (SNDIO_sio_read(device->hidden->dev, buf, sizeof(buf)) > 0)) { // do nothing } } @@ -224,26 +224,23 @@ static void SNDIO_CloseDevice(SDL_AudioDevice *device) } } -static int SNDIO_OpenDevice(SDL_AudioDevice *device) +static bool SNDIO_OpenDevice(SDL_AudioDevice *device) { device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } - // !!! FIXME: we really should standardize this on a specific SDL hint. - const char *audiodev = SDL_getenv("AUDIODEV"); - - // Capture devices must be non-blocking for SNDIO_FlushCapture - device->hidden->dev = SNDIO_sio_open(audiodev ? audiodev : SIO_DEVANY, - device->iscapture ? SIO_REC : SIO_PLAY, device->iscapture); + // Recording devices must be non-blocking for SNDIO_FlushRecording + device->hidden->dev = SNDIO_sio_open(SIO_DEVANY, + device->recording ? SIO_REC : SIO_PLAY, device->recording); if (!device->hidden->dev) { return SDL_SetError("sio_open() failed"); } device->hidden->pfd = SDL_malloc(sizeof(struct pollfd) * SNDIO_sio_nfds(device->hidden->dev)); if (!device->hidden->pfd) { - return -1; + return false; } struct sio_par par; @@ -308,7 +305,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) // Allocate mixing buffer device->hidden->mixbuf = (Uint8 *)SDL_malloc(device->buffer_size); if (!device->hidden->mixbuf) { - return -1; + return false; } SDL_memset(device->hidden->mixbuf, device->silence_value, device->buffer_size); @@ -316,7 +313,7 @@ static int SNDIO_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("sio_start() failed"); } - return 0; // We're ready to rock and roll. :-) + return true; // We're ready to rock and roll. :-) } static void SNDIO_Deinitialize(void) @@ -324,16 +321,16 @@ static void SNDIO_Deinitialize(void) UnloadSNDIOLibrary(); } -static void SNDIO_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void SNDIO_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - *default_output = SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, NULL, (void *)0x1); - *default_capture = SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, NULL, (void *)0x2); + *default_playback = SDL_AddAudioDevice(false, DEFAULT_PLAYBACK_DEVNAME, NULL, (void *)0x1); + *default_recording = SDL_AddAudioDevice(true, DEFAULT_RECORDING_DEVNAME, NULL, (void *)0x2); } -static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl) +static bool SNDIO_Init(SDL_AudioDriverImpl *impl) { - if (LoadSNDIOLibrary() < 0) { - return SDL_FALSE; + if (!LoadSNDIOLibrary()) { + return false; } impl->OpenDevice = SNDIO_OpenDevice; @@ -341,19 +338,19 @@ static SDL_bool SNDIO_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = SNDIO_PlayDevice; impl->GetDeviceBuf = SNDIO_GetDeviceBuf; impl->CloseDevice = SNDIO_CloseDevice; - impl->WaitCaptureDevice = SNDIO_WaitDevice; - impl->CaptureFromDevice = SNDIO_CaptureFromDevice; - impl->FlushCapture = SNDIO_FlushCapture; + impl->WaitRecordingDevice = SNDIO_WaitDevice; + impl->RecordDevice = SNDIO_RecordDevice; + impl->FlushRecording = SNDIO_FlushRecording; impl->Deinitialize = SNDIO_Deinitialize; impl->DetectDevices = SNDIO_DetectDevices; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap SNDIO_bootstrap = { - "sndio", "OpenBSD sndio", SNDIO_Init, SDL_FALSE + "sndio", "OpenBSD sndio", SNDIO_Init, false }; #endif // SDL_AUDIO_DRIVER_SNDIO diff --git a/libs/SDL3/src/audio/vita/SDL_vitaaudio.c b/libs/SDL3/src/audio/vita/SDL_vitaaudio.c index 2de08d93c..ad479f984 100644 --- a/libs/SDL3/src/audio/vita/SDL_vitaaudio.c +++ b/libs/SDL3/src/audio/vita/SDL_vitaaudio.c @@ -37,7 +37,7 @@ #define SCE_AUDIO_SAMPLE_ALIGN(s) (((s) + 63) & ~63) #define SCE_AUDIO_MAX_VOLUME 0x8000 -static int VITAAUD_OpenCaptureDevice(SDL_AudioDevice *device) +static bool VITAAUD_OpenRecordingDevice(SDL_AudioDevice *device) { device->spec.freq = 16000; device->spec.channels = 1; @@ -51,10 +51,10 @@ static int VITAAUD_OpenCaptureDevice(SDL_AudioDevice *device) return SDL_SetError("Couldn't open audio in port: %x", device->hidden->port); } - return 0; + return true; } -static int VITAAUD_OpenDevice(SDL_AudioDevice *device) +static bool VITAAUD_OpenDevice(SDL_AudioDevice *device) { int format, mixlen, i, port = SCE_AUDIO_OUT_PORT_TYPE_MAIN; int vols[2] = { SCE_AUDIO_MAX_VOLUME, SCE_AUDIO_MAX_VOLUME }; @@ -64,7 +64,7 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; + return false; } closefmts = SDL_ClosestAudioFormats(device->spec.format); @@ -79,8 +79,8 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) return SDL_SetError("Unsupported audio format"); } - if (device->iscapture) { - return VITAAUD_OpenCaptureDevice(device); + if (device->recording) { + return VITAAUD_OpenRecordingDevice(device); } // The sample count must be a multiple of 64. @@ -125,36 +125,36 @@ static int VITAAUD_OpenDevice(SDL_AudioDevice *device) } device->hidden->next_buffer = 0; - return 0; + return true; } -static int VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) +static bool VITAAUD_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buffer_size) { - return (sceAudioOutOutput(device->hidden->port, buffer) == 0) ? 0 : -1; + return (sceAudioOutOutput(device->hidden->port, buffer) == 0); } // This function waits until it is possible to write a full sound buffer -static int VITAAUD_WaitDevice(SDL_AudioDevice *device) +static bool VITAAUD_WaitDevice(SDL_AudioDevice *device) { // !!! FIXME: we might just need to sleep roughly as long as playback buffers take to process, based on sample rate, etc. - while (!SDL_AtomicGet(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) { + while (!SDL_GetAtomicInt(&device->shutdown) && (sceAudioOutGetRestSample(device->hidden->port) >= device->buffer_size)) { SDL_Delay(1); } - return 0; + return true; } static Uint8 *VITAAUD_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) { - Uint8 *retval = device->hidden->mixbufs[device->hidden->next_buffer]; + Uint8 *result = device->hidden->mixbufs[device->hidden->next_buffer]; device->hidden->next_buffer = (device->hidden->next_buffer + 1) % NUM_BUFFERS; - return retval; + return result; } static void VITAAUD_CloseDevice(SDL_AudioDevice *device) { if (device->hidden) { if (device->hidden->port >= 0) { - if (device->iscapture) { + if (device->recording) { sceAudioInReleasePort(device->hidden->port); } else { sceAudioOutReleasePort(device->hidden->port); @@ -162,7 +162,7 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device) device->hidden->port = -1; } - if (!device->iscapture && device->hidden->rawbuf) { + if (!device->recording && device->hidden->rawbuf) { SDL_aligned_free(device->hidden->rawbuf); // this uses SDL_aligned_alloc(), not SDL_malloc() device->hidden->rawbuf = NULL; } @@ -171,29 +171,30 @@ static void VITAAUD_CloseDevice(SDL_AudioDevice *device) } } -static int VITAAUD_WaitCaptureDevice(SDL_AudioDevice *device) +static bool VITAAUD_WaitRecordingDevice(SDL_AudioDevice *device) { // there's only a blocking call to obtain more data, so we'll just sleep as // long as a buffer would run. const Uint64 endticks = SDL_GetTicks() + ((device->sample_frames * 1000) / device->spec.freq); - while (!SDL_AtomicGet(&device->shutdown) && (SDL_GetTicks() < endticks)) { + while (!SDL_GetAtomicInt(&device->shutdown) && (SDL_GetTicks() < endticks)) { SDL_Delay(1); } - return 0; + return true; } -static int VITAAUD_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int VITAAUD_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { int ret; SDL_assert(buflen == device->buffer_size); ret = sceAudioInInput(device->hidden->port, buffer); if (ret < 0) { - return SDL_SetError("Failed to capture from device: %x", ret); + SDL_SetError("Failed to record from device: %x", ret); + return -1; } return device->buffer_size; } -static void VITAAUD_FlushCapture(SDL_AudioDevice *device) +static void VITAAUD_FlushRecording(SDL_AudioDevice *device) { // just grab the latest and dump it. sceAudioInInput(device->hidden->port, device->work_buffer); @@ -211,7 +212,7 @@ static void VITAAUD_ThreadInit(SDL_AudioDevice *device) } } -static SDL_bool VITAAUD_Init(SDL_AudioDriverImpl *impl) +static bool VITAAUD_Init(SDL_AudioDriverImpl *impl) { impl->OpenDevice = VITAAUD_OpenDevice; impl->PlayDevice = VITAAUD_PlayDevice; @@ -219,19 +220,19 @@ static SDL_bool VITAAUD_Init(SDL_AudioDriverImpl *impl) impl->GetDeviceBuf = VITAAUD_GetDeviceBuf; impl->CloseDevice = VITAAUD_CloseDevice; impl->ThreadInit = VITAAUD_ThreadInit; - impl->WaitCaptureDevice = VITAAUD_WaitCaptureDevice; - impl->FlushCapture = VITAAUD_FlushCapture; - impl->CaptureFromDevice = VITAAUD_CaptureFromDevice; + impl->WaitRecordingDevice = VITAAUD_WaitRecordingDevice; + impl->FlushRecording = VITAAUD_FlushRecording; + impl->RecordDevice = VITAAUD_RecordDevice; - impl->HasCaptureSupport = SDL_TRUE; - impl->OnlyHasDefaultOutputDevice = SDL_TRUE; - impl->OnlyHasDefaultCaptureDevice = SDL_TRUE; + impl->HasRecordingSupport = true; + impl->OnlyHasDefaultPlaybackDevice = true; + impl->OnlyHasDefaultRecordingDevice = true; - return SDL_TRUE; + return true; } AudioBootStrap VITAAUD_bootstrap = { - "vita", "VITA audio driver", VITAAUD_Init, SDL_FALSE + "vita", "VITA audio driver", VITAAUD_Init, false }; #endif // SDL_AUDIO_DRIVER_VITA diff --git a/libs/SDL3/src/audio/wasapi/SDL_wasapi.c b/libs/SDL3/src/audio/wasapi/SDL_wasapi.c index ee1f25b7c..6c8eee6ca 100644 --- a/libs/SDL3/src/audio/wasapi/SDL_wasapi.c +++ b/libs/SDL3/src/audio/wasapi/SDL_wasapi.c @@ -46,6 +46,9 @@ // Some GUIDs we need to know without linking to libraries that aren't available before Vista. static const IID SDL_IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483, { 0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2 } }; static const IID SDL_IID_IAudioCaptureClient = { 0xc8adbd64, 0xe71e, 0x48a0, { 0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17 } }; +#ifdef __IAudioClient3_INTERFACE_DEFINED__ +static const IID SDL_IID_IAudioClient3 = { 0x7ed4ee07, 0x8e67, 0x4cd4, { 0x8c, 0x1a, 0x2b, 0x7a, 0x59, 0x87, 0xad, 0x42 } }; +#endif // // WASAPI is _really_ particular about various things happening on the same thread, for COM and such, @@ -55,7 +58,7 @@ typedef struct ManagementThreadPendingTask { ManagementThreadTask fn; void *userdata; - int result; + bool result; SDL_Semaphore *task_complete_sem; char *errorstr; struct ManagementThreadPendingTask *next; @@ -71,16 +74,16 @@ static void ManagementThreadMainloop(void) { SDL_LockMutex(ManagementThreadLock); ManagementThreadPendingTask *task; - while (((task = (ManagementThreadPendingTask *)SDL_AtomicGetPtr((void **)&ManagementThreadPendingTasks)) != NULL) || !SDL_AtomicGet(&ManagementThreadShutdown)) { + while (((task = (ManagementThreadPendingTask *)SDL_GetAtomicPointer((void **)&ManagementThreadPendingTasks)) != NULL) || !SDL_GetAtomicInt(&ManagementThreadShutdown)) { if (!task) { SDL_WaitCondition(ManagementThreadCondition, ManagementThreadLock); // block until there's something to do. } else { - SDL_AtomicSetPtr((void **) &ManagementThreadPendingTasks, task->next); // take task off the pending list. + SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, task->next); // take task off the pending list. SDL_UnlockMutex(ManagementThreadLock); // let other things add to the list while we chew on this task. task->result = task->fn(task->userdata); // run this task. if (task->task_complete_sem) { // something waiting on result? task->errorstr = SDL_strdup(SDL_GetError()); - SDL_PostSemaphore(task->task_complete_sem); + SDL_SignalSemaphore(task->task_complete_sem); } else { // nothing waiting, we're done, free it. SDL_free(task); } @@ -90,21 +93,21 @@ static void ManagementThreadMainloop(void) SDL_UnlockMutex(ManagementThreadLock); // told to shut down and out of tasks, let go of the lock and return. } -int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_on_result) +bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, bool *wait_on_result) { // We want to block for a result, but we are already running from the management thread! Just run the task now so we don't deadlock. if ((wait_on_result) && (SDL_GetCurrentThreadID() == SDL_GetThreadID(ManagementThread))) { *wait_on_result = task(userdata); - return 0; // completed! + return true; // completed! } - if (SDL_AtomicGet(&ManagementThreadShutdown)) { + if (SDL_GetAtomicInt(&ManagementThreadShutdown)) { return SDL_SetError("Can't add task, we're shutting down"); } ManagementThreadPendingTask *pending = (ManagementThreadPendingTask *)SDL_calloc(1, sizeof(ManagementThreadPendingTask)); if (!pending) { - return -1; + return false; } pending->fn = task; @@ -114,7 +117,7 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in pending->task_complete_sem = SDL_CreateSemaphore(0); if (!pending->task_complete_sem) { SDL_free(pending); - return -1; + return false; } } @@ -124,14 +127,14 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in // add to end of task list. ManagementThreadPendingTask *prev = NULL; - for (ManagementThreadPendingTask *i = (ManagementThreadPendingTask *)SDL_AtomicGetPtr((void **)&ManagementThreadPendingTasks); i; i = i->next) { + for (ManagementThreadPendingTask *i = (ManagementThreadPendingTask *)SDL_GetAtomicPointer((void **)&ManagementThreadPendingTasks); i; i = i->next) { prev = i; } if (prev) { prev->next = pending; } else { - SDL_AtomicSetPtr((void **) &ManagementThreadPendingTasks, pending); + SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, pending); } // task is added to the end of the pending list, let management thread rip! @@ -149,19 +152,19 @@ int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, in SDL_free(pending); } - return 0; // successfully added (and possibly executed)! + return true; // successfully added (and possibly executed)! } -static int ManagementThreadPrepare(void) +static bool ManagementThreadPrepare(void) { - if (WASAPI_PlatformInit() == -1) { - return -1; + if (!WASAPI_PlatformInit()) { + return false; } ManagementThreadLock = SDL_CreateMutex(); if (!ManagementThreadLock) { WASAPI_PlatformDeinit(); - return -1; + return false; } ManagementThreadCondition = SDL_CreateCondition(); @@ -169,10 +172,10 @@ static int ManagementThreadPrepare(void) SDL_DestroyMutex(ManagementThreadLock); ManagementThreadLock = NULL; WASAPI_PlatformDeinit(); - return -1; + return false; } - return 0; + return true; } typedef struct @@ -185,33 +188,33 @@ static int ManagementThreadEntry(void *userdata) { ManagementThreadEntryData *data = (ManagementThreadEntryData *)userdata; - if (ManagementThreadPrepare() < 0) { + if (!ManagementThreadPrepare()) { data->errorstr = SDL_strdup(SDL_GetError()); - SDL_PostSemaphore(data->ready_sem); // unblock calling thread. + SDL_SignalSemaphore(data->ready_sem); // unblock calling thread. return 0; } - SDL_PostSemaphore(data->ready_sem); // unblock calling thread. + SDL_SignalSemaphore(data->ready_sem); // unblock calling thread. ManagementThreadMainloop(); WASAPI_PlatformDeinit(); return 0; } -static int InitManagementThread(void) +static bool InitManagementThread(void) { ManagementThreadEntryData mgmtdata; SDL_zero(mgmtdata); mgmtdata.ready_sem = SDL_CreateSemaphore(0); if (!mgmtdata.ready_sem) { - return -1; + return false; } - SDL_AtomicSetPtr((void **) &ManagementThreadPendingTasks, NULL); - SDL_AtomicSet(&ManagementThreadShutdown, 0); - ManagementThread = SDL_CreateThreadInternal(ManagementThreadEntry, "SDLWASAPIMgmt", 256 * 1024, &mgmtdata); // !!! FIXME: maybe even smaller stack size? + SDL_SetAtomicPointer((void **) &ManagementThreadPendingTasks, NULL); + SDL_SetAtomicInt(&ManagementThreadShutdown, 0); + ManagementThread = SDL_CreateThreadWithStackSize(ManagementThreadEntry, "SDLWASAPIMgmt", 256 * 1024, &mgmtdata); // !!! FIXME: maybe even smaller stack size? if (!ManagementThread) { - return -1; + return false; } SDL_WaitSemaphore(mgmtdata.ready_sem); @@ -222,16 +225,16 @@ static int InitManagementThread(void) ManagementThread = NULL; SDL_SetError("%s", mgmtdata.errorstr); SDL_free(mgmtdata.errorstr); - return -1; + return false; } - return 0; + return true; } static void DeinitManagementThread(void) { if (ManagementThread) { - SDL_AtomicSet(&ManagementThreadShutdown, 1); + SDL_SetAtomicInt(&ManagementThreadShutdown, 1); SDL_LockMutex(ManagementThreadLock); SDL_SignalCondition(ManagementThreadCondition); SDL_UnlockMutex(ManagementThreadLock); @@ -239,99 +242,93 @@ static void DeinitManagementThread(void) ManagementThread = NULL; } - SDL_assert(SDL_AtomicGetPtr((void **) &ManagementThreadPendingTasks) == NULL); + SDL_assert(SDL_GetAtomicPointer((void **) &ManagementThreadPendingTasks) == NULL); SDL_DestroyCondition(ManagementThreadCondition); SDL_DestroyMutex(ManagementThreadLock); ManagementThreadCondition = NULL; ManagementThreadLock = NULL; - SDL_AtomicSet(&ManagementThreadShutdown, 0); + SDL_SetAtomicInt(&ManagementThreadShutdown, 0); } typedef struct { - SDL_AudioDevice **default_output; - SDL_AudioDevice **default_capture; + SDL_AudioDevice **default_playback; + SDL_AudioDevice **default_recording; } mgmtthrtask_DetectDevicesData; -static int mgmtthrtask_DetectDevices(void *userdata) +static bool mgmtthrtask_DetectDevices(void *userdata) { mgmtthrtask_DetectDevicesData *data = (mgmtthrtask_DetectDevicesData *)userdata; - WASAPI_EnumerateEndpoints(data->default_output, data->default_capture); - return 0; + WASAPI_EnumerateEndpoints(data->default_playback, data->default_recording); + return true; } -static void WASAPI_DetectDevices(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +static void WASAPI_DetectDevices(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - int rc; + bool rc; // this blocks because it needs to finish before the audio subsystem inits mgmtthrtask_DetectDevicesData data; - data.default_output = default_output; - data.default_capture = default_capture; + data.default_playback = default_playback; + data.default_recording = default_recording; WASAPI_ProxyToManagementThread(mgmtthrtask_DetectDevices, &data, &rc); } -static int mgmtthrtask_DisconnectDevice(void *userdata) +static bool mgmtthrtask_DisconnectDevice(void *userdata) { SDL_AudioDeviceDisconnected((SDL_AudioDevice *)userdata); - return 0; + return true; } void WASAPI_DisconnectDevice(SDL_AudioDevice *device) { - int rc; // block on this; don't disconnect while holding the device lock! + bool rc; // block on this; don't disconnect while holding the device lock! WASAPI_ProxyToManagementThread(mgmtthrtask_DisconnectDevice, device, &rc); } -static SDL_bool WasapiFailed(SDL_AudioDevice *device, const HRESULT err) +static bool WasapiFailed(SDL_AudioDevice *device, const HRESULT err) { if (err == S_OK) { - return SDL_FALSE; + return false; } else if (err == AUDCLNT_E_DEVICE_INVALIDATED) { - device->hidden->device_lost = SDL_TRUE; + device->hidden->device_lost = true; } else { - device->hidden->device_dead = SDL_TRUE; + device->hidden->device_dead = true; } - return SDL_TRUE; + return true; } -static int mgmtthrtask_StopAndReleaseClient(void *userdata) +static bool mgmtthrtask_StopAndReleaseClient(void *userdata) { IAudioClient *client = (IAudioClient *) userdata; IAudioClient_Stop(client); IAudioClient_Release(client); - return 0; + return true; } -static int mgmtthrtask_ReleaseCaptureClient(void *userdata) +static bool mgmtthrtask_ReleaseCaptureClient(void *userdata) { IAudioCaptureClient_Release((IAudioCaptureClient *)userdata); - return 0; + return true; } -static int mgmtthrtask_ReleaseRenderClient(void *userdata) +static bool mgmtthrtask_ReleaseRenderClient(void *userdata) { IAudioRenderClient_Release((IAudioRenderClient *)userdata); - return 0; + return true; } -static int mgmtthrtask_CoTaskMemFree(void *userdata) +static bool mgmtthrtask_CoTaskMemFree(void *userdata) { CoTaskMemFree(userdata); - return 0; + return true; } -static int mgmtthrtask_PlatformDeleteActivationHandler(void *userdata) -{ - WASAPI_PlatformDeleteActivationHandler(userdata); - return 0; -} - -static int mgmtthrtask_CloseHandle(void *userdata) +static bool mgmtthrtask_CloseHandle(void *userdata) { CloseHandle((HANDLE) userdata); - return 0; + return true; } static void ResetWasapiDevice(SDL_AudioDevice *device) @@ -367,12 +364,6 @@ static void ResetWasapiDevice(SDL_AudioDevice *device) WASAPI_ProxyToManagementThread(mgmtthrtask_CoTaskMemFree, ptr, NULL); } - if (device->hidden->activation_handler) { - void *activation_handler = device->hidden->activation_handler; - device->hidden->activation_handler = NULL; - WASAPI_ProxyToManagementThread(mgmtthrtask_PlatformDeleteActivationHandler, activation_handler, NULL); - } - if (device->hidden->event) { HANDLE event = device->hidden->event; device->hidden->event = NULL; @@ -380,52 +371,52 @@ static void ResetWasapiDevice(SDL_AudioDevice *device) } } -static int mgmtthrtask_ActivateDevice(void *userdata) +static bool mgmtthrtask_ActivateDevice(void *userdata) { return WASAPI_ActivateDevice((SDL_AudioDevice *)userdata); } -static int ActivateWasapiDevice(SDL_AudioDevice *device) +static bool ActivateWasapiDevice(SDL_AudioDevice *device) { // this blocks because we're either being notified from a background thread or we're running during device open, // both of which won't deadlock vs the device thread. - int rc = -1; - return ((WASAPI_ProxyToManagementThread(mgmtthrtask_ActivateDevice, device, &rc) < 0) || (rc < 0)) ? -1 : 0; + bool rc = false; + return (WASAPI_ProxyToManagementThread(mgmtthrtask_ActivateDevice, device, &rc) && rc); } // do not call when holding the device lock! -static SDL_bool RecoverWasapiDevice(SDL_AudioDevice *device) +static bool RecoverWasapiDevice(SDL_AudioDevice *device) { ResetWasapiDevice(device); // dump the lost device's handles. // This handles a non-default device that simply had its format changed in the Windows Control Panel. - if (ActivateWasapiDevice(device) == -1) { + if (!ActivateWasapiDevice(device)) { WASAPI_DisconnectDevice(device); - return SDL_FALSE; + return false; } - device->hidden->device_lost = SDL_FALSE; + device->hidden->device_lost = false; - return SDL_TRUE; // okay, carry on with new device details! + return true; // okay, carry on with new device details! } // do not call when holding the device lock! -static SDL_bool RecoverWasapiIfLost(SDL_AudioDevice *device) +static bool RecoverWasapiIfLost(SDL_AudioDevice *device) { - if (SDL_AtomicGet(&device->shutdown)) { - return SDL_FALSE; // already failed. + if (SDL_GetAtomicInt(&device->shutdown)) { + return false; // already failed. } else if (device->hidden->device_dead) { // had a fatal error elsewhere, clean up and quit IAudioClient_Stop(device->hidden->client); WASAPI_DisconnectDevice(device); - SDL_assert(SDL_AtomicGet(&device->shutdown)); // so we don't come back through here. - return SDL_FALSE; // already failed. - } else if (SDL_AtomicGet(&device->zombie)) { - return SDL_FALSE; // we're already dead, so just leave and let the Zombie implementations take over. + SDL_assert(SDL_GetAtomicInt(&device->shutdown)); // so we don't come back through here. + return false; // already failed. + } else if (SDL_GetAtomicInt(&device->zombie)) { + return false; // we're already dead, so just leave and let the Zombie implementations take over. } else if (!device->hidden->client) { - return SDL_TRUE; // still waiting for activation. + return true; // still waiting for activation. } - return device->hidden->device_lost ? RecoverWasapiDevice(device) : SDL_TRUE; + return device->hidden->device_lost ? RecoverWasapiDevice(device) : true; } static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) @@ -449,42 +440,61 @@ static Uint8 *WASAPI_GetDeviceBuf(SDL_AudioDevice *device, int *buffer_size) return (Uint8 *)buffer; } -static int WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) +static bool WASAPI_PlayDevice(SDL_AudioDevice *device, const Uint8 *buffer, int buflen) { if (device->hidden->render) { // definitely activated? // WasapiFailed() will mark the device for reacquisition or removal elsewhere. WasapiFailed(device, IAudioRenderClient_ReleaseBuffer(device->hidden->render, device->sample_frames, 0)); } - return 0; + return true; } -static int WASAPI_WaitDevice(SDL_AudioDevice *device) +static bool WASAPI_WaitDevice(SDL_AudioDevice *device) { // WaitDevice does not hold the device lock, so check for recovery/disconnect details here. while (RecoverWasapiIfLost(device) && device->hidden->client && device->hidden->event) { - DWORD waitResult = WaitForSingleObjectEx(device->hidden->event, 200, FALSE); - if (waitResult == WAIT_OBJECT_0) { - const UINT32 maxpadding = device->sample_frames; + if (device->recording) { + // Recording devices should return immediately if there is any data available UINT32 padding = 0; if (!WasapiFailed(device, IAudioClient_GetCurrentPadding(device->hidden->client, &padding))) { - //SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding);*/ - if (device->iscapture && (padding > 0)) { - break; - } else if (!device->iscapture && (padding <= maxpadding)) { + //SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding); + if (padding > 0) { break; } } - } else if (waitResult != WAIT_TIMEOUT) { - //SDL_Log("WASAPI FAILED EVENT!");*/ - IAudioClient_Stop(device->hidden->client); - return -1; + + switch (WaitForSingleObjectEx(device->hidden->event, 200, FALSE)) { + case WAIT_OBJECT_0: + case WAIT_TIMEOUT: + break; + + default: + //SDL_Log("WASAPI FAILED EVENT!"); + IAudioClient_Stop(device->hidden->client); + return false; + } + } else { + DWORD waitResult = WaitForSingleObjectEx(device->hidden->event, 200, FALSE); + if (waitResult == WAIT_OBJECT_0) { + UINT32 padding = 0; + if (!WasapiFailed(device, IAudioClient_GetCurrentPadding(device->hidden->client, &padding))) { + //SDL_Log("WASAPI EVENT! padding=%u maxpadding=%u", (unsigned int)padding, (unsigned int)maxpadding); + if (padding <= (UINT32)device->sample_frames) { + break; + } + } + } else if (waitResult != WAIT_TIMEOUT) { + //SDL_Log("WASAPI FAILED EVENT!");*/ + IAudioClient_Stop(device->hidden->client); + return false; + } } } - return 0; + return true; } -static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int buflen) +static int WASAPI_RecordDevice(SDL_AudioDevice *device, void *buffer, int buflen) { BYTE *ptr = NULL; UINT32 frames = 0; @@ -502,7 +512,7 @@ static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b const int total = ((int)frames) * device->hidden->framesize; const int cpy = SDL_min(buflen, total); const int leftover = total - cpy; - const SDL_bool silent = (flags & AUDCLNT_BUFFERFLAGS_SILENT) ? SDL_TRUE : SDL_FALSE; + const bool silent = (flags & AUDCLNT_BUFFERFLAGS_SILENT) ? true : false; SDL_assert(leftover == 0); // according to MSDN, this isn't everything available, just one "packet" of data per-GetBuffer call. @@ -521,14 +531,14 @@ static int WASAPI_CaptureFromDevice(SDL_AudioDevice *device, void *buffer, int b return -1; // unrecoverable error. } -static void WASAPI_FlushCapture(SDL_AudioDevice *device) +static void WASAPI_FlushRecording(SDL_AudioDevice *device) { BYTE *ptr = NULL; UINT32 frames = 0; DWORD flags = 0; // just read until we stop getting packets, throwing them away. - while (!SDL_AtomicGet(&device->shutdown) && device->hidden->capture) { + while (!SDL_GetAtomicInt(&device->shutdown) && device->hidden->capture) { const HRESULT ret = IAudioCaptureClient_GetBuffer(device->hidden->capture, &ptr, &frames, &flags, NULL, NULL); if (ret == AUDCLNT_S_BUFFER_EMPTY) { break; // no more buffered data; we're done. @@ -550,7 +560,7 @@ static void WASAPI_CloseDevice(SDL_AudioDevice *device) } } -static int mgmtthrtask_PrepDevice(void *userdata) +static bool mgmtthrtask_PrepDevice(void *userdata) { SDL_AudioDevice *device = (SDL_AudioDevice *)userdata; @@ -570,7 +580,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) IAudioClient *client = device->hidden->client; SDL_assert(client != NULL); -#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP. +#if defined(SDL_PLATFORM_GDK) // CreateEventEx() arrived in Vista, so we need an #ifdef for XP. device->hidden->event = CreateEventEx(NULL, NULL, 0, EVENT_ALL_ACCESS); #else device->hidden->event = CreateEventW(NULL, 0, 0, NULL); @@ -632,7 +642,42 @@ static int mgmtthrtask_PrepDevice(void *userdata) newspec.freq = waveformat->nSamplesPerSec; streamflags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK; - ret = IAudioClient_Initialize(client, sharemode, streamflags, 0, 0, waveformat, NULL); + + int new_sample_frames = 0; + bool iaudioclient3_initialized = false; + +#ifdef __IAudioClient3_INTERFACE_DEFINED__ + // Try querying IAudioClient3 if sharemode is AUDCLNT_SHAREMODE_SHARED + if (sharemode == AUDCLNT_SHAREMODE_SHARED) { + IAudioClient3 *client3 = NULL; + ret = IAudioClient_QueryInterface(client, &SDL_IID_IAudioClient3, (void**)&client3); + if (SUCCEEDED(ret)) { + UINT32 default_period_in_frames = 0; + UINT32 fundamental_period_in_frames = 0; + UINT32 min_period_in_frames = 0; + UINT32 max_period_in_frames = 0; + ret = IAudioClient3_GetSharedModeEnginePeriod(client3, waveformat, + &default_period_in_frames, &fundamental_period_in_frames, &min_period_in_frames, &max_period_in_frames); + if (SUCCEEDED(ret)) { + // IAudioClient3_InitializeSharedAudioStream only accepts the integral multiple of fundamental_period_in_frames + UINT32 period_in_frames = fundamental_period_in_frames * (UINT32)SDL_round((double)device->sample_frames / fundamental_period_in_frames); + period_in_frames = SDL_clamp(period_in_frames, min_period_in_frames, max_period_in_frames); + + ret = IAudioClient3_InitializeSharedAudioStream(client3, streamflags, period_in_frames, waveformat, NULL); + if (SUCCEEDED(ret)) { + new_sample_frames = (int)period_in_frames; + iaudioclient3_initialized = true; + } + } + + IAudioClient3_Release(client3); + } + } +#endif + + if (!iaudioclient3_initialized) + ret = IAudioClient_Initialize(client, sharemode, streamflags, 0, 0, waveformat, NULL); + if (FAILED(ret)) { return WIN_SetErrorFromHRESULT("WASAPI can't initialize audio client", ret); } @@ -650,9 +695,11 @@ static int mgmtthrtask_PrepDevice(void *userdata) // Match the callback size to the period size to cut down on the number of // interrupts waited for in each call to WaitDevice - const float period_millis = default_period / 10000.0f; - const float period_frames = period_millis * newspec.freq / 1000.0f; - int new_sample_frames = (int) SDL_ceilf(period_frames); + if (new_sample_frames <= 0) { + const float period_millis = default_period / 10000.0f; + const float period_frames = period_millis * newspec.freq / 1000.0f; + new_sample_frames = (int) SDL_ceilf(period_frames); + } // regardless of what we calculated for the period size, clamp it to the expected hardware buffer size. if (new_sample_frames > (int) bufsize) { @@ -660,13 +707,13 @@ static int mgmtthrtask_PrepDevice(void *userdata) } // Update the fragment size as size in bytes - if (SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames) < 0) { - return -1; + if (!SDL_AudioDeviceFormatChangedAlreadyLocked(device, &newspec, new_sample_frames)) { + return false; } device->hidden->framesize = SDL_AUDIO_FRAMESIZE(device->spec); - if (device->iscapture) { + if (device->recording) { IAudioCaptureClient *capture = NULL; ret = IAudioClient_GetService(client, &SDL_IID_IAudioCaptureClient, (void **)&capture); if (FAILED(ret)) { @@ -680,7 +727,7 @@ static int mgmtthrtask_PrepDevice(void *userdata) return WIN_SetErrorFromHRESULT("WASAPI can't start capture", ret); } - WASAPI_FlushCapture(device); // MSDN says you should flush capture endpoint right after startup. + WASAPI_FlushRecording(device); // MSDN says you should flush the recording endpoint right after startup. } else { IAudioRenderClient *render = NULL; ret = IAudioClient_GetService(client, &SDL_IID_IAudioRenderClient, (void **)&render); @@ -696,32 +743,32 @@ static int mgmtthrtask_PrepDevice(void *userdata) } } - return 0; // good to go. + return true; // good to go. } // This is called once a device is activated, possibly asynchronously. -int WASAPI_PrepDevice(SDL_AudioDevice *device) +bool WASAPI_PrepDevice(SDL_AudioDevice *device) { - int rc = 0; - return (WASAPI_ProxyToManagementThread(mgmtthrtask_PrepDevice, device, &rc) < 0) ? -1 : rc; + bool rc = true; + return (WASAPI_ProxyToManagementThread(mgmtthrtask_PrepDevice, device, &rc) && rc); } -static int WASAPI_OpenDevice(SDL_AudioDevice *device) +static bool WASAPI_OpenDevice(SDL_AudioDevice *device) { // Initialize all variables that we clean on shutdown device->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, sizeof(*device->hidden)); if (!device->hidden) { - return -1; - } else if (ActivateWasapiDevice(device) < 0) { - return -1; // already set error. + return false; + } else if (!ActivateWasapiDevice(device)) { + return false; // already set error. } /* Ready, but possibly waiting for async device activation. - Until activation is successful, we will report silence from capture + Until activation is successful, we will report silence from recording devices and ignore data on playback devices. Upon activation, we'll make sure any bound audio streams are adjusted for the final device format. */ - return 0; + return true; } static void WASAPI_ThreadInit(SDL_AudioDevice *device) @@ -734,27 +781,27 @@ static void WASAPI_ThreadDeinit(SDL_AudioDevice *device) WASAPI_PlatformThreadDeinit(device); } -static int mgmtthrtask_FreeDeviceHandle(void *userdata) +static bool mgmtthrtask_FreeDeviceHandle(void *userdata) { WASAPI_PlatformFreeDeviceHandle((SDL_AudioDevice *)userdata); - return 0; + return true; } static void WASAPI_FreeDeviceHandle(SDL_AudioDevice *device) { - int rc; + bool rc; WASAPI_ProxyToManagementThread(mgmtthrtask_FreeDeviceHandle, device, &rc); } -static int mgmtthrtask_DeinitializeStart(void *userdata) +static bool mgmtthrtask_DeinitializeStart(void *userdata) { WASAPI_PlatformDeinitializeStart(); - return 0; + return true; } static void WASAPI_DeinitializeStart(void) { - int rc; + bool rc; WASAPI_ProxyToManagementThread(mgmtthrtask_DeinitializeStart, NULL, &rc); } @@ -763,10 +810,10 @@ static void WASAPI_Deinitialize(void) DeinitManagementThread(); } -static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl) +static bool WASAPI_Init(SDL_AudioDriverImpl *impl) { - if (InitManagementThread() < 0) { - return SDL_FALSE; + if (!InitManagementThread()) { + return false; } impl->DetectDevices = WASAPI_DetectDevices; @@ -776,21 +823,21 @@ static SDL_bool WASAPI_Init(SDL_AudioDriverImpl *impl) impl->PlayDevice = WASAPI_PlayDevice; impl->WaitDevice = WASAPI_WaitDevice; impl->GetDeviceBuf = WASAPI_GetDeviceBuf; - impl->WaitCaptureDevice = WASAPI_WaitDevice; - impl->CaptureFromDevice = WASAPI_CaptureFromDevice; - impl->FlushCapture = WASAPI_FlushCapture; + impl->WaitRecordingDevice = WASAPI_WaitDevice; + impl->RecordDevice = WASAPI_RecordDevice; + impl->FlushRecording = WASAPI_FlushRecording; impl->CloseDevice = WASAPI_CloseDevice; impl->DeinitializeStart = WASAPI_DeinitializeStart; impl->Deinitialize = WASAPI_Deinitialize; impl->FreeDeviceHandle = WASAPI_FreeDeviceHandle; - impl->HasCaptureSupport = SDL_TRUE; + impl->HasRecordingSupport = true; - return SDL_TRUE; + return true; } AudioBootStrap WASAPI_bootstrap = { - "wasapi", "WASAPI", WASAPI_Init, SDL_FALSE + "wasapi", "WASAPI", WASAPI_Init, false }; #endif // SDL_AUDIO_DRIVER_WASAPI diff --git a/libs/SDL3/src/audio/wasapi/SDL_wasapi.h b/libs/SDL3/src/audio/wasapi/SDL_wasapi.h index 45a817351..3d4744cf1 100644 --- a/libs/SDL3/src/audio/wasapi/SDL_wasapi.h +++ b/libs/SDL3/src/audio/wasapi/SDL_wasapi.h @@ -38,32 +38,30 @@ struct SDL_PrivateAudioData IAudioCaptureClient *capture; HANDLE event; HANDLE task; - SDL_bool coinitialized; + bool coinitialized; int framesize; - SDL_bool device_lost; - SDL_bool device_dead; - void *activation_handler; + bool device_lost; + bool device_dead; }; -// win32 and winrt implementations call into these. -int WASAPI_PrepDevice(SDL_AudioDevice *device); +// win32 implementation calls into these. +bool WASAPI_PrepDevice(SDL_AudioDevice *device); void WASAPI_DisconnectDevice(SDL_AudioDevice *device); // don't hold the device lock when calling this! // BE CAREFUL: if you are holding the device lock and proxy to the management thread with wait_until_complete, and grab the lock again, you will deadlock. -typedef int (*ManagementThreadTask)(void *userdata); -int WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, int *wait_until_complete); +typedef bool (*ManagementThreadTask)(void *userdata); +bool WASAPI_ProxyToManagementThread(ManagementThreadTask task, void *userdata, bool *wait_until_complete); -// These are functions that are implemented differently for Windows vs WinRT. +// These are functions that are (were...?) implemented differently for various Windows versions. // UNLESS OTHERWISE NOTED THESE ALL HAPPEN ON THE MANAGEMENT THREAD. -int WASAPI_PlatformInit(void); +bool WASAPI_PlatformInit(void); void WASAPI_PlatformDeinit(void); void WASAPI_PlatformDeinitializeStart(void); -void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); -int WASAPI_ActivateDevice(SDL_AudioDevice *device); +void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording); +bool WASAPI_ActivateDevice(SDL_AudioDevice *device); void WASAPI_PlatformThreadInit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread. void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device); // this happens on the audio device thread, not the management thread. -void WASAPI_PlatformDeleteActivationHandler(void *handler); void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device); #ifdef __cplusplus diff --git a/libs/SDL3/src/audio/wasapi/SDL_wasapi_win32.c b/libs/SDL3/src/audio/wasapi/SDL_wasapi_win32.c index c72c54b4d..5ef776d43 100644 --- a/libs/SDL3/src/audio/wasapi/SDL_wasapi_win32.c +++ b/libs/SDL3/src/audio/wasapi/SDL_wasapi_win32.c @@ -20,13 +20,14 @@ */ #include "SDL_internal.h" -/* This is code that Windows uses to talk to WASAPI-related system APIs. +/* !!! FIXME: merge this all into SDL_wasapi.c, now that WinRT is gone. + This is code that Windows uses to talk to WASAPI-related system APIs. This is for non-WinRT desktop apps. The C++/CX implementation of these functions, exclusive to WinRT, are in SDL_wasapi_winrt.cpp. The code in SDL_wasapi.c is used by both standard Windows and WinRT builds to deal with audio and calls into these functions. */ -#if defined(SDL_AUDIO_DRIVER_WASAPI) && !defined(SDL_PLATFORM_WINRT) +#if defined(SDL_AUDIO_DRIVER_WASAPI) #include "../../core/windows/SDL_windows.h" #include "../../core/windows/SDL_immdevice.h" @@ -43,17 +44,17 @@ typedef BOOL(WINAPI *pfnAvRevertMmThreadCharacteristics)(HANDLE); static pfnAvSetMmThreadCharacteristicsW pAvSetMmThreadCharacteristicsW = NULL; static pfnAvRevertMmThreadCharacteristics pAvRevertMmThreadCharacteristics = NULL; -static SDL_bool immdevice_initialized = SDL_FALSE; +static bool immdevice_initialized = false; // Some GUIDs we need to know without linking to libraries that aren't available before Vista. static const IID SDL_IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, { 0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2 } }; -static int mgmtthrtask_AudioDeviceDisconnected(void *userdata) +static bool mgmtthrtask_AudioDeviceDisconnected(void *userdata) { SDL_AudioDevice *device = (SDL_AudioDevice *) userdata; SDL_AudioDeviceDisconnected(device); UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes. - return 0; + return true; } static void WASAPI_AudioDeviceDisconnected(SDL_AudioDevice *device) @@ -65,12 +66,12 @@ static void WASAPI_AudioDeviceDisconnected(SDL_AudioDevice *device) } } -static int mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) +static bool mgmtthrtask_DefaultAudioDeviceChanged(void *userdata) { SDL_AudioDevice *device = (SDL_AudioDevice *) userdata; SDL_DefaultAudioDeviceChanged(device); UnrefPhysicalAudioDevice(device); // make sure this lived until the task completes. - return 0; + return true; } static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device) @@ -82,16 +83,16 @@ static void WASAPI_DefaultAudioDeviceChanged(SDL_AudioDevice *new_default_device } } -int WASAPI_PlatformInit(void) +bool WASAPI_PlatformInit(void) { const SDL_IMMDevice_callbacks callbacks = { WASAPI_AudioDeviceDisconnected, WASAPI_DefaultAudioDeviceChanged }; if (FAILED(WIN_CoInitialize())) { return SDL_SetError("CoInitialize() failed"); - } else if (SDL_IMMDevice_Init(&callbacks) < 0) { - return -1; // Error string is set by SDL_IMMDevice_Init + } else if (!SDL_IMMDevice_Init(&callbacks)) { + return false; // Error string is set by SDL_IMMDevice_Init } - immdevice_initialized = SDL_TRUE; + immdevice_initialized = true; libavrt = LoadLibrary(TEXT("avrt.dll")); // this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! if (libavrt) { @@ -99,14 +100,14 @@ int WASAPI_PlatformInit(void) pAvRevertMmThreadCharacteristics = (pfnAvRevertMmThreadCharacteristics)GetProcAddress(libavrt, "AvRevertMmThreadCharacteristics"); } - return 0; + return true; } static void StopWasapiHotplug(void) { if (immdevice_initialized) { SDL_IMMDevice_Quit(); - immdevice_initialized = SDL_FALSE; + immdevice_initialized = false; } } @@ -134,7 +135,7 @@ void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) { // this thread uses COM. if (SUCCEEDED(WIN_CoInitialize())) { // can't report errors, hope it worked! - device->hidden->coinitialized = SDL_TRUE; + device->hidden->coinitialized = true; } // Set this thread to very high "Pro Audio" priority. @@ -142,7 +143,7 @@ void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) DWORD idx = 0; device->hidden->task = pAvSetMmThreadCharacteristicsW(L"Pro Audio", &idx); } else { - SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); + SDL_SetCurrentThreadPriority(device->recording ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); } } @@ -157,16 +158,16 @@ void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device) if (device->hidden->coinitialized) { WIN_CoUninitialize(); - device->hidden->coinitialized = SDL_FALSE; + device->hidden->coinitialized = false; } } -int WASAPI_ActivateDevice(SDL_AudioDevice *device) +bool WASAPI_ActivateDevice(SDL_AudioDevice *device) { IMMDevice *immdevice = NULL; - if (SDL_IMMDevice_Get(device, &immdevice, device->iscapture) < 0) { + if (!SDL_IMMDevice_Get(device, &immdevice, device->recording)) { device->hidden->client = NULL; - return -1; // This is already set by SDL_IMMDevice_Get + return false; // This is already set by SDL_IMMDevice_Get } // this is _not_ async in standard win32, yay! @@ -179,22 +180,16 @@ int WASAPI_ActivateDevice(SDL_AudioDevice *device) } SDL_assert(device->hidden->client != NULL); - if (WASAPI_PrepDevice(device) == -1) { // not async, fire it right away. - return -1; + if (!WASAPI_PrepDevice(device)) { // not async, fire it right away. + return false; } - return 0; // good to go. + return true; // good to go. } -void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - SDL_IMMDevice_EnumerateEndpoints(default_output, default_capture); -} - -void WASAPI_PlatformDeleteActivationHandler(void *handler) -{ - // not asynchronous. - SDL_assert(!"This function should have only been called on WinRT."); + SDL_IMMDevice_EnumerateEndpoints(default_playback, default_recording); } void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) @@ -202,4 +197,4 @@ void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) SDL_IMMDevice_FreeDeviceHandle(device); } -#endif // SDL_AUDIO_DRIVER_WASAPI && !defined(SDL_PLATFORM_WINRT) +#endif // SDL_AUDIO_DRIVER_WASAPI diff --git a/libs/SDL3/src/audio/wasapi/SDL_wasapi_winrt.cpp b/libs/SDL3/src/audio/wasapi/SDL_wasapi_winrt.cpp deleted file mode 100644 index 700f5cf51..000000000 --- a/libs/SDL3/src/audio/wasapi/SDL_wasapi_winrt.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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" - -// This is C++/CX code that the WinRT port uses to talk to WASAPI-related -// system APIs. The C implementation of these functions, for non-WinRT apps, -// is in SDL_wasapi_win32.c. The code in SDL_wasapi.c is used by both standard -// Windows and WinRT builds to deal with audio and calls into these functions. - -#if defined(SDL_AUDIO_DRIVER_WASAPI) && defined(SDL_PLATFORM_WINRT) - -#include -#include -#include -#include -#include -#include - -extern "C" { -#include "../../core/windows/SDL_windows.h" -#include "../SDL_sysaudio.h" -} - -#define COBJMACROS -#include -#include - -#include "SDL_wasapi.h" - -using namespace Windows::Devices::Enumeration; -using namespace Windows::Media::Devices; -using namespace Windows::Foundation; -using namespace Microsoft::WRL; - -static Platform::String ^ SDL_PKEY_AudioEngine_DeviceFormat = L"{f19f064d-082c-4e27-bc73-6882a1bb8e4c} 0"; - - -static SDL_bool FindWinRTAudioDeviceCallback(SDL_AudioDevice *device, void *userdata) -{ - return (SDL_wcscmp((LPCWSTR) device->handle, (LPCWSTR) userdata) == 0); -} - -static SDL_AudioDevice *FindWinRTAudioDevice(LPCWSTR devid) -{ - return SDL_FindPhysicalAudioDeviceByCallback(FindWinRTAudioDeviceCallback, (void *) devid); -} - -class SDL_WasapiDeviceEventHandler -{ - public: - SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture); - ~SDL_WasapiDeviceEventHandler(); - void OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ args); - void OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args); - void OnDeviceUpdated(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args); - void OnEnumerationCompleted(DeviceWatcher ^ sender, Platform::Object ^ args); - void OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args); - void OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args); - void WaitForCompletion(); - - private: - SDL_Semaphore *completed_semaphore; - const SDL_bool iscapture; - DeviceWatcher ^ watcher; - Windows::Foundation::EventRegistrationToken added_handler; - Windows::Foundation::EventRegistrationToken removed_handler; - Windows::Foundation::EventRegistrationToken updated_handler; - Windows::Foundation::EventRegistrationToken completed_handler; - Windows::Foundation::EventRegistrationToken default_changed_handler; -}; - -SDL_WasapiDeviceEventHandler::SDL_WasapiDeviceEventHandler(const SDL_bool _iscapture) - : iscapture(_iscapture), completed_semaphore(SDL_CreateSemaphore(0)) -{ - if (!completed_semaphore) { - return; // uhoh. - } - - Platform::String ^ selector = _iscapture ? MediaDevice::GetAudioCaptureSelector() : MediaDevice::GetAudioRenderSelector(); - Platform::Collections::Vector properties; - properties.Append(SDL_PKEY_AudioEngine_DeviceFormat); - watcher = DeviceInformation::CreateWatcher(selector, properties.GetView()); - if (!watcher) - return; // uhoh. - - // !!! FIXME: this doesn't need a lambda here, I think, if I make SDL_WasapiDeviceEventHandler a proper C++/CX class. --ryan. - added_handler = watcher->Added += ref new TypedEventHandler([this](DeviceWatcher ^ sender, DeviceInformation ^ args) { OnDeviceAdded(sender, args); }); - removed_handler = watcher->Removed += ref new TypedEventHandler([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceRemoved(sender, args); }); - updated_handler = watcher->Updated += ref new TypedEventHandler([this](DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) { OnDeviceUpdated(sender, args); }); - completed_handler = watcher->EnumerationCompleted += ref new TypedEventHandler([this](DeviceWatcher ^ sender, Platform::Object ^ args) { OnEnumerationCompleted(sender, args); }); - if (iscapture) { - default_changed_handler = MediaDevice::DefaultAudioCaptureDeviceChanged += ref new TypedEventHandler([this](Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) { OnDefaultCaptureDeviceChanged(sender, args); }); - } else { - default_changed_handler = MediaDevice::DefaultAudioRenderDeviceChanged += ref new TypedEventHandler([this](Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) { OnDefaultRenderDeviceChanged(sender, args); }); - } - watcher->Start(); -} - -SDL_WasapiDeviceEventHandler::~SDL_WasapiDeviceEventHandler() -{ - if (watcher) { - watcher->Added -= added_handler; - watcher->Removed -= removed_handler; - watcher->Updated -= updated_handler; - watcher->EnumerationCompleted -= completed_handler; - watcher->Stop(); - watcher = nullptr; - } - - if (completed_semaphore) { - SDL_DestroySemaphore(completed_semaphore); - completed_semaphore = nullptr; - } - - if (iscapture) { - MediaDevice::DefaultAudioCaptureDeviceChanged -= default_changed_handler; - } else { - MediaDevice::DefaultAudioRenderDeviceChanged -= default_changed_handler; - } -} - -void SDL_WasapiDeviceEventHandler::OnDeviceAdded(DeviceWatcher ^ sender, DeviceInformation ^ info) -{ - /* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever). - In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for - phones and tablets, where you might have an internal speaker and a headphone jack and expect both to be - available and switch automatically. (!!! FIXME...?) */ - - SDL_assert(sender == this->watcher); - char *utf8dev = WIN_StringToUTF8(info->Name->Data()); - if (utf8dev) { - SDL_AudioSpec spec; - SDL_zero(spec); - - Platform::Object ^ obj = info->Properties->Lookup(SDL_PKEY_AudioEngine_DeviceFormat); - if (obj) { - IPropertyValue ^ property = (IPropertyValue ^) obj; - Platform::Array ^ data; - property->GetUInt8Array(&data); - WAVEFORMATEXTENSIBLE fmt; - SDL_zero(fmt); - SDL_memcpy(&fmt, data->Data, SDL_min(data->Length, sizeof(WAVEFORMATEXTENSIBLE))); - spec.channels = (Uint8)fmt.Format.nChannels; - spec.freq = fmt.Format.nSamplesPerSec; - spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)&fmt); - } - - LPWSTR devid = SDL_wcsdup(info->Id->Data()); - if (devid) { - SDL_AddAudioDevice(this->iscapture, utf8dev, spec.channels ? &spec : NULL, devid); - } - SDL_free(utf8dev); - } -} - -void SDL_WasapiDeviceEventHandler::OnDeviceRemoved(DeviceWatcher ^ sender, DeviceInformationUpdate ^ info) -{ - SDL_assert(sender == this->watcher); - WASAPI_DisconnectDevice(FindWinRTAudioDevice(info->Id->Data())); -} - -void SDL_WasapiDeviceEventHandler::OnDeviceUpdated(DeviceWatcher ^ sender, DeviceInformationUpdate ^ args) -{ - SDL_assert(sender == this->watcher); -} - -void SDL_WasapiDeviceEventHandler::OnEnumerationCompleted(DeviceWatcher ^ sender, Platform::Object ^ args) -{ - SDL_assert(sender == this->watcher); - if (this->completed_semaphore) { - SDL_PostSemaphore(this->completed_semaphore); - } -} - -void SDL_WasapiDeviceEventHandler::OnDefaultRenderDeviceChanged(Platform::Object ^ sender, DefaultAudioRenderDeviceChangedEventArgs ^ args) -{ - SDL_assert(!this->iscapture); - SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data())); -} - -void SDL_WasapiDeviceEventHandler::OnDefaultCaptureDeviceChanged(Platform::Object ^ sender, DefaultAudioCaptureDeviceChangedEventArgs ^ args) -{ - SDL_assert(this->iscapture); - SDL_DefaultAudioDeviceChanged(FindWinRTAudioDevice(args->Id->Data())); -} - -void SDL_WasapiDeviceEventHandler::WaitForCompletion() -{ - if (this->completed_semaphore) { - SDL_WaitSemaphore(this->completed_semaphore); - SDL_DestroySemaphore(this->completed_semaphore); - this->completed_semaphore = nullptr; - } -} - -static SDL_WasapiDeviceEventHandler *playback_device_event_handler; -static SDL_WasapiDeviceEventHandler *capture_device_event_handler; - -int WASAPI_PlatformInit(void) -{ - return 0; -} - -static void StopWasapiHotplug(void) -{ - delete playback_device_event_handler; - playback_device_event_handler = nullptr; - delete capture_device_event_handler; - capture_device_event_handler = nullptr; -} - -void WASAPI_PlatformDeinit(void) -{ - StopWasapiHotplug(); -} - -void WASAPI_PlatformDeinitializeStart(void) -{ - StopWasapiHotplug(); -} - - -void WASAPI_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) -{ - Platform::String ^ defdevid; - - // DeviceWatchers will fire an Added event for each existing device at - // startup, so we don't need to enumerate them separately before - // listening for updates. - playback_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_FALSE); - playback_device_event_handler->WaitForCompletion(); - defdevid = MediaDevice::GetDefaultAudioRenderId(AudioDeviceRole::Default); - if (defdevid) { - *default_output = FindWinRTAudioDevice(defdevid->Data()); - } - - capture_device_event_handler = new SDL_WasapiDeviceEventHandler(SDL_TRUE); - capture_device_event_handler->WaitForCompletion(); - defdevid = MediaDevice::GetDefaultAudioCaptureId(AudioDeviceRole::Default); - if (defdevid) { - *default_capture = FindWinRTAudioDevice(defdevid->Data()); - } -} - -class SDL_WasapiActivationHandler : public RuntimeClass, FtmBase, IActivateAudioInterfaceCompletionHandler> -{ -public: - SDL_WasapiActivationHandler() : completion_semaphore(SDL_CreateSemaphore(0)) { SDL_assert(completion_semaphore != NULL); } - STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation); - void WaitForCompletion(); -private: - SDL_Semaphore *completion_semaphore; -}; - -void SDL_WasapiActivationHandler::WaitForCompletion() -{ - if (completion_semaphore) { - SDL_WaitSemaphore(completion_semaphore); - SDL_DestroySemaphore(completion_semaphore); - completion_semaphore = NULL; - } -} - -HRESULT -SDL_WasapiActivationHandler::ActivateCompleted(IActivateAudioInterfaceAsyncOperation *async) -{ - // Just set a flag, since we're probably in a different thread. We'll pick it up and init everything on our own thread to prevent races. - SDL_PostSemaphore(completion_semaphore); - return S_OK; -} - -void WASAPI_PlatformDeleteActivationHandler(void *handler) -{ - ((SDL_WasapiActivationHandler *)handler)->Release(); -} - -int WASAPI_ActivateDevice(SDL_AudioDevice *device) -{ - LPCWSTR devid = (LPCWSTR) device->handle; - SDL_assert(devid != NULL); - - ComPtr handler = Make(); - if (handler == nullptr) { - return SDL_SetError("Failed to allocate WASAPI activation handler"); - } - - handler.Get()->AddRef(); // we hold a reference after ComPtr destructs on return, causing a Release, and Release ourselves in WASAPI_PlatformDeleteActivationHandler(), etc. - device->hidden->activation_handler = handler.Get(); - - IActivateAudioInterfaceAsyncOperation *async = nullptr; - const HRESULT ret = ActivateAudioInterfaceAsync(devid, __uuidof(IAudioClient), nullptr, handler.Get(), &async); - - if (FAILED(ret) || async == nullptr) { - if (async != nullptr) { - async->Release(); - } - handler.Get()->Release(); - return WIN_SetErrorFromHRESULT("WASAPI can't activate requested audio endpoint", ret); - } - - // !!! FIXME: the problems in SDL2 that needed this to be synchronous are _probably_ solved by SDL3, and this can block indefinitely if a user prompt is shown to get permission to use a microphone. - handler.Get()->WaitForCompletion(); // block here until we have an answer, so this is synchronous to us after all. - - HRESULT activateRes = S_OK; - IUnknown *iunknown = nullptr; - const HRESULT getActivateRes = async->GetActivateResult(&activateRes, &iunknown); - async->Release(); - if (FAILED(getActivateRes)) { - return WIN_SetErrorFromHRESULT("Failed to get WASAPI activate result", getActivateRes); - } else if (FAILED(activateRes)) { - return WIN_SetErrorFromHRESULT("Failed to activate WASAPI device", activateRes); - } - - iunknown->QueryInterface(IID_PPV_ARGS(&device->hidden->client)); - if (!device->hidden->client) { - return SDL_SetError("Failed to query WASAPI client interface"); - } - - if (WASAPI_PrepDevice(device) == -1) { - return -1; - } - - return 0; -} - -void WASAPI_PlatformThreadInit(SDL_AudioDevice *device) -{ - // !!! FIXME: set this thread to "Pro Audio" priority. - SDL_SetThreadPriority(device->iscapture ? SDL_THREAD_PRIORITY_HIGH : SDL_THREAD_PRIORITY_TIME_CRITICAL); -} - -void WASAPI_PlatformThreadDeinit(SDL_AudioDevice *device) -{ - // !!! FIXME: set this thread to "Pro Audio" priority. -} - -void WASAPI_PlatformFreeDeviceHandle(SDL_AudioDevice *device) -{ - SDL_free(device->handle); -} - -#endif // SDL_AUDIO_DRIVER_WASAPI && defined(SDL_PLATFORM_WINRT) diff --git a/libs/SDL3/src/camera/SDL_camera.c b/libs/SDL3/src/camera/SDL_camera.c index 49cc9c137..d220a3d66 100644 --- a/libs/SDL3/src/camera/SDL_camera.c +++ b/libs/SDL3/src/camera/SDL_camera.c @@ -23,6 +23,7 @@ #include "SDL_syscamera.h" #include "SDL_camera_c.h" #include "../video/SDL_pixels_c.h" +#include "../video/SDL_surface_c.h" #include "../thread/SDL_systhread.h" @@ -31,6 +32,9 @@ // Available camera drivers static const CameraBootStrap *const bootstrap[] = { +#ifdef SDL_CAMERA_DRIVER_PIPEWIRE + &PIPEWIRECAMERA_bootstrap, +#endif #ifdef SDL_CAMERA_DRIVER_V4L2 &V4L2_bootstrap, #endif @@ -73,35 +77,36 @@ const char *SDL_GetCurrentCameraDriver(void) return camera_driver.name; } -char *SDL_GetCameraThreadName(SDL_CameraDevice *device, char *buf, size_t buflen) +char *SDL_GetCameraThreadName(SDL_Camera *device, char *buf, size_t buflen) { (void)SDL_snprintf(buf, buflen, "SDLCamera%d", (int) device->instance_id); return buf; } -int SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormatEnum fmt, int w, int h, int interval_numerator, int interval_denominator) +bool SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormat format, SDL_Colorspace colorspace, int w, int h, int framerate_numerator, int framerate_denominator) { SDL_assert(data != NULL); if (data->allocated_specs <= data->num_specs) { const int newalloc = data->allocated_specs ? (data->allocated_specs * 2) : 16; void *ptr = SDL_realloc(data->specs, sizeof (SDL_CameraSpec) * newalloc); if (!ptr) { - return -1; + return false; } data->specs = (SDL_CameraSpec *) ptr; data->allocated_specs = newalloc; } SDL_CameraSpec *spec = &data->specs[data->num_specs]; - spec->format = fmt; + spec->format = format; + spec->colorspace = colorspace; spec->width = w; spec->height = h; - spec->interval_numerator = interval_numerator; - spec->interval_denominator = interval_denominator; + spec->framerate_numerator = framerate_numerator; + spec->framerate_denominator = framerate_denominator; data->num_specs++; - return 0; + return true; } @@ -109,14 +114,14 @@ int SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormatEnum fmt, int // These get used when a device is disconnected or fails. Apps that ignore the // loss notifications will get black frames but otherwise keep functioning. -static int ZombieWaitDevice(SDL_CameraDevice *device) +static bool ZombieWaitDevice(SDL_Camera *device) { - if (!SDL_AtomicGet(&device->shutdown)) { - // !!! FIXME: this is bad for several reasons (uses double, could be precalculated, doesn't track elasped time). - const double duration = ((double) device->actual_spec.interval_numerator / ((double) device->actual_spec.interval_denominator)); + if (!SDL_GetAtomicInt(&device->shutdown)) { + // !!! FIXME: this is bad for several reasons (uses double, could be precalculated, doesn't track elapsed time). + const double duration = ((double) device->actual_spec.framerate_denominator / ((double) device->actual_spec.framerate_numerator)); SDL_Delay((Uint32) (duration * 1000.0)); } - return 0; + return true; } static size_t GetFrameBufLen(const SDL_CameraSpec *spec) @@ -124,7 +129,7 @@ static size_t GetFrameBufLen(const SDL_CameraSpec *spec) const size_t w = (const size_t) spec->width; const size_t h = (const size_t) spec->height; const size_t wxh = w * h; - const Uint32 fmt = spec->format; + const SDL_PixelFormat fmt = spec->format; switch (fmt) { // Some YUV formats have a larger Y plane than their U or V planes. @@ -141,17 +146,17 @@ static size_t GetFrameBufLen(const SDL_CameraSpec *spec) return wxh * SDL_BYTESPERPIXEL(fmt); } -static int ZombieAcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult ZombieAcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { const SDL_CameraSpec *spec = &device->actual_spec; if (!device->zombie_pixels) { // attempt to allocate and initialize a fake frame of pixels. const size_t buflen = GetFrameBufLen(&device->actual_spec); - device->zombie_pixels = (Uint8 *)SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + device->zombie_pixels = (Uint8 *)SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (!device->zombie_pixels) { *timestampNS = 0; - return 0; // oh well, say there isn't a frame yet, so we'll go back to waiting. Maybe allocation will succeed later...? + return SDL_CAMERA_FRAME_SKIP; // oh well, say there isn't a frame yet, so we'll go back to waiting. Maybe allocation will succeed later...? } Uint8 *dst = device->zombie_pixels; @@ -208,10 +213,10 @@ static int ZombieAcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint SDL_Log("CAMERA: dev[%p] Acquired Zombie frame, timestamp %llu", device, (unsigned long long) *timestampNS); #endif - return 1; // frame is available. + return SDL_CAMERA_FRAME_READY; // frame is available. } -static void ZombieReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) // Reclaim frame->pixels and frame->pitch! +static void ZombieReleaseFrame(SDL_Camera *device, SDL_Surface *frame) // Reclaim frame->pixels and frame->pitch! { if (frame->pixels != device->zombie_pixels) { // this was a frame from before the disconnect event; let the backend make an attempt to free it. @@ -220,13 +225,13 @@ static void ZombieReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) // // we just leave zombie_pixels alone, as we'll reuse it for every new frame until the camera is closed. } -static void ClosePhysicalCameraDevice(SDL_CameraDevice *device) +static void ClosePhysicalCamera(SDL_Camera *device) { if (!device) { return; } - SDL_AtomicSet(&device->shutdown, 1); + SDL_SetAtomicInt(&device->shutdown, 1); // !!! FIXME: the close_cond stuff from audio might help the race condition here. @@ -272,11 +277,11 @@ static void ClosePhysicalCameraDevice(SDL_CameraDevice *device) } // this must not be called while `device` is still in a device list, or while a device's camera thread is still running. -static void DestroyPhysicalCameraDevice(SDL_CameraDevice *device) +static void DestroyPhysicalCamera(SDL_Camera *device) { if (device) { // Destroy any logical devices that still exist... - ClosePhysicalCameraDevice(device); + ClosePhysicalCamera(device); camera_driver.impl.FreeDeviceHandle(device); SDL_DestroyMutex(device->lock); SDL_free(device->all_specs); @@ -287,56 +292,56 @@ static void DestroyPhysicalCameraDevice(SDL_CameraDevice *device) // Don't hold the device lock when calling this, as we may destroy the device! -void UnrefPhysicalCameraDevice(SDL_CameraDevice *device) +void UnrefPhysicalCamera(SDL_Camera *device) { if (SDL_AtomicDecRef(&device->refcount)) { // take it out of the device list. SDL_LockRWLockForWriting(camera_driver.device_hash_lock); if (SDL_RemoveFromHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id)) { - SDL_AtomicAdd(&camera_driver.device_count, -1); + SDL_AddAtomicInt(&camera_driver.device_count, -1); } SDL_UnlockRWLock(camera_driver.device_hash_lock); - DestroyPhysicalCameraDevice(device); // ...and nuke it. + DestroyPhysicalCamera(device); // ...and nuke it. } } -void RefPhysicalCameraDevice(SDL_CameraDevice *device) +void RefPhysicalCamera(SDL_Camera *device) { SDL_AtomicIncRef(&device->refcount); } -static void ObtainPhysicalCameraDeviceObj(SDL_CameraDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXMEL SDL_ACQUIRE +static void ObtainPhysicalCameraObj(SDL_Camera *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_ACQUIRE { if (device) { - RefPhysicalCameraDevice(device); + RefPhysicalCamera(device); SDL_LockMutex(device->lock); } } -static SDL_CameraDevice *ObtainPhysicalCameraDevice(SDL_CameraDeviceID devid) // !!! FIXME: SDL_ACQUIRE +static SDL_Camera *ObtainPhysicalCamera(SDL_CameraID devid) // !!! FIXME: SDL_ACQUIRE { if (!SDL_GetCurrentCameraDriver()) { SDL_SetError("Camera subsystem is not initialized"); return NULL; } - SDL_CameraDevice *device = NULL; + SDL_Camera *device = NULL; SDL_LockRWLockForReading(camera_driver.device_hash_lock); SDL_FindInHashTable(camera_driver.device_hash, (const void *) (uintptr_t) devid, (const void **) &device); SDL_UnlockRWLock(camera_driver.device_hash_lock); if (!device) { SDL_SetError("Invalid camera device instance ID"); } else { - ObtainPhysicalCameraDeviceObj(device); + ObtainPhysicalCameraObj(device); } return device; } -static void ReleaseCameraDevice(SDL_CameraDevice *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_RELEASE +static void ReleaseCamera(SDL_Camera *device) SDL_NO_THREAD_SAFETY_ANALYSIS // !!! FIXME: SDL_RELEASE { if (device) { SDL_UnlockMutex(device->lock); - UnrefPhysicalCameraDevice(device); + UnrefPhysicalCamera(device); } } @@ -361,8 +366,8 @@ static int SDLCALL CameraSpecCmp(const void *vpa, const void *vpb) SDL_assert(b->width > 0); SDL_assert(b->height > 0); - const Uint32 afmt = a->format; - const Uint32 bfmt = b->format; + const SDL_PixelFormat afmt = a->format; + const SDL_PixelFormat bfmt = b->format; if (SDL_ISPIXELFORMAT_FOURCC(afmt) && !SDL_ISPIXELFORMAT_FOURCC(bfmt)) { return -1; } else if (!SDL_ISPIXELFORMAT_FOURCC(afmt) && SDL_ISPIXELFORMAT_FOURCC(bfmt)) { @@ -382,25 +387,34 @@ static int SDLCALL CameraSpecCmp(const void *vpa, const void *vpb) } // still here? We care about framerate less than format or size, but faster is better than slow. - if (a->interval_numerator && !b->interval_numerator) { + if (a->framerate_numerator && !b->framerate_numerator) { return -1; - } else if (!a->interval_numerator && b->interval_numerator) { + } else if (!a->framerate_numerator && b->framerate_numerator) { return 1; } - const float fpsa = ((float) a->interval_denominator)/ ((float) a->interval_numerator); - const float fpsb = ((float) b->interval_denominator)/ ((float) b->interval_numerator); + const float fpsa = ((float)a->framerate_numerator / a->framerate_denominator); + const float fpsb = ((float)b->framerate_numerator / b->framerate_denominator); if (fpsa > fpsb) { return -1; } else if (fpsb > fpsa) { return 1; } + if (SDL_COLORSPACERANGE(a->colorspace) == SDL_COLOR_RANGE_FULL && + SDL_COLORSPACERANGE(b->colorspace) != SDL_COLOR_RANGE_FULL) { + return -1; + } + if (SDL_COLORSPACERANGE(a->colorspace) != SDL_COLOR_RANGE_FULL && + SDL_COLORSPACERANGE(b->colorspace) == SDL_COLOR_RANGE_FULL) { + return 1; + } + return 0; // apparently, they're equal. } // The camera backends call this when a new device is plugged in. -SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle) +SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle) { SDL_assert(name != NULL); SDL_assert(num_specs >= 0); @@ -408,13 +422,13 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition posit SDL_assert(handle != NULL); SDL_LockRWLockForReading(camera_driver.device_hash_lock); - const int shutting_down = SDL_AtomicGet(&camera_driver.shutting_down); + const int shutting_down = SDL_GetAtomicInt(&camera_driver.shutting_down); SDL_UnlockRWLock(camera_driver.device_hash_lock); if (shutting_down) { return NULL; // we're shutting down, don't add any devices that are hotplugged at the last possible moment. } - SDL_CameraDevice *device = (SDL_CameraDevice *)SDL_calloc(1, sizeof(SDL_CameraDevice)); + SDL_Camera *device = (SDL_Camera *)SDL_calloc(1, sizeof(SDL_Camera)); if (!device) { return NULL; } @@ -468,20 +482,20 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition posit SDL_Log("CAMERA: Adding device '%s' (%s) with %d spec%s%s", name, posstr, num_specs, (num_specs == 1) ? "" : "s", (num_specs == 0) ? "" : ":"); for (int i = 0; i < num_specs; i++) { const SDL_CameraSpec *spec = &device->all_specs[i]; - SDL_Log("CAMERA: - fmt=%s, w=%d, h=%d, numerator=%d, denominator=%d", SDL_GetPixelFormatName(spec->format), spec->width, spec->height, spec->interval_numerator, spec->interval_denominator); + SDL_Log("CAMERA: - fmt=%s, w=%d, h=%d, numerator=%d, denominator=%d", SDL_GetPixelFormatName(spec->format), spec->width, spec->height, spec->framerate_numerator, spec->framerate_denominator); } #endif device->num_specs = num_specs; device->handle = handle; device->instance_id = SDL_GetNextObjectID(); - SDL_AtomicSet(&device->shutdown, 0); - SDL_AtomicSet(&device->zombie, 0); - RefPhysicalCameraDevice(device); + SDL_SetAtomicInt(&device->shutdown, 0); + SDL_SetAtomicInt(&device->zombie, 0); + RefPhysicalCamera(device); SDL_LockRWLockForWriting(camera_driver.device_hash_lock); if (SDL_InsertIntoHashTable(camera_driver.device_hash, (const void *) (uintptr_t) device->instance_id, device)) { - SDL_AtomicAdd(&camera_driver.device_count, 1); + SDL_AddAtomicInt(&camera_driver.device_count, 1); } else { SDL_DestroyMutex(device->lock); SDL_free(device->all_specs); @@ -492,7 +506,7 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition posit // Add a device add event to the pending list, to be pushed when the event queue is pumped (away from any of our internal threads). if (device) { - SDL_PendingCameraDeviceEvent *p = (SDL_PendingCameraDeviceEvent *) SDL_malloc(sizeof (SDL_PendingCameraDeviceEvent)); + SDL_PendingCameraEvent *p = (SDL_PendingCameraEvent *) SDL_malloc(sizeof (SDL_PendingCameraEvent)); if (p) { // if allocation fails, you won't get an event, but we can't help that. p->type = SDL_EVENT_CAMERA_DEVICE_ADDED; p->devid = device->instance_id; @@ -509,7 +523,7 @@ SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition posit } // Called when a device is removed from the system, or it fails unexpectedly, from any thread, possibly even the camera device's thread. -void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device) +void SDL_CameraDisconnected(SDL_Camera *device) { if (!device) { return; @@ -523,13 +537,13 @@ void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device) // time the event queue pumps, in case something tries to close a device // from an event filter, as this would risk deadlocks and other disasters // if done from the device thread. - SDL_PendingCameraDeviceEvent pending; + SDL_PendingCameraEvent pending; pending.next = NULL; - SDL_PendingCameraDeviceEvent *pending_tail = &pending; + SDL_PendingCameraEvent *pending_tail = &pending; - ObtainPhysicalCameraDeviceObj(device); + ObtainPhysicalCameraObj(device); - const SDL_bool first_disconnect = SDL_AtomicCompareAndSwap(&device->zombie, 0, 1); + const bool first_disconnect = SDL_CompareAndSwapAtomicInt(&device->zombie, 0, 1); if (first_disconnect) { // if already disconnected this device, don't do it twice. // Swap in "Zombie" versions of the usual platform interfaces, so the device will keep // making progress until the app closes it. Otherwise, streams might continue to @@ -543,7 +557,7 @@ void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device) device->adjust_timestamp = 0; device->base_timestamp = 0; - SDL_PendingCameraDeviceEvent *p = (SDL_PendingCameraDeviceEvent *) SDL_malloc(sizeof (SDL_PendingCameraDeviceEvent)); + SDL_PendingCameraEvent *p = (SDL_PendingCameraEvent *) SDL_malloc(sizeof (SDL_PendingCameraEvent)); if (p) { // if this failed, no event for you, but you have deeper problems anyhow. p->type = SDL_EVENT_CAMERA_DEVICE_REMOVED; p->devid = device->instance_id; @@ -553,7 +567,7 @@ void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device) } } - ReleaseCameraDevice(device); + ReleaseCamera(device); if (first_disconnect) { if (pending.next) { // NULL if event is disabled or disaster struck. @@ -567,22 +581,22 @@ void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device) } } -void SDL_CameraDevicePermissionOutcome(SDL_CameraDevice *device, SDL_bool approved) +void SDL_CameraPermissionOutcome(SDL_Camera *device, bool approved) { if (!device) { return; } - SDL_PendingCameraDeviceEvent pending; + SDL_PendingCameraEvent pending; pending.next = NULL; - SDL_PendingCameraDeviceEvent *pending_tail = &pending; + SDL_PendingCameraEvent *pending_tail = &pending; const int permission = approved ? 1 : -1; - ObtainPhysicalCameraDeviceObj(device); + ObtainPhysicalCameraObj(device); if (device->permission != permission) { device->permission = permission; - SDL_PendingCameraDeviceEvent *p = (SDL_PendingCameraDeviceEvent *) SDL_malloc(sizeof (SDL_PendingCameraDeviceEvent)); + SDL_PendingCameraEvent *p = (SDL_PendingCameraEvent *) SDL_malloc(sizeof (SDL_PendingCameraEvent)); if (p) { // if this failed, no event for you, but you have deeper problems anyhow. p->type = approved ? SDL_EVENT_CAMERA_DEVICE_APPROVED : SDL_EVENT_CAMERA_DEVICE_DENIED; p->devid = device->instance_id; @@ -592,18 +606,20 @@ void SDL_CameraDevicePermissionOutcome(SDL_CameraDevice *device, SDL_bool approv } } - ReleaseCameraDevice(device); + ReleaseCamera(device); - SDL_LockRWLockForWriting(camera_driver.device_hash_lock); - SDL_assert(camera_driver.pending_events_tail != NULL); - SDL_assert(camera_driver.pending_events_tail->next == NULL); - camera_driver.pending_events_tail->next = pending.next; - camera_driver.pending_events_tail = pending_tail; - SDL_UnlockRWLock(camera_driver.device_hash_lock); + if (pending.next) { // NULL if event is disabled or disaster struck. + SDL_LockRWLockForWriting(camera_driver.device_hash_lock); + SDL_assert(camera_driver.pending_events_tail != NULL); + SDL_assert(camera_driver.pending_events_tail->next == NULL); + camera_driver.pending_events_tail->next = pending.next; + camera_driver.pending_events_tail = pending_tail; + SDL_UnlockRWLock(camera_driver.device_hash_lock); + } } -SDL_CameraDevice *SDL_FindPhysicalCameraDeviceByCallback(SDL_bool (*callback)(SDL_CameraDevice *device, void *userdata), void *userdata) +SDL_Camera *SDL_FindPhysicalCameraByCallback(bool (*callback)(SDL_Camera *device, void *userdata), void *userdata) { if (!SDL_GetCurrentCameraDriver()) { SDL_SetError("Camera subsystem is not initialized"); @@ -616,7 +632,7 @@ SDL_CameraDevice *SDL_FindPhysicalCameraDeviceByCallback(SDL_bool (*callback)(SD SDL_LockRWLockForReading(camera_driver.device_hash_lock); while (SDL_IterateHashTable(camera_driver.device_hash, &key, &value, &iter)) { - SDL_CameraDevice *device = (SDL_CameraDevice *) value; + SDL_Camera *device = (SDL_Camera *) value; if (callback(device, userdata)) { // found it? SDL_UnlockRWLock(camera_driver.device_hash_lock); return device; @@ -631,54 +647,58 @@ SDL_CameraDevice *SDL_FindPhysicalCameraDeviceByCallback(SDL_bool (*callback)(SD void SDL_CloseCamera(SDL_Camera *camera) { - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ClosePhysicalCameraDevice(device); + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ClosePhysicalCamera(device); } -int SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec) +bool SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec) { + bool result; + if (!camera) { return SDL_InvalidParamError("camera"); } else if (!spec) { return SDL_InvalidParamError("spec"); } - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); - const int retval = (device->permission > 0) ? 0 : SDL_SetError("Camera permission has not been granted"); - if (retval == 0) { + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraObj(device); + if (device->permission > 0) { SDL_copyp(spec, &device->spec); + result = true; } else { SDL_zerop(spec); + result = SDL_SetError("Camera permission has not been granted"); } - ReleaseCameraDevice(device); - return 0; + ReleaseCamera(device); + + return result; } -char *SDL_GetCameraDeviceName(SDL_CameraDeviceID instance_id) +const char *SDL_GetCameraName(SDL_CameraID instance_id) { - char *retval = NULL; - SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + const char *result = NULL; + SDL_Camera *device = ObtainPhysicalCamera(instance_id); if (device) { - retval = SDL_strdup(device->name); - ReleaseCameraDevice(device); + result = SDL_GetPersistentString(device->name); + ReleaseCamera(device); } - return retval; + return result; } -SDL_CameraPosition SDL_GetCameraDevicePosition(SDL_CameraDeviceID instance_id) +SDL_CameraPosition SDL_GetCameraPosition(SDL_CameraID instance_id) { - SDL_CameraPosition retval = SDL_CAMERA_POSITION_UNKNOWN; - SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + SDL_CameraPosition result = SDL_CAMERA_POSITION_UNKNOWN; + SDL_Camera *device = ObtainPhysicalCamera(instance_id); if (device) { - retval = device->position; - ReleaseCameraDevice(device); + result = device->position; + ReleaseCamera(device); } - return retval; + return result; } -SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) +SDL_CameraID *SDL_GetCameras(int *count) { int dummy_count; if (!count) { @@ -691,12 +711,12 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) return NULL; } - SDL_CameraDeviceID *retval = NULL; + SDL_CameraID *result = NULL; SDL_LockRWLockForReading(camera_driver.device_hash_lock); - int num_devices = SDL_AtomicGet(&camera_driver.device_count); - retval = (SDL_CameraDeviceID *) SDL_malloc((num_devices + 1) * sizeof (SDL_CameraDeviceID)); - if (!retval) { + int num_devices = SDL_GetAtomicInt(&camera_driver.device_count); + result = (SDL_CameraID *) SDL_malloc((num_devices + 1) * sizeof (SDL_CameraID)); + if (!result) { num_devices = 0; } else { int devs_seen = 0; @@ -704,47 +724,55 @@ SDL_CameraDeviceID *SDL_GetCameraDevices(int *count) const void *value; void *iter = NULL; while (SDL_IterateHashTable(camera_driver.device_hash, &key, &value, &iter)) { - retval[devs_seen++] = (SDL_CameraDeviceID) (uintptr_t) key; + result[devs_seen++] = (SDL_CameraID) (uintptr_t) key; } SDL_assert(devs_seen == num_devices); - retval[devs_seen] = 0; // null-terminated. + result[devs_seen] = 0; // null-terminated. } SDL_UnlockRWLock(camera_driver.device_hash_lock); *count = num_devices; - return retval; + return result; } -SDL_CameraSpec *SDL_GetCameraDeviceSupportedFormats(SDL_CameraDeviceID instance_id, int *count) +SDL_CameraSpec **SDL_GetCameraSupportedFormats(SDL_CameraID instance_id, int *count) { if (count) { *count = 0; } - SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + SDL_Camera *device = ObtainPhysicalCamera(instance_id); if (!device) { return NULL; } - SDL_CameraSpec *retval = (SDL_CameraSpec *) SDL_calloc(device->num_specs + 1, sizeof (SDL_CameraSpec)); - if (retval) { - SDL_memcpy(retval, device->all_specs, sizeof (SDL_CameraSpec) * device->num_specs); + int i; + int num_specs = device->num_specs; + SDL_CameraSpec **result = (SDL_CameraSpec **) SDL_malloc(((num_specs + 1) * sizeof(*result)) + (num_specs * sizeof (**result))); + if (result) { + SDL_CameraSpec *specs = (SDL_CameraSpec *)(result + (num_specs + 1)); + SDL_memcpy(specs, device->all_specs, num_specs * sizeof(*specs)); + for (i = 0; i < num_specs; ++i) { + result[i] = specs++; + } + result[i] = NULL; + if (count) { - *count = device->num_specs; + *count = num_specs; } } - ReleaseCameraDevice(device); + ReleaseCamera(device); - return retval; + return result; } // Camera device thread. This is split into chunks, so drivers that need to control this directly can use the pieces they need without duplicating effort. -void SDL_CameraThreadSetup(SDL_CameraDevice *device) +void SDL_CameraThreadSetup(SDL_Camera *device) { //camera_driver.impl.ThreadInit(device); #ifdef SDL_VIDEO_DRIVER_ANDROID @@ -753,39 +781,39 @@ void SDL_CameraThreadSetup(SDL_CameraDevice *device) { // Set thread priority to THREAD_PRIORITY_VIDEO extern void Android_JNI_CameraSetThreadPriority(int, int); - Android_JNI_CameraSetThreadPriority(device->iscapture, device); + Android_JNI_CameraSetThreadPriority(device->recording, device); }*/ #else // The camera capture is always a high priority thread - SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH); + SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_HIGH); #endif } -SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) +bool SDL_CameraThreadIterate(SDL_Camera *device) { SDL_LockMutex(device->lock); - if (SDL_AtomicGet(&device->shutdown)) { + if (SDL_GetAtomicInt(&device->shutdown)) { SDL_UnlockMutex(device->lock); - return SDL_FALSE; // we're done, shut it down. + return false; // we're done, shut it down. } const int permission = device->permission; if (permission <= 0) { SDL_UnlockMutex(device->lock); - return (permission < 0) ? SDL_FALSE : SDL_TRUE; // if permission was denied, shut it down. if undecided, we're done for now. + return (permission < 0) ? false : true; // if permission was denied, shut it down. if undecided, we're done for now. } - SDL_bool failed = SDL_FALSE; // set to true if disaster worthy of treating the device as lost has happened. + bool failed = false; // set to true if disaster worthy of treating the device as lost has happened. SDL_Surface *acquired = NULL; SDL_Surface *output_surface = NULL; SurfaceList *slist = NULL; Uint64 timestampNS = 0; // AcquireFrame SHOULD NOT BLOCK, as we are holding a lock right now. Block in WaitDevice instead! - const int rc = device->AcquireFrame(device, device->acquire_surface, ×tampNS); + const SDL_CameraFrameResult rc = device->AcquireFrame(device, device->acquire_surface, ×tampNS); - if (rc == 1) { // new frame acquired! + if (rc == SDL_CAMERA_FRAME_READY) { // new frame acquired! #if DEBUG_CAMERA SDL_Log("CAMERA: New frame available! pixels=%p pitch=%d", device->acquire_surface->pixels, device->acquire_surface->pitch); #endif @@ -819,16 +847,15 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) acquired = device->acquire_surface; slist->timestampNS = timestampNS; } - } else if (rc == 0) { // no frame available yet; not an error. + } else if (rc == SDL_CAMERA_FRAME_SKIP) { // no frame available yet; not an error. #if 0 //DEBUG_CAMERA SDL_Log("CAMERA: No frame available yet."); #endif } else { // fatal error! - SDL_assert(rc == -1); #if DEBUG_CAMERA SDL_Log("CAMERA: dev[%p] error AcquireFrame: %s", device, SDL_GetError()); #endif - failed = SDL_TRUE; + failed = true; } // we can let go of the lock once we've tried to grab a frame of video and maybe moved the output frame off the empty list. @@ -838,13 +865,15 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) if (failed) { SDL_assert(slist == NULL); SDL_assert(acquired == NULL); - SDL_CameraDeviceDisconnected(device); // doh. + SDL_CameraDisconnected(device); // doh. } else if (acquired) { // we have a new frame, scale/convert if necessary and queue it for the app! SDL_assert(slist != NULL); if (!device->needs_scaling && !device->needs_conversion) { // no conversion needed? Just move the pointer/pitch into the output surface. #if DEBUG_CAMERA SDL_Log("CAMERA: Frame is going through without conversion!"); #endif + output_surface->w = acquired->w; + output_surface->h = acquired->h; output_surface->pixels = acquired->pixels; output_surface->pitch = acquired->pitch; } else { // convert/scale into a different surface. @@ -860,8 +889,8 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) if (device->needs_conversion) { SDL_Surface *dstsurf = (device->needs_scaling == 1) ? device->conversion_surface : output_surface; SDL_ConvertPixels(srcsurf->w, srcsurf->h, - srcsurf->format->format, srcsurf->pixels, srcsurf->pitch, - dstsurf->format->format, dstsurf->pixels, dstsurf->pitch); + srcsurf->format, srcsurf->pixels, srcsurf->pitch, + dstsurf->format, dstsurf->pixels, dstsurf->pitch); srcsurf = dstsurf; } if (device->needs_scaling == 1) { // upscaling? Do it last. -1: downscale, 0: no scaling, 1: upscale @@ -883,12 +912,12 @@ SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device) SDL_UnlockMutex(device->lock); } - return SDL_TRUE; // always go on if not shutting down, even if device failed. + return true; // always go on if not shutting down, even if device failed. } -void SDL_CameraThreadShutdown(SDL_CameraDevice *device) +void SDL_CameraThreadShutdown(SDL_Camera *device) { - //device->FlushCapture(device); + //device->FlushRecording(device); //camera_driver.impl.ThreadDeinit(device); //SDL_CameraThreadFinalize(device); } @@ -896,7 +925,7 @@ void SDL_CameraThreadShutdown(SDL_CameraDevice *device) // Actual thread entry point, if driver didn't handle this itself. static int SDLCALL CameraThread(void *devicep) { - SDL_CameraDevice *device = (SDL_CameraDevice *) devicep; + SDL_Camera *device = (SDL_Camera *) devicep; #if DEBUG_CAMERA SDL_Log("CAMERA: dev[%p] Start thread 'CameraThread'", devicep); @@ -906,8 +935,8 @@ static int SDLCALL CameraThread(void *devicep) SDL_CameraThreadSetup(device); do { - if (device->WaitDevice(device) < 0) { - SDL_CameraDeviceDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) + if (!device->WaitDevice(device)) { + SDL_CameraDisconnected(device); // doh. (but don't break out of the loop, just be a zombie for now!) } } while (SDL_CameraThreadIterate(device)); @@ -920,7 +949,7 @@ static int SDLCALL CameraThread(void *devicep) return 0; } -static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec *spec, SDL_CameraSpec *closest) +static void ChooseBestCameraSpec(SDL_Camera *device, const SDL_CameraSpec *spec, SDL_CameraSpec *closest) { // Find the closest available native format/size... // @@ -948,76 +977,85 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec int wantw = spec->width; int wanth = spec->height; - // Find the sizes with the closest aspect ratio and then find the best fit of those. - const float wantaspect = ((float)wantw) / ((float) wanth); - const float epsilon = 1e-6f; - float closestaspect = -9999999.0f; - float closestdiff = 999999.0f; - int closestdiffw = 9999999; - - for (int i = 0; i < num_specs; i++) { - const SDL_CameraSpec *thisspec = &device->all_specs[i]; - const int thisw = thisspec->width; - const int thish = thisspec->height; - const float thisaspect = ((float)thisw) / ((float) thish); - const float aspectdiff = SDL_fabs(wantaspect - thisaspect); - const float diff = SDL_fabs(closestaspect - thisaspect); - const int diffw = SDL_abs(thisw - wantw); - if (diff < epsilon) { // matches current closestaspect? See if resolution is closer in size. - if (diffw < closestdiffw) { + if (wantw > 0 && wanth > 0) { + // Find the sizes with the closest aspect ratio and then find the best fit of those. + const float wantaspect = ((float)wantw) / ((float)wanth); + const float epsilon = 1e-6f; + float closestaspect = -9999999.0f; + float closestdiff = 999999.0f; + int closestdiffw = 9999999; + + for (int i = 0; i < num_specs; i++) { + const SDL_CameraSpec *thisspec = &device->all_specs[i]; + const int thisw = thisspec->width; + const int thish = thisspec->height; + const float thisaspect = ((float)thisw) / ((float)thish); + const float aspectdiff = SDL_fabsf(wantaspect - thisaspect); + const float diff = SDL_fabsf(closestaspect - thisaspect); + const int diffw = SDL_abs(thisw - wantw); + if (diff < epsilon) { // matches current closestaspect? See if resolution is closer in size. + if (diffw < closestdiffw) { + closestdiffw = diffw; + closest->width = thisw; + closest->height = thish; + } + } else if (aspectdiff < closestdiff) { // this is a closer aspect ratio? Take it, reset resolution checks. + closestdiff = aspectdiff; + closestaspect = thisaspect; closestdiffw = diffw; closest->width = thisw; closest->height = thish; } - } else if (aspectdiff < closestdiff) { // this is a closer aspect ratio? Take it, reset resolution checks. - closestdiff = aspectdiff; - closestaspect = thisaspect; - closestdiffw = diffw; - closest->width = thisw; - closest->height = thish; } + } else { + SDL_copyp(closest, &device->all_specs[0]); } SDL_assert(closest->width > 0); SDL_assert(closest->height > 0); // okay, we have what we think is the best resolution, now we just need the best format that supports it... - const SDL_PixelFormatEnum wantfmt = spec->format; - SDL_PixelFormatEnum bestfmt = SDL_PIXELFORMAT_UNKNOWN; + const SDL_PixelFormat wantfmt = spec->format; + SDL_PixelFormat best_format = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace best_colorspace = SDL_COLORSPACE_UNKNOWN; for (int i = 0; i < num_specs; i++) { const SDL_CameraSpec *thisspec = &device->all_specs[i]; if ((thisspec->width == closest->width) && (thisspec->height == closest->height)) { - if (bestfmt == SDL_PIXELFORMAT_UNKNOWN) { - bestfmt = thisspec->format; // spec list is sorted by what we consider "best" format, so unless we find an exact match later, first size match is the one! + if (best_format == SDL_PIXELFORMAT_UNKNOWN) { + best_format = thisspec->format; // spec list is sorted by what we consider "best" format, so unless we find an exact match later, first size match is the one! + best_colorspace = thisspec->colorspace; } if (thisspec->format == wantfmt) { - bestfmt = thisspec->format; + best_format = thisspec->format; + best_colorspace = thisspec->colorspace; break; // exact match, stop looking. } } } - SDL_assert(bestfmt != SDL_PIXELFORMAT_UNKNOWN); - closest->format = bestfmt; + SDL_assert(best_format != SDL_PIXELFORMAT_UNKNOWN); + SDL_assert(best_colorspace != SDL_COLORSPACE_UNKNOWN); + closest->format = best_format; + closest->colorspace = best_colorspace; // We have a resolution and a format, find the closest framerate... - const float wantfps = spec->interval_numerator ? (spec->interval_denominator / spec->interval_numerator) : 0.0f; + const float wantfps = spec->framerate_denominator ? ((float)spec->framerate_numerator / spec->framerate_denominator) : 0.0f; float closestfps = 9999999.0f; for (int i = 0; i < num_specs; i++) { const SDL_CameraSpec *thisspec = &device->all_specs[i]; if ((thisspec->format == closest->format) && (thisspec->width == closest->width) && (thisspec->height == closest->height)) { - if ((thisspec->interval_numerator == spec->interval_numerator) && (thisspec->interval_denominator == spec->interval_denominator)) { - closest->interval_numerator = thisspec->interval_numerator; - closest->interval_denominator = thisspec->interval_denominator; + if ((thisspec->framerate_numerator == spec->framerate_numerator) && (thisspec->framerate_denominator == spec->framerate_denominator)) { + closest->framerate_numerator = thisspec->framerate_numerator; + closest->framerate_denominator = thisspec->framerate_denominator; break; // exact match, stop looking. } - const float thisfps = thisspec->interval_numerator ? (thisspec->interval_denominator / thisspec->interval_numerator) : 0.0f; - const float fpsdiff = SDL_fabs(wantfps - thisfps); + const float thisfps = thisspec->framerate_denominator ? ((float)thisspec->framerate_numerator / thisspec->framerate_denominator) : 0.0f; + const float fpsdiff = SDL_fabsf(wantfps - thisfps); if (fpsdiff < closestfps) { // this is a closest FPS? Take it until something closer arrives. closestfps = fpsdiff; - closest->interval_numerator = thisspec->interval_numerator; - closest->interval_denominator = thisspec->interval_denominator; + closest->framerate_numerator = thisspec->framerate_numerator; + closest->framerate_denominator = thisspec->framerate_denominator; } } } @@ -1028,30 +1066,20 @@ static void ChooseBestCameraSpec(SDL_CameraDevice *device, const SDL_CameraSpec SDL_assert(closest->format != SDL_PIXELFORMAT_UNKNOWN); } -SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_CameraSpec *spec) +SDL_Camera *SDL_OpenCamera(SDL_CameraID instance_id, const SDL_CameraSpec *spec) { - if (spec) { - if ((spec->width <= 0) || (spec->height <= 0)) { - SDL_SetError("Requested spec frame size is invalid"); - return NULL; - } else if (spec->format == SDL_PIXELFORMAT_UNKNOWN) { - SDL_SetError("Requested spec format is invalid"); - return NULL; - } - } - - SDL_CameraDevice *device = ObtainPhysicalCameraDevice(instance_id); + SDL_Camera *device = ObtainPhysicalCamera(instance_id); if (!device) { return NULL; } if (device->hidden != NULL) { - ReleaseCameraDevice(device); + ReleaseCamera(device); SDL_SetError("Camera already opened"); // we may remove this limitation at some point. return NULL; } - SDL_AtomicSet(&device->shutdown, 0); + SDL_SetAtomicInt(&device->shutdown, 0); // These start with the backend's implementation, but we might swap them out with zombie versions later. device->WaitDevice = camera_driver.impl.WaitDevice; @@ -1062,21 +1090,32 @@ SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_Camer ChooseBestCameraSpec(device, spec, &closest); #if DEBUG_CAMERA - SDL_Log("CAMERA: App wanted [(%dx%d) fmt=%s interval=%d/%d], chose [(%dx%d) fmt=%s interval=%d/%d]", - spec ? spec->width : -1, spec ? spec->height : -1, spec ? SDL_GetPixelFormatName(spec->format) : "(null)", spec ? spec->interval_numerator : -1, spec ? spec->interval_denominator : -1, - closest.width, closest.height, SDL_GetPixelFormatName(closest.format), closest.interval_numerator, closest.interval_denominator); + SDL_Log("CAMERA: App wanted [(%dx%d) fmt=%s framerate=%d/%d], chose [(%dx%d) fmt=%s framerate=%d/%d]", + spec ? spec->width : -1, spec ? spec->height : -1, spec ? SDL_GetPixelFormatName(spec->format) : "(null)", spec ? spec->framerate_numerator : -1, spec ? spec->framerate_denominator : -1, + closest.width, closest.height, SDL_GetPixelFormatName(closest.format), closest.framerate_numerator, closest.framerate_denominator); #endif - if (camera_driver.impl.OpenDevice(device, &closest) < 0) { - ClosePhysicalCameraDevice(device); // in case anything is half-initialized. - ReleaseCameraDevice(device); + if (!camera_driver.impl.OpenDevice(device, &closest)) { + ClosePhysicalCamera(device); // in case anything is half-initialized. + ReleaseCamera(device); return NULL; } - if (!spec) { - SDL_copyp(&device->spec, &closest); - } else { + if (spec) { SDL_copyp(&device->spec, spec); + if (spec->width <= 0 || spec->height <= 0) { + device->spec.width = closest.width; + device->spec.height = closest.height; + } + if (spec->format == SDL_PIXELFORMAT_UNKNOWN) { + device->spec.format = closest.format; + } + if (spec->framerate_denominator == 0) { + device->spec.framerate_numerator = closest.framerate_numerator; + device->spec.framerate_denominator = closest.framerate_denominator; + } + } else { + SDL_copyp(&device->spec, &closest); } SDL_copyp(&device->actual_spec, &closest); @@ -1095,19 +1134,26 @@ SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_Camer device->needs_conversion = (closest.format != device->spec.format); - device->acquire_surface = SDL_CreateSurfaceFrom(NULL, closest.width, closest.height, 0, closest.format); + device->acquire_surface = SDL_CreateSurfaceFrom(closest.width, closest.height, closest.format, NULL, 0); if (!device->acquire_surface) { - ClosePhysicalCameraDevice(device); - ReleaseCameraDevice(device); + ClosePhysicalCamera(device); + ReleaseCamera(device); return NULL; } + SDL_SetSurfaceColorspace(device->acquire_surface, closest.colorspace); // if we have to scale _and_ convert, we need a middleman surface, since we can't do both changes at once. if (device->needs_scaling && device->needs_conversion) { - const SDL_bool downsampling_first = (device->needs_scaling < 0); + const bool downsampling_first = (device->needs_scaling < 0); const SDL_CameraSpec *s = downsampling_first ? &device->spec : &closest; - const SDL_PixelFormatEnum fmt = downsampling_first ? closest.format : device->spec.format; + const SDL_PixelFormat fmt = downsampling_first ? closest.format : device->spec.format; device->conversion_surface = SDL_CreateSurface(s->width, s->height, fmt); + if (!device->conversion_surface) { + ClosePhysicalCamera(device); + ReleaseCamera(device); + return NULL; + } + SDL_SetSurfaceColorspace(device->conversion_surface, closest.colorspace); } // output surfaces are in the app-requested format. If no conversion is necessary, we'll just use the pointers @@ -1124,14 +1170,14 @@ SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_Camer if (device->needs_scaling || device->needs_conversion) { surf = SDL_CreateSurface(device->spec.width, device->spec.height, device->spec.format); } else { - surf = SDL_CreateSurfaceFrom(NULL, device->spec.width, device->spec.height, 0, device->spec.format); + surf = SDL_CreateSurfaceFrom(device->spec.width, device->spec.height, device->spec.format, NULL, 0); } - if (!surf) { - ClosePhysicalCameraDevice(device); - ReleaseCameraDevice(device); + ClosePhysicalCamera(device); + ReleaseCamera(device); return NULL; } + SDL_SetSurfaceColorspace(surf, closest.colorspace); device->output_surfaces[i].surface = surf; } @@ -1142,16 +1188,16 @@ SDL_Camera *SDL_OpenCameraDevice(SDL_CameraDeviceID instance_id, const SDL_Camer if (!camera_driver.impl.ProvidesOwnCallbackThread) { char threadname[64]; SDL_GetCameraThreadName(device, threadname, sizeof (threadname)); - device->thread = SDL_CreateThreadInternal(CameraThread, threadname, 0, device); + device->thread = SDL_CreateThread(CameraThread, threadname, device); if (!device->thread) { - ClosePhysicalCameraDevice(device); - ReleaseCameraDevice(device); + ClosePhysicalCamera(device); + ReleaseCamera(device); SDL_SetError("Couldn't create camera thread"); return NULL; } } - ReleaseCameraDevice(device); // unlock, we're good to go! + ReleaseCamera(device); // unlock, we're good to go! return (SDL_Camera *) device; // currently there's no separation between physical and logical device. } @@ -1167,17 +1213,17 @@ SDL_Surface *SDL_AcquireCameraFrame(SDL_Camera *camera, Uint64 *timestampNS) return NULL; } - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); + ObtainPhysicalCameraObj(device); if (device->permission <= 0) { - ReleaseCameraDevice(device); + ReleaseCamera(device); SDL_SetError("Camera permission has not been granted"); return NULL; } - SDL_Surface *retval = NULL; + SDL_Surface *result = NULL; // frames are in this list from newest to oldest, so find the end of the list... SurfaceList *slistprev = &device->filled_output_surfaces; @@ -1187,32 +1233,30 @@ SDL_Surface *SDL_AcquireCameraFrame(SDL_Camera *camera, Uint64 *timestampNS) slist = slist->next; } - const SDL_bool list_is_empty = (slist == slistprev); + const bool list_is_empty = (slist == slistprev); if (!list_is_empty) { // report the oldest frame. if (timestampNS) { *timestampNS = slist->timestampNS; } - retval = slist->surface; + result = slist->surface; slistprev->next = slist->next; // remove from filled list. slist->next = device->app_held_output_surfaces.next; // add to app_held list. device->app_held_output_surfaces.next = slist; } - ReleaseCameraDevice(device); + ReleaseCamera(device); - return retval; + return result; } -int SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame) +void SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame) { - if (!camera) { - return SDL_InvalidParamError("camera"); - } else if (frame == NULL) { - return SDL_InvalidParamError("frame"); + if (!camera || !frame) { + return; } - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraObj(device); SurfaceList *slistprev = &device->app_held_output_surfaces; SurfaceList *slist; @@ -1224,8 +1268,8 @@ int SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame) } if (!slist) { - ReleaseCameraDevice(device); - return SDL_SetError("Surface was not acquired from this camera, or was already released"); + ReleaseCamera(device); + return; } // this pointer was owned by the backend (DMA memory or whatever), clear it out. @@ -1244,57 +1288,55 @@ int SDL_ReleaseCameraFrame(SDL_Camera *camera, SDL_Surface *frame) slist->next = device->empty_output_surfaces.next; device->empty_output_surfaces.next = slist; - ReleaseCameraDevice(device); - - return 0; + ReleaseCamera(device); } -SDL_CameraDeviceID SDL_GetCameraInstanceID(SDL_Camera *camera) +SDL_CameraID SDL_GetCameraID(SDL_Camera *camera) { - SDL_CameraDeviceID retval = 0; + SDL_CameraID result = 0; if (!camera) { SDL_InvalidParamError("camera"); } else { - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); - retval = device->instance_id; - ReleaseCameraDevice(device); + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraObj(device); + result = device->instance_id; + ReleaseCamera(device); } - return retval; + return result; } SDL_PropertiesID SDL_GetCameraProperties(SDL_Camera *camera) { - SDL_PropertiesID retval = 0; + SDL_PropertiesID result = 0; if (!camera) { SDL_InvalidParamError("camera"); } else { - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraObj(device); if (device->props == 0) { device->props = SDL_CreateProperties(); } - retval = device->props; - ReleaseCameraDevice(device); + result = device->props; + ReleaseCamera(device); } - return retval; + return result; } int SDL_GetCameraPermissionState(SDL_Camera *camera) { - int retval; + int result; if (!camera) { - retval = SDL_InvalidParamError("camera"); + SDL_InvalidParamError("camera"); + result = -1; } else { - SDL_CameraDevice *device = (SDL_CameraDevice *) camera; // currently there's no separation between physical and logical device. - ObtainPhysicalCameraDeviceObj(device); - retval = device->permission; - ReleaseCameraDevice(device); + SDL_Camera *device = (SDL_Camera *) camera; // currently there's no separation between physical and logical device. + ObtainPhysicalCameraObj(device); + result = device->permission; + ReleaseCamera(device); } - - return retval; + return result; } @@ -1319,16 +1361,16 @@ void SDL_QuitCamera(void) } SDL_LockRWLockForWriting(camera_driver.device_hash_lock); - SDL_AtomicSet(&camera_driver.shutting_down, 1); + SDL_SetAtomicInt(&camera_driver.shutting_down, 1); SDL_HashTable *device_hash = camera_driver.device_hash; camera_driver.device_hash = NULL; - SDL_PendingCameraDeviceEvent *pending_events = camera_driver.pending_events.next; + SDL_PendingCameraEvent *pending_events = camera_driver.pending_events.next; camera_driver.pending_events.next = NULL; - SDL_AtomicSet(&camera_driver.device_count, 0); + SDL_SetAtomicInt(&camera_driver.device_count, 0); SDL_UnlockRWLock(camera_driver.device_hash_lock); - SDL_PendingCameraDeviceEvent *pending_next = NULL; - for (SDL_PendingCameraDeviceEvent *i = pending_events; i; i = pending_next) { + SDL_PendingCameraEvent *pending_next = NULL; + for (SDL_PendingCameraEvent *i = pending_events; i; i = pending_next) { pending_next = i->next; SDL_free(i); } @@ -1337,7 +1379,7 @@ void SDL_QuitCamera(void) const void *value; void *iter = NULL; while (SDL_IterateHashTable(device_hash, &key, &value, &iter)) { - DestroyPhysicalCameraDevice((SDL_CameraDevice *) value); + DestroyPhysicalCamera((SDL_Camera *) value); } // Free the driver data @@ -1350,23 +1392,23 @@ void SDL_QuitCamera(void) } -static Uint32 HashCameraDeviceID(const void *key, void *data) +static Uint32 HashCameraID(const void *key, void *data) { // The values are unique incrementing integers, starting at 1, so just return minus 1 to start with bucket zero. return ((Uint32) ((uintptr_t) key)) - 1; } -static SDL_bool MatchCameraDeviceID(const void *a, const void *b, void *data) +static bool MatchCameraID(const void *a, const void *b, void *data) { return (a == b); // simple integers, just compare them as pointer values. } -static void NukeCameraDeviceHashItem(const void *key, const void *value, void *data) +static void NukeCameraHashItem(const void *key, const void *value, void *data) { // no-op, keys and values in this hashtable are treated as Plain Old Data and don't get freed here. } -int SDL_CameraInit(const char *driver_name) +bool SDL_CameraInit(const char *driver_name) { if (SDL_GetCurrentCameraDriver()) { SDL_QuitCamera(); // shutdown driver if already running. @@ -1374,13 +1416,13 @@ int SDL_CameraInit(const char *driver_name) SDL_RWLock *device_hash_lock = SDL_CreateRWLock(); // create this early, so if it fails we don't have to tear down the whole camera subsystem. if (!device_hash_lock) { - return -1; + return false; } - SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashCameraDeviceID, MatchCameraDeviceID, NukeCameraDeviceHashItem, SDL_FALSE); + SDL_HashTable *device_hash = SDL_CreateHashTable(NULL, 8, HashCameraID, MatchCameraID, NukeCameraHashItem, false); if (!device_hash) { SDL_DestroyRWLock(device_hash_lock); - return -1; + return false; } // Select the proper camera driver @@ -1388,8 +1430,8 @@ int SDL_CameraInit(const char *driver_name) driver_name = SDL_GetHint(SDL_HINT_CAMERA_DRIVER); } - SDL_bool initialized = SDL_FALSE; - SDL_bool tried_to_init = SDL_FALSE; + bool initialized = false; + bool tried_to_init = false; if (driver_name && (*driver_name != 0)) { char *driver_name_copy = SDL_strdup(driver_name); @@ -1398,7 +1440,7 @@ int SDL_CameraInit(const char *driver_name) if (!driver_name_copy) { SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); - return -1; + return false; } while (driver_attempt && (*driver_attempt != 0) && !initialized) { @@ -1409,7 +1451,7 @@ int SDL_CameraInit(const char *driver_name) for (int i = 0; bootstrap[i]; i++) { if (SDL_strcasecmp(bootstrap[i]->name, driver_attempt) == 0) { - tried_to_init = SDL_TRUE; + tried_to_init = true; SDL_zero(camera_driver); camera_driver.pending_events_tail = &camera_driver.pending_events; camera_driver.device_hash_lock = device_hash_lock; @@ -1417,7 +1459,7 @@ int SDL_CameraInit(const char *driver_name) if (bootstrap[i]->init(&camera_driver.impl)) { camera_driver.name = bootstrap[i]->name; camera_driver.desc = bootstrap[i]->desc; - initialized = SDL_TRUE; + initialized = true; } break; } @@ -1433,7 +1475,7 @@ int SDL_CameraInit(const char *driver_name) continue; } - tried_to_init = SDL_TRUE; + tried_to_init = true; SDL_zero(camera_driver); camera_driver.pending_events_tail = &camera_driver.pending_events; camera_driver.device_hash_lock = device_hash_lock; @@ -1441,7 +1483,7 @@ int SDL_CameraInit(const char *driver_name) if (bootstrap[i]->init(&camera_driver.impl)) { camera_driver.name = bootstrap[i]->name; camera_driver.desc = bootstrap[i]->desc; - initialized = SDL_TRUE; + initialized = true; } } } @@ -1459,7 +1501,7 @@ int SDL_CameraInit(const char *driver_name) SDL_zero(camera_driver); SDL_DestroyRWLock(device_hash_lock); SDL_DestroyHashTable(device_hash); - return -1; // No driver was available, so fail. + return false; // No driver was available, so fail. } CompleteCameraEntryPoints(); @@ -1467,7 +1509,7 @@ int SDL_CameraInit(const char *driver_name) // Make sure we have a list of devices available at startup... camera_driver.impl.DetectDevices(); - return 0; + return true; } // This is an internal function, so SDL_PumpEvents() can check for pending camera device events. @@ -1475,7 +1517,7 @@ int SDL_CameraInit(const char *driver_name) void SDL_UpdateCamera(void) { SDL_LockRWLockForReading(camera_driver.device_hash_lock); - SDL_PendingCameraDeviceEvent *pending_events = camera_driver.pending_events.next; + SDL_PendingCameraEvent *pending_events = camera_driver.pending_events.next; SDL_UnlockRWLock(camera_driver.device_hash_lock); if (!pending_events) { @@ -1489,14 +1531,14 @@ void SDL_UpdateCamera(void) camera_driver.pending_events_tail = &camera_driver.pending_events; SDL_UnlockRWLock(camera_driver.device_hash_lock); - SDL_PendingCameraDeviceEvent *pending_next = NULL; - for (SDL_PendingCameraDeviceEvent *i = pending_events; i; i = pending_next) { + SDL_PendingCameraEvent *pending_next = NULL; + for (SDL_PendingCameraEvent *i = pending_events; i; i = pending_next) { pending_next = i->next; if (SDL_EventEnabled(i->type)) { SDL_Event event; SDL_zero(event); event.type = i->type; - event.adevice.which = (Uint32) i->devid; + event.cdevice.which = (Uint32) i->devid; SDL_PushEvent(&event); } SDL_free(i); diff --git a/libs/SDL3/src/camera/SDL_camera_c.h b/libs/SDL3/src/camera/SDL_camera_c.h index 6fae3101d..7436ab43c 100644 --- a/libs/SDL3/src/camera/SDL_camera_c.h +++ b/libs/SDL3/src/camera/SDL_camera_c.h @@ -24,10 +24,10 @@ #define SDL_camera_c_h_ // Initialize the camera subsystem -int SDL_CameraInit(const char *driver_name); +extern bool SDL_CameraInit(const char *driver_name); // Shutdown the camera subsystem -void SDL_QuitCamera(void); +extern void SDL_QuitCamera(void); // "Pump" the event queue. extern void SDL_UpdateCamera(void); diff --git a/libs/SDL3/src/camera/SDL_syscamera.h b/libs/SDL3/src/camera/SDL_syscamera.h index 335ce4b18..51b88355e 100644 --- a/libs/SDL3/src/camera/SDL_syscamera.h +++ b/libs/SDL3/src/camera/SDL_syscamera.h @@ -23,38 +23,38 @@ #ifndef SDL_syscamera_h_ #define SDL_syscamera_h_ -#include "../SDL_hashtable.h" +#include "../video/SDL_surface_c.h" #define DEBUG_CAMERA 0 -typedef struct SDL_CameraDevice SDL_CameraDevice; +typedef struct SDL_Camera SDL_Camera; /* Backends should call this as devices are added to the system (such as a USB camera being plugged in), and should also be called for for every device found during DetectDevices(). */ -extern SDL_CameraDevice *SDL_AddCameraDevice(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle); +extern SDL_Camera *SDL_AddCamera(const char *name, SDL_CameraPosition position, int num_specs, const SDL_CameraSpec *specs, void *handle); /* Backends should call this if an opened camera device is lost. This can happen due to i/o errors, or a device being unplugged, etc. */ -extern void SDL_CameraDeviceDisconnected(SDL_CameraDevice *device); +extern void SDL_CameraDisconnected(SDL_Camera *device); -// Find an SDL_CameraDevice, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. -extern SDL_CameraDevice *SDL_FindPhysicalCameraDeviceByCallback(SDL_bool (*callback)(SDL_CameraDevice *device, void *userdata), void *userdata); +// Find an SDL_Camera, selected by a callback. NULL if not found. DOES NOT LOCK THE DEVICE. +extern SDL_Camera *SDL_FindPhysicalCameraByCallback(bool (*callback)(SDL_Camera *device, void *userdata), void *userdata); // Backends should call this when the user has approved/denied access to a camera. -extern void SDL_CameraDevicePermissionOutcome(SDL_CameraDevice *device, SDL_bool approved); +extern void SDL_CameraPermissionOutcome(SDL_Camera *device, bool approved); // Backends can call this to get a standardized name for a thread to power a specific camera device. -extern char *SDL_GetCameraThreadName(SDL_CameraDevice *device, char *buf, size_t buflen); +extern char *SDL_GetCameraThreadName(SDL_Camera *device, char *buf, size_t buflen); // Backends can call these to change a device's refcount. -extern void RefPhysicalCameraDevice(SDL_CameraDevice *device); -extern void UnrefPhysicalCameraDevice(SDL_CameraDevice *device); +extern void RefPhysicalCamera(SDL_Camera *device); +extern void UnrefPhysicalCamera(SDL_Camera *device); // These functions are the heart of the camera threads. Backends can call them directly if they aren't using the SDL-provided thread. -extern void SDL_CameraThreadSetup(SDL_CameraDevice *device); -extern SDL_bool SDL_CameraThreadIterate(SDL_CameraDevice *device); -extern void SDL_CameraThreadShutdown(SDL_CameraDevice *device); +extern void SDL_CameraThreadSetup(SDL_Camera *device); +extern bool SDL_CameraThreadIterate(SDL_Camera *device); +extern void SDL_CameraThreadShutdown(SDL_Camera *device); // common utility functionality to gather up camera specs. Not required! typedef struct CameraFormatAddData @@ -64,7 +64,14 @@ typedef struct CameraFormatAddData int allocated_specs; } CameraFormatAddData; -int SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormatEnum fmt, int w, int h, int interval_numerator, int interval_denominator); +bool SDL_AddCameraFormat(CameraFormatAddData *data, SDL_PixelFormat format, SDL_Colorspace colorspace, int w, int h, int framerate_numerator, int framerate_denominator); + +typedef enum SDL_CameraFrameResult +{ + SDL_CAMERA_FRAME_ERROR, + SDL_CAMERA_FRAME_SKIP, + SDL_CAMERA_FRAME_READY +} SDL_CameraFrameResult; typedef struct SurfaceList { @@ -74,7 +81,7 @@ typedef struct SurfaceList } SurfaceList; // Define the SDL camera driver structure -struct SDL_CameraDevice +struct SDL_Camera { // A mutex for locking SDL_Mutex *lock; @@ -89,9 +96,9 @@ struct SDL_CameraDevice SDL_AtomicInt refcount; // These are, initially, set from camera_driver, but we might swap them out with Zombie versions on disconnect/failure. - int (*WaitDevice)(SDL_CameraDevice *device); - int (*AcquireFrame)(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS); - void (*ReleaseFrame)(SDL_CameraDevice *device, SDL_Surface *frame); + bool (*WaitDevice)(SDL_Camera *device); + SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS); + void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); // All supported formats/dimensions for this device. SDL_CameraSpec *all_specs; @@ -106,7 +113,7 @@ struct SDL_CameraDevice SDL_CameraSpec spec; // Unique value assigned at creation time. - SDL_CameraDeviceID instance_id; + SDL_CameraID instance_id; // Driver-specific hardware data on how to open device (`hidden` is driver-specific data _when opened_). void *handle; @@ -138,8 +145,8 @@ struct SDL_CameraDevice // non-zero if acquire_surface needs to be scaled for final output. int needs_scaling; // -1: downscale, 0: no scaling, 1: upscale - // SDL_TRUE if acquire_surface needs to be converted for final output. - SDL_bool needs_conversion; + // true if acquire_surface needs to be converted for final output. + bool needs_conversion; // Current state flags SDL_AtomicInt shutdown; @@ -161,23 +168,23 @@ struct SDL_CameraDevice typedef struct SDL_CameraDriverImpl { void (*DetectDevices)(void); - int (*OpenDevice)(SDL_CameraDevice *device, const SDL_CameraSpec *spec); - void (*CloseDevice)(SDL_CameraDevice *device); - int (*WaitDevice)(SDL_CameraDevice *device); - int (*AcquireFrame)(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS); // set frame->pixels, frame->pitch, and *timestampNS! - void (*ReleaseFrame)(SDL_CameraDevice *device, SDL_Surface *frame); // Reclaim frame->pixels and frame->pitch! - void (*FreeDeviceHandle)(SDL_CameraDevice *device); // SDL is done with this device; free the handle from SDL_AddCameraDevice() + bool (*OpenDevice)(SDL_Camera *device, const SDL_CameraSpec *spec); + void (*CloseDevice)(SDL_Camera *device); + bool (*WaitDevice)(SDL_Camera *device); + SDL_CameraFrameResult (*AcquireFrame)(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS); // set frame->pixels, frame->pitch, and *timestampNS! + void (*ReleaseFrame)(SDL_Camera *device, SDL_Surface *frame); // Reclaim frame->pixels and frame->pitch! + void (*FreeDeviceHandle)(SDL_Camera *device); // SDL is done with this device; free the handle from SDL_AddCamera() void (*Deinitialize)(void); - SDL_bool ProvidesOwnCallbackThread; + bool ProvidesOwnCallbackThread; } SDL_CameraDriverImpl; -typedef struct SDL_PendingCameraDeviceEvent +typedef struct SDL_PendingCameraEvent { Uint32 type; - SDL_CameraDeviceID devid; - struct SDL_PendingCameraDeviceEvent *next; -} SDL_PendingCameraDeviceEvent; + SDL_CameraID devid; + struct SDL_PendingCameraEvent *next; +} SDL_PendingCameraEvent; typedef struct SDL_CameraDriver { @@ -187,8 +194,8 @@ typedef struct SDL_CameraDriver SDL_RWLock *device_hash_lock; // A rwlock that protects `device_hash` SDL_HashTable *device_hash; // the collection of currently-available camera devices - SDL_PendingCameraDeviceEvent pending_events; - SDL_PendingCameraDeviceEvent *pending_events_tail; + SDL_PendingCameraEvent pending_events; + SDL_PendingCameraEvent *pending_events_tail; SDL_AtomicInt device_count; SDL_AtomicInt shutting_down; // non-zero during SDL_Quit, so we known not to accept any last-minute device hotplugs. @@ -198,12 +205,13 @@ typedef struct CameraBootStrap { const char *name; const char *desc; - SDL_bool (*init)(SDL_CameraDriverImpl *impl); - SDL_bool demand_only; // if SDL_TRUE: request explicitly, or it won't be available. + bool (*init)(SDL_CameraDriverImpl *impl); + bool demand_only; // if true: request explicitly, or it won't be available. } CameraBootStrap; // Not all of these are available in a given build. Use #ifdefs, etc. extern CameraBootStrap DUMMYCAMERA_bootstrap; +extern CameraBootStrap PIPEWIRECAMERA_bootstrap; extern CameraBootStrap V4L2_bootstrap; extern CameraBootStrap COREMEDIA_bootstrap; extern CameraBootStrap ANDROIDCAMERA_bootstrap; diff --git a/libs/SDL3/src/camera/android/SDL_camera_android.c b/libs/SDL3/src/camera/android/SDL_camera_android.c index f96990eef..7c60bfd69 100644 --- a/libs/SDL3/src/camera/android/SDL_camera_android.c +++ b/libs/SDL3/src/camera/android/SDL_camera_android.c @@ -23,6 +23,7 @@ #include "../SDL_syscamera.h" #include "../SDL_camera_c.h" #include "../../video/SDL_pixels_c.h" +#include "../../video/SDL_surface_c.h" #include "../../thread/SDL_systhread.h" #ifdef SDL_CAMERA_DRIVER_ANDROID @@ -150,7 +151,7 @@ struct SDL_PrivateCameraData SDL_CameraSpec requested_spec; }; -static int SetErrorStr(const char *what, const char *errstr, const int rc) +static bool SetErrorStr(const char *what, const char *errstr, const int rc) { char errbuf[128]; if (!errstr) { @@ -185,7 +186,7 @@ static const char *CameraStatusStr(const camera_status_t rc) return NULL; // unknown error } -static int SetCameraError(const char *what, const camera_status_t rc) +static bool SetCameraError(const char *what, const camera_status_t rc) { return SetErrorStr(what, CameraStatusStr(rc), (int) rc); } @@ -194,7 +195,7 @@ static const char *MediaStatusStr(const media_status_t rc) { switch (rc) { case AMEDIA_OK: return "no error"; - case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE: return "insuffient resources"; + case AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE: return "insufficient resources"; case AMEDIACODEC_ERROR_RECLAIMED: return "reclaimed"; case AMEDIA_ERROR_UNKNOWN: return "unknown error"; case AMEDIA_ERROR_MALFORMED: return "malformed"; @@ -225,7 +226,7 @@ static const char *MediaStatusStr(const media_status_t rc) return NULL; // unknown error } -static int SetMediaError(const char *what, const media_status_t rc) +static bool SetMediaError(const char *what, const media_status_t rc) { return SetErrorStr(what, MediaStatusStr(rc), (int) rc); } @@ -233,7 +234,7 @@ static int SetMediaError(const char *what, const media_status_t rc) static ACameraManager *cameraMgr = NULL; -static int CreateCameraManager(void) +static bool CreateCameraManager(void) { SDL_assert(cameraMgr == NULL); @@ -241,7 +242,7 @@ static int CreateCameraManager(void) if (!cameraMgr) { return SDL_SetError("Error creating ACameraManager"); } - return 0; + return true; } static void DestroyCameraManager(void) @@ -252,18 +253,16 @@ static void DestroyCameraManager(void) } } -static Uint32 format_android_to_sdl(Uint32 fmt) +static void format_android_to_sdl(Uint32 fmt, SDL_PixelFormat *format, SDL_Colorspace *colorspace) { switch (fmt) { - #define CASE(x, y) case x: return y - CASE(AIMAGE_FORMAT_YUV_420_888, SDL_PIXELFORMAT_NV12); - CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565); - CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888); - CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888); - CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888); - //CASE(AIMAGE_FORMAT_RGBA_FP16, SDL_PIXELFORMAT_UNKNOWN); // 64bits - //CASE(AIMAGE_FORMAT_RAW_PRIVATE, SDL_PIXELFORMAT_UNKNOWN); - //CASE(AIMAGE_FORMAT_JPEG, SDL_PIXELFORMAT_UNKNOWN); + #define CASE(x, y, z) case x: *format = y; *colorspace = z; return + CASE(AIMAGE_FORMAT_YUV_420_888, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED); + CASE(AIMAGE_FORMAT_RGB_565, SDL_PIXELFORMAT_RGB565, SDL_COLORSPACE_SRGB); + CASE(AIMAGE_FORMAT_RGB_888, SDL_PIXELFORMAT_XRGB8888, SDL_COLORSPACE_SRGB); + CASE(AIMAGE_FORMAT_RGBA_8888, SDL_PIXELFORMAT_RGBA8888, SDL_COLORSPACE_SRGB); + CASE(AIMAGE_FORMAT_RGBX_8888, SDL_PIXELFORMAT_RGBX8888, SDL_COLORSPACE_SRGB); + CASE(AIMAGE_FORMAT_RGBA_FP16, SDL_PIXELFORMAT_RGBA64_FLOAT, SDL_COLORSPACE_SRGB); #undef CASE default: break; } @@ -272,10 +271,11 @@ static Uint32 format_android_to_sdl(Uint32 fmt) //SDL_Log("Unknown format AIMAGE_FORMAT '%d'", fmt); #endif - return SDL_PIXELFORMAT_UNKNOWN; + *format = SDL_PIXELFORMAT_UNKNOWN; + *colorspace = SDL_COLORSPACE_UNKNOWN; } -static Uint32 format_sdl_to_android(Uint32 fmt) +static Uint32 format_sdl_to_android(SDL_PixelFormat fmt) { switch (fmt) { #define CASE(x, y) case y: return x @@ -290,14 +290,14 @@ static Uint32 format_sdl_to_android(Uint32 fmt) } } -static int ANDROIDCAMERA_WaitDevice(SDL_CameraDevice *device) +static bool ANDROIDCAMERA_WaitDevice(SDL_Camera *device) { - return 0; // this isn't used atm, since we run our own thread via onImageAvailable callbacks. + return true; // this isn't used atm, since we run our own thread via onImageAvailable callbacks. } -static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult ANDROIDCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { - int retval = 1; + SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY; media_status_t res; AImage *image = NULL; @@ -308,7 +308,8 @@ static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *fra SDL_assert(res != AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE); // we should only be here if onImageAvailable was called. if (res != AMEDIA_OK) { - return SetMediaError("Error AImageReader_acquireNextImage", res); + SetMediaError("Error AImageReader_acquireNextImage", res); + return SDL_CAMERA_FRAME_ERROR; } int64_t atimestamp = 0; @@ -335,9 +336,9 @@ static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *fra buflen += (int) datalen; } - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { int32_t row_stride = 0; Uint8 *dst = frame->pixels; @@ -356,10 +357,10 @@ static int ANDROIDCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *fra pAImage_delete(image); - return retval; + return result; } -static void ANDROIDCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void ANDROIDCAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { // !!! FIXME: this currently copies the data to the surface, but in theory we could just keep the AImage until ReleaseFrame... SDL_aligned_free(frame->pixels); @@ -370,7 +371,7 @@ static void onImageAvailable(void *context, AImageReader *reader) #if DEBUG_CAMERA SDL_Log("CAMERA: CB onImageAvailable"); #endif - SDL_CameraDevice *device = (SDL_CameraDevice *) context; + SDL_Camera *device = (SDL_Camera *) context; SDL_CameraThreadIterate(device); } @@ -379,7 +380,7 @@ static void onDisconnected(void *context, ACameraDevice *device) #if DEBUG_CAMERA SDL_Log("CAMERA: CB onDisconnected"); #endif - SDL_CameraDeviceDisconnected((SDL_CameraDevice *) context); + SDL_CameraDisconnected((SDL_Camera *) context); } static void onError(void *context, ACameraDevice *device, int error) @@ -387,12 +388,12 @@ static void onError(void *context, ACameraDevice *device, int error) #if DEBUG_CAMERA SDL_Log("CAMERA: CB onError"); #endif - SDL_CameraDeviceDisconnected((SDL_CameraDevice *) context); + SDL_CameraDisconnected((SDL_Camera *) context); } static void onClosed(void* context, ACameraCaptureSession *session) { - // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + // SDL_Camera *_this = (SDL_Camera *) context; #if DEBUG_CAMERA SDL_Log("CAMERA: CB onClosed"); #endif @@ -400,7 +401,7 @@ static void onClosed(void* context, ACameraCaptureSession *session) static void onReady(void* context, ACameraCaptureSession *session) { - // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + // SDL_Camera *_this = (SDL_Camera *) context; #if DEBUG_CAMERA SDL_Log("CAMERA: CB onReady"); #endif @@ -408,13 +409,13 @@ static void onReady(void* context, ACameraCaptureSession *session) static void onActive(void* context, ACameraCaptureSession *session) { - // SDL_CameraDevice *_this = (SDL_CameraDevice *) context; + // SDL_Camera *_this = (SDL_Camera *) context; #if DEBUG_CAMERA SDL_Log("CAMERA: CB onActive"); #endif } -static void ANDROIDCAMERA_CloseDevice(SDL_CameraDevice *device) +static void ANDROIDCAMERA_CloseDevice(SDL_Camera *device) { if (device && device->hidden) { struct SDL_PrivateCameraData *hidden = device->hidden; @@ -459,7 +460,7 @@ static void ANDROIDCAMERA_CloseDevice(SDL_CameraDevice *device) } // this is where the "opening" of the camera happens, after permission is granted. -static int PrepareCamera(SDL_CameraDevice *device) +static bool PrepareCamera(SDL_Camera *device) { SDL_assert(device->hidden != NULL); @@ -484,7 +485,7 @@ static int PrepareCamera(SDL_CameraDevice *device) imglistener.context = device; imglistener.onImageAvailable = onImageAvailable; - // just in case SDL_OpenCameraDevice is overwriting device->spec as CameraPermissionCallback runs, we work from a different copy. + // just in case SDL_OpenCamera is overwriting device->spec as CameraPermissionCallback runs, we work from a different copy. const SDL_CameraSpec *spec = &device->hidden->requested_spec; if ((res = pACameraManager_openCamera(cameraMgr, (const char *) device->handle, &dev_callbacks, &device->hidden->device)) != ACAMERA_OK) { @@ -513,29 +514,29 @@ static int PrepareCamera(SDL_CameraDevice *device) return SetMediaError("Error AImageReader_setImageListener", res2); } - return 0; + return true; } -static void SDLCALL CameraPermissionCallback(void *userdata, const char *permission, SDL_bool granted) +static void SDLCALL CameraPermissionCallback(void *userdata, const char *permission, bool granted) { - SDL_CameraDevice *device = (SDL_CameraDevice *) userdata; + SDL_Camera *device = (SDL_Camera *) userdata; if (device->hidden != NULL) { // if device was already closed, don't send an event. if (!granted) { - SDL_CameraDevicePermissionOutcome(device, SDL_FALSE); // sorry, permission denied. - } else if (PrepareCamera(device) < 0) { // permission given? Actually open the camera now. + SDL_CameraPermissionOutcome(device, false); // sorry, permission denied. + } else if (!PrepareCamera(device)) { // permission given? Actually open the camera now. // uhoh, setup failed; since the app thinks we already "opened" the device, mark it as disconnected and don't report the permission. - SDL_CameraDeviceDisconnected(device); + SDL_CameraDisconnected(device); } else { // okay! We have permission to use the camera _and_ opening the hardware worked out, report that the camera is usable! - SDL_CameraDevicePermissionOutcome(device, SDL_TRUE); // go go go! + SDL_CameraPermissionOutcome(device, true); // go go go! } } - UnrefPhysicalCameraDevice(device); // we ref'd this in OpenDevice, release the extra reference. + UnrefPhysicalCamera(device); // we ref'd this in OpenDevice, release the extra reference. } -static int ANDROIDCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool ANDROIDCAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { #if 0 // !!! FIXME: for now, we'll just let this fail if it is going to fail, without checking for this /* Cannot open a second camera, while the first one is opened. @@ -553,22 +554,22 @@ static int ANDROIDCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSp device->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); if (device->hidden == NULL) { - return -1; + return false; } - RefPhysicalCameraDevice(device); // ref'd until permission callback fires. + RefPhysicalCamera(device); // ref'd until permission callback fires. - // just in case SDL_OpenCameraDevice is overwriting device->spec as CameraPermissionCallback runs, we work from a different copy. + // just in case SDL_OpenCamera is overwriting device->spec as CameraPermissionCallback runs, we work from a different copy. SDL_copyp(&device->hidden->requested_spec, spec); - if (SDL_AndroidRequestPermission("android.permission.CAMERA", CameraPermissionCallback, device) < 0) { - UnrefPhysicalCameraDevice(device); - return -1; + if (!SDL_RequestAndroidPermission("android.permission.CAMERA", CameraPermissionCallback, device)) { + UnrefPhysicalCamera(device); + return false; } - return 0; // we don't open the camera until permission is granted, so always succeed for now. + return true; // we don't open the camera until permission is granted, so always succeed for now. } -static void ANDROIDCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +static void ANDROIDCAMERA_FreeDeviceHandle(SDL_Camera *device) { if (device) { SDL_free(device->handle); @@ -633,14 +634,18 @@ static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, const int w = (int) i32ptr[1]; const int h = (int) i32ptr[2]; const int32_t type = i32ptr[3]; - Uint32 sdlfmt; + SDL_PixelFormat sdlfmt = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN; if (type == ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT) { continue; } else if ((w <= 0) || (h <= 0)) { continue; - } else if ((sdlfmt = format_android_to_sdl(fmt)) == SDL_PIXELFORMAT_UNKNOWN) { - continue; + } else { + format_android_to_sdl(fmt, &sdlfmt, &colorspace); + if (sdlfmt == SDL_PIXELFORMAT_UNKNOWN) { + continue; + } } #if 0 // !!! FIXME: these all come out with 0 durations on my test phone. :( @@ -650,20 +655,20 @@ static void GatherCameraSpecs(const char *devid, CameraFormatAddData *add_data, const int fpsw = (int) i64ptr[1]; const int fpsh = (int) i64ptr[2]; const long long duration = (long long) i64ptr[3]; - SDL_Log("CAMERA: possible fps %s %dx%d duration=%lld", SDL_GetPixelFormatName(format_android_to_sdl(fpsfmt)), fpsw, fpsh, duration); + SDL_Log("CAMERA: possible fps %s %dx%d duration=%lld", SDL_GetPixelFormatName(sdlfmt), fpsw, fpsh, duration); if ((duration > 0) && (fpsfmt == fmt) && (fpsw == w) && (fpsh == h)) { - SDL_AddCameraFormat(add_data, sdlfmt, w, h, duration, 1000000000); + SDL_AddCameraFormat(add_data, sdlfmt, colorspace, w, h, 1000000000, duration); } } #else - SDL_AddCameraFormat(add_data, sdlfmt, w, h, 1, 30); + SDL_AddCameraFormat(add_data, sdlfmt, colorspace, w, h, 30, 1); #endif } pACameraMetadata_free(metadata); } -static SDL_bool FindAndroidCameraDeviceByID(SDL_CameraDevice *device, void *userdata) +static bool FindAndroidCameraByID(SDL_Camera *device, void *userdata) { const char *devid = (const char *) userdata; return (SDL_strcmp(devid, (const char *) device->handle) == 0); @@ -675,7 +680,7 @@ static void MaybeAddDevice(const char *devid) SDL_Log("CAMERA: MaybeAddDevice('%s')", devid); #endif - if (SDL_FindPhysicalCameraDeviceByCallback(FindAndroidCameraDeviceByID, (void *) devid)) { + if (SDL_FindPhysicalCameraByCallback(FindAndroidCameraByID, (void *) devid)) { return; // already have this one. } @@ -686,7 +691,7 @@ static void MaybeAddDevice(const char *devid) if (add_data.num_specs > 0) { char *namecpy = SDL_strdup(devid); if (namecpy) { - SDL_CameraDevice *device = SDL_AddCameraDevice(fullname, position, add_data.num_specs, add_data.specs, namecpy); + SDL_Camera *device = SDL_AddCamera(fullname, position, add_data.num_specs, add_data.specs, namecpy); if (!device) { SDL_free(namecpy); } @@ -722,9 +727,9 @@ static void onCameraUnavailable(void *context, const char *cameraId) // THIS CALLBACK FIRES WHEN YOU OPEN THE DEVICE YOURSELF. :( // Make sure we don't have the device opened, in which case onDisconnected will fire instead if actually lost. - SDL_CameraDevice *device = SDL_FindPhysicalCameraDeviceByCallback(FindAndroidCameraDeviceByID, (void *) cameraId); + SDL_Camera *device = SDL_FindPhysicalCameraByCallback(FindAndroidCameraByID, (void *) cameraId); if (device && !device->hidden) { - SDL_CameraDeviceDisconnected(device); + SDL_CameraDisconnected(device); } } @@ -797,25 +802,25 @@ static void ANDROIDCAMERA_Deinitialize(void) pAImageReader_new = NULL; } -static SDL_bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl) +static bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl) { // !!! FIXME: slide this off into a subroutine // system libraries are in android-24 and later; we currently target android-16 and later, so check if they exist at runtime. void *libcamera2 = dlopen("libcamera2ndk.so", RTLD_NOW | RTLD_LOCAL); if (!libcamera2) { SDL_Log("CAMERA: libcamera2ndk.so can't be loaded: %s", dlerror()); - return SDL_FALSE; + return false; } void *libmedia = dlopen("libmediandk.so", RTLD_NOW | RTLD_LOCAL); if (!libmedia) { SDL_Log("CAMERA: libmediandk.so can't be loaded: %s", dlerror()); dlclose(libcamera2); - return SDL_FALSE; + return false; } - SDL_bool okay = SDL_TRUE; - #define LOADSYM(lib, fn) if (okay) { p##fn = (pfn##fn) dlsym(lib, #fn); if (!p##fn) { SDL_Log("CAMERA: symbol '%s' can't be found in %s: %s", #fn, #lib "ndk.so", dlerror()); okay = SDL_FALSE; } } + bool okay = true; + #define LOADSYM(lib, fn) if (okay) { p##fn = (pfn##fn) dlsym(lib, #fn); if (!p##fn) { SDL_Log("CAMERA: symbol '%s' can't be found in %s: %s", #fn, #lib "ndk.so", dlerror()); okay = false; } } //#define LOADSYM(lib, fn) p##fn = (pfn##fn) fn LOADSYM(libcamera2, ACameraManager_create); LOADSYM(libcamera2, ACameraManager_registerAvailabilityCallback); @@ -861,10 +866,10 @@ static SDL_bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl) dlclose(libcamera2); } - if (CreateCameraManager() < 0) { + if (!CreateCameraManager()) { dlclose(libmedia); dlclose(libcamera2); - return SDL_FALSE; + return false; } libcamera2ndk = libcamera2; @@ -879,13 +884,13 @@ static SDL_bool ANDROIDCAMERA_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = ANDROIDCAMERA_FreeDeviceHandle; impl->Deinitialize = ANDROIDCAMERA_Deinitialize; - impl->ProvidesOwnCallbackThread = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; - return SDL_TRUE; + return true; } CameraBootStrap ANDROIDCAMERA_bootstrap = { - "android", "SDL Android camera driver", ANDROIDCAMERA_Init, SDL_FALSE + "android", "SDL Android camera driver", ANDROIDCAMERA_Init, false }; #endif diff --git a/libs/SDL3/src/camera/coremedia/SDL_camera_coremedia.m b/libs/SDL3/src/camera/coremedia/SDL_camera_coremedia.m index 049c4a406..800340b4d 100644 --- a/libs/SDL3/src/camera/coremedia/SDL_camera_coremedia.m +++ b/libs/SDL3/src/camera/coremedia/SDL_camera_coremedia.m @@ -41,20 +41,24 @@ * com.apple.security.device.camera */ -static Uint32 CoreMediaFormatToSDL(FourCharCode fmt) +static void CoreMediaFormatToSDL(FourCharCode fmt, SDL_PixelFormat *pixel_format, SDL_Colorspace *colorspace) { switch (fmt) { - #define CASE(x, y) case x: return y + #define CASE(x, y, z) case x: *pixel_format = y; *colorspace = z; return // the 16LE ones should use 16BE if we're on a Bigendian system like PowerPC, // but at current time there is no bigendian Apple platform that has CoreMedia. - CASE(kCMPixelFormat_16LE555, SDL_PIXELFORMAT_RGB555); - CASE(kCMPixelFormat_16LE5551, SDL_PIXELFORMAT_RGBA5551); - CASE(kCMPixelFormat_16LE565, SDL_PIXELFORMAT_RGB565); - CASE(kCMPixelFormat_24RGB, SDL_PIXELFORMAT_RGB24); - CASE(kCMPixelFormat_32ARGB, SDL_PIXELFORMAT_ARGB32); - CASE(kCMPixelFormat_32BGRA, SDL_PIXELFORMAT_BGRA32); - CASE(kCMPixelFormat_422YpCbCr8, SDL_PIXELFORMAT_YUY2); - CASE(kCMPixelFormat_422YpCbCr8_yuvs, SDL_PIXELFORMAT_UYVY); + CASE(kCMPixelFormat_16LE555, SDL_PIXELFORMAT_XRGB1555, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_16LE5551, SDL_PIXELFORMAT_RGBA5551, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_16LE565, SDL_PIXELFORMAT_RGB565, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_24RGB, SDL_PIXELFORMAT_RGB24, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_32ARGB, SDL_PIXELFORMAT_ARGB32, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_32BGRA, SDL_PIXELFORMAT_BGRA32, SDL_COLORSPACE_SRGB); + CASE(kCMPixelFormat_422YpCbCr8, SDL_PIXELFORMAT_UYVY, SDL_COLORSPACE_BT709_LIMITED); + CASE(kCMPixelFormat_422YpCbCr8_yuvs, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED); + CASE(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED); + CASE(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_FULL); + CASE(kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, SDL_PIXELFORMAT_P010, SDL_COLORSPACE_BT2020_LIMITED); + CASE(kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, SDL_PIXELFORMAT_P010, SDL_COLORSPACE_BT2020_FULL); #undef CASE default: #if DEBUG_CAMERA @@ -62,7 +66,8 @@ static Uint32 CoreMediaFormatToSDL(FourCharCode fmt) #endif break; } - return SDL_PIXELFORMAT_UNKNOWN; + *pixel_format = SDL_PIXELFORMAT_UNKNOWN; + *colorspace = SDL_COLORSPACE_UNKNOWN; } @class SDLCaptureVideoDataOutputSampleBufferDelegate; @@ -78,16 +83,16 @@ @implementation SDLPrivateCameraData @end -static SDL_bool CheckCameraPermissions(SDL_CameraDevice *device) +static bool CheckCameraPermissions(SDL_Camera *device) { if (device->permission == 0) { // still expecting a permission result. if (@available(macOS 14, *)) { const AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (status != AVAuthorizationStatusNotDetermined) { // NotDetermined == still waiting for an answer from the user. - SDL_CameraDevicePermissionOutcome(device, (status == AVAuthorizationStatusAuthorized) ? SDL_TRUE : SDL_FALSE); + SDL_CameraPermissionOutcome(device, (status == AVAuthorizationStatusAuthorized) ? true : false); } } else { - SDL_CameraDevicePermissionOutcome(device, SDL_TRUE); // always allowed (or just unqueryable...?) on older macOS. + SDL_CameraPermissionOutcome(device, true); // always allowed (or just unqueryable...?) on older macOS. } } @@ -97,14 +102,14 @@ static SDL_bool CheckCameraPermissions(SDL_CameraDevice *device) // this delegate just receives new video frames on a Grand Central Dispatch queue, and fires off the // main device thread iterate function directly to consume it. @interface SDLCaptureVideoDataOutputSampleBufferDelegate : NSObject - @property SDL_CameraDevice *device; - -(id) init:(SDL_CameraDevice *) dev; + @property SDL_Camera *device; + -(id) init:(SDL_Camera *) dev; -(void) captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection; @end @implementation SDLCaptureVideoDataOutputSampleBufferDelegate - -(id) init:(SDL_CameraDevice *) dev { + -(id) init:(SDL_Camera *) dev { if ( self = [super init] ) { _device = dev; } @@ -113,7 +118,7 @@ -(id) init:(SDL_CameraDevice *) dev { - (void) captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { - SDL_CameraDevice *device = self.device; + SDL_Camera *device = self.device; if (!device || !device->hidden) { return; // oh well. } @@ -136,14 +141,14 @@ - (void)captureOutput:(AVCaptureOutput *)output didDropSampleBuffer:(CMSampleBuf } @end -static int COREMEDIA_WaitDevice(SDL_CameraDevice *device) +static bool COREMEDIA_WaitDevice(SDL_Camera *device) { - return 0; // this isn't used atm, since we run our own thread out of Grand Central Dispatch. + return true; // this isn't used atm, since we run our own thread out of Grand Central Dispatch. } -static int COREMEDIA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult COREMEDIA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { - int retval = 1; + SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY; SDLPrivateCameraData *hidden = (__bridge SDLPrivateCameraData *) device->hidden; CMSampleBufferRef sample_buffer = hidden.current_sample; hidden.current_sample = NULL; @@ -172,12 +177,15 @@ static int COREMEDIA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, // !!! FIXME: this currently copies the data to the surface (see FIXME about non-contiguous planar surfaces, but in theory we could just keep this locked until ReleaseFrame... CVPixelBufferLockBaseAddress(image, 0); + frame->w = (int)CVPixelBufferGetWidth(image); + frame->h = (int)CVPixelBufferGetHeight(image); + if ((planar == 0) && (numPlanes == 0)) { const int pitch = (int) CVPixelBufferGetBytesPerRow(image); const size_t buflen = pitch * frame->h; - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { frame->pitch = pitch; SDL_memcpy(frame->pixels, CVPixelBufferGetBaseAddress(image), buflen); @@ -185,38 +193,42 @@ static int COREMEDIA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, } else { // !!! FIXME: we have an open issue in SDL3 to allow SDL_Surface to support non-contiguous planar data, but we don't have it yet. size_t buflen = 0; - for (int i = 0; (i < numPlanes) && (i < 3); i++) { - buflen += CVPixelBufferGetBytesPerRowOfPlane(image, i); + for (int i = 0; i < numPlanes; i++) { + size_t plane_height = CVPixelBufferGetHeightOfPlane(image, i); + size_t plane_pitch = CVPixelBufferGetBytesPerRowOfPlane(image, i); + size_t plane_size = (plane_pitch * plane_height); + buflen += plane_size; } - buflen *= frame->h; - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pitch = (int)CVPixelBufferGetBytesPerRowOfPlane(image, 0); // this is what SDL3 currently expects + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { Uint8 *dst = frame->pixels; - frame->pitch = (int) CVPixelBufferGetBytesPerRowOfPlane(image, 0); // this is what SDL3 currently expects, probably incorrectly. - for (int i = 0; (i < numPlanes) && (i < 3); i++) { + for (int i = 0; i < numPlanes; i++) { const void *src = CVPixelBufferGetBaseAddressOfPlane(image, i); - const size_t pitch = CVPixelBufferGetBytesPerRowOfPlane(image, i); - SDL_memcpy(dst, src, pitch * frame->h); - dst += pitch * frame->h; + size_t plane_height = CVPixelBufferGetHeightOfPlane(image, i); + size_t plane_pitch = CVPixelBufferGetBytesPerRowOfPlane(image, i); + size_t plane_size = (plane_pitch * plane_height); + SDL_memcpy(dst, src, plane_size); + dst += plane_size; } } } CVPixelBufferUnlockBaseAddress(image, 0); - return retval; + return result; } -static void COREMEDIA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void COREMEDIA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { // !!! FIXME: this currently copies the data to the surface, but in theory we could just keep this locked until ReleaseFrame... SDL_aligned_free(frame->pixels); } -static void COREMEDIA_CloseDevice(SDL_CameraDevice *device) +static void COREMEDIA_CloseDevice(SDL_Camera *device) { if (device && device->hidden) { SDLPrivateCameraData *hidden = (SDLPrivateCameraData *) CFBridgingRelease(device->hidden); @@ -236,30 +248,34 @@ static void COREMEDIA_CloseDevice(SDL_CameraDevice *device) } } -static int COREMEDIA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool COREMEDIA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { AVCaptureDevice *avdevice = (__bridge AVCaptureDevice *) device->handle; // Pick format that matches the spec - const Uint32 sdlfmt = spec->format; const int w = spec->width; const int h = spec->height; - const int rate = spec->interval_denominator; + const float rate = (float)spec->framerate_numerator / spec->framerate_denominator; AVCaptureDeviceFormat *spec_format = nil; NSArray *formats = [avdevice formats]; for (AVCaptureDeviceFormat *format in formats) { CMFormatDescriptionRef formatDescription = [format formatDescription]; - if (CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(formatDescription)) != sdlfmt) { + SDL_PixelFormat device_format = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace device_colorspace = SDL_COLORSPACE_UNKNOWN; + CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(formatDescription), &device_format, &device_colorspace); + if (device_format != spec->format || device_colorspace != spec->colorspace) { continue; } const CMVideoDimensions dim = CMVideoFormatDescriptionGetDimensions(formatDescription); - if ( ((int) dim.width != w) || (((int) dim.height) != h) ) { + if ((int)dim.width != w || (int)dim.height != h) { continue; } + const float FRAMERATE_EPSILON = 0.01f; for (AVFrameRateRange *framerate in format.videoSupportedFrameRateRanges) { - if ((rate == (int) SDL_ceil((double) framerate.minFrameRate)) || (rate == (int) SDL_floor((double) framerate.maxFrameRate))) { + if (rate > (framerate.minFrameRate - FRAMERATE_EPSILON) && + rate < (framerate.maxFrameRate + FRAMERATE_EPSILON)) { spec_format = format; break; } @@ -285,6 +301,11 @@ static int COREMEDIA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec * } session.sessionPreset = AVCaptureSessionPresetHigh; +#if defined(SDL_PLATFORM_IOS) + if (@available(iOS 10.0, tvOS 17.0, *)) { + session.automaticallyConfiguresCaptureDeviceForWideColor = NO; + } +#endif NSError *error = nil; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:avdevice error:&error]; @@ -297,6 +318,12 @@ static int COREMEDIA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec * return SDL_SetError("Cannot create AVCaptureVideoDataOutput"); } + output.videoSettings = @{ + (id)kCVPixelBufferWidthKey : @(spec->width), + (id)kCVPixelBufferHeightKey : @(spec->height), + (id)kCVPixelBufferPixelFormatTypeKey : @(CMFormatDescriptionGetMediaSubType([spec_format formatDescription])) + }; + char threadname[64]; SDL_GetCameraThreadName(device, threadname, sizeof (threadname)); dispatch_queue_t queue = dispatch_queue_create(threadname, NULL); @@ -337,10 +364,10 @@ static int COREMEDIA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec * CheckCameraPermissions(device); // check right away, in case the process is already granted permission. - return 0; + return true; } -static void COREMEDIA_FreeDeviceHandle(SDL_CameraDevice *device) +static void COREMEDIA_FreeDeviceHandle(SDL_Camera *device) { if (device && device->handle) { CFBridgingRelease(device->handle); @@ -356,8 +383,11 @@ static void GatherCameraSpecs(AVCaptureDevice *device, CameraFormatAddData *add_ continue; } - const Uint32 sdlfmt = CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(fmt.formatDescription)); - if (sdlfmt == SDL_PIXELFORMAT_UNKNOWN) { +//NSLog(@"Available camera format: %@\n", fmt); + SDL_PixelFormat device_format = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace device_colorspace = SDL_COLORSPACE_UNKNOWN; + CoreMediaFormatToSDL(CMFormatDescriptionGetMediaSubType(fmt.formatDescription), &device_format, &device_colorspace); + if (device_format == SDL_PIXELFORMAT_UNKNOWN) { continue; } @@ -365,25 +395,24 @@ static void GatherCameraSpecs(AVCaptureDevice *device, CameraFormatAddData *add_ const int w = (int) dims.width; const int h = (int) dims.height; for (AVFrameRateRange *framerate in fmt.videoSupportedFrameRateRanges) { - int rate; - - rate = (int) SDL_ceil((double) framerate.minFrameRate); - if (rate) { - SDL_AddCameraFormat(add_data, sdlfmt, w, h, 1, rate); - } - rate = (int) SDL_floor((double) framerate.maxFrameRate); - if (rate) { - SDL_AddCameraFormat(add_data, sdlfmt, w, h, 1, rate); + int min_numerator = 0, min_denominator = 1; + int max_numerator = 0, max_denominator = 1; + + SDL_CalculateFraction(framerate.minFrameRate, &min_numerator, &min_denominator); + SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, min_numerator, min_denominator); + SDL_CalculateFraction(framerate.maxFrameRate, &max_numerator, &max_denominator); + if (max_numerator != min_numerator || max_denominator != min_denominator) { + SDL_AddCameraFormat(add_data, device_format, device_colorspace, w, h, max_numerator, max_denominator); } } } } -static SDL_bool FindCoreMediaCameraDeviceByUniqueID(SDL_CameraDevice *device, void *userdata) +static bool FindCoreMediaCameraByUniqueID(SDL_Camera *device, void *userdata) { NSString *uniqueid = (__bridge NSString *) userdata; AVCaptureDevice *avdev = (__bridge AVCaptureDevice *) device->handle; - return ([uniqueid isEqualToString:avdev.uniqueID]) ? SDL_TRUE : SDL_FALSE; + return ([uniqueid isEqualToString:avdev.uniqueID]) ? true : false; } static void MaybeAddDevice(AVCaptureDevice *avdevice) @@ -392,7 +421,7 @@ static void MaybeAddDevice(AVCaptureDevice *avdevice) return; // not connected. } else if (![avdevice hasMediaType:AVMediaTypeVideo]) { return; // not a camera. - } else if (SDL_FindPhysicalCameraDeviceByCallback(FindCoreMediaCameraDeviceByUniqueID, (__bridge void *) avdevice.uniqueID)) { + } else if (SDL_FindPhysicalCameraByCallback(FindCoreMediaCameraByUniqueID, (__bridge void *) avdevice.uniqueID)) { return; // already have this one. } @@ -405,7 +434,7 @@ static void MaybeAddDevice(AVCaptureDevice *avdevice) } else if (avdevice.position == AVCaptureDevicePositionBack) { position = SDL_CAMERA_POSITION_BACK_FACING; } - SDL_AddCameraDevice(avdevice.localizedName.UTF8String, position, add_data.num_specs, add_data.specs, (void *) CFBridgingRetain(avdevice)); + SDL_AddCamera(avdevice.localizedName.UTF8String, position, add_data.num_specs, add_data.specs, (void *) CFBridgingRetain(avdevice)); } SDL_free(add_data.specs); @@ -455,7 +484,7 @@ static void COREMEDIA_Deinitialize(void) // !!! FIXME: disable hotplug. } -static SDL_bool COREMEDIA_Init(SDL_CameraDriverImpl *impl) +static bool COREMEDIA_Init(SDL_CameraDriverImpl *impl) { impl->DetectDevices = COREMEDIA_DetectDevices; impl->OpenDevice = COREMEDIA_OpenDevice; @@ -466,13 +495,13 @@ static SDL_bool COREMEDIA_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = COREMEDIA_FreeDeviceHandle; impl->Deinitialize = COREMEDIA_Deinitialize; - impl->ProvidesOwnCallbackThread = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; - return SDL_TRUE; + return true; } CameraBootStrap COREMEDIA_bootstrap = { - "coremedia", "SDL Apple CoreMedia camera driver", COREMEDIA_Init, SDL_FALSE + "coremedia", "SDL Apple CoreMedia camera driver", COREMEDIA_Init, false }; #endif // SDL_CAMERA_DRIVER_COREMEDIA diff --git a/libs/SDL3/src/camera/dummy/SDL_camera_dummy.c b/libs/SDL3/src/camera/dummy/SDL_camera_dummy.c index b93eecbbe..d2e9a898e 100644 --- a/libs/SDL3/src/camera/dummy/SDL_camera_dummy.c +++ b/libs/SDL3/src/camera/dummy/SDL_camera_dummy.c @@ -24,26 +24,27 @@ #include "../SDL_syscamera.h" -static int DUMMYCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool DUMMYCAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { return SDL_Unsupported(); } -static void DUMMYCAMERA_CloseDevice(SDL_CameraDevice *device) +static void DUMMYCAMERA_CloseDevice(SDL_Camera *device) { } -static int DUMMYCAMERA_WaitDevice(SDL_CameraDevice *device) +static bool DUMMYCAMERA_WaitDevice(SDL_Camera *device) { return SDL_Unsupported(); } -static int DUMMYCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult DUMMYCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { - return SDL_Unsupported(); + SDL_Unsupported(); + return SDL_CAMERA_FRAME_ERROR; } -static void DUMMYCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void DUMMYCAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { } @@ -51,7 +52,7 @@ static void DUMMYCAMERA_DetectDevices(void) { } -static void DUMMYCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +static void DUMMYCAMERA_FreeDeviceHandle(SDL_Camera *device) { } @@ -59,7 +60,7 @@ static void DUMMYCAMERA_Deinitialize(void) { } -static SDL_bool DUMMYCAMERA_Init(SDL_CameraDriverImpl *impl) +static bool DUMMYCAMERA_Init(SDL_CameraDriverImpl *impl) { impl->DetectDevices = DUMMYCAMERA_DetectDevices; impl->OpenDevice = DUMMYCAMERA_OpenDevice; @@ -70,11 +71,11 @@ static SDL_bool DUMMYCAMERA_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = DUMMYCAMERA_FreeDeviceHandle; impl->Deinitialize = DUMMYCAMERA_Deinitialize; - return SDL_TRUE; + return true; } CameraBootStrap DUMMYCAMERA_bootstrap = { - "dummy", "SDL dummy camera driver", DUMMYCAMERA_Init, SDL_TRUE + "dummy", "SDL dummy camera driver", DUMMYCAMERA_Init, true }; #endif // SDL_CAMERA_DRIVER_DUMMY diff --git a/libs/SDL3/src/camera/emscripten/SDL_camera_emscripten.c b/libs/SDL3/src/camera/emscripten/SDL_camera_emscripten.c index 9a605a752..3662bffce 100644 --- a/libs/SDL3/src/camera/emscripten/SDL_camera_emscripten.c +++ b/libs/SDL3/src/camera/emscripten/SDL_camera_emscripten.c @@ -25,26 +25,27 @@ #include "../SDL_syscamera.h" #include "../SDL_camera_c.h" #include "../../video/SDL_pixels_c.h" +#include "../../video/SDL_surface_c.h" #include // just turn off clang-format for this whole file, this INDENT_OFF stuff on // each EM_ASM section is ugly. -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off EM_JS_DEPS(sdlcamera, "$dynCall"); -static int EMSCRIPTENCAMERA_WaitDevice(SDL_CameraDevice *device) +static bool EMSCRIPTENCAMERA_WaitDevice(SDL_Camera *device) { SDL_assert(!"This shouldn't be called"); // we aren't using SDL's internal thread. - return -1; + return false; } -static int EMSCRIPTENCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult EMSCRIPTENCAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { void *rgba = SDL_malloc(device->actual_spec.width * device->actual_spec.height * 4); if (!rgba) { - return SDL_OutOfMemory(); + return SDL_CAMERA_FRAME_ERROR; } *timestampNS = SDL_GetTicksNS(); // best we can do here. @@ -67,21 +68,21 @@ static int EMSCRIPTENCAMERA_AcquireFrame(SDL_CameraDevice *device, SDL_Surface * if (!rc) { SDL_free(rgba); - return 0; // something went wrong, maybe shutting down; just don't return a frame. + return SDL_CAMERA_FRAME_ERROR; // something went wrong, maybe shutting down; just don't return a frame. } frame->pixels = rgba; frame->pitch = device->actual_spec.width * 4; - return 1; + return SDL_CAMERA_FRAME_READY; } -static void EMSCRIPTENCAMERA_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void EMSCRIPTENCAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { SDL_free(frame->pixels); } -static void EMSCRIPTENCAMERA_CloseDevice(SDL_CameraDevice *device) +static void EMSCRIPTENCAMERA_CloseDevice(SDL_Camera *device) { if (device) { MAIN_THREAD_EM_ASM({ @@ -90,7 +91,6 @@ static void EMSCRIPTENCAMERA_CloseDevice(SDL_CameraDevice *device) return; // camera was closed and/or subsystem was shut down, we're already done. } SDL3.camera.stream.getTracks().forEach(track => track.stop()); // stop all recording. - _SDL_free(SDL3.camera.rgba); SDL3.camera = {}; // dump our references to everything. }); SDL_free(device->hidden); @@ -98,16 +98,20 @@ static void EMSCRIPTENCAMERA_CloseDevice(SDL_CameraDevice *device) } } -static void SDLEmscriptenCameraDevicePermissionOutcome(SDL_CameraDevice *device, int approved, int w, int h, int fps) +static void SDLEmscriptenCameraPermissionOutcome(SDL_Camera *device, int approved, int w, int h, int fps) { device->spec.width = device->actual_spec.width = w; device->spec.height = device->actual_spec.height = h; - device->spec.interval_numerator = device->actual_spec.interval_numerator = 1; - device->spec.interval_denominator = device->actual_spec.interval_denominator = fps; - SDL_CameraDevicePermissionOutcome(device, approved ? SDL_TRUE : SDL_FALSE); + device->spec.framerate_numerator = device->actual_spec.framerate_numerator = fps; + device->spec.framerate_denominator = device->actual_spec.framerate_denominator = 1; + if (device->acquire_surface) { + device->acquire_surface->w = w; + device->acquire_surface->h = h; + } + SDL_CameraPermissionOutcome(device, approved ? true : false); } -static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool EMSCRIPTENCAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { MAIN_THREAD_EM_ASM({ // Since we can't get actual specs until we make a move that prompts the user for @@ -115,8 +119,8 @@ static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_Camer const device = $0; const w = $1; const h = $2; - const interval_numerator = $3; - const interval_denominator = $4; + const framerate_numerator = $3; + const framerate_denominator = $4; const outcome = $5; const iterate = $6; @@ -129,8 +133,8 @@ static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_Camer constraints.video.height = h; } - if ((interval_numerator > 0) && (interval_denominator > 0)) { - var fps = interval_denominator / interval_numerator; + if ((framerate_numerator > 0) && (framerate_denominator > 0)) { + var fps = framerate_numerator / framerate_denominator; constraints.video.frameRate = { ideal: fps }; } @@ -187,7 +191,6 @@ static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_Camer SDL3.camera.video = video; SDL3.camera.canvas = canvas; SDL3.camera.ctx2d = ctx2d; - SDL3.camera.rgba = 0; SDL3.camera.next_frame_time = performance.now(); video.play(); @@ -199,12 +202,12 @@ static int EMSCRIPTENCAMERA_OpenDevice(SDL_CameraDevice *device, const SDL_Camer console.error("Tried to open camera but it threw an error! " + err.name + ": " + err.message); dynCall('viiiii', outcome, [device, 0, 0, 0, 0]); // we call this a permission error, because it probably is. }); - }, device, spec->width, spec->height, spec->interval_numerator, spec->interval_denominator, SDLEmscriptenCameraDevicePermissionOutcome, SDL_CameraThreadIterate); + }, device, spec->width, spec->height, spec->framerate_numerator, spec->framerate_denominator, SDLEmscriptenCameraPermissionOutcome, SDL_CameraThreadIterate); - return 0; // the real work waits until the user approves a camera. + return true; // the real work waits until the user approves a camera. } -static void EMSCRIPTENCAMERA_FreeDeviceHandle(SDL_CameraDevice *device) +static void EMSCRIPTENCAMERA_FreeDeviceHandle(SDL_Camera *device) { // no-op. } @@ -228,11 +231,11 @@ static void EMSCRIPTENCAMERA_DetectDevices(void) // will pop up a user permission dialog warning them we're trying to access the camera, and we generally // don't want that during SDL_Init(). if (supported) { - SDL_AddCameraDevice("Web browser's camera", SDL_CAMERA_POSITION_UNKNOWN, 0, NULL, (void *) (size_t) 0x1); + SDL_AddCamera("Web browser's camera", SDL_CAMERA_POSITION_UNKNOWN, 0, NULL, (void *) (size_t) 0x1); } } -static SDL_bool EMSCRIPTENCAMERA_Init(SDL_CameraDriverImpl *impl) +static bool EMSCRIPTENCAMERA_Init(SDL_CameraDriverImpl *impl) { MAIN_THREAD_EM_ASM({ if (typeof(Module['SDL3']) === 'undefined') { @@ -250,16 +253,16 @@ static SDL_bool EMSCRIPTENCAMERA_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = EMSCRIPTENCAMERA_FreeDeviceHandle; impl->Deinitialize = EMSCRIPTENCAMERA_Deinitialize; - impl->ProvidesOwnCallbackThread = SDL_TRUE; + impl->ProvidesOwnCallbackThread = true; - return SDL_TRUE; + return true; } CameraBootStrap EMSCRIPTENCAMERA_bootstrap = { - "emscripten", "SDL Emscripten MediaStream camera driver", EMSCRIPTENCAMERA_Init, SDL_FALSE + "emscripten", "SDL Emscripten MediaStream camera driver", EMSCRIPTENCAMERA_Init, false }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on #endif // SDL_CAMERA_DRIVER_EMSCRIPTEN diff --git a/libs/SDL3/src/camera/mediafoundation/SDL_camera_mediafoundation.c b/libs/SDL3/src/camera/mediafoundation/SDL_camera_mediafoundation.c index 86d500592..1e7941690 100644 --- a/libs/SDL3/src/camera/mediafoundation/SDL_camera_mediafoundation.c +++ b/libs/SDL3/src/camera/mediafoundation/SDL_camera_mediafoundation.c @@ -44,9 +44,18 @@ static const IID SDL_IID_IMF2DBuffer2 = { 0x33ae5ea6, 0x4316, 0x436f, { 0x8d, 0x static const GUID SDL_MF_MT_DEFAULT_STRIDE = { 0x644b4e48, 0x1e02, 0x4516, { 0xb0, 0xeb, 0xc0, 0x1c, 0xa9, 0xd4, 0x9a, 0xc6 } }; static const GUID SDL_MF_MT_MAJOR_TYPE = { 0x48eba18e, 0xf8c9, 0x4687, { 0xbf, 0x11, 0x0a, 0x74, 0xc9, 0xf9, 0x6a, 0x8f } }; static const GUID SDL_MF_MT_SUBTYPE = { 0xf7e34c9a, 0x42e8, 0x4714, { 0xb7, 0x4b, 0xcb, 0x29, 0xd7, 0x2c, 0x35, 0xe5 } }; +static const GUID SDL_MF_MT_VIDEO_NOMINAL_RANGE = { 0xc21b8ee5, 0xb956, 0x4071, { 0x8d, 0xaf, 0x32, 0x5e, 0xdf, 0x5c, 0xab, 0x11 } }; +static const GUID SDL_MF_MT_VIDEO_PRIMARIES = { 0xdbfbe4d7, 0x0740, 0x4ee0, { 0x81, 0x92, 0x85, 0x0a, 0xb0, 0xe2, 0x19, 0x35 } }; +static const GUID SDL_MF_MT_TRANSFER_FUNCTION = { 0x5fb0fce9, 0xbe5c, 0x4935, { 0xa8, 0x11, 0xec, 0x83, 0x8f, 0x8e, 0xed, 0x93 } }; +static const GUID SDL_MF_MT_YUV_MATRIX = { 0x3e23d450, 0x2c75, 0x4d25, { 0xa0, 0x0e, 0xb9, 0x16, 0x70, 0xd1, 0x23, 0x27 } }; +static const GUID SDL_MF_MT_VIDEO_CHROMA_SITING = { 0x65df2370, 0xc773, 0x4c33, { 0xaa, 0x64, 0x84, 0x3e, 0x06, 0x8e, 0xfb, 0x0c } }; static const GUID SDL_MF_MT_FRAME_SIZE = { 0x1652c33d, 0xd6b2, 0x4012, { 0xb8, 0x34, 0x72, 0x03, 0x08, 0x49, 0xa3, 0x7d } }; static const GUID SDL_MF_MT_FRAME_RATE = { 0xc459a2e8, 0x3d2c, 0x4e44, { 0xb1, 0x32, 0xfe, 0xe5, 0x15, 0x6c, 0x7b, 0xb0 } }; static const GUID SDL_MFMediaType_Video = { 0x73646976, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 } }; +static const IID SDL_MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME = { 0x60d0e559, 0x52f8, 0x4fa2, { 0xbb, 0xce, 0xac, 0xdb, 0x34, 0xa8, 0xec, 0x1 } }; +static const IID SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE = { 0xc60ac5fe, 0x252a, 0x478f, { 0xa0, 0xef, 0xbc, 0x8f, 0xa5, 0xf7, 0xca, 0xd3 } }; +static const IID SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK = { 0x58f0aad8, 0x22bf, 0x4f8a, { 0xbb, 0x3d, 0xd2, 0xc4, 0x97, 0x8c, 0x6e, 0x2f } }; +static const IID SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID = { 0x8ac3587a, 0x4ae7, 0x42d8, { 0x99, 0xe0, 0x0a, 0x60, 0x13, 0xee, 0xf9, 0x0f } }; #ifdef __GNUC__ #pragma GCC diagnostic push @@ -76,39 +85,225 @@ SDL_DEFINE_MEDIATYPE_GUID(MFVideoFormat_NV21, FCC('NV21')); static const struct { const GUID *guid; - const SDL_PixelFormatEnum sdlfmt; + SDL_PixelFormat format; + SDL_Colorspace colorspace; } fmtmappings[] = { // This is not every possible format, just popular ones that SDL can reasonably handle. // (and we should probably trim this list more.) - { &SDL_MFVideoFormat_RGB555, SDL_PIXELFORMAT_XRGB1555 }, - { &SDL_MFVideoFormat_RGB565, SDL_PIXELFORMAT_RGB565 }, - { &SDL_MFVideoFormat_RGB24, SDL_PIXELFORMAT_RGB24 }, - { &SDL_MFVideoFormat_RGB32, SDL_PIXELFORMAT_XRGB8888 }, - { &SDL_MFVideoFormat_ARGB32, SDL_PIXELFORMAT_ARGB8888 }, - { &SDL_MFVideoFormat_A2R10G10B10, SDL_PIXELFORMAT_ARGB2101010 }, - { &SDL_MFVideoFormat_YV12, SDL_PIXELFORMAT_YV12 }, - { &SDL_MFVideoFormat_IYUV, SDL_PIXELFORMAT_IYUV }, - { &SDL_MFVideoFormat_YUY2, SDL_PIXELFORMAT_YUY2 }, - { &SDL_MFVideoFormat_UYVY, SDL_PIXELFORMAT_UYVY }, - { &SDL_MFVideoFormat_YVYU, SDL_PIXELFORMAT_YVYU }, - { &SDL_MFVideoFormat_NV12, SDL_PIXELFORMAT_NV12 }, - { &SDL_MFVideoFormat_NV21, SDL_PIXELFORMAT_NV21 } + { &SDL_MFVideoFormat_RGB555, SDL_PIXELFORMAT_XRGB1555, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_RGB565, SDL_PIXELFORMAT_RGB565, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_RGB24, SDL_PIXELFORMAT_RGB24, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_RGB32, SDL_PIXELFORMAT_XRGB8888, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_ARGB32, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_A2R10G10B10, SDL_PIXELFORMAT_ARGB2101010, SDL_COLORSPACE_SRGB }, + { &SDL_MFVideoFormat_YV12, SDL_PIXELFORMAT_YV12, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_IYUV, SDL_PIXELFORMAT_IYUV, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_YUY2, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_UYVY, SDL_PIXELFORMAT_UYVY, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_YVYU, SDL_PIXELFORMAT_YVYU, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_NV12, SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED }, + { &SDL_MFVideoFormat_NV21, SDL_PIXELFORMAT_NV21, SDL_COLORSPACE_BT709_LIMITED } }; -static SDL_PixelFormatEnum MFVidFmtGuidToSDLFmt(const GUID *guid) +static SDL_Colorspace GetMediaTypeColorspace(IMFMediaType *mediatype, SDL_Colorspace default_colorspace) { - for (size_t i = 0; i < SDL_arraysize(fmtmappings); i++) { - if (WIN_IsEqualGUID(guid, fmtmappings[i].guid)) { - return fmtmappings[i].sdlfmt; + SDL_Colorspace colorspace = default_colorspace; + + if (SDL_COLORSPACETYPE(colorspace) == SDL_COLOR_TYPE_YCBCR) { + HRESULT ret; + UINT32 range = 0, primaries = 0, transfer = 0, matrix = 0, chroma = 0; + + ret = IMFMediaType_GetUINT32(mediatype, &SDL_MF_MT_VIDEO_NOMINAL_RANGE, &range); + if (SUCCEEDED(ret)) { + switch (range) { + case MFNominalRange_0_255: + range = SDL_COLOR_RANGE_FULL; + break; + case MFNominalRange_16_235: + range = SDL_COLOR_RANGE_LIMITED; + break; + default: + range = (UINT32)SDL_COLORSPACERANGE(default_colorspace); + break; + } + } else { + range = (UINT32)SDL_COLORSPACERANGE(default_colorspace); + } + + ret = IMFMediaType_GetUINT32(mediatype, &SDL_MF_MT_VIDEO_PRIMARIES, &primaries); + if (SUCCEEDED(ret)) { + switch (primaries) { + case MFVideoPrimaries_BT709: + primaries = SDL_COLOR_PRIMARIES_BT709; + break; + case MFVideoPrimaries_BT470_2_SysM: + primaries = SDL_COLOR_PRIMARIES_BT470M; + break; + case MFVideoPrimaries_BT470_2_SysBG: + primaries = SDL_COLOR_PRIMARIES_BT470BG; + break; + case MFVideoPrimaries_SMPTE170M: + primaries = SDL_COLOR_PRIMARIES_BT601; + break; + case MFVideoPrimaries_SMPTE240M: + primaries = SDL_COLOR_PRIMARIES_SMPTE240; + break; + case MFVideoPrimaries_EBU3213: + primaries = SDL_COLOR_PRIMARIES_EBU3213; + break; + case MFVideoPrimaries_BT2020: + primaries = SDL_COLOR_PRIMARIES_BT2020; + break; + case MFVideoPrimaries_XYZ: + primaries = SDL_COLOR_PRIMARIES_XYZ; + break; + case MFVideoPrimaries_DCI_P3: + primaries = SDL_COLOR_PRIMARIES_SMPTE432; + break; + default: + primaries = (UINT32)SDL_COLORSPACEPRIMARIES(default_colorspace); + break; + } + } else { + primaries = (UINT32)SDL_COLORSPACEPRIMARIES(default_colorspace); + } + + ret = IMFMediaType_GetUINT32(mediatype, &SDL_MF_MT_TRANSFER_FUNCTION, &transfer); + if (SUCCEEDED(ret)) { + switch (transfer) { + case MFVideoTransFunc_10: + transfer = SDL_TRANSFER_CHARACTERISTICS_LINEAR; + break; + case MFVideoTransFunc_22: + transfer = SDL_TRANSFER_CHARACTERISTICS_GAMMA22; + break; + case MFVideoTransFunc_709: + transfer = SDL_TRANSFER_CHARACTERISTICS_BT709; + break; + case MFVideoTransFunc_240M: + transfer = SDL_TRANSFER_CHARACTERISTICS_SMPTE240; + break; + case MFVideoTransFunc_sRGB: + transfer = SDL_TRANSFER_CHARACTERISTICS_SRGB; + break; + case MFVideoTransFunc_28: + transfer = SDL_TRANSFER_CHARACTERISTICS_GAMMA28; + break; + case MFVideoTransFunc_Log_100: + transfer = SDL_TRANSFER_CHARACTERISTICS_LOG100; + break; + case MFVideoTransFunc_2084: + transfer = SDL_TRANSFER_CHARACTERISTICS_PQ; + break; + case MFVideoTransFunc_HLG: + transfer = SDL_TRANSFER_CHARACTERISTICS_HLG; + break; + case 18 /* MFVideoTransFunc_BT1361_ECG */: + transfer = SDL_TRANSFER_CHARACTERISTICS_BT1361; + break; + case 19 /* MFVideoTransFunc_SMPTE428 */: + transfer = SDL_TRANSFER_CHARACTERISTICS_SMPTE428; + break; + default: + transfer = (UINT32)SDL_COLORSPACETRANSFER(default_colorspace); + break; + } + } else { + transfer = (UINT32)SDL_COLORSPACETRANSFER(default_colorspace); + } + + ret = IMFMediaType_GetUINT32(mediatype, &SDL_MF_MT_YUV_MATRIX, &matrix); + if (SUCCEEDED(ret)) { + switch (matrix) { + case MFVideoTransferMatrix_BT709: + matrix = SDL_MATRIX_COEFFICIENTS_BT709; + break; + case MFVideoTransferMatrix_BT601: + matrix = SDL_MATRIX_COEFFICIENTS_BT601; + break; + case MFVideoTransferMatrix_SMPTE240M: + matrix = SDL_MATRIX_COEFFICIENTS_SMPTE240; + break; + case MFVideoTransferMatrix_BT2020_10: + matrix = SDL_MATRIX_COEFFICIENTS_BT2020_NCL; + break; + case 6 /* MFVideoTransferMatrix_Identity */: + matrix = SDL_MATRIX_COEFFICIENTS_IDENTITY; + break; + case 7 /* MFVideoTransferMatrix_FCC47 */: + matrix = SDL_MATRIX_COEFFICIENTS_FCC; + break; + case 8 /* MFVideoTransferMatrix_YCgCo */: + matrix = SDL_MATRIX_COEFFICIENTS_YCGCO; + break; + case 9 /* MFVideoTransferMatrix_SMPTE2085 */: + matrix = SDL_MATRIX_COEFFICIENTS_SMPTE2085; + break; + case 10 /* MFVideoTransferMatrix_Chroma */: + matrix = SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL; + break; + case 11 /* MFVideoTransferMatrix_Chroma_const */: + matrix = SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL; + break; + case 12 /* MFVideoTransferMatrix_ICtCp */: + matrix = SDL_MATRIX_COEFFICIENTS_ICTCP; + break; + default: + matrix = (UINT32)SDL_COLORSPACEMATRIX(default_colorspace); + break; + } + } else { + matrix = (UINT32)SDL_COLORSPACEMATRIX(default_colorspace); + } + + ret = IMFMediaType_GetUINT32(mediatype, &SDL_MF_MT_VIDEO_CHROMA_SITING, &chroma); + if (SUCCEEDED(ret)) { + switch (chroma) { + case MFVideoChromaSubsampling_MPEG2: + chroma = SDL_CHROMA_LOCATION_LEFT; + break; + case MFVideoChromaSubsampling_MPEG1: + chroma = SDL_CHROMA_LOCATION_CENTER; + break; + case MFVideoChromaSubsampling_DV_PAL: + chroma = SDL_CHROMA_LOCATION_TOPLEFT; + break; + default: + chroma = (UINT32)SDL_COLORSPACECHROMA(default_colorspace); + break; + } + } else { + chroma = (UINT32)SDL_COLORSPACECHROMA(default_colorspace); + } + + colorspace = SDL_DEFINE_COLORSPACE(SDL_COLOR_TYPE_YCBCR, range, primaries, transfer, matrix, chroma); + } + return colorspace; +} + +static void MediaTypeToSDLFmt(IMFMediaType *mediatype, SDL_PixelFormat *format, SDL_Colorspace *colorspace) +{ + HRESULT ret; + GUID type; + + ret = IMFMediaType_GetGUID(mediatype, &SDL_MF_MT_SUBTYPE, &type); + if (SUCCEEDED(ret)) { + for (size_t i = 0; i < SDL_arraysize(fmtmappings); i++) { + if (WIN_IsEqualGUID(&type, fmtmappings[i].guid)) { + *format = fmtmappings[i].format; + *colorspace = GetMediaTypeColorspace(mediatype, fmtmappings[i].colorspace); + return; + } } } - return SDL_PIXELFORMAT_UNKNOWN; + *format = SDL_PIXELFORMAT_UNKNOWN; + *colorspace = SDL_COLORSPACE_UNKNOWN; } -static const GUID *SDLFmtToMFVidFmtGuid(SDL_PixelFormatEnum sdlfmt) +static const GUID *SDLFmtToMFVidFmtGuid(SDL_PixelFormat format) { for (size_t i = 0; i < SDL_arraysize(fmtmappings); i++) { - if (fmtmappings[i].sdlfmt == sdlfmt) { + if (fmtmappings[i].format == format) { return fmtmappings[i].guid; } } @@ -152,28 +347,28 @@ typedef struct SDL_PrivateCameraData int pitch; } SDL_PrivateCameraData; -static int MEDIAFOUNDATION_WaitDevice(SDL_CameraDevice *device) +static bool MEDIAFOUNDATION_WaitDevice(SDL_Camera *device) { SDL_assert(device->hidden->current_sample == NULL); IMFSourceReader *srcreader = device->hidden->srcreader; IMFSample *sample = NULL; - while (!SDL_AtomicGet(&device->shutdown)) { + while (!SDL_GetAtomicInt(&device->shutdown)) { DWORD stream_flags = 0; const HRESULT ret = IMFSourceReader_ReadSample(srcreader, (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, &stream_flags, NULL, &sample); if (FAILED(ret)) { - return -1; // ruh roh. + return false; // ruh roh. } // we currently ignore stream_flags format changes, but my _hope_ is that IMFSourceReader is handling this and - // will continue to give us the explictly-specified format we requested when opening the device, though, and + // will continue to give us the explicitly-specified format we requested when opening the device, though, and // we don't have to manually deal with it. if (sample != NULL) { break; } else if (stream_flags & (MF_SOURCE_READERF_ERROR | MF_SOURCE_READERF_ENDOFSTREAM)) { - return -1; // apparently this camera has gone down. :/ + return false; // apparently this camera has gone down. :/ } // otherwise, there was some minor burp, probably; just try again. @@ -181,7 +376,7 @@ static int MEDIAFOUNDATION_WaitDevice(SDL_CameraDevice *device) device->hidden->current_sample = sample; - return 0; + return true; } @@ -226,17 +421,17 @@ static void SDLCALL CleanupIMFMediaBuffer(void *userdata, void *value) SDL_free(objs); } -static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { SDL_assert(device->hidden->current_sample != NULL); - - int retval = 1; + + SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY; HRESULT ret; LONGLONG timestamp100NS = 0; SDL_IMFObjects *objs = (SDL_IMFObjects *) SDL_calloc(1, sizeof (SDL_IMFObjects)); if (objs == NULL) { - return -1; + return SDL_CAMERA_FRAME_ERROR; } objs->sample = device->hidden->current_sample; @@ -244,21 +439,21 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); if (!surfprops) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { ret = IMFSample_GetSampleTime(objs->sample, ×tamp100NS); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } *timestampNS = timestamp100NS * 100; // the timestamps are in 100-nanosecond increments; move to full nanoseconds. } - ret = (retval < 0) ? E_FAIL : IMFSample_ConvertToContiguousBuffer(objs->sample, &objs->buffer); /*IMFSample_GetBufferByIndex(objs->sample, 0, &objs->buffer);*/ + ret = (result == SDL_CAMERA_FRAME_ERROR) ? E_FAIL : IMFSample_ConvertToContiguousBuffer(objs->sample, &objs->buffer); // IMFSample_GetBufferByIndex(objs->sample, 0, &objs->buffer); if (FAILED(ret)) { SDL_free(objs); - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { BYTE *pixels = NULL; LONG pitch = 0; @@ -268,27 +463,25 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f DWORD buflen = 0; ret = IMF2DBuffer2_Lock2DSize(objs->buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; CleanupIMF2DBuffer2(NULL, objs); } else { frame->pixels = pixels; frame->pitch = (int) pitch; - if (SDL_SetPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL) == -1) { - CleanupIMF2DBuffer2(NULL, objs); - retval = -1; + if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer2, NULL)) { + result = SDL_CAMERA_FRAME_ERROR; } } } else if (SUCCEEDED(IMFMediaBuffer_QueryInterface(objs->buffer, &SDL_IID_IMF2DBuffer, (void **)&objs->buffer2d))) { ret = IMF2DBuffer_Lock2D(objs->buffer2d, &pixels, &pitch); if (FAILED(ret)) { CleanupIMF2DBuffer(NULL, objs); - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { frame->pixels = pixels; frame->pitch = (int) pitch; - if (SDL_SetPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer, NULL) == -1) { - CleanupIMF2DBuffer(NULL, objs); - retval = -1; + if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMF2DBuffer, NULL)) { + result = SDL_CAMERA_FRAME_ERROR; } } } else { @@ -296,7 +489,7 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f ret = IMFMediaBuffer_Lock(objs->buffer, &pixels, &maxlen, ¤tlen); if (FAILED(ret)) { CleanupIMFMediaBuffer(NULL, objs); - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { pitch = (LONG) device->hidden->pitch; if (pitch < 0) { // image rows are reversed. @@ -304,22 +497,21 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f } frame->pixels = pixels; frame->pitch = (int) pitch; - if (SDL_SetPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL) == -1) { - CleanupIMFMediaBuffer(NULL, objs); - retval = -1; + if (!SDL_SetPointerPropertyWithCleanup(surfprops, PROP_SURFACE_IMFOBJS_POINTER, objs, CleanupIMFMediaBuffer, NULL)) { + result = SDL_CAMERA_FRAME_ERROR; } } } } - if (retval < 0) { + if (result != SDL_CAMERA_FRAME_READY) { *timestampNS = 0; } - return retval; + return result; } -static void MEDIAFOUNDATION_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void MEDIAFOUNDATION_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); if (surfprops) { @@ -330,11 +522,11 @@ static void MEDIAFOUNDATION_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface * #else -static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult MEDIAFOUNDATION_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { SDL_assert(device->hidden->current_sample != NULL); - int retval = 1; + SDL_CameraFrameResult result = SDL_CAMERA_FRAME_READY; HRESULT ret; LONGLONG timestamp100NS = 0; @@ -343,21 +535,21 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f const SDL_PropertiesID surfprops = SDL_GetSurfaceProperties(frame); if (!surfprops) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { ret = IMFSample_GetSampleTime(sample, ×tamp100NS); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } *timestampNS = timestamp100NS * 100; // the timestamps are in 100-nanosecond increments; move to full nanoseconds. } IMFMediaBuffer *buffer = NULL; - ret = (retval < 0) ? E_FAIL : IMFSample_ConvertToContiguousBuffer(sample, &buffer); /*IMFSample_GetBufferByIndex(sample, 0, &buffer);*/ + ret = (result < 0) ? E_FAIL : IMFSample_ConvertToContiguousBuffer(sample, &buffer); // IMFSample_GetBufferByIndex(sample, 0, &buffer); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { IMF2DBuffer *buffer2d = NULL; IMF2DBuffer2 *buffer2d2 = NULL; @@ -369,11 +561,11 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f DWORD buflen = 0; ret = IMF2DBuffer2_Lock2DSize(buffer2d2, MF2DBuffer_LockFlags_Read, &pixels, &pitch, &bufstart, &buflen); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { SDL_memcpy(frame->pixels, pixels, buflen); frame->pitch = (int)pitch; @@ -384,16 +576,16 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f } else if (SUCCEEDED(IMFMediaBuffer_QueryInterface(buffer, &SDL_IID_IMF2DBuffer, (void **)&buffer2d))) { ret = IMF2DBuffer_Lock2D(buffer2d, &pixels, &pitch); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { BYTE *bufstart = pixels; const DWORD buflen = (SDL_abs((int)pitch) * frame->w) * frame->h; if (pitch < 0) { // image rows are reversed. bufstart += -pitch * (frame->h - 1); } - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { SDL_memcpy(frame->pixels, bufstart, buflen); frame->pitch = (int)pitch; @@ -405,7 +597,7 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f DWORD maxlen = 0, currentlen = 0; ret = IMFMediaBuffer_Lock(buffer, &pixels, &maxlen, ¤tlen); if (FAILED(ret)) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { BYTE *bufstart = pixels; pitch = (LONG)device->hidden->pitch; @@ -413,9 +605,9 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f if (pitch < 0) { // image rows are reversed. bufstart += -pitch * (frame->h - 1); } - frame->pixels = SDL_aligned_alloc(SDL_SIMDGetAlignment(), buflen); + frame->pixels = SDL_aligned_alloc(SDL_GetSIMDAlignment(), buflen); if (frame->pixels == NULL) { - retval = -1; + result = SDL_CAMERA_FRAME_ERROR; } else { SDL_memcpy(frame->pixels, bufstart, buflen); frame->pitch = (int)pitch; @@ -428,21 +620,21 @@ static int MEDIAFOUNDATION_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *f IMFSample_Release(sample); - if (retval < 0) { + if (result != SDL_CAMERA_FRAME_READY) { *timestampNS = 0; } - return retval; + return result; } -static void MEDIAFOUNDATION_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void MEDIAFOUNDATION_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { SDL_aligned_free(frame->pixels); } #endif -static void MEDIAFOUNDATION_CloseDevice(SDL_CameraDevice *device) +static void MEDIAFOUNDATION_CloseDevice(SDL_Camera *device) { if (device && device->hidden) { if (device->hidden->srcreader) { @@ -468,7 +660,7 @@ static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) GUID subtype = GUID_NULL; UINT32 width = 0; - /* UINT32 height = 0; */ + // UINT32 height = 0; UINT64 val = 0; // Get the subtype and the image size. @@ -483,7 +675,7 @@ static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) } width = (UINT32) (val >> 32); - /* height = (UINT32) val; */ + // height = (UINT32) val; ret = pMFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lStride); if (FAILED(ret)) { @@ -503,7 +695,7 @@ static HRESULT GetDefaultStride(IMFMediaType *pType, LONG *plStride) } -static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool MEDIAFOUNDATION_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { const char *utf8symlink = (const char *) device->handle; IMFAttributes *attrs = NULL; @@ -538,10 +730,10 @@ static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_Camera ret = pMFCreateAttributes(&attrs, 1); CHECK_HRESULT("MFCreateAttributes", ret); - ret = IMFAttributes_SetGUID(attrs, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); + ret = IMFAttributes_SetGUID(attrs, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); CHECK_HRESULT("IMFAttributes_SetGUID(srctype)", ret); - ret = IMFAttributes_SetString(attrs, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, wstrsymlink); + ret = IMFAttributes_SetString(attrs, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, wstrsymlink); CHECK_HRESULT("IMFAttributes_SetString(symlink)", ret); ret = pMFCreateDeviceSource(attrs, &source); @@ -573,7 +765,7 @@ static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_Camera ret = IMFMediaType_SetUINT64(mediatype, &SDL_MF_MT_FRAME_SIZE, (((UINT64)spec->width) << 32) | ((UINT64)spec->height)); CHECK_HRESULT("MFSetAttributeSize(frame_size)", ret); - ret = IMFMediaType_SetUINT64(mediatype, &SDL_MF_MT_FRAME_RATE, (((UINT64)spec->interval_numerator) << 32) | ((UINT64)spec->interval_denominator)); + ret = IMFMediaType_SetUINT64(mediatype, &SDL_MF_MT_FRAME_RATE, (((UINT64)spec->framerate_numerator) << 32) | ((UINT64)spec->framerate_denominator)); CHECK_HRESULT("MFSetAttributeRatio(frame_rate)", ret); ret = IMFSourceReader_SetCurrentMediaType(srcreader, (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, mediatype); @@ -629,11 +821,11 @@ static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_Camera IMFMediaSource_Release(source); // srcreader is holding a reference to this. // There is no user permission prompt for camera access (I think?) - SDL_CameraDevicePermissionOutcome(device, SDL_TRUE); + SDL_CameraPermissionOutcome(device, true); #undef CHECK_HRESULT - return 0; + return true; failed: @@ -669,10 +861,10 @@ static int MEDIAFOUNDATION_OpenDevice(SDL_CameraDevice *device, const SDL_Camera } SDL_free(wstrsymlink); - return -1; + return false; } -static void MEDIAFOUNDATION_FreeDeviceHandle(SDL_CameraDevice *device) +static void MEDIAFOUNDATION_FreeDeviceHandle(SDL_Camera *device) { if (device) { SDL_free(device->handle); // the device's symlink string. @@ -738,23 +930,22 @@ static void GatherCameraSpecs(IMFMediaSource *source, CameraFormatAddData *add_d GUID type; ret = IMFMediaType_GetGUID(mediatype, &SDL_MF_MT_MAJOR_TYPE, &type); if (SUCCEEDED(ret) && WIN_IsEqualGUID(&type, &SDL_MFMediaType_Video)) { - ret = IMFMediaType_GetGUID(mediatype, &SDL_MF_MT_SUBTYPE, &type); - if (SUCCEEDED(ret)) { - const SDL_PixelFormatEnum sdlfmt = MFVidFmtGuidToSDLFmt(&type); - if (sdlfmt != SDL_PIXELFORMAT_UNKNOWN) { - UINT64 val = 0; - UINT32 w = 0, h = 0; - ret = IMFMediaType_GetUINT64(mediatype, &SDL_MF_MT_FRAME_SIZE, &val); - w = (UINT32)(val >> 32); - h = (UINT32)val; - if (SUCCEEDED(ret) && w && h) { - UINT32 interval_numerator = 0, interval_denominator = 0; - ret = IMFMediaType_GetUINT64(mediatype, &SDL_MF_MT_FRAME_RATE, &val); - interval_numerator = (UINT32)(val >> 32); - interval_denominator = (UINT32)val; - if (SUCCEEDED(ret) && interval_numerator && interval_denominator) { - SDL_AddCameraFormat(add_data, sdlfmt, (int) w, (int) h, (int) interval_numerator, (int) interval_denominator); // whew. - } + SDL_PixelFormat sdlfmt = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN; + MediaTypeToSDLFmt(mediatype, &sdlfmt, &colorspace); + if (sdlfmt != SDL_PIXELFORMAT_UNKNOWN) { + UINT64 val = 0; + UINT32 w = 0, h = 0; + ret = IMFMediaType_GetUINT64(mediatype, &SDL_MF_MT_FRAME_SIZE, &val); + w = (UINT32)(val >> 32); + h = (UINT32)val; + if (SUCCEEDED(ret) && w && h) { + UINT32 framerate_numerator = 0, framerate_denominator = 0; + ret = IMFMediaType_GetUINT64(mediatype, &SDL_MF_MT_FRAME_RATE, &val); + framerate_numerator = (UINT32)(val >> 32); + framerate_denominator = (UINT32)val; + if (SUCCEEDED(ret) && framerate_numerator && framerate_denominator) { + SDL_AddCameraFormat(add_data, sdlfmt, colorspace, (int) w, (int) h, (int)framerate_numerator, (int)framerate_denominator); } } } @@ -771,21 +962,21 @@ static void GatherCameraSpecs(IMFMediaSource *source, CameraFormatAddData *add_d IMFPresentationDescriptor_Release(presentdesc); } -static SDL_bool FindMediaFoundationCameraDeviceBySymlink(SDL_CameraDevice *device, void *userdata) +static bool FindMediaFoundationCameraBySymlink(SDL_Camera *device, void *userdata) { return (SDL_strcmp((const char *) device->handle, (const char *) userdata) == 0); } static void MaybeAddDevice(IMFActivate *activation) { - char *symlink = QueryActivationObjectString(activation, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK); + char *symlink = QueryActivationObjectString(activation, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK); - if (SDL_FindPhysicalCameraDeviceByCallback(FindMediaFoundationCameraDeviceBySymlink, symlink)) { + if (SDL_FindPhysicalCameraByCallback(FindMediaFoundationCameraBySymlink, symlink)) { SDL_free(symlink); return; // already have this one. } - char *name = QueryActivationObjectString(activation, &MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME); + char *name = QueryActivationObjectString(activation, &SDL_MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME); if (name && symlink) { IMFMediaSource *source = NULL; // "activating" here only creates an object, it doesn't open the actual camera hardware or start recording. @@ -794,7 +985,7 @@ static void MaybeAddDevice(IMFActivate *activation) CameraFormatAddData add_data; GatherCameraSpecs(source, &add_data); if (add_data.num_specs > 0) { - SDL_AddCameraDevice(name, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, symlink); + SDL_AddCamera(name, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, symlink); } SDL_free(add_data.specs); IMFActivate_ShutdownObject(activation); @@ -817,8 +1008,7 @@ static void MEDIAFOUNDATION_DetectDevices(void) return; // oh well, no cameras for you. } - // !!! FIXME: We need these GUIDs hardcoded in this file. - ret = IMFAttributes_SetGUID(attrs, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); + ret = IMFAttributes_SetGUID(attrs, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, &SDL_MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); if (FAILED(ret)) { IMFAttributes_Release(attrs); return; // oh well, no cameras for you. @@ -861,29 +1051,29 @@ static void MEDIAFOUNDATION_Deinitialize(void) pMFGetStrideForBitmapInfoHeader = NULL; } -static SDL_bool MEDIAFOUNDATION_Init(SDL_CameraDriverImpl *impl) +static bool MEDIAFOUNDATION_Init(SDL_CameraDriverImpl *impl) { // !!! FIXME: slide this off into a subroutine HMODULE mf = LoadLibrary(TEXT("Mf.dll")); // this library is available in Vista and later, but also can be on XP with service packs and Windows if (!mf) { - return SDL_FALSE; + return false; } HMODULE mfplat = LoadLibrary(TEXT("Mfplat.dll")); // this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! if (!mfplat) { FreeLibrary(mf); - return SDL_FALSE; + return false; } HMODULE mfreadwrite = LoadLibrary(TEXT("Mfreadwrite.dll")); // this library is available in Vista and later. No WinXP, so have to LoadLibrary to use it for now! if (!mfreadwrite) { FreeLibrary(mfplat); FreeLibrary(mf); - return SDL_FALSE; + return false; } - SDL_bool okay = SDL_TRUE; - #define LOADSYM(lib, fn) if (okay) { p##fn = (pfn##fn) GetProcAddress(lib, #fn); if (!p##fn) { okay = SDL_FALSE; } } + bool okay = true; + #define LOADSYM(lib, fn) if (okay) { p##fn = (pfn##fn) GetProcAddress(lib, #fn); if (!p##fn) { okay = false; } } LOADSYM(mf, MFEnumDeviceSources); LOADSYM(mf, MFCreateDeviceSource); LOADSYM(mfplat, MFStartup); @@ -894,25 +1084,24 @@ static SDL_bool MEDIAFOUNDATION_Init(SDL_CameraDriverImpl *impl) LOADSYM(mfreadwrite, MFCreateSourceReaderFromMediaSource); #undef LOADSYM + if (okay) { + const HRESULT ret = pMFStartup(MF_VERSION, MFSTARTUP_LITE); + if (FAILED(ret)) { + okay = false; + } + } + if (!okay) { FreeLibrary(mfreadwrite); FreeLibrary(mfplat); FreeLibrary(mf); + return false; } libmf = mf; libmfplat = mfplat; libmfreadwrite = mfreadwrite; - const HRESULT ret = pMFStartup(MF_VERSION, MFSTARTUP_LITE); - if (FAILED(ret)) { - FreeLibrary(libmfplat); - libmfplat = NULL; - FreeLibrary(libmf); - libmf = NULL; - return SDL_FALSE; - } - impl->DetectDevices = MEDIAFOUNDATION_DetectDevices; impl->OpenDevice = MEDIAFOUNDATION_OpenDevice; impl->CloseDevice = MEDIAFOUNDATION_CloseDevice; @@ -922,11 +1111,11 @@ static SDL_bool MEDIAFOUNDATION_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = MEDIAFOUNDATION_FreeDeviceHandle; impl->Deinitialize = MEDIAFOUNDATION_Deinitialize; - return SDL_TRUE; + return true; } CameraBootStrap MEDIAFOUNDATION_bootstrap = { - "mediafoundation", "SDL Windows Media Foundation camera driver", MEDIAFOUNDATION_Init, SDL_FALSE + "mediafoundation", "SDL Windows Media Foundation camera driver", MEDIAFOUNDATION_Init, false }; #endif // SDL_CAMERA_DRIVER_MEDIAFOUNDATION diff --git a/libs/SDL3/src/camera/pipewire/SDL_camera_pipewire.c b/libs/SDL3/src/camera/pipewire/SDL_camera_pipewire.c new file mode 100644 index 000000000..8460d995e --- /dev/null +++ b/libs/SDL3/src/camera/pipewire/SDL_camera_pipewire.c @@ -0,0 +1,1091 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2023 Sam Lantinga + Copyright (C) 2024 Wim Taymans + + 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_CAMERA_DRIVER_PIPEWIRE + +#include "../SDL_syscamera.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PW_POD_BUFFER_LENGTH 1024 +#define PW_THREAD_NAME_BUFFER_LENGTH 128 +#define PW_MAX_IDENTIFIER_LENGTH 256 + +#define PW_REQUIRED_MAJOR 1 +#define PW_REQUIRED_MINOR 0 +#define PW_REQUIRED_PATCH 0 + +enum PW_READY_FLAGS +{ + PW_READY_FLAG_BUFFER_ADDED = 0x1, + PW_READY_FLAG_STREAM_READY = 0x2, + PW_READY_FLAG_ALL_BITS = 0x3 +}; + +#define PW_ID_TO_HANDLE(x) (void *)((uintptr_t)x) +#define PW_HANDLE_TO_ID(x) (uint32_t)((uintptr_t)x) + +static bool pipewire_initialized = false; + +// Pipewire entry points +static const char *(*PIPEWIRE_pw_get_library_version)(void); +static bool (*PIPEWIRE_pw_check_library_version)(int major, int minor, int micro); +static void (*PIPEWIRE_pw_init)(int *, char ***); +static void (*PIPEWIRE_pw_deinit)(void); +static struct pw_main_loop *(*PIPEWIRE_pw_main_loop_new)(const struct spa_dict *loop); +static struct pw_loop *(*PIPEWIRE_pw_main_loop_get_loop)(struct pw_main_loop *loop); +static int (*PIPEWIRE_pw_main_loop_run)(struct pw_main_loop *loop); +static int (*PIPEWIRE_pw_main_loop_quit)(struct pw_main_loop *loop); +static void(*PIPEWIRE_pw_main_loop_destroy)(struct pw_main_loop *loop); +static struct pw_thread_loop *(*PIPEWIRE_pw_thread_loop_new)(const char *, const struct spa_dict *); +static void (*PIPEWIRE_pw_thread_loop_destroy)(struct pw_thread_loop *); +static void (*PIPEWIRE_pw_thread_loop_stop)(struct pw_thread_loop *); +static struct pw_loop *(*PIPEWIRE_pw_thread_loop_get_loop)(struct pw_thread_loop *); +static void (*PIPEWIRE_pw_thread_loop_lock)(struct pw_thread_loop *); +static void (*PIPEWIRE_pw_thread_loop_unlock)(struct pw_thread_loop *); +static void (*PIPEWIRE_pw_thread_loop_signal)(struct pw_thread_loop *, bool); +static void (*PIPEWIRE_pw_thread_loop_wait)(struct pw_thread_loop *); +static int (*PIPEWIRE_pw_thread_loop_start)(struct pw_thread_loop *); +static struct pw_context *(*PIPEWIRE_pw_context_new)(struct pw_loop *, struct pw_properties *, size_t); +static void (*PIPEWIRE_pw_context_destroy)(struct pw_context *); +static struct pw_core *(*PIPEWIRE_pw_context_connect)(struct pw_context *, struct pw_properties *, size_t); +static void (*PIPEWIRE_pw_proxy_add_object_listener)(struct pw_proxy *, struct spa_hook *, const void *, void *); +static void (*PIPEWIRE_pw_proxy_add_listener)(struct pw_proxy *, struct spa_hook *, const struct pw_proxy_events *, void *); +static void *(*PIPEWIRE_pw_proxy_get_user_data)(struct pw_proxy *); +static void (*PIPEWIRE_pw_proxy_destroy)(struct pw_proxy *); +static int (*PIPEWIRE_pw_core_disconnect)(struct pw_core *); +static struct pw_node_info * (*PIPEWIRE_pw_node_info_merge)(struct pw_node_info *info, const struct pw_node_info *update, bool reset); +static void (*PIPEWIRE_pw_node_info_free)(struct pw_node_info *info); +static struct pw_stream *(*PIPEWIRE_pw_stream_new)(struct pw_core *, const char *, struct pw_properties *); +static void (*PIPEWIRE_pw_stream_add_listener)(struct pw_stream *stream, struct spa_hook *listener, const struct pw_stream_events *events, void *data); +static void (*PIPEWIRE_pw_stream_destroy)(struct pw_stream *); +static int (*PIPEWIRE_pw_stream_connect)(struct pw_stream *, enum pw_direction, uint32_t, enum pw_stream_flags, + const struct spa_pod **, uint32_t); +static enum pw_stream_state (*PIPEWIRE_pw_stream_get_state)(struct pw_stream *stream, const char **error); +static struct pw_buffer *(*PIPEWIRE_pw_stream_dequeue_buffer)(struct pw_stream *); +static int (*PIPEWIRE_pw_stream_queue_buffer)(struct pw_stream *, struct pw_buffer *); +static struct pw_properties *(*PIPEWIRE_pw_properties_new)(const char *, ...)SPA_SENTINEL; +static struct pw_properties *(*PIPEWIRE_pw_properties_new_dict)(const struct spa_dict *dict); +static int (*PIPEWIRE_pw_properties_set)(struct pw_properties *, const char *, const char *); +static int (*PIPEWIRE_pw_properties_setf)(struct pw_properties *, const char *, const char *, ...) SPA_PRINTF_FUNC(3, 4); + +#ifdef SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC + +static const char *pipewire_library = SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC; +static SDL_SharedObject *pipewire_handle = NULL; + +static bool pipewire_dlsym(const char *fn, void **addr) +{ + *addr = SDL_LoadFunction(pipewire_handle, fn); + if (!*addr) { + // Don't call SDL_SetError(): SDL_LoadFunction already did. + return false; + } + + return true; +} + +#define SDL_PIPEWIRE_SYM(x) \ + if (!pipewire_dlsym(#x, (void **)(char *)&PIPEWIRE_##x)) \ + return false + +static bool load_pipewire_library(void) +{ + pipewire_handle = SDL_LoadObject(pipewire_library); + return pipewire_handle ? true : false; +} + +static void unload_pipewire_library(void) +{ + if (pipewire_handle) { + SDL_UnloadObject(pipewire_handle); + pipewire_handle = NULL; + } +} + +#else + +#define SDL_PIPEWIRE_SYM(x) PIPEWIRE_##x = x + +static bool load_pipewire_library(void) +{ + return true; +} + +static void unload_pipewire_library(void) +{ + // Nothing to do +} + +#endif // SDL_AUDIO_DRIVER_PIPEWIRE_DYNAMIC + +static bool load_pipewire_syms(void) +{ + SDL_PIPEWIRE_SYM(pw_get_library_version); + SDL_PIPEWIRE_SYM(pw_check_library_version); + SDL_PIPEWIRE_SYM(pw_init); + SDL_PIPEWIRE_SYM(pw_deinit); + SDL_PIPEWIRE_SYM(pw_main_loop_new); + SDL_PIPEWIRE_SYM(pw_main_loop_get_loop); + SDL_PIPEWIRE_SYM(pw_main_loop_run); + SDL_PIPEWIRE_SYM(pw_main_loop_quit); + SDL_PIPEWIRE_SYM(pw_main_loop_destroy); + SDL_PIPEWIRE_SYM(pw_thread_loop_new); + SDL_PIPEWIRE_SYM(pw_thread_loop_destroy); + SDL_PIPEWIRE_SYM(pw_thread_loop_stop); + SDL_PIPEWIRE_SYM(pw_thread_loop_get_loop); + SDL_PIPEWIRE_SYM(pw_thread_loop_lock); + SDL_PIPEWIRE_SYM(pw_thread_loop_unlock); + SDL_PIPEWIRE_SYM(pw_thread_loop_signal); + SDL_PIPEWIRE_SYM(pw_thread_loop_wait); + SDL_PIPEWIRE_SYM(pw_thread_loop_start); + SDL_PIPEWIRE_SYM(pw_context_new); + SDL_PIPEWIRE_SYM(pw_context_destroy); + SDL_PIPEWIRE_SYM(pw_context_connect); + SDL_PIPEWIRE_SYM(pw_proxy_add_listener); + SDL_PIPEWIRE_SYM(pw_proxy_add_object_listener); + SDL_PIPEWIRE_SYM(pw_proxy_get_user_data); + SDL_PIPEWIRE_SYM(pw_proxy_destroy); + SDL_PIPEWIRE_SYM(pw_core_disconnect); + SDL_PIPEWIRE_SYM(pw_node_info_merge); + SDL_PIPEWIRE_SYM(pw_node_info_free); + SDL_PIPEWIRE_SYM(pw_stream_new); + SDL_PIPEWIRE_SYM(pw_stream_add_listener); + SDL_PIPEWIRE_SYM(pw_stream_destroy); + SDL_PIPEWIRE_SYM(pw_stream_connect); + SDL_PIPEWIRE_SYM(pw_stream_get_state); + SDL_PIPEWIRE_SYM(pw_stream_dequeue_buffer); + SDL_PIPEWIRE_SYM(pw_stream_queue_buffer); + SDL_PIPEWIRE_SYM(pw_properties_new); + SDL_PIPEWIRE_SYM(pw_properties_new_dict); + SDL_PIPEWIRE_SYM(pw_properties_set); + SDL_PIPEWIRE_SYM(pw_properties_setf); + + return true; +} + +static bool init_pipewire_library(void) +{ + if (load_pipewire_library()) { + if (load_pipewire_syms()) { + PIPEWIRE_pw_init(NULL, NULL); + return true; + } + } + return false; +} + +static void deinit_pipewire_library(void) +{ + PIPEWIRE_pw_deinit(); + unload_pipewire_library(); +} + +// The global hotplug thread and associated objects. +static struct +{ + struct pw_thread_loop *loop; + + struct pw_context *context; + + struct pw_core *core; + struct spa_hook core_listener; + int server_major; + int server_minor; + int server_patch; + int last_seq; + int pending_seq; + + struct pw_registry *registry; + struct spa_hook registry_listener; + + struct spa_list global_list; + + bool have_1_0_5; + bool init_complete; + bool events_enabled; +} hotplug; + +struct global +{ + struct spa_list link; + + const struct global_class *class; + + uint32_t id; + uint32_t permissions; + struct pw_properties *props; + + char *name; + + struct pw_proxy *proxy; + struct spa_hook proxy_listener; + struct spa_hook object_listener; + + int changed; + void *info; + struct spa_list pending_list; + struct spa_list param_list; + + bool added; +}; + +struct global_class +{ + const char *type; + uint32_t version; + const void *events; + int (*init) (struct global *g); + void (*destroy) (struct global *g); +}; + +struct param { + uint32_t id; + int32_t seq; + struct spa_list link; + struct spa_pod *param; +}; + +static uint32_t param_clear(struct spa_list *param_list, uint32_t id) +{ + struct param *p, *t; + uint32_t count = 0; + + spa_list_for_each_safe(p, t, param_list, link) { + if (id == SPA_ID_INVALID || p->id == id) { + spa_list_remove(&p->link); + free(p); // This should NOT be SDL_free() + count++; + } + } + return count; +} + +#if PW_CHECK_VERSION(0,3,60) +#define SPA_PARAMS_INFO_SEQ(p) ((p).seq) +#else +#define SPA_PARAMS_INFO_SEQ(p) ((p).padding[0]) +#endif + +static struct param *param_add(struct spa_list *params, + int seq, uint32_t id, const struct spa_pod *param) +{ + struct param *p; + + if (id == SPA_ID_INVALID) { + if (param == NULL || !spa_pod_is_object(param)) { + errno = EINVAL; + return NULL; + } + id = SPA_POD_OBJECT_ID(param); + } + + p = malloc(sizeof(*p) + (param != NULL ? SPA_POD_SIZE(param) : 0)); + if (p == NULL) + return NULL; + + p->id = id; + p->seq = seq; + if (param != NULL) { + p->param = SPA_PTROFF(p, sizeof(*p), struct spa_pod); + SDL_memcpy(p->param, param, SPA_POD_SIZE(param)); + } else { + param_clear(params, id); + p->param = NULL; + } + spa_list_append(params, &p->link); + + return p; +} + +static void param_update(struct spa_list *param_list, struct spa_list *pending_list, + uint32_t n_params, struct spa_param_info *params) +{ + struct param *p, *t; + uint32_t i; + + for (i = 0; i < n_params; i++) { + spa_list_for_each_safe(p, t, pending_list, link) { + if (p->id == params[i].id && + p->seq != SPA_PARAMS_INFO_SEQ(params[i]) && + p->param != NULL) { + spa_list_remove(&p->link); + free(p); // This should NOT be SDL_free() + } + } + } + spa_list_consume(p, pending_list, link) { + spa_list_remove(&p->link); + if (p->param == NULL) { + param_clear(param_list, p->id); + free(p); // This should NOT be SDL_free() + } else { + spa_list_append(param_list, &p->link); + } + } +} + +static struct sdl_video_format { + SDL_PixelFormat format; + SDL_Colorspace colorspace; + uint32_t id; +} sdl_video_formats[] = { +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + { SDL_PIXELFORMAT_RGBX8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_RGBx }, + { SDL_PIXELFORMAT_BGRX8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_BGRx }, + { SDL_PIXELFORMAT_RGBA8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_RGBA }, + { SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_ARGB }, + { SDL_PIXELFORMAT_BGRA8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_BGRA }, + { SDL_PIXELFORMAT_ABGR8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_ABGR }, +#else + { SDL_PIXELFORMAT_RGBX8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_xBGR }, + { SDL_PIXELFORMAT_BGRX8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_xRGB }, + { SDL_PIXELFORMAT_RGBA8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_ABGR }, + { SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_BGRA }, + { SDL_PIXELFORMAT_BGRA8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_ARGB }, + { SDL_PIXELFORMAT_ABGR8888, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_RGBA }, +#endif + { SDL_PIXELFORMAT_RGB24, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_RGB }, + { SDL_PIXELFORMAT_BGR24, SDL_COLORSPACE_SRGB, SPA_VIDEO_FORMAT_BGR }, + { SDL_PIXELFORMAT_YV12, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_YV12 }, + { SDL_PIXELFORMAT_IYUV, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_I420 }, + { SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_YUY2 }, + { SDL_PIXELFORMAT_UYVY, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_UYVY }, + { SDL_PIXELFORMAT_YVYU, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_YVYU }, +#if SDL_VERSION_ATLEAST(2,0,4) + { SDL_PIXELFORMAT_NV12, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_NV12 }, + { SDL_PIXELFORMAT_NV21, SDL_COLORSPACE_BT709_LIMITED, SPA_VIDEO_FORMAT_NV21 }, +#endif +}; + +static uint32_t sdl_format_to_id(SDL_PixelFormat format) +{ + struct sdl_video_format *f; + SPA_FOR_EACH_ELEMENT(sdl_video_formats, f) { + if (f->format == format) + return f->id; + } + return SPA_VIDEO_FORMAT_UNKNOWN; +} + +static void id_to_sdl_format(uint32_t id, SDL_PixelFormat *format, SDL_Colorspace *colorspace) +{ + struct sdl_video_format *f; + SPA_FOR_EACH_ELEMENT(sdl_video_formats, f) { + if (f->id == id) { + *format = f->format; + *colorspace = f->colorspace; + return; + } + } + *format = SDL_PIXELFORMAT_UNKNOWN; + *colorspace = SDL_COLORSPACE_UNKNOWN; +} + +struct SDL_PrivateCameraData +{ + struct pw_stream *stream; + struct spa_hook stream_listener; + + struct pw_array buffers; +}; + +static void on_process(void *data) +{ + PIPEWIRE_pw_thread_loop_signal(hotplug.loop, false); +} + +static void on_stream_state_changed(void *data, enum pw_stream_state old, + enum pw_stream_state state, const char *error) +{ + SDL_Camera *device = data; + switch (state) { + case PW_STREAM_STATE_UNCONNECTED: + break; + case PW_STREAM_STATE_STREAMING: + SDL_CameraPermissionOutcome(device, true); + break; + default: + break; + } +} + +static void on_stream_param_changed(void *data, uint32_t id, const struct spa_pod *param) +{ +} + +static void on_add_buffer(void *data, struct pw_buffer *buffer) +{ + SDL_Camera *device = data; + pw_array_add_ptr(&device->hidden->buffers, buffer); +} + +static void on_remove_buffer(void *data, struct pw_buffer *buffer) +{ + SDL_Camera *device = data; + struct pw_buffer **p; + pw_array_for_each(p, &device->hidden->buffers) { + if (*p == buffer) { + pw_array_remove(&device->hidden->buffers, p); + return; + } + } +} + +static const struct pw_stream_events stream_events = { + .version = PW_VERSION_STREAM_EVENTS, + .add_buffer = on_add_buffer, + .remove_buffer = on_remove_buffer, + .state_changed = on_stream_state_changed, + .param_changed = on_stream_param_changed, + .process = on_process, +}; + +static bool PIPEWIRECAMERA_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) +{ + struct pw_properties *props; + const struct spa_pod *params[3]; + int res, n_params = 0; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + + if (!device) { + return false; + } + device->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); + if (device->hidden == NULL) { + return false; + } + pw_array_init(&device->hidden->buffers, 64); + + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + + props = PIPEWIRE_pw_properties_new(PW_KEY_MEDIA_TYPE, "Video", + PW_KEY_MEDIA_CATEGORY, "Capture", + PW_KEY_MEDIA_ROLE, "Camera", + PW_KEY_TARGET_OBJECT, device->name, + NULL); + if (props == NULL) { + return false; + } + + device->hidden->stream = PIPEWIRE_pw_stream_new(hotplug.core, "SDL PipeWire Camera", props); + if (device->hidden->stream == NULL) { + return false; + } + + PIPEWIRE_pw_stream_add_listener(device->hidden->stream, + &device->hidden->stream_listener, + &stream_events, device); + + params[n_params++] = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), + SPA_FORMAT_VIDEO_format, SPA_POD_Id(sdl_format_to_id(spec->format)), + SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&SPA_RECTANGLE(spec->width, spec->height)), + SPA_FORMAT_VIDEO_framerate, + SPA_POD_Fraction(&SPA_FRACTION(spec->framerate_numerator, spec->framerate_denominator))); + + if ((res = PIPEWIRE_pw_stream_connect(device->hidden->stream, + PW_DIRECTION_INPUT, + PW_ID_ANY, + PW_STREAM_FLAG_AUTOCONNECT | + PW_STREAM_FLAG_MAP_BUFFERS, + params, n_params)) < 0) { + return false; + } + + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + + return true; +} + +static void PIPEWIRECAMERA_CloseDevice(SDL_Camera *device) +{ + if (!device) { + return; + } + + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + if (device->hidden) { + if (device->hidden->stream) + PIPEWIRE_pw_stream_destroy(device->hidden->stream); + pw_array_clear(&device->hidden->buffers); + SDL_free(device->hidden); + device->hidden = NULL; + } + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); +} + +static bool PIPEWIRECAMERA_WaitDevice(SDL_Camera *device) +{ + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + PIPEWIRE_pw_thread_loop_wait(hotplug.loop); + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + return true; +} + +static SDL_CameraFrameResult PIPEWIRECAMERA_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) +{ + struct pw_buffer *b; + + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + b = NULL; + while (true) { + struct pw_buffer *t; + if ((t = PIPEWIRE_pw_stream_dequeue_buffer(device->hidden->stream)) == NULL) + break; + if (b) + PIPEWIRE_pw_stream_queue_buffer(device->hidden->stream, b); + b = t; + } + if (b == NULL) { + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + return SDL_CAMERA_FRAME_SKIP; + } + +#if PW_CHECK_VERSION(1,0,5) + *timestampNS = hotplug.have_1_0_5 ? b->time : SDL_GetTicksNS(); +#else + *timestampNS = SDL_GetTicksNS(); +#endif + frame->pixels = b->buffer->datas[0].data; + frame->pitch = b->buffer->datas[0].chunk->stride; + + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + + return SDL_CAMERA_FRAME_READY; +} + +static void PIPEWIRECAMERA_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) +{ + struct pw_buffer **p; + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + pw_array_for_each(p, &device->hidden->buffers) { + if ((*p)->buffer->datas[0].data == frame->pixels) { + PIPEWIRE_pw_stream_queue_buffer(device->hidden->stream, (*p)); + break; + } + } + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); +} + +static void collect_rates(CameraFormatAddData *data, struct param *p, SDL_PixelFormat sdlfmt, SDL_Colorspace colorspace, const struct spa_rectangle *size) +{ + const struct spa_pod_prop *prop; + struct spa_pod * values; + uint32_t i, n_vals, choice; + struct spa_fraction *rates; + + prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_framerate); + if (prop == NULL) + return; + + values = spa_pod_get_values(&prop->value, &n_vals, &choice); + if (values->type != SPA_TYPE_Fraction || n_vals == 0) + return; + + rates = SPA_POD_BODY(values); + switch (choice) { + case SPA_CHOICE_None: + n_vals = 1; + SPA_FALLTHROUGH; + case SPA_CHOICE_Enum: + for (i = 0; i < n_vals; i++) { + if (!SDL_AddCameraFormat(data, sdlfmt, colorspace, size->width, size->height, rates[i].num, rates[i].denom)) { + return; // Probably out of memory; we'll go with what we have, if anything. + } + } + break; + default: + SDL_Log("CAMERA: unimplemented choice:%d", choice); + break; + } +} + +static void collect_size(CameraFormatAddData *data, struct param *p, SDL_PixelFormat sdlfmt, SDL_Colorspace colorspace) +{ + const struct spa_pod_prop *prop; + struct spa_pod * values; + uint32_t i, n_vals, choice; + struct spa_rectangle *rectangles; + + prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_size); + if (prop == NULL) + return; + + values = spa_pod_get_values(&prop->value, &n_vals, &choice); + if (values->type != SPA_TYPE_Rectangle || n_vals == 0) + return; + + rectangles = SPA_POD_BODY(values); + switch (choice) { + case SPA_CHOICE_None: + n_vals = 1; + SPA_FALLTHROUGH; + case SPA_CHOICE_Enum: + for (i = 0; i < n_vals; i++) { + collect_rates(data, p, sdlfmt, colorspace, &rectangles[i]); + } + break; + default: + SDL_Log("CAMERA: unimplemented choice:%d", choice); + break; + } +} + +static void collect_format(CameraFormatAddData *data, struct param *p) +{ + const struct spa_pod_prop *prop; + SDL_PixelFormat sdlfmt; + SDL_Colorspace colorspace; + struct spa_pod * values; + uint32_t i, n_vals, choice, *ids; + + prop = spa_pod_find_prop(p->param, NULL, SPA_FORMAT_VIDEO_format); + if (prop == NULL) + return; + + values = spa_pod_get_values(&prop->value, &n_vals, &choice); + if (values->type != SPA_TYPE_Id || n_vals == 0) + return; + + ids = SPA_POD_BODY(values); + switch (choice) { + case SPA_CHOICE_None: + n_vals = 1; + SPA_FALLTHROUGH; + case SPA_CHOICE_Enum: + for (i = 0; i < n_vals; i++) { + id_to_sdl_format(ids[i], &sdlfmt, &colorspace); + if (sdlfmt == SDL_PIXELFORMAT_UNKNOWN) { + continue; + } + collect_size(data, p, sdlfmt, colorspace); + } + break; + default: + SDL_Log("CAMERA: unimplemented choice:%d", choice); + break; + } +} + +static void add_device(struct global *g) +{ + struct param *p; + CameraFormatAddData data; + + SDL_zero(data); + + spa_list_for_each(p, &g->param_list, link) { + if (p->id != SPA_PARAM_EnumFormat) + continue; + + collect_format(&data, p); + } + if (data.num_specs > 0) { + SDL_AddCamera(g->name, SDL_CAMERA_POSITION_UNKNOWN, + data.num_specs, data.specs, g); + } + SDL_free(data.specs); + + g->added = true; +} + +static void PIPEWIRECAMERA_DetectDevices(void) +{ + struct global *g; + + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + + // Wait until the initial registry enumeration is complete + while (!hotplug.init_complete) { + PIPEWIRE_pw_thread_loop_wait(hotplug.loop); + } + + spa_list_for_each (g, &hotplug.global_list, link) { + if (!g->added) { + add_device(g); + } + } + + hotplug.events_enabled = true; + + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); +} + +static void PIPEWIRECAMERA_FreeDeviceHandle(SDL_Camera *device) +{ +} + +static void do_resync(void) +{ + hotplug.pending_seq = pw_core_sync(hotplug.core, PW_ID_CORE, 0); +} + +/** node */ +static void node_event_info(void *object, const struct pw_node_info *info) +{ + struct global *g = object; + uint32_t i; + + info = g->info = PIPEWIRE_pw_node_info_merge(g->info, info, g->changed == 0); + if (info == NULL) + return; + + if (info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) { + for (i = 0; i < info->n_params; i++) { + uint32_t id = info->params[i].id; + int res; + + if (info->params[i].user == 0) + continue; + info->params[i].user = 0; + + if (id != SPA_PARAM_EnumFormat) + continue; + + param_add(&g->pending_list, SPA_PARAMS_INFO_SEQ(info->params[i]), id, NULL); + if (!(info->params[i].flags & SPA_PARAM_INFO_READ)) + continue; + + res = pw_node_enum_params((struct pw_node*)g->proxy, + ++SPA_PARAMS_INFO_SEQ(info->params[i]), id, 0, -1, NULL); + if (SPA_RESULT_IS_ASYNC(res)) + SPA_PARAMS_INFO_SEQ(info->params[i]) = res; + + g->changed++; + } + } + do_resync(); +} + +static void node_event_param(void *object, int seq, + uint32_t id, uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct global *g = object; + param_add(&g->pending_list, seq, id, param); +} + +static const struct pw_node_events node_events = { + .version = PW_VERSION_NODE_EVENTS, + .info = node_event_info, + .param = node_event_param, +}; + +static void node_destroy(struct global *g) +{ + if (g->info) { + PIPEWIRE_pw_node_info_free(g->info); + g->info = NULL; + } +} + + +static const struct global_class node_class = { + .type = PW_TYPE_INTERFACE_Node, + .version = PW_VERSION_NODE, + .events = &node_events, + .destroy = node_destroy, +}; + +/** proxy */ +static void proxy_removed(void *data) +{ + struct global *g = data; + PIPEWIRE_pw_proxy_destroy(g->proxy); +} + +static void proxy_destroy(void *data) +{ + struct global *g = data; + spa_list_remove(&g->link); + g->proxy = NULL; + if (g->class) { + if (g->class->events) + spa_hook_remove(&g->object_listener); + if (g->class->destroy) + g->class->destroy(g); + } + param_clear(&g->param_list, SPA_ID_INVALID); + param_clear(&g->pending_list, SPA_ID_INVALID); + free(g->name); // This should NOT be SDL_free() +} + +static const struct pw_proxy_events proxy_events = { + .version = PW_VERSION_PROXY_EVENTS, + .removed = proxy_removed, + .destroy = proxy_destroy +}; + +// called with thread_loop lock +static void hotplug_registry_global_callback(void *object, uint32_t id, + uint32_t permissions, const char *type, uint32_t version, + const struct spa_dict *props) +{ + const struct global_class *class = NULL; + struct pw_proxy *proxy; + const char *str, *name = NULL; + + if (spa_streq(type, PW_TYPE_INTERFACE_Node)) { + if (props == NULL) + return; + if (((str = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS)) == NULL) || + (!spa_streq(str, "Video/Source"))) + return; + + if ((name = spa_dict_lookup(props, PW_KEY_NODE_DESCRIPTION)) == NULL && + (name = spa_dict_lookup(props, PW_KEY_NODE_NAME)) == NULL) + name = "unnamed camera"; + + class = &node_class; + } + if (class) { + struct global *g; + + proxy = pw_registry_bind(hotplug.registry, + id, class->type, class->version, + sizeof(struct global)); + + g = PIPEWIRE_pw_proxy_get_user_data(proxy); + g->class = class; + g->id = id; + g->permissions = permissions; + g->props = props ? PIPEWIRE_pw_properties_new_dict(props) : NULL; + g->proxy = proxy; + g->name = strdup(name); + spa_list_init(&g->pending_list); + spa_list_init(&g->param_list); + spa_list_append(&hotplug.global_list, &g->link); + + PIPEWIRE_pw_proxy_add_listener(proxy, + &g->proxy_listener, + &proxy_events, g); + + if (class->events) { + PIPEWIRE_pw_proxy_add_object_listener(proxy, + &g->object_listener, + class->events, g); + } + if (class->init) + class->init(g); + + do_resync(); + } +} + +// called with thread_loop lock +static void hotplug_registry_global_remove_callback(void *object, uint32_t id) +{ +} + +static const struct pw_registry_events hotplug_registry_events = +{ + .version = PW_VERSION_REGISTRY_EVENTS, + .global = hotplug_registry_global_callback, + .global_remove = hotplug_registry_global_remove_callback +}; + +static void parse_version(const char *str, int *major, int *minor, int *patch) +{ + if (SDL_sscanf(str, "%d.%d.%d", major, minor, patch) < 3) { + *major = 0; + *minor = 0; + *patch = 0; + } +} + +// Core info, called with thread_loop lock +static void hotplug_core_info_callback(void *data, const struct pw_core_info *info) +{ + parse_version(info->version, &hotplug.server_major, &hotplug.server_minor, &hotplug.server_patch); +} + +// Core sync points, called with thread_loop lock +static void hotplug_core_done_callback(void *object, uint32_t id, int seq) +{ + hotplug.last_seq = seq; + if (id == PW_ID_CORE && seq == hotplug.pending_seq) { + struct global *g; + struct pw_node_info *info; + + spa_list_for_each(g, &hotplug.global_list, link) { + if (!g->changed) + continue; + + info = g->info; + param_update(&g->param_list, &g->pending_list, info->n_params, info->params); + + if (!g->added && hotplug.events_enabled) { + add_device(g); + } + } + hotplug.init_complete = true; + PIPEWIRE_pw_thread_loop_signal(hotplug.loop, false); + } +} +static const struct pw_core_events hotplug_core_events = +{ + .version = PW_VERSION_CORE_EVENTS, + .info = hotplug_core_info_callback, + .done = hotplug_core_done_callback +}; + +/* When in a container, the library version can differ from the underlying core version, + * so make sure the underlying Pipewire implementation meets the version requirement. + */ +static bool pipewire_server_version_at_least(int major, int minor, int patch) +{ + return (hotplug.server_major >= major) && + (hotplug.server_major > major || hotplug.server_minor >= minor) && + (hotplug.server_major > major || hotplug.server_minor > minor || hotplug.server_patch >= patch); +} + +// The hotplug thread +static bool hotplug_loop_init(void) +{ + int res; + + spa_list_init(&hotplug.global_list); + + hotplug.have_1_0_5 = PIPEWIRE_pw_check_library_version(1,0,5); + + hotplug.loop = PIPEWIRE_pw_thread_loop_new("SDLPwCameraPlug", NULL); + if (!hotplug.loop) { + return SDL_SetError("Pipewire: Failed to create hotplug detection loop (%i)", errno); + } + + hotplug.context = PIPEWIRE_pw_context_new(PIPEWIRE_pw_thread_loop_get_loop(hotplug.loop), NULL, 0); + if (!hotplug.context) { + return SDL_SetError("Pipewire: Failed to create hotplug detection context (%i)", errno); + } + + hotplug.core = PIPEWIRE_pw_context_connect(hotplug.context, NULL, 0); + if (!hotplug.core) { + return SDL_SetError("Pipewire: Failed to connect hotplug detection context (%i)", errno); + } + spa_zero(hotplug.core_listener); + pw_core_add_listener(hotplug.core, &hotplug.core_listener, &hotplug_core_events, NULL); + + hotplug.registry = pw_core_get_registry(hotplug.core, PW_VERSION_REGISTRY, 0); + if (!hotplug.registry) { + return SDL_SetError("Pipewire: Failed to acquire hotplug detection registry (%i)", errno); + } + + spa_zero(hotplug.registry_listener); + pw_registry_add_listener(hotplug.registry, &hotplug.registry_listener, &hotplug_registry_events, NULL); + + do_resync(); + + res = PIPEWIRE_pw_thread_loop_start(hotplug.loop); + if (res != 0) { + return SDL_SetError("Pipewire: Failed to start hotplug detection loop"); + } + + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + while (!hotplug.init_complete) { + PIPEWIRE_pw_thread_loop_wait(hotplug.loop); + } + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + + if (!pipewire_server_version_at_least(PW_REQUIRED_MAJOR, PW_REQUIRED_MINOR, PW_REQUIRED_PATCH)) { + return SDL_SetError("Pipewire: server version is too old %d.%d.%d < %d.%d.%d", + hotplug.server_major, hotplug.server_minor, hotplug.server_patch, + PW_REQUIRED_MAJOR, PW_REQUIRED_MINOR, PW_REQUIRED_PATCH); + } + + return true; +} + + +static void PIPEWIRECAMERA_Deinitialize(void) +{ + if (pipewire_initialized) { + if (hotplug.loop) { + PIPEWIRE_pw_thread_loop_lock(hotplug.loop); + } + if (hotplug.registry) { + spa_hook_remove(&hotplug.registry_listener); + PIPEWIRE_pw_proxy_destroy((struct pw_proxy *)hotplug.registry); + } + if (hotplug.core) { + spa_hook_remove(&hotplug.core_listener); + PIPEWIRE_pw_core_disconnect(hotplug.core); + } + if (hotplug.context) { + PIPEWIRE_pw_context_destroy(hotplug.context); + } + if (hotplug.loop) { + PIPEWIRE_pw_thread_loop_unlock(hotplug.loop); + PIPEWIRE_pw_thread_loop_destroy(hotplug.loop); + } + deinit_pipewire_library(); + spa_zero(hotplug); + pipewire_initialized = false; + } +} + +static bool PIPEWIRECAMERA_Init(SDL_CameraDriverImpl *impl) +{ + if (!pipewire_initialized) { + + if (!init_pipewire_library()) { + return false; + } + + pipewire_initialized = true; + + if (!hotplug_loop_init()) { + PIPEWIRECAMERA_Deinitialize(); + return false; + } + } + + impl->DetectDevices = PIPEWIRECAMERA_DetectDevices; + impl->OpenDevice = PIPEWIRECAMERA_OpenDevice; + impl->CloseDevice = PIPEWIRECAMERA_CloseDevice; + impl->WaitDevice = PIPEWIRECAMERA_WaitDevice; + impl->AcquireFrame = PIPEWIRECAMERA_AcquireFrame; + impl->ReleaseFrame = PIPEWIRECAMERA_ReleaseFrame; + impl->FreeDeviceHandle = PIPEWIRECAMERA_FreeDeviceHandle; + impl->Deinitialize = PIPEWIRECAMERA_Deinitialize; + + return true; +} + +CameraBootStrap PIPEWIRECAMERA_bootstrap = { + "pipewire", "SDL PipeWire camera driver", PIPEWIRECAMERA_Init, false +}; + +#endif // SDL_CAMERA_DRIVER_PIPEWIRE diff --git a/libs/SDL3/src/camera/v4l2/SDL_camera_v4l2.c b/libs/SDL3/src/camera/v4l2/SDL_camera_v4l2.c index 8d061c969..8a1928092 100644 --- a/libs/SDL3/src/camera/v4l2/SDL_camera_v4l2.c +++ b/libs/SDL3/src/camera/v4l2/SDL_camera_v4l2.c @@ -22,13 +22,14 @@ #ifdef SDL_CAMERA_DRIVER_V4L2 +#include +#include +#include // low-level i/o #include -#include #include -#include // low-level i/o -#include #include #include +#include #include #ifndef V4L2_CAP_DEVICE_CAPS @@ -40,6 +41,7 @@ SDL_COMPILE_TIME_ASSERT(v4l2devicecaps, offsetof(struct v4l2_capability,device_c #include "../SDL_syscamera.h" #include "../SDL_camera_c.h" #include "../../video/SDL_pixels_c.h" +#include "../../video/SDL_surface_c.h" #include "../../thread/SDL_systhread.h" #include "../../core/linux/SDL_evdev_capabilities.h" #include "../../core/linux/SDL_udev.h" @@ -88,11 +90,11 @@ static int xioctl(int fh, int request, void *arg) return r; } -static int V4L2_WaitDevice(SDL_CameraDevice *device) +static bool V4L2_WaitDevice(SDL_Camera *device) { const int fd = device->hidden->fd; - int retval; + int rc; do { fd_set fds; @@ -103,16 +105,24 @@ static int V4L2_WaitDevice(SDL_CameraDevice *device) tv.tv_sec = 0; tv.tv_usec = 100 * 1000; - retval = select(fd + 1, &fds, NULL, NULL, &tv); - if ((retval == -1) && (errno == EINTR)) { - retval = 0; // pretend it was a timeout, keep looping. + rc = select(fd + 1, &fds, NULL, NULL, &tv); + if ((rc == -1) && (errno == EINTR)) { + rc = 0; // pretend it was a timeout, keep looping. + } else if (rc > 0) { + return true; + } + + // Thread is requested to shut down + if (SDL_GetAtomicInt(&device->shutdown)) { + return true; } - } while (retval == 0); - return retval; + } while (rc == 0); + + return false; } -static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint64 *timestampNS) +static SDL_CameraFrameResult V4L2_AcquireFrame(SDL_Camera *device, SDL_Surface *frame, Uint64 *timestampNS) { const int fd = device->hidden->fd; const io_method io = device->hidden->io; @@ -123,15 +133,16 @@ static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint6 case IO_METHOD_READ: if (read(fd, device->hidden->buffers[0].start, size) == -1) { switch (errno) { - case EAGAIN: - return 0; + case EAGAIN: + return SDL_CAMERA_FRAME_SKIP; - case EIO: - // Could ignore EIO, see spec. - // fall through + case EIO: + // Could ignore EIO, see spec. + // fall through - default: - return SDL_SetError("read"); + default: + SDL_SetError("read"); + return SDL_CAMERA_FRAME_ERROR; } } @@ -148,20 +159,22 @@ static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint6 if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { switch (errno) { - case EAGAIN: - return 0; + case EAGAIN: + return SDL_CAMERA_FRAME_SKIP; - case EIO: - // Could ignore EIO, see spec. - // fall through + case EIO: + // Could ignore EIO, see spec. + // fall through - default: - return SDL_SetError("VIDIOC_DQBUF: %d", errno); + default: + SDL_SetError("VIDIOC_DQBUF: %d", errno); + return SDL_CAMERA_FRAME_ERROR; } } if ((int)buf.index < 0 || (int)buf.index >= device->hidden->nb_buffers) { - return SDL_SetError("invalid buffer index"); + SDL_SetError("invalid buffer index"); + return SDL_CAMERA_FRAME_ERROR; } frame->pixels = device->hidden->buffers[buf.index].start; @@ -183,16 +196,16 @@ static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint6 if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1) { switch (errno) { - case EAGAIN: - return 0; - - case EIO: - // Could ignore EIO, see spec. + case EAGAIN: + return SDL_CAMERA_FRAME_SKIP; - // fall through + case EIO: + // Could ignore EIO, see spec. + // fall through - default: - return SDL_SetError("VIDIOC_DQBUF"); + default: + SDL_SetError("VIDIOC_DQBUF"); + return SDL_CAMERA_FRAME_ERROR; } } @@ -204,7 +217,8 @@ static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint6 } if (i >= device->hidden->nb_buffers) { - return SDL_SetError("invalid buffer index"); + SDL_SetError("invalid buffer index"); + return SDL_CAMERA_FRAME_ERROR; } frame->pixels = (void*)buf.m.userptr; @@ -223,10 +237,10 @@ static int V4L2_AcquireFrame(SDL_CameraDevice *device, SDL_Surface *frame, Uint6 break; } - return 1; + return SDL_CAMERA_FRAME_READY; } -static void V4L2_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) +static void V4L2_ReleaseFrame(SDL_Camera *device, SDL_Surface *frame) { struct v4l2_buffer buf; const int fd = device->hidden->fd; @@ -283,7 +297,7 @@ static void V4L2_ReleaseFrame(SDL_CameraDevice *device, SDL_Surface *frame) } } -static int EnqueueBuffers(SDL_CameraDevice *device) +static bool EnqueueBuffers(SDL_Camera *device) { const int fd = device->hidden->fd; const io_method io = device->hidden->io; @@ -329,17 +343,17 @@ static int EnqueueBuffers(SDL_CameraDevice *device) case IO_METHOD_INVALID: SDL_assert(!"Shouldn't have hit this"); break; } - return 0; + return true; } -static int AllocBufferRead(SDL_CameraDevice *device, size_t buffer_size) +static bool AllocBufferRead(SDL_Camera *device, size_t buffer_size) { device->hidden->buffers[0].length = buffer_size; device->hidden->buffers[0].start = SDL_calloc(1, buffer_size); - return device->hidden->buffers[0].start ? 0 : -1; + return (device->hidden->buffers[0].start != NULL); } -static int AllocBufferMmap(SDL_CameraDevice *device) +static bool AllocBufferMmap(SDL_Camera *device) { const int fd = device->hidden->fd; int i; @@ -368,10 +382,10 @@ static int AllocBufferMmap(SDL_CameraDevice *device) return SDL_SetError("mmap"); } } - return 0; + return true; } -static int AllocBufferUserPtr(SDL_CameraDevice *device, size_t buffer_size) +static bool AllocBufferUserPtr(SDL_Camera *device, size_t buffer_size) { int i; for (i = 0; i < device->hidden->nb_buffers; ++i) { @@ -379,28 +393,29 @@ static int AllocBufferUserPtr(SDL_CameraDevice *device, size_t buffer_size) device->hidden->buffers[i].start = SDL_calloc(1, buffer_size); if (!device->hidden->buffers[i].start) { - return -1; + return false; } } - return 0; + return true; } -static Uint32 format_v4l2_to_sdl(Uint32 fmt) +static void format_v4l2_to_sdl(Uint32 fmt, SDL_PixelFormat *format, SDL_Colorspace *colorspace) { switch (fmt) { - #define CASE(x, y) case x: return y - CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2); - CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); - #undef CASE - default: - #if DEBUG_CAMERA - SDL_Log("CAMERA: Unknown format V4L2_PIX_FORMAT '%d'", fmt); - #endif - return SDL_PIXELFORMAT_UNKNOWN; + #define CASE(x, y, z) case x: *format = y; *colorspace = z; return + CASE(V4L2_PIX_FMT_YUYV, SDL_PIXELFORMAT_YUY2, SDL_COLORSPACE_BT709_LIMITED); + #undef CASE + default: + #if DEBUG_CAMERA + SDL_Log("CAMERA: Unknown format V4L2_PIX_FORMAT '%d'", fmt); + #endif + break; } + *format = SDL_PIXELFORMAT_UNKNOWN; + *colorspace = SDL_COLORSPACE_UNKNOWN; } -static Uint32 format_sdl_to_v4l2(Uint32 fmt) +static Uint32 format_sdl_to_v4l2(SDL_PixelFormat fmt) { switch (fmt) { #define CASE(y, x) case x: return y @@ -408,11 +423,11 @@ static Uint32 format_sdl_to_v4l2(Uint32 fmt) CASE(V4L2_PIX_FMT_MJPEG, SDL_PIXELFORMAT_UNKNOWN); #undef CASE default: - return 0; + return true; } } -static void V4L2_CloseDevice(SDL_CameraDevice *device) +static void V4L2_CloseDevice(SDL_Camera *device) { if (!device) { return; @@ -463,7 +478,7 @@ static void V4L2_CloseDevice(SDL_CameraDevice *device) } } -static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) +static bool V4L2_OpenDevice(SDL_Camera *device, const SDL_CameraSpec *spec) { const V4L2DeviceHandle *handle = (const V4L2DeviceHandle *) device->handle; struct stat st; @@ -494,7 +509,7 @@ static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) device->hidden = (struct SDL_PrivateCameraData *) SDL_calloc(1, sizeof (struct SDL_PrivateCameraData)); if (device->hidden == NULL) { close(fd); - return -1; + return false; } device->hidden->fd = fd; @@ -531,16 +546,16 @@ static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) return SDL_SetError("Error VIDIOC_S_FMT"); } - if (spec->interval_numerator && spec->interval_denominator) { + if (spec->framerate_numerator && spec->framerate_denominator) { struct v4l2_streamparm setfps; SDL_zero(setfps); setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(fd, VIDIOC_G_PARM, &setfps) == 0) { - if ( (setfps.parm.capture.timeperframe.numerator != spec->interval_numerator) || - (setfps.parm.capture.timeperframe.denominator = spec->interval_denominator) ) { + if ( (setfps.parm.capture.timeperframe.denominator != spec->framerate_numerator) || + (setfps.parm.capture.timeperframe.numerator = spec->framerate_denominator) ) { setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - setfps.parm.capture.timeperframe.numerator = spec->interval_numerator; - setfps.parm.capture.timeperframe.denominator = spec->interval_denominator; + setfps.parm.capture.timeperframe.numerator = spec->framerate_denominator; + setfps.parm.capture.timeperframe.denominator = spec->framerate_numerator; if (xioctl(fd, VIDIOC_S_PARM, &setfps) == -1) { return SDL_SetError("Error VIDIOC_S_PARM"); } @@ -590,13 +605,15 @@ static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) device->hidden->buffers = SDL_calloc(device->hidden->nb_buffers, sizeof(*device->hidden->buffers)); if (!device->hidden->buffers) { - return -1; + return false; } size_t size, pitch; - SDL_CalculateSurfaceSize(device->spec.format, device->spec.width, device->spec.height, &size, &pitch, SDL_FALSE); + if (!SDL_CalculateSurfaceSize(device->spec.format, device->spec.width, device->spec.height, &size, &pitch, false)) { + return false; + } - int rc = 0; + bool rc = true; switch (io) { case IO_METHOD_READ: rc = AllocBufferRead(device, size); @@ -615,10 +632,10 @@ static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) break; } - if (rc < 0) { - return -1; - } else if (EnqueueBuffers(device) < 0) { - return -1; + if (!rc) { + return false; + } else if (!EnqueueBuffers(device)) { + return false; } else if (io != IO_METHOD_READ) { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) { @@ -627,18 +644,18 @@ static int V4L2_OpenDevice(SDL_CameraDevice *device, const SDL_CameraSpec *spec) } // Currently there is no user permission prompt for camera access, but maybe there will be a D-Bus portal interface at some point. - SDL_CameraDevicePermissionOutcome(device, SDL_TRUE); + SDL_CameraPermissionOutcome(device, true); - return 0; + return true; } -static SDL_bool FindV4L2CameraDeviceByBusInfoCallback(SDL_CameraDevice *device, void *userdata) +static bool FindV4L2CameraByBusInfoCallback(SDL_Camera *device, void *userdata) { const V4L2DeviceHandle *handle = (const V4L2DeviceHandle *) device->handle; return (SDL_strcmp(handle->bus_info, (const char *) userdata) == 0); } -static int AddCameraFormat(const int fd, CameraFormatAddData *data, Uint32 sdlfmt, Uint32 v4l2fmt, int w, int h) +static bool AddCameraFormat(const int fd, CameraFormatAddData *data, SDL_PixelFormat sdlfmt, SDL_Colorspace colorspace, Uint32 v4l2fmt, int w, int h) { struct v4l2_frmivalenum frmivalenum; SDL_zero(frmivalenum); @@ -654,8 +671,8 @@ static int AddCameraFormat(const int fd, CameraFormatAddData *data, Uint32 sdlfm const float fps = (float) denominator / (float) numerator; SDL_Log("CAMERA: * Has discrete frame interval (%d / %d), fps=%f", numerator, denominator, fps); #endif - if (SDL_AddCameraFormat(data, sdlfmt, w, h, numerator, denominator) == -1) { - return -1; // Probably out of memory; we'll go with what we have, if anything. + if (!SDL_AddCameraFormat(data, sdlfmt, colorspace, w, h, denominator, numerator)) { + return false; // Probably out of memory; we'll go with what we have, if anything. } frmivalenum.index++; // set up for the next one. } else if ((frmivalenum.type == V4L2_FRMIVAL_TYPE_STEPWISE) || (frmivalenum.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) { @@ -666,8 +683,9 @@ static int AddCameraFormat(const int fd, CameraFormatAddData *data, Uint32 sdlfm const float fps = (float) d / (float) n; SDL_Log("CAMERA: * Has %s frame interval (%d / %d), fps=%f", (frmivalenum.type == V4L2_FRMIVAL_TYPE_STEPWISE) ? "stepwise" : "continuous", n, d, fps); #endif - if (SDL_AddCameraFormat(data, sdlfmt, w, h, n, d) == -1) { - return -1; // Probably out of memory; we'll go with what we have, if anything. + // SDL expects framerate, V4L2 provides interval + if (!SDL_AddCameraFormat(data, sdlfmt, colorspace, w, h, d, n)) { + return false; // Probably out of memory; we'll go with what we have, if anything. } d += (int) frmivalenum.stepwise.step.denominator; } @@ -675,7 +693,7 @@ static int AddCameraFormat(const int fd, CameraFormatAddData *data, Uint32 sdlfm } } - return 0; + return true; } @@ -705,7 +723,7 @@ static void MaybeAddDevice(const char *path) } else if ((vcap.device_caps & V4L2_CAP_VIDEO_CAPTURE) == 0) { close(fd); return; // not a video capture device. - } else if (SDL_FindPhysicalCameraDeviceByCallback(FindV4L2CameraDeviceByBusInfoCallback, vcap.bus_info)) { + } else if (SDL_FindPhysicalCameraByCallback(FindV4L2CameraByBusInfoCallback, vcap.bus_info)) { close(fd); return; // already have it. } @@ -721,7 +739,9 @@ static void MaybeAddDevice(const char *path) SDL_zero(fmtdesc); fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { - const Uint32 sdlfmt = format_v4l2_to_sdl(fmtdesc.pixelformat); + SDL_PixelFormat sdlfmt = SDL_PIXELFORMAT_UNKNOWN; + SDL_Colorspace colorspace = SDL_COLORSPACE_UNKNOWN; + format_v4l2_to_sdl(fmtdesc.pixelformat, &sdlfmt, &colorspace); #if DEBUG_CAMERA SDL_Log("CAMERA: - Has format '%s'%s%s", SDL_GetPixelFormatName(sdlfmt), @@ -746,7 +766,7 @@ static void MaybeAddDevice(const char *path) #if DEBUG_CAMERA SDL_Log("CAMERA: * Has discrete size %dx%d", w, h); #endif - if (AddCameraFormat(fd, &add_data, sdlfmt, fmtdesc.pixelformat, w, h) == -1) { + if (!AddCameraFormat(fd, &add_data, sdlfmt, colorspace, fmtdesc.pixelformat, w, h)) { break; // Probably out of memory; we'll go with what we have, if anything. } frmsizeenum.index++; // set up for the next one. @@ -762,7 +782,7 @@ static void MaybeAddDevice(const char *path) #if DEBUG_CAMERA SDL_Log("CAMERA: * Has %s size %dx%d", (frmsizeenum.type == V4L2_FRMSIZE_TYPE_STEPWISE) ? "stepwise" : "continuous", w, h); #endif - if (AddCameraFormat(fd, &add_data, sdlfmt, fmtdesc.pixelformat, w, h) == -1) { + if (!AddCameraFormat(fd, &add_data, sdlfmt, colorspace, fmtdesc.pixelformat, w, h)) { break; // Probably out of memory; we'll go with what we have, if anything. } } @@ -785,7 +805,7 @@ static void MaybeAddDevice(const char *path) if (handle->path) { handle->bus_info = SDL_strdup((char *)vcap.bus_info); if (handle->bus_info) { - if (SDL_AddCameraDevice((const char *) vcap.card, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, handle)) { + if (SDL_AddCamera((const char *) vcap.card, SDL_CAMERA_POSITION_UNKNOWN, add_data.num_specs, add_data.specs, handle)) { SDL_free(add_data.specs); return; // good to go. } @@ -799,7 +819,7 @@ static void MaybeAddDevice(const char *path) SDL_free(add_data.specs); } -static void V4L2_FreeDeviceHandle(SDL_CameraDevice *device) +static void V4L2_FreeDeviceHandle(SDL_Camera *device) { if (device) { V4L2DeviceHandle *handle = (V4L2DeviceHandle *) device->handle; @@ -810,7 +830,7 @@ static void V4L2_FreeDeviceHandle(SDL_CameraDevice *device) } #ifdef SDL_USE_LIBUDEV -static SDL_bool FindV4L2CameraDeviceByPathCallback(SDL_CameraDevice *device, void *userdata) +static bool FindV4L2CameraByPathCallback(SDL_Camera *device, void *userdata) { const V4L2DeviceHandle *handle = (const V4L2DeviceHandle *) device->handle; return (SDL_strcmp(handle->path, (const char *) userdata) == 0); @@ -819,7 +839,7 @@ static SDL_bool FindV4L2CameraDeviceByPathCallback(SDL_CameraDevice *device, voi static void MaybeRemoveDevice(const char *path) { if (path) { - SDL_CameraDeviceDisconnected(SDL_FindPhysicalCameraDeviceByCallback(FindV4L2CameraDeviceByPathCallback, (void *) path)); + SDL_CameraDisconnected(SDL_FindPhysicalCameraByCallback(FindV4L2CameraByPathCallback, (void *) path)); } } @@ -846,12 +866,14 @@ static void V4L2_Deinitialize(void) static void V4L2_DetectDevices(void) { #ifdef SDL_USE_LIBUDEV - if (SDL_UDEV_Init() == 0) { - if (SDL_UDEV_AddCallback(CameraUdevCallback) == 0) { + if (SDL_UDEV_Init()) { + if (SDL_UDEV_AddCallback(CameraUdevCallback)) { SDL_UDEV_Scan(); // Force a scan to build the initial device list } + return; } -#else +#endif // SDL_USE_LIBUDEV + DIR *dirp = opendir("/dev"); if (dirp) { struct dirent *dent; @@ -865,10 +887,9 @@ static void V4L2_DetectDevices(void) } closedir(dirp); } -#endif // SDL_USE_LIBUDEV } -static SDL_bool V4L2_Init(SDL_CameraDriverImpl *impl) +static bool V4L2_Init(SDL_CameraDriverImpl *impl) { impl->DetectDevices = V4L2_DetectDevices; impl->OpenDevice = V4L2_OpenDevice; @@ -879,11 +900,11 @@ static SDL_bool V4L2_Init(SDL_CameraDriverImpl *impl) impl->FreeDeviceHandle = V4L2_FreeDeviceHandle; impl->Deinitialize = V4L2_Deinitialize; - return SDL_TRUE; + return true; } CameraBootStrap V4L2_bootstrap = { - "v4l2", "SDL Video4Linux2 camera driver", V4L2_Init, SDL_FALSE + "v4l2", "SDL Video4Linux2 camera driver", V4L2_Init, false }; #endif // SDL_CAMERA_DRIVER_V4L2 diff --git a/libs/SDL3/src/core/SDL_core_unsupported.c b/libs/SDL3/src/core/SDL_core_unsupported.c index 2196aa404..b36c7f744 100644 --- a/libs/SDL3/src/core/SDL_core_unsupported.c +++ b/libs/SDL3/src/core/SDL_core_unsupported.c @@ -22,7 +22,8 @@ #ifndef SDL_VIDEO_DRIVER_X11 -DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) +SDL_DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata); +void SDL_SetX11EventHook(SDL_X11EventHook callback, void *userdata) { } @@ -30,16 +31,16 @@ DECLSPEC void SDLCALL SDL_SetX11EventHook(SDL_X11EventHook callback, void *userd #ifndef SDL_PLATFORM_LINUX -DECLSPEC int SDLCALL SDL_LinuxSetThreadPriority(Sint64 threadID, int priority); -int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) +SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriority(Sint64 threadID, int priority); +bool SDL_SetLinuxThreadPriority(Sint64 threadID, int priority) { (void)threadID; (void)priority; return SDL_Unsupported(); } -DECLSPEC int SDLCALL SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); -int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy) +SDL_DECLSPEC bool SDLCALL SDL_SetLinuxThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy); +bool SDL_SetLinuxThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy) { (void)threadID; (void)sdlPriority; @@ -51,24 +52,34 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc #ifndef SDL_PLATFORM_GDK -DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); +SDL_DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void); void SDL_GDKSuspendComplete(void) { SDL_Unsupported(); } -DECLSPEC int SDLCALL SDL_GDKGetDefaultUser(void *outUserHandle); /* XUserHandle *outUserHandle */ -int SDL_GDKGetDefaultUser(void *outUserHandle) +SDL_DECLSPEC bool SDLCALL SDL_GetGDKDefaultUser(void *outUserHandle); /* XUserHandle *outUserHandle */ +bool SDL_GetGDKDefaultUser(void *outUserHandle) { return SDL_Unsupported(); } +SDL_DECLSPEC void SDLCALL SDL_GDKSuspendGPU(SDL_GPUDevice *device); +void SDL_GDKSuspendGPU(SDL_GPUDevice *device) +{ +} + +SDL_DECLSPEC void SDLCALL SDL_GDKResumeGPU(SDL_GPUDevice *device); +void SDL_GDKResumeGPU(SDL_GPUDevice *device) +{ +} + #endif -#if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK)) +#if !defined(SDL_PLATFORM_WINDOWS) -DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); -int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) +SDL_DECLSPEC bool SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst); +bool SDL_RegisterApp(const char *name, Uint32 style, void *hInst) { (void)name; (void)style; @@ -76,7 +87,7 @@ int SDL_RegisterApp(const char *name, Uint32 style, void *hInst) return SDL_Unsupported(); } -DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(void *callback, void *userdata); /* SDL_WindowsMessageHook callback */ +SDL_DECLSPEC void SDLCALL SDL_SetWindowsMessageHook(void *callback, void *userdata); // SDL_WindowsMessageHook callback void SDL_SetWindowsMessageHook(void *callback, void *userdata) { (void)callback; @@ -84,7 +95,7 @@ void SDL_SetWindowsMessageHook(void *callback, void *userdata) SDL_Unsupported(); } -DECLSPEC void SDLCALL SDL_UnregisterApp(void); +SDL_DECLSPEC void SDLCALL SDL_UnregisterApp(void); void SDL_UnregisterApp(void) { SDL_Unsupported(); @@ -92,78 +103,59 @@ void SDL_UnregisterApp(void) #endif -#ifndef SDL_PLATFORM_WINRT +#ifndef SDL_PLATFORM_ANDROID -/* Returns SDL_WinRT_DeviceFamily enum */ -DECLSPEC int SDLCALL SDL_WinRTGetDeviceFamily(void); -int SDL_WinRTGetDeviceFamily() +SDL_DECLSPEC void SDLCALL SDL_SendAndroidBackButton(void); +void SDL_SendAndroidBackButton(void) { SDL_Unsupported(); - return 0; /* SDL_WINRT_DEVICEFAMILY_UNKNOWN */ } -DECLSPEC const wchar_t *SDLCALL SDL_WinRTGetFSPathUNICODE(int pathType); /* SDL_WinRT_Path pathType */ -const wchar_t *SDL_WinRTGetFSPathUNICODE(int pathType) +SDL_DECLSPEC void *SDLCALL SDL_GetAndroidActivity(void); +void *SDL_GetAndroidActivity(void) { - (void)pathType; SDL_Unsupported(); return NULL; } -DECLSPEC const char *SDLCALL SDL_WinRTGetFSPathUTF8(int pathType); /* SDL_WinRT_Path pathType */ -const char *SDL_WinRTGetFSPathUTF8(int pathType) +SDL_DECLSPEC const char *SDLCALL SDL_GetAndroidCachePath(void); +const char* SDL_GetAndroidCachePath(void) { - (void)pathType; SDL_Unsupported(); return NULL; } -#endif -#ifndef SDL_PLATFORM_ANDROID -DECLSPEC void SDLCALL SDL_AndroidBackButton(void); -void SDL_AndroidBackButton() -{ - SDL_Unsupported(); -} - -DECLSPEC void *SDLCALL SDL_AndroidGetActivity(void); -void *SDL_AndroidGetActivity() +SDL_DECLSPEC const char *SDLCALL SDL_GetAndroidExternalStoragePath(void); +const char* SDL_GetAndroidExternalStoragePath(void) { SDL_Unsupported(); return NULL; } -DECLSPEC const char *SDLCALL SDL_AndroidGetExternalStoragePath(void); -const char* SDL_AndroidGetExternalStoragePath() +SDL_DECLSPEC Uint32 SDLCALL SDL_GetAndroidExternalStorageState(void); +Uint32 SDL_GetAndroidExternalStorageState(void) { SDL_Unsupported(); - return NULL; + return 0; } - -DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(Uint32 *state); -int SDL_AndroidGetExternalStorageState(Uint32 *state) -{ - (void)state; - return SDL_Unsupported(); -} -DECLSPEC const char *SDLCALL SDL_AndroidGetInternalStoragePath(void); -const char *SDL_AndroidGetInternalStoragePath() +SDL_DECLSPEC const char *SDLCALL SDL_GetAndroidInternalStoragePath(void); +const char *SDL_GetAndroidInternalStoragePath(void) { SDL_Unsupported(); return NULL; } -DECLSPEC void *SDLCALL SDL_AndroidGetJNIEnv(void); -void *SDL_AndroidGetJNIEnv() +SDL_DECLSPEC void *SDLCALL SDL_GetAndroidJNIEnv(void); +void *SDL_GetAndroidJNIEnv(void) { SDL_Unsupported(); return NULL; } -typedef void (SDLCALL *SDL_AndroidRequestPermissionCallback)(void *userdata, const char *permission, SDL_bool granted); -DECLSPEC int SDLCALL SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata); -int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata) +typedef void (SDLCALL *SDL_RequestAndroidPermissionCallback)(void *userdata, const char *permission, bool granted); +SDL_DECLSPEC bool SDLCALL SDL_RequestAndroidPermission(const char *permission, SDL_RequestAndroidPermissionCallback cb, void *userdata); +bool SDL_RequestAndroidPermission(const char *permission, SDL_RequestAndroidPermissionCallback cb, void *userdata) { (void)permission; (void)cb; @@ -171,16 +163,16 @@ int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermi return SDL_Unsupported(); } -DECLSPEC int SDLCALL SDL_AndroidSendMessage(Uint32 command, int param); -int SDL_AndroidSendMessage(Uint32 command, int param) +SDL_DECLSPEC bool SDLCALL SDL_SendAndroidMessage(Uint32 command, int param); +bool SDL_SendAndroidMessage(Uint32 command, int param) { (void)command; (void)param; return SDL_Unsupported(); } -DECLSPEC int SDLCALL SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset); -int SDL_AndroidShowToast(const char* message, int duration, int gravity, int xoffset, int yoffset) +SDL_DECLSPEC bool SDLCALL SDL_ShowAndroidToast(const char* message, int duration, int gravity, int xoffset, int yoffset); +bool SDL_ShowAndroidToast(const char* message, int duration, int gravity, int xoffset, int yoffset) { (void)message; (void)duration; @@ -190,48 +182,32 @@ int SDL_AndroidShowToast(const char* message, int duration, int gravity, int xof return SDL_Unsupported(); } -DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); -int SDL_GetAndroidSDKVersion() +SDL_DECLSPEC int SDLCALL SDL_GetAndroidSDKVersion(void); +int SDL_GetAndroidSDKVersion(void) { return SDL_Unsupported(); } -DECLSPEC SDL_bool SDLCALL SDL_IsAndroidTV(void); -SDL_bool SDL_IsAndroidTV() -{ - SDL_Unsupported(); - return SDL_FALSE; -} - -DECLSPEC SDL_bool SDLCALL SDL_IsChromebook(void); -SDL_bool SDL_IsChromebook() +SDL_DECLSPEC bool SDLCALL SDL_IsChromebook(void); +bool SDL_IsChromebook(void) { SDL_Unsupported(); - return SDL_FALSE; + return false; } -DECLSPEC SDL_bool SDLCALL SDL_IsDeXMode(void); -SDL_bool SDL_IsDeXMode(void) +SDL_DECLSPEC bool SDLCALL SDL_IsDeXMode(void); +bool SDL_IsDeXMode(void) { SDL_Unsupported(); - return SDL_FALSE; + return false; } -DECLSPEC Sint32 SDLCALL JNI_OnLoad(void *vm, void *reserved); +SDL_DECLSPEC Sint32 SDLCALL JNI_OnLoad(void *vm, void *reserved); Sint32 JNI_OnLoad(void *vm, void *reserved) { (void)vm; (void)reserved; SDL_Unsupported(); - return -1; /* JNI_ERR */ -} -#endif - -#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) -char *SDL_GetUserFolder(SDL_Folder folder) -{ - (void)folder; - SDL_Unsupported(); - return NULL; + return -1; // JNI_ERR } #endif diff --git a/libs/SDL3/src/core/android/SDL_android.c b/libs/SDL3/src/core/android/SDL_android.c index 01e03bde6..78d8b7194 100644 --- a/libs/SDL3/src/core/android/SDL_android.c +++ b/libs/SDL3/src/core/android/SDL_android.c @@ -52,18 +52,24 @@ #define SDL_JAVA_CONTROLLER_INTERFACE(function) CONCAT1(SDL_JAVA_PREFIX, SDLControllerManager, function) #define SDL_JAVA_INTERFACE_INPUT_CONNECTION(function) CONCAT1(SDL_JAVA_PREFIX, SDLInputConnection, function) -/* Audio encoding definitions */ +// Audio encoding definitions #define ENCODING_PCM_8BIT 3 #define ENCODING_PCM_16BIT 2 #define ENCODING_PCM_FLOAT 4 -/* Java class SDLActivity */ +// Java class SDLActivity JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetVersion)( JNIEnv *env, jclass cls); JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)( JNIEnv *env, jclass cls); +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)( + JNIEnv *env, jclass cls); + +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeCleanupMainThread)( + JNIEnv *env, jclass cls); + JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)( JNIEnv *env, jclass cls, jstring library, jstring function, jobject array); @@ -163,6 +169,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)( JNIEnv *env, jclass cls, jint rotation); +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeInsetsChanged)( + JNIEnv *env, jclass cls, + jint left, jint right, jint top, jint bottom); + JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)( JNIEnv *env, jclass cls, jint touchId, jstring name); @@ -177,9 +187,15 @@ JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)( JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)( JNIEnv *env, jclass jcls); +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)( + JNIEnv *env, jclass jcls, + jint requestCode, jobjectArray fileList, jint filter); + static JNINativeMethod SDLActivity_tab[] = { { "nativeGetVersion", "()Ljava/lang/String;", SDL_JAVA_INTERFACE(nativeGetVersion) }, { "nativeSetupJNI", "()I", SDL_JAVA_INTERFACE(nativeSetupJNI) }, + { "nativeInitMainThread", "()V", SDL_JAVA_INTERFACE(nativeInitMainThread) }, + { "nativeCleanupMainThread", "()V", SDL_JAVA_INTERFACE(nativeCleanupMainThread) }, { "nativeRunMain", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)I", SDL_JAVA_INTERFACE(nativeRunMain) }, { "onNativeDropFile", "(Ljava/lang/String;)V", SDL_JAVA_INTERFACE(onNativeDropFile) }, { "nativeSetScreenResolution", "(IIIIFF)V", SDL_JAVA_INTERFACE(nativeSetScreenResolution) }, @@ -208,13 +224,15 @@ static JNINativeMethod SDLActivity_tab[] = { { "nativeSetenv", "(Ljava/lang/String;Ljava/lang/String;)V", SDL_JAVA_INTERFACE(nativeSetenv) }, { "nativeSetNaturalOrientation", "(I)V", SDL_JAVA_INTERFACE(nativeSetNaturalOrientation) }, { "onNativeRotationChanged", "(I)V", SDL_JAVA_INTERFACE(onNativeRotationChanged) }, + { "onNativeInsetsChanged", "(IIII)V", SDL_JAVA_INTERFACE(onNativeInsetsChanged) }, { "nativeAddTouch", "(ILjava/lang/String;)V", SDL_JAVA_INTERFACE(nativeAddTouch) }, { "nativePermissionResult", "(IZ)V", SDL_JAVA_INTERFACE(nativePermissionResult) }, { "nativeAllowRecreateActivity", "()Z", SDL_JAVA_INTERFACE(nativeAllowRecreateActivity) }, - { "nativeCheckSDLThreadCounter", "()I", SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter) } + { "nativeCheckSDLThreadCounter", "()I", SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter) }, + { "onNativeFileDialog", "(I[Ljava/lang/String;I)V", SDL_JAVA_INTERFACE(onNativeFileDialog) } }; -/* Java class SDLInputConnection */ +// Java class SDLInputConnection JNIEXPORT void JNICALL SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeCommitText)( JNIEnv *env, jclass cls, jstring text, jint newCursorPosition); @@ -228,16 +246,16 @@ static JNINativeMethod SDLInputConnection_tab[] = { { "nativeGenerateScancodeForUnichar", "(C)V", SDL_JAVA_INTERFACE_INPUT_CONNECTION(nativeGenerateScancodeForUnichar) } }; -/* Java class SDLAudioManager */ +// Java class SDLAudioManager JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)( JNIEnv *env, jclass jcls); JNIEXPORT void JNICALL - SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, jstring name, + SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording, jstring name, jint device_id); JNIEXPORT void JNICALL - SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, + SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording, jint device_id); static JNINativeMethod SDLAudioManager_tab[] = { @@ -246,15 +264,15 @@ static JNINativeMethod SDLAudioManager_tab[] = { { "removeAudioDevice", "(ZI)V", SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice) } }; -/* Java class SDLControllerManager */ +// Java class SDLControllerManager JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)( JNIEnv *env, jclass jcls); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)( +JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)( JNIEnv *env, jclass jcls, jint device_id, jint keycode); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)( +JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)( JNIEnv *env, jclass jcls, jint device_id, jint keycode); @@ -266,37 +284,37 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)( JNIEnv *env, jclass jcls, jint device_id, jint hat_id, jint x, jint y); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)( JNIEnv *env, jclass jcls, jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id, - jint button_mask, jint naxes, jint axis_mask, jint nhats); + jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)( JNIEnv *env, jclass jcls, jint device_id); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)( JNIEnv *env, jclass jcls, jint device_id, jstring device_name); -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)( JNIEnv *env, jclass jcls, jint device_id); static JNINativeMethod SDLControllerManager_tab[] = { { "nativeSetupJNI", "()I", SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI) }, - { "onNativePadDown", "(II)I", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) }, - { "onNativePadUp", "(II)I", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) }, + { "onNativePadDown", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) }, + { "onNativePadUp", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) }, { "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) }, { "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) }, - { "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIII)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) }, - { "nativeRemoveJoystick", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) }, - { "nativeAddHaptic", "(ILjava/lang/String;)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) }, - { "nativeRemoveHaptic", "(I)I", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) } + { "nativeAddJoystick", "(ILjava/lang/String;Ljava/lang/String;IIIIIIZ)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick) }, + { "nativeRemoveJoystick", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick) }, + { "nativeAddHaptic", "(ILjava/lang/String;)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic) }, + { "nativeRemoveHaptic", "(I)V", SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic) } }; -/* Uncomment this to log messages entering and exiting methods in this file */ -/* #define DEBUG_JNI */ +// Uncomment this to log messages entering and exiting methods in this file +// #define DEBUG_JNI static void checkJNIReady(void); @@ -312,10 +330,10 @@ static pthread_key_t mThreadKey; static pthread_once_t key_once = PTHREAD_ONCE_INIT; static JavaVM *mJavaVM = NULL; -/* Main activity */ +// Main activity static jclass mActivityClass; -/* method signatures */ +// method signatures static jmethodID midClipboardGetText; static jmethodID midClipboardHasText; static jmethodID midClipboardSetText; @@ -345,51 +363,50 @@ static jmethodID midSetWindowStyle; static jmethodID midShouldMinimizeOnFocusLoss; static jmethodID midShowTextInput; static jmethodID midSupportsRelativeMouse; +static jmethodID midOpenFileDescriptor; +static jmethodID midShowFileDialog; -/* audio manager */ +// audio manager static jclass mAudioManagerClass; -/* method signatures */ +// method signatures static jmethodID midRegisterAudioDeviceCallback; static jmethodID midUnregisterAudioDeviceCallback; -static jmethodID midAudioOpen; -static jmethodID midAudioWriteByteBuffer; -static jmethodID midAudioWriteShortBuffer; -static jmethodID midAudioWriteFloatBuffer; -static jmethodID midAudioClose; -static jmethodID midCaptureOpen; -static jmethodID midCaptureReadByteBuffer; -static jmethodID midCaptureReadShortBuffer; -static jmethodID midCaptureReadFloatBuffer; -static jmethodID midCaptureClose; static jmethodID midAudioSetThreadPriority; -/* controller manager */ +// controller manager static jclass mControllerManagerClass; -/* method signatures */ +// method signatures static jmethodID midPollInputDevices; static jmethodID midPollHapticDevices; static jmethodID midHapticRun; +static jmethodID midHapticRumble; static jmethodID midHapticStop; -/* Accelerometer data storage */ +// Accelerometer data storage static SDL_DisplayOrientation displayNaturalOrientation; static SDL_DisplayOrientation displayCurrentOrientation; static float fLastAccelerometer[3]; -static SDL_bool bHasNewData; +static bool bHasNewData; -static SDL_bool bHasEnvironmentVariables; +static bool bHasEnvironmentVariables; -/* Android AssetManager */ +// Android AssetManager static void Internal_Android_Create_AssetManager(void); static void Internal_Android_Destroy_AssetManager(void); static AAssetManager *asset_manager = NULL; static jobject javaAssetManagerRef = 0; -/* Re-create activity hint */ +// Re-create activity hint static SDL_AtomicInt bAllowRecreateActivity; +static SDL_Mutex *Android_ActivityMutex = NULL; +static SDL_Mutex *Android_LifecycleMutex = NULL; +static SDL_Semaphore *Android_LifecycleEventSem = NULL; +static SDL_AndroidLifecycleEvent Android_LifecycleEvents[SDL_NUM_ANDROID_LIFECYCLE_EVENTS]; +static int Android_NumLifecycleEvents; + /******************************************************************************* Functions called by JNI *******************************************************************************/ @@ -416,26 +433,27 @@ static SDL_AtomicInt bAllowRecreateActivity; * (except for some lost CPU cycles) */ -/* Set local storage value */ -static int Android_JNI_SetEnv(JNIEnv *env) +// Set local storage value +static bool Android_JNI_SetEnv(JNIEnv *env) { int status = pthread_setspecific(mThreadKey, env); if (status < 0) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed pthread_setspecific() in Android_JNI_SetEnv() (err=%d)", status); + return false; } - return status; + return true; } -/* Get local storage value */ +// Get local storage value JNIEnv *Android_JNI_GetEnv(void) { - /* Get JNIEnv from the Thread local storage */ + // Get JNIEnv from the Thread local storage JNIEnv *env = pthread_getspecific(mThreadKey); if (!env) { - /* If it fails, try to attach ! (e.g the thread isn't created with SDL_CreateThread() */ + // If it fails, try to attach ! (e.g the thread isn't created with SDL_CreateThread() int status; - /* There should be a JVM */ + // There should be a JVM if (!mJavaVM) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM"); return NULL; @@ -449,8 +467,8 @@ JNIEnv *Android_JNI_GetEnv(void) return NULL; } - /* Save JNIEnv into the Thread local storage */ - if (Android_JNI_SetEnv(env) < 0) { + // Save JNIEnv into the Thread local storage + if (!Android_JNI_SetEnv(env)) { return NULL; } } @@ -458,16 +476,16 @@ JNIEnv *Android_JNI_GetEnv(void) return env; } -/* Set up an external thread for using JNI with Android_JNI_GetEnv() */ -int Android_JNI_SetupThread(void) +// Set up an external thread for using JNI with Android_JNI_GetEnv() +bool Android_JNI_SetupThread(void) { JNIEnv *env; int status; - /* There should be a JVM */ + // There should be a JVM if (!mJavaVM) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed, there is no JavaVM"); - return 0; + return false; } /* Attach the current thread to the JVM and get a JNIEnv. @@ -475,21 +493,21 @@ int Android_JNI_SetupThread(void) status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL); if (status < 0) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "Failed to attach current thread (err=%d)", status); - return 0; + return false; } - /* Save JNIEnv into the Thread local storage */ - if (Android_JNI_SetEnv(env) < 0) { - return 0; + // Save JNIEnv into the Thread local storage + if (!Android_JNI_SetEnv(env)) { + return false; } - return 1; + return true; } -/* Destructor called for each thread where mThreadKey is not NULL */ +// Destructor called for each thread where mThreadKey is not NULL static void Android_JNI_ThreadDestroyed(void *value) { - /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */ + // The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required JNIEnv *env = (JNIEnv *)value; if (env) { (*mJavaVM)->DetachCurrentThread(mJavaVM); @@ -497,7 +515,7 @@ static void Android_JNI_ThreadDestroyed(void *value) } } -/* Creation of local storage mThreadKey */ +// Creation of local storage mThreadKey static void Android_JNI_CreateKey(void) { int status = pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed); @@ -523,7 +541,7 @@ static void register_methods(JNIEnv *env, const char *classname, JNINativeMethod } } -/* Library init */ +// Library init JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env = NULL; @@ -540,7 +558,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) register_methods(env, "org/libsdl/app/SDLAudioManager", SDLAudioManager_tab, SDL_arraysize(SDLAudioManager_tab)); register_methods(env, "org/libsdl/app/SDLControllerManager", SDLControllerManager_tab, SDL_arraysize(SDLControllerManager_tab)); register_methods(env, "org/libsdl/app/HIDDeviceManager", HIDDeviceManager_tab, SDL_arraysize(HIDDeviceManager_tab)); - SDL_AtomicSet(&bAllowRecreateActivity, SDL_FALSE); + SDL_SetAtomicInt(&bAllowRecreateActivity, false); return JNI_VERSION_1_4; } @@ -548,29 +566,29 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) void checkJNIReady(void) { if (!mActivityClass || !mAudioManagerClass || !mControllerManagerClass) { - /* We aren't fully initialized, let's just return. */ + // We aren't fully initialized, let's just return. return; } SDL_SetMainReady(); } -/* Get SDL version -- called before SDL_main() to verify JNI bindings */ +// Get SDL version -- called before SDL_main() to verify JNI bindings JNIEXPORT jstring JNICALL SDL_JAVA_INTERFACE(nativeGetVersion)(JNIEnv *env, jclass cls) { char version[128]; - SDL_snprintf(version, sizeof(version), "%d.%d.%d", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL); + SDL_snprintf(version, sizeof(version), "%d.%d.%d", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_MICRO_VERSION); return (*env)->NewStringUTF(env, version); } -/* Activity initialization -- called before SDL_main() to initialize JNI bindings */ +// Activity initialization -- called before SDL_main() to initialize JNI bindings JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cls) { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeSetupJNI()"); - /* Start with a clean slate */ + // Start with a clean slate SDL_ClearError(); /* @@ -579,7 +597,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl */ Android_JNI_CreateKey_once(); - /* Save JNIEnv of SDLActivity */ + // Save JNIEnv of SDLActivity Android_JNI_SetEnv(env); if (!mJavaVM) { @@ -590,21 +608,21 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl * (Eg. Java sending Touch events, while native code is destroying the main SDL_Window. ) */ if (!Android_ActivityMutex) { - Android_ActivityMutex = SDL_CreateMutex(); /* Could this be created twice if onCreate() is called a second time ? */ + Android_ActivityMutex = SDL_CreateMutex(); // Could this be created twice if onCreate() is called a second time ? } if (!Android_ActivityMutex) { __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ActivityMutex mutex"); } - Android_PauseSem = SDL_CreateSemaphore(0); - if (!Android_PauseSem) { - __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_PauseSem semaphore"); + Android_LifecycleMutex = SDL_CreateMutex(); + if (!Android_LifecycleMutex) { + __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_LifecycleMutex mutex"); } - Android_ResumeSem = SDL_CreateSemaphore(0); - if (!Android_ResumeSem) { - __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_ResumeSem semaphore"); + Android_LifecycleEventSem = SDL_CreateSemaphore(0); + if (!Android_LifecycleEventSem) { + __android_log_print(ANDROID_LOG_ERROR, "SDL", "failed to create Android_LifecycleEventSem semaphore"); } mActivityClass = (jclass)((*env)->NewGlobalRef(env, cls)); @@ -625,9 +643,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl midIsTablet = (*env)->GetStaticMethodID(env, mActivityClass, "isTablet", "()Z"); midManualBackButton = (*env)->GetStaticMethodID(env, mActivityClass, "manualBackButton", "()V"); midMinimizeWindow = (*env)->GetStaticMethodID(env, mActivityClass, "minimizeWindow", "()V"); - midOpenURL = (*env)->GetStaticMethodID(env, mActivityClass, "openURL", "(Ljava/lang/String;)I"); + midOpenURL = (*env)->GetStaticMethodID(env, mActivityClass, "openURL", "(Ljava/lang/String;)Z"); midRequestPermission = (*env)->GetStaticMethodID(env, mActivityClass, "requestPermission", "(Ljava/lang/String;I)V"); - midShowToast = (*env)->GetStaticMethodID(env, mActivityClass, "showToast", "(Ljava/lang/String;IIII)I"); + midShowToast = (*env)->GetStaticMethodID(env, mActivityClass, "showToast", "(Ljava/lang/String;IIII)Z"); midSendMessage = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z"); midSetActivityTitle = (*env)->GetStaticMethodID(env, mActivityClass, "setActivityTitle", "(Ljava/lang/String;)Z"); midSetCustomCursor = (*env)->GetStaticMethodID(env, mActivityClass, "setCustomCursor", "(I)Z"); @@ -636,8 +654,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl midSetSystemCursor = (*env)->GetStaticMethodID(env, mActivityClass, "setSystemCursor", "(I)Z"); midSetWindowStyle = (*env)->GetStaticMethodID(env, mActivityClass, "setWindowStyle", "(Z)V"); midShouldMinimizeOnFocusLoss = (*env)->GetStaticMethodID(env, mActivityClass, "shouldMinimizeOnFocusLoss", "()Z"); - midShowTextInput = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z"); + midShowTextInput = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIIII)Z"); midSupportsRelativeMouse = (*env)->GetStaticMethodID(env, mActivityClass, "supportsRelativeMouse", "()Z"); + midOpenFileDescriptor = (*env)->GetStaticMethodID(env, mActivityClass, "openFileDescriptor", "(Ljava/lang/String;Ljava/lang/String;)I"); + midShowFileDialog = (*env)->GetStaticMethodID(env, mActivityClass, "showFileDialog", "([Ljava/lang/String;ZZI)Z"); if (!midClipboardGetText || !midClipboardHasText || @@ -667,14 +687,16 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cl !midSetWindowStyle || !midShouldMinimizeOnFocusLoss || !midShowTextInput || - !midSupportsRelativeMouse) { + !midSupportsRelativeMouse || + !midOpenFileDescriptor || + !midShowFileDialog) { __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLActivity.java?"); } checkJNIReady(); } -/* Audio initialization -- called before SDL_main() to initialize JNI bindings */ +// Audio initialization -- called before SDL_main() to initialize JNI bindings JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cls) { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "AUDIO nativeSetupJNI()"); @@ -687,34 +709,10 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jcl midUnregisterAudioDeviceCallback = (*env)->GetStaticMethodID(env, mAudioManagerClass, "unregisterAudioDeviceCallback", "()V"); - midAudioOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "audioOpen", "(IIIII)[I"); - midAudioWriteByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "audioWriteByteBuffer", "([B)V"); - midAudioWriteShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "audioWriteShortBuffer", "([S)V"); - midAudioWriteFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "audioWriteFloatBuffer", "([F)V"); - midAudioClose = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "audioClose", "()V"); - midCaptureOpen = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "captureOpen", "(IIIII)[I"); - midCaptureReadByteBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "captureReadByteBuffer", "([BZ)I"); - midCaptureReadShortBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "captureReadShortBuffer", "([SZ)I"); - midCaptureReadFloatBuffer = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "captureReadFloatBuffer", "([FZ)I"); - midCaptureClose = (*env)->GetStaticMethodID(env, mAudioManagerClass, - "captureClose", "()V"); midAudioSetThreadPriority = (*env)->GetStaticMethodID(env, mAudioManagerClass, "audioSetThreadPriority", "(ZI)V"); - if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioOpen || - !midAudioWriteByteBuffer || !midAudioWriteShortBuffer || !midAudioWriteFloatBuffer || - !midAudioClose || - !midCaptureOpen || !midCaptureReadByteBuffer || !midCaptureReadShortBuffer || - !midCaptureReadFloatBuffer || !midCaptureClose || !midAudioSetThreadPriority) { + if (!midRegisterAudioDeviceCallback || !midUnregisterAudioDeviceCallback || !midAudioSetThreadPriority) { __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLAudioManager.java?"); } @@ -722,7 +720,7 @@ JNIEXPORT void JNICALL SDL_JAVA_AUDIO_INTERFACE(nativeSetupJNI)(JNIEnv *env, jcl checkJNIReady(); } -/* Controller initialization -- called before SDL_main() to initialize JNI bindings */ +// Controller initialization -- called before SDL_main() to initialize JNI bindings JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env, jclass cls) { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "CONTROLLER nativeSetupJNI()"); @@ -735,17 +733,19 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(JNIEnv *env "pollHapticDevices", "()V"); midHapticRun = (*env)->GetStaticMethodID(env, mControllerManagerClass, "hapticRun", "(IFI)V"); + midHapticRumble = (*env)->GetStaticMethodID(env, mControllerManagerClass, + "hapticRumble", "(IFFI)V"); midHapticStop = (*env)->GetStaticMethodID(env, mControllerManagerClass, "hapticStop", "(I)V"); - if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun || !midHapticStop) { + if (!midPollInputDevices || !midPollHapticDevices || !midHapticRun || !midHapticRumble || !midHapticStop) { __android_log_print(ANDROID_LOG_WARN, "SDL", "Missing some Java callbacks, do you have the latest version of SDLControllerManager.java?"); } checkJNIReady(); } -/* SDL main function prototype */ +// SDL main function prototype typedef int (*SDL_main_func)(int argc, char *argv[]); static int run_count = 0; @@ -760,34 +760,46 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeCheckSDLThreadCounter)( static void SDLCALL SDL_AllowRecreateActivityChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { - if (SDL_GetStringBoolean(hint, SDL_FALSE)) { - SDL_AtomicSet(&bAllowRecreateActivity, SDL_TRUE); + if (SDL_GetStringBoolean(hint, false)) { + SDL_SetAtomicInt(&bAllowRecreateActivity, true); } else { - SDL_AtomicSet(&bAllowRecreateActivity, SDL_FALSE); + SDL_SetAtomicInt(&bAllowRecreateActivity, false); } } JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(nativeAllowRecreateActivity)( JNIEnv *env, jclass jcls) { - return SDL_AtomicGet(&bAllowRecreateActivity); + return SDL_GetAtomicInt(&bAllowRecreateActivity); } -/* Start up the SDL app */ -JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, jstring library, jstring function, jobject array) +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeInitMainThread)( + JNIEnv *env, jclass jcls) { - int status = -1; - const char *library_file; - void *library_handle; - - __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeRunMain() %d time", run_count); + __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeInitSDLThread() %d time", run_count); if (run_count == 1) { SDL_AddHintCallback(SDL_HINT_ANDROID_ALLOW_RECREATE_ACTIVITY, SDL_AllowRecreateActivityChanged, NULL); } run_count += 1; - /* Save JNIEnv of SDLThread */ + // Save JNIEnv of SDLThread Android_JNI_SetEnv(env); +} + +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeCleanupMainThread)( + JNIEnv *env, jclass jcls) +{ + /* This is a Java thread, it doesn't need to be Detached from the JVM. + * Set to mThreadKey value to NULL not to call pthread_create destructor 'Android_JNI_ThreadDestroyed' */ + Android_JNI_SetEnv(NULL); +} + +// Start up the SDL app +JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, jstring library, jstring function, jobject array) +{ + int status = -1; + const char *library_file; + void *library_handle; library_file = (*env)->GetStringUTFChars(env, library, NULL); library_handle = dlopen(library_file, RTLD_GLOBAL); @@ -813,11 +825,11 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, int argc; int len; char **argv; - SDL_bool isstack; + bool isstack; - /* Prepare the arguments. */ + // Prepare the arguments. len = (*env)->GetArrayLength(env, array); - argv = SDL_small_alloc(char *, 1 + len + 1, &isstack); /* !!! FIXME: check for NULL */ + argv = SDL_small_alloc(char *, 1 + len + 1, &isstack); // !!! FIXME: check for NULL argc = 0; /* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works. https://github.com/love2d/love-android/issues/24 @@ -841,10 +853,10 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, } argv[argc] = NULL; - /* Run the application. */ + // Run the application. status = SDL_main(argc, argv); - /* Release the arguments. */ + // Release the arguments. for (i = 0; i < argc; ++i) { SDL_free(argv[i]); } @@ -862,59 +874,129 @@ JNIEXPORT int JNICALL SDL_JAVA_INTERFACE(nativeRunMain)(JNIEnv *env, jclass cls, } (*env)->ReleaseStringUTFChars(env, library, library_file); - /* This is a Java thread, it doesn't need to be Detached from the JVM. - * Set to mThreadKey value to NULL not to call pthread_create destructor 'Android_JNI_ThreadDestroyed' */ - Android_JNI_SetEnv(NULL); - - /* Do not issue an exit or the whole application will terminate instead of just the SDL thread */ - /* exit(status); */ + // Do not issue an exit or the whole application will terminate instead of just the SDL thread + // exit(status); return status; } -/* Drop file */ -JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)( - JNIEnv *env, jclass jcls, - jstring filename) +static int FindLifecycleEvent(SDL_AndroidLifecycleEvent event) { - const char *path = (*env)->GetStringUTFChars(env, filename, NULL); - SDL_SendDropFile(NULL, NULL, path); - (*env)->ReleaseStringUTFChars(env, filename, path); - SDL_SendDropComplete(NULL); + for (int index = 0; index < Android_NumLifecycleEvents; ++index) { + if (Android_LifecycleEvents[index] == event) { + return index; + } + } + return -1; } -/* Lock / Unlock Mutex */ -void Android_ActivityMutex_Lock() +static void RemoveLifecycleEvent(int index) { - SDL_LockMutex(Android_ActivityMutex); + if (index < Android_NumLifecycleEvents - 1) { + SDL_memcpy(&Android_LifecycleEvents[index], &Android_LifecycleEvents[index+1], (Android_NumLifecycleEvents - index - 1) * sizeof(Android_LifecycleEvents[index])); + } + --Android_NumLifecycleEvents; } -void Android_ActivityMutex_Unlock() +void Android_SendLifecycleEvent(SDL_AndroidLifecycleEvent event) { - SDL_UnlockMutex(Android_ActivityMutex); + SDL_LockMutex(Android_LifecycleMutex); + { + int index; + bool add_event = true; + + switch (event) { + case SDL_ANDROID_LIFECYCLE_WAKE: + // We don't need more than one wake queued + index = FindLifecycleEvent(SDL_ANDROID_LIFECYCLE_WAKE); + if (index >= 0) { + add_event = false; + } + break; + case SDL_ANDROID_LIFECYCLE_PAUSE: + // If we have a resume queued, just stay in the paused state + index = FindLifecycleEvent(SDL_ANDROID_LIFECYCLE_RESUME); + if (index >= 0) { + RemoveLifecycleEvent(index); + add_event = false; + } + break; + case SDL_ANDROID_LIFECYCLE_RESUME: + // If we have a pause queued, just stay in the resumed state + index = FindLifecycleEvent(SDL_ANDROID_LIFECYCLE_PAUSE); + if (index >= 0) { + RemoveLifecycleEvent(index); + add_event = false; + } + break; + case SDL_ANDROID_LIFECYCLE_LOWMEMORY: + // We don't need more than one low memory event queued + index = FindLifecycleEvent(SDL_ANDROID_LIFECYCLE_LOWMEMORY); + if (index >= 0) { + add_event = false; + } + break; + case SDL_ANDROID_LIFECYCLE_DESTROY: + // Remove all other events, we're done! + while (Android_NumLifecycleEvents > 0) { + RemoveLifecycleEvent(0); + } + break; + default: + SDL_assert(!"Sending unexpected lifecycle event"); + add_event = false; + break; + } + + if (add_event) { + SDL_assert(Android_NumLifecycleEvents < SDL_arraysize(Android_LifecycleEvents)); + Android_LifecycleEvents[Android_NumLifecycleEvents++] = event; + SDL_SignalSemaphore(Android_LifecycleEventSem); + } + } + SDL_UnlockMutex(Android_LifecycleMutex); } -/* Lock the Mutex when the Activity is in its 'Running' state */ -void Android_ActivityMutex_Lock_Running() +bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeoutNS) { - int pauseSignaled = 0; - int resumeSignaled = 0; + bool got_event = false; -retry: + while (!got_event && SDL_WaitSemaphoreTimeoutNS(Android_LifecycleEventSem, timeoutNS)) { + SDL_LockMutex(Android_LifecycleMutex); + { + if (Android_NumLifecycleEvents > 0) { + *event = Android_LifecycleEvents[0]; + RemoveLifecycleEvent(0); + got_event = true; + } + } + SDL_UnlockMutex(Android_LifecycleMutex); + } + return got_event; +} +void Android_LockActivityMutex(void) +{ SDL_LockMutex(Android_ActivityMutex); +} - pauseSignaled = SDL_GetSemaphoreValue(Android_PauseSem); - resumeSignaled = SDL_GetSemaphoreValue(Android_ResumeSem); +void Android_UnlockActivityMutex(void) +{ + SDL_UnlockMutex(Android_ActivityMutex); +} - if (pauseSignaled > resumeSignaled) { - SDL_UnlockMutex(Android_ActivityMutex); - SDL_Delay(50); - goto retry; - } +// Drop file +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDropFile)( + JNIEnv *env, jclass jcls, + jstring filename) +{ + const char *path = (*env)->GetStringUTFChars(env, filename, NULL); + SDL_SendDropFile(NULL, NULL, path); + (*env)->ReleaseStringUTFChars(env, filename, path); + SDL_SendDropComplete(NULL); } -/* Set screen resolution */ +// Set screen resolution JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetScreenResolution)( JNIEnv *env, jclass jcls, jint surfaceWidth, jint surfaceHeight, @@ -927,7 +1009,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetScreenResolution)( SDL_UnlockMutex(Android_ActivityMutex); } -/* Resize */ +// Resize JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeResize)( JNIEnv *env, jclass jcls) { @@ -977,7 +1059,20 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeRotationChanged)( if (Android_Window) { SDL_VideoDisplay *display = SDL_GetVideoDisplay(SDL_GetPrimaryDisplay()); - SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation); + SDL_SendDisplayEvent(display, SDL_EVENT_DISPLAY_ORIENTATION, displayCurrentOrientation, 0); + } + + SDL_UnlockMutex(Android_ActivityMutex); +} + +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeInsetsChanged)( + JNIEnv *env, jclass jcls, + jint left, jint right, jint top, jint bottom) +{ + SDL_LockMutex(Android_ActivityMutex); + + if (Android_Window) { + SDL_SetWindowSafeAreaInsets(Android_Window, left, right, top, bottom); } SDL_UnlockMutex(Android_ActivityMutex); @@ -995,7 +1090,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeAddTouch)( } JNIEXPORT void JNICALL -SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, +SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording, jstring name, jint device_id) { #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES @@ -1003,7 +1098,7 @@ SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_c void *handle = (void *)((size_t)device_id); if (!SDL_FindPhysicalAudioDeviceByHandle(handle)) { const char *utf8name = (*env)->GetStringUTFChars(env, name, NULL); - SDL_AddAudioDevice(is_capture, SDL_strdup(utf8name), NULL, handle); + SDL_AddAudioDevice(recording, SDL_strdup(utf8name), NULL, handle); (*env)->ReleaseStringUTFChars(env, name, utf8name); } } @@ -1011,102 +1106,117 @@ SDL_JAVA_AUDIO_INTERFACE(addAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_c } JNIEXPORT void JNICALL -SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean is_capture, +SDL_JAVA_AUDIO_INTERFACE(removeAudioDevice)(JNIEnv *env, jclass jcls, jboolean recording, jint device_id) { #if ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES if (SDL_GetCurrentAudioDriver() != NULL) { - SDL_Log("Removing device with handle %d, capture %d", device_id, is_capture); + SDL_Log("Removing device with handle %d, recording %d", device_id, recording); SDL_AudioDeviceDisconnected(SDL_FindPhysicalAudioDeviceByHandle((void *)((size_t)device_id))); } #endif } -/* Paddown */ -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)( +// Paddown +JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)( JNIEnv *env, jclass jcls, jint device_id, jint keycode) { +#ifdef SDL_JOYSTICK_ANDROID return Android_OnPadDown(device_id, keycode); +#else + return false; +#endif // SDL_JOYSTICK_ANDROID } -/* Padup */ -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)( +// Padup +JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)( JNIEnv *env, jclass jcls, jint device_id, jint keycode) { +#ifdef SDL_JOYSTICK_ANDROID return Android_OnPadUp(device_id, keycode); +#else + return false; +#endif // SDL_JOYSTICK_ANDROID } -/* Joy */ +// Joy JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)( JNIEnv *env, jclass jcls, jint device_id, jint axis, jfloat value) { +#ifdef SDL_JOYSTICK_ANDROID Android_OnJoy(device_id, axis, value); +#endif // SDL_JOYSTICK_ANDROID } -/* POV Hat */ +// POV Hat JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat)( JNIEnv *env, jclass jcls, jint device_id, jint hat_id, jint x, jint y) { +#ifdef SDL_JOYSTICK_ANDROID Android_OnHat(device_id, hat_id, x, y); +#endif // SDL_JOYSTICK_ANDROID } -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddJoystick)( JNIEnv *env, jclass jcls, jint device_id, jstring device_name, jstring device_desc, jint vendor_id, jint product_id, - jint button_mask, jint naxes, jint axis_mask, jint nhats) + jint button_mask, jint naxes, jint axis_mask, jint nhats, jboolean can_rumble) { - int retval; +#ifdef SDL_JOYSTICK_ANDROID const char *name = (*env)->GetStringUTFChars(env, device_name, NULL); const char *desc = (*env)->GetStringUTFChars(env, device_desc, NULL); - retval = Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats); + Android_AddJoystick(device_id, name, desc, vendor_id, product_id, button_mask, naxes, axis_mask, nhats, can_rumble); (*env)->ReleaseStringUTFChars(env, device_name, name); (*env)->ReleaseStringUTFChars(env, device_desc, desc); - - return retval; +#endif // SDL_JOYSTICK_ANDROID } -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveJoystick)( JNIEnv *env, jclass jcls, jint device_id) { - return Android_RemoveJoystick(device_id); +#ifdef SDL_JOYSTICK_ANDROID + Android_RemoveJoystick(device_id); +#endif // SDL_JOYSTICK_ANDROID } -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeAddHaptic)( JNIEnv *env, jclass jcls, jint device_id, jstring device_name) { - int retval; +#ifdef SDL_HAPTIC_ANDROID const char *name = (*env)->GetStringUTFChars(env, device_name, NULL); - retval = Android_AddHaptic(device_id, name); + Android_AddHaptic(device_id, name); (*env)->ReleaseStringUTFChars(env, device_name, name); - - return retval; +#endif // SDL_HAPTIC_ANDROID } -JNIEXPORT jint JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)( +JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)( JNIEnv *env, jclass jcls, jint device_id) { - return Android_RemoveHaptic(device_id); +#ifdef SDL_HAPTIC_ANDROID + Android_RemoveHaptic(device_id); +#endif } -/* Called from surfaceCreated() */ +// Called from surfaceCreated() JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(JNIEnv *env, jclass jcls) { SDL_LockMutex(Android_ActivityMutex); if (Android_Window) { - SDL_WindowData *data = Android_Window->driverdata; + SDL_WindowData *data = Android_Window->internal; data->native_window = Android_JNI_GetNativeWindow(); + SDL_SetPointerProperty(SDL_GetWindowProperties(Android_Window), SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, data->native_window); if (data->native_window == NULL) { SDL_SetError("Could not fetch native window from UI thread"); } @@ -1115,29 +1225,30 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceCreated)(JNIEnv *env, j SDL_UnlockMutex(Android_ActivityMutex); } -/* Called from surfaceChanged() */ +// Called from surfaceChanged() JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceChanged)(JNIEnv *env, jclass jcls) { SDL_LockMutex(Android_ActivityMutex); #ifdef SDL_VIDEO_OPENGL_EGL - if (Android_Window) { + if (Android_Window && (Android_Window->flags & SDL_WINDOW_OPENGL)) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_WindowData *data = Android_Window->driverdata; + SDL_WindowData *data = Android_Window->internal; - /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */ + // If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here if (data->egl_surface == EGL_NO_SURFACE) { data->egl_surface = SDL_EGL_CreateSurface(_this, Android_Window, (NativeWindowType)data->native_window); + SDL_SetPointerProperty(SDL_GetWindowProperties(Android_Window), SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, data->egl_surface); } - /* GL Context handling is done in the event loop because this function is run from the Java thread */ + // GL Context handling is done in the event loop because this function is run from the Java thread } #endif SDL_UnlockMutex(Android_ActivityMutex); } -/* Called from surfaceDestroyed() */ +// Called from surfaceDestroyed() JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, jclass jcls) { int nb_attempt = 50; @@ -1147,10 +1258,10 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, SDL_LockMutex(Android_ActivityMutex); if (Android_Window) { - SDL_WindowData *data = Android_Window->driverdata; + SDL_WindowData *data = Android_Window->internal; - /* Wait for Main thread being paused and context un-activated to release 'egl_surface' */ - if (!data->backup_done) { + // Wait for Main thread being paused and context un-activated to release 'egl_surface' + if ((Android_Window->flags & SDL_WINDOW_OPENGL) && !data->backup_done) { nb_attempt -= 1; if (nb_attempt == 0) { SDL_SetError("Try to release egl_surface with context probably still active"); @@ -1173,13 +1284,13 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeSurfaceDestroyed)(JNIEnv *env, data->native_window = NULL; } - /* GL Context handling is done in the event loop because this function is run from the Java thread */ + // GL Context handling is done in the event loop because this function is run from the Java thread } SDL_UnlockMutex(Android_ActivityMutex); } -/* Keydown */ +// Keydown JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)( JNIEnv *env, jclass jcls, jint keycode) @@ -1193,7 +1304,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyDown)( SDL_UnlockMutex(Android_ActivityMutex); } -/* Keyup */ +// Keyup JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)( JNIEnv *env, jclass jcls, jint keycode) @@ -1207,26 +1318,26 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyUp)( SDL_UnlockMutex(Android_ActivityMutex); } -/* Virtual keyboard return key might stop text input */ +// Virtual keyboard return key might stop text input JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(onNativeSoftReturnKey)( JNIEnv *env, jclass jcls) { - if (SDL_GetHintBoolean(SDL_HINT_RETURN_KEY_HIDES_IME, SDL_FALSE)) { - SDL_StopTextInput(); + if (SDL_GetHintBoolean(SDL_HINT_RETURN_KEY_HIDES_IME, false)) { + SDL_StopTextInput(Android_Window); return JNI_TRUE; } return JNI_FALSE; } -/* Keyboard Focus Lost */ +// Keyboard Focus Lost JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)( JNIEnv *env, jclass jcls) { - /* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */ - SDL_StopTextInput(); + // Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget + SDL_StopTextInput(Android_Window); } -/* Touch */ +// Touch JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)( JNIEnv *env, jclass jcls, jint touch_device_id_in, jint pointer_finger_id_in, @@ -1239,7 +1350,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeTouch)( SDL_UnlockMutex(Android_ActivityMutex); } -/* Mouse */ +// Mouse JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)( JNIEnv *env, jclass jcls, jint button, jint action, jfloat x, jfloat y, jboolean relative) @@ -1251,7 +1362,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeMouse)( SDL_UnlockMutex(Android_ActivityMutex); } -/* Accelerometer */ +// Accelerometer JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)( JNIEnv *env, jclass jcls, jfloat x, jfloat y, jfloat z) @@ -1259,21 +1370,22 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeAccel)( fLastAccelerometer[0] = x; fLastAccelerometer[1] = y; fLastAccelerometer[2] = z; - bHasNewData = SDL_TRUE; + bHasNewData = true; } -/* Clipboard */ +// Clipboard JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeClipboardChanged)( JNIEnv *env, jclass jcls) { - SDL_SendClipboardUpdate(); + // TODO: compute new mime types + SDL_SendClipboardUpdate(false, NULL, 0); } -/* Low memory */ +// Low memory JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeLowMemory)( JNIEnv *env, jclass cls) { - SDL_SendAppEvent(SDL_EVENT_LOW_MEMORY); + Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_LOWMEMORY); } /* Locale @@ -1284,34 +1396,21 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeLocaleChanged)( SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED); } -/* Dark mode */ +// Dark mode JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeDarkModeChanged)( JNIEnv *env, jclass cls, jboolean enabled) { Android_SetDarkMode(enabled); } -/* Send Quit event to "SDLThread" thread */ +// Send Quit event to "SDLThread" thread JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSendQuit)( JNIEnv *env, jclass cls) { - /* Discard previous events. The user should have handled state storage - * in SDL_EVENT_WILL_ENTER_BACKGROUND. After nativeSendQuit() is called, no - * events other than SDL_EVENT_QUIT and SDL_EVENT_TERMINATING should fire */ - SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); - /* Inject a SDL_EVENT_QUIT event */ - SDL_SendQuit(); - SDL_SendAppEvent(SDL_EVENT_TERMINATING); - /* Robustness: clear any pending Pause */ - while (SDL_TryWaitSemaphore(Android_PauseSem) == 0) { - /* empty */ - } - /* Resume the event loop so that the app can catch SDL_EVENT_QUIT which - * should now be the top event in the event queue. */ - SDL_PostSemaphore(Android_ResumeSem); + Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_DESTROY); } -/* Activity ends */ +// Activity ends JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeQuit)( JNIEnv *env, jclass cls) { @@ -1322,16 +1421,18 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeQuit)( Android_ActivityMutex = NULL; } - if (Android_PauseSem) { - SDL_DestroySemaphore(Android_PauseSem); - Android_PauseSem = NULL; + if (Android_LifecycleMutex) { + SDL_DestroyMutex(Android_LifecycleMutex); + Android_LifecycleMutex = NULL; } - if (Android_ResumeSem) { - SDL_DestroySemaphore(Android_ResumeSem); - Android_ResumeSem = NULL; + if (Android_LifecycleEventSem) { + SDL_DestroySemaphore(Android_LifecycleEventSem); + Android_LifecycleEventSem = NULL; } + Android_NumLifecycleEvents = 0; + Internal_Android_Destroy_AssetManager(); str = SDL_GetError(); @@ -1342,28 +1443,22 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeQuit)( } } -/* Pause */ +// Pause JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePause)( JNIEnv *env, jclass cls) { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()"); - /* Signal the pause semaphore so the event loop knows to pause and (optionally) block itself. - * Sometimes 2 pauses can be queued (eg pause/resume/pause), so it's always increased. */ - SDL_PostSemaphore(Android_PauseSem); + Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_PAUSE); } -/* Resume */ +// Resume JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeResume)( JNIEnv *env, jclass cls) { __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()"); - /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context - * We can't restore the GL Context here because it needs to be done on the SDL main thread - * and this function will be called from the Java thread instead. - */ - SDL_PostSemaphore(Android_ResumeSem); + Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_RESUME); } JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeFocusChanged)( @@ -1430,7 +1525,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativeSetenv)( const char *utfname = (*env)->GetStringUTFChars(env, name, NULL); const char *utfvalue = (*env)->GetStringUTFChars(env, value, NULL); - SDL_setenv(utfname, utfvalue, 1); + // This is only called at startup, to initialize the environment + // Note that we call setenv() directly to avoid affecting SDL environments + setenv(utfname, utfvalue, 1); // This should NOT be SDL_setenv() (*env)->ReleaseStringUTFChars(env, name, utfname); (*env)->ReleaseStringUTFChars(env, value, utfvalue); @@ -1458,16 +1555,16 @@ static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func) return refholder; } -static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env) +static bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env) { const int capacity = 16; if ((*env)->PushLocalFrame(env, capacity) < 0) { SDL_SetError("Failed to allocate enough JVM local references"); - return SDL_FALSE; + return false; } SDL_AtomicIncRef(&s_active); refholder->m_env = env; - return SDL_TRUE; + return true; } static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder) @@ -1506,7 +1603,7 @@ void Android_JNI_SetActivityTitle(const char *title) (*env)->DeleteLocalRef(env, jtitle); } -void Android_JNI_SetWindowStyle(SDL_bool fullscreen) +void Android_JNI_SetWindowStyle(bool fullscreen) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticVoidMethod(env, mActivityClass, midSetWindowStyle, fullscreen ? 1 : 0); @@ -1521,49 +1618,53 @@ void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint) (*env)->DeleteLocalRef(env, jhint); } -void Android_JNI_MinizeWindow() +SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void) +{ + return displayNaturalOrientation; +} + +SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void) +{ + return displayCurrentOrientation; +} + +void Android_JNI_MinizeWindow(void) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticVoidMethod(env, mActivityClass, midMinimizeWindow); } -SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss() +bool Android_JNI_ShouldMinimizeOnFocusLoss(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midShouldMinimizeOnFocusLoss); } -SDL_bool Android_JNI_GetAccelerometerValues(float values[3]) +bool Android_JNI_GetAccelerometerValues(float values[3]) { - SDL_bool retval = SDL_FALSE; + bool result = false; if (bHasNewData) { int i; for (i = 0; i < 3; ++i) { values[i] = fLastAccelerometer[i]; } - bHasNewData = SDL_FALSE; - retval = SDL_TRUE; + bHasNewData = false; + result = true; } - return retval; + return result; } /* * Audio support */ -static int audioBufferFormat = 0; -static jobject audioBuffer = NULL; -static void *audioBufferPinned = NULL; -static int captureBufferFormat = 0; -static jobject captureBuffer = NULL; - -void Android_StartAudioHotplug(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +void Android_StartAudioHotplug(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { JNIEnv *env = Android_JNI_GetEnv(); // this will fire the callback for each existing device right away (which will eventually SDL_AddAudioDevice), and again later when things change. (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midRegisterAudioDeviceCallback); - *default_output = *default_capture = NULL; // !!! FIXME: how do you decide the default device id? + *default_playback = *default_recording = NULL; // !!! FIXME: how do you decide the default device id? } void Android_StopAudioHotplug(void) @@ -1572,308 +1673,32 @@ void Android_StopAudioHotplug(void) (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midUnregisterAudioDeviceCallback); } -int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device) +static void Android_JNI_AudioSetThreadPriority(int recording, int device_id) { - const SDL_bool iscapture = device->iscapture; - SDL_AudioSpec *spec = &device->spec; - const int device_id = (int) ((size_t) device->handle); - int audioformat; - jobject jbufobj = NULL; - jobject result; - int *resultElements; - jboolean isCopy; - JNIEnv *env = Android_JNI_GetEnv(); - - switch (spec->format) { - case SDL_AUDIO_U8: - audioformat = ENCODING_PCM_8BIT; - break; - case SDL_AUDIO_S16: - audioformat = ENCODING_PCM_16BIT; - break; - case SDL_AUDIO_F32: - audioformat = ENCODING_PCM_FLOAT; - break; - default: - return SDL_SetError("Unsupported audio format: 0x%x", spec->format); - } - - if (iscapture) { - __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture"); - result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midCaptureOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id); - } else { - __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output"); - result = (*env)->CallStaticObjectMethod(env, mAudioManagerClass, midAudioOpen, spec->freq, audioformat, spec->channels, device->sample_frames, device_id); - } - if (!result) { - /* Error during audio initialization, error printed from Java */ - return SDL_SetError("Java-side initialization failed"); - } - - if ((*env)->GetArrayLength(env, (jintArray)result) != 4) { - return SDL_SetError("Unexpected results from Java, expected 4, got %d", (*env)->GetArrayLength(env, (jintArray)result)); - } - isCopy = JNI_FALSE; - resultElements = (*env)->GetIntArrayElements(env, (jintArray)result, &isCopy); - spec->freq = resultElements[0]; - audioformat = resultElements[1]; - switch (audioformat) { - case ENCODING_PCM_8BIT: - spec->format = SDL_AUDIO_U8; - break; - case ENCODING_PCM_16BIT: - spec->format = SDL_AUDIO_S16; - break; - case ENCODING_PCM_FLOAT: - spec->format = SDL_AUDIO_F32; - break; - default: - return SDL_SetError("Unexpected audio format from Java: %d", audioformat); - } - spec->channels = resultElements[2]; - device->sample_frames = resultElements[3]; - (*env)->ReleaseIntArrayElements(env, (jintArray)result, resultElements, JNI_ABORT); - (*env)->DeleteLocalRef(env, result); - - /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on - * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */ - switch (audioformat) { - case ENCODING_PCM_8BIT: - { - jbyteArray audioBufferLocal = (*env)->NewByteArray(env, device->sample_frames * spec->channels); - if (audioBufferLocal) { - jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal); - (*env)->DeleteLocalRef(env, audioBufferLocal); - } - } break; - case ENCODING_PCM_16BIT: - { - jshortArray audioBufferLocal = (*env)->NewShortArray(env, device->sample_frames * spec->channels); - if (audioBufferLocal) { - jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal); - (*env)->DeleteLocalRef(env, audioBufferLocal); - } - } break; - case ENCODING_PCM_FLOAT: - { - jfloatArray audioBufferLocal = (*env)->NewFloatArray(env, device->sample_frames * spec->channels); - if (audioBufferLocal) { - jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal); - (*env)->DeleteLocalRef(env, audioBufferLocal); - } - } break; - default: - return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat); - } - - if (!jbufobj) { - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer"); - return SDL_OutOfMemory(); - } - - if (iscapture) { - captureBufferFormat = audioformat; - captureBuffer = jbufobj; - } else { - audioBufferFormat = audioformat; - audioBuffer = jbufobj; - } - - if (!iscapture) { - isCopy = JNI_FALSE; - - switch (audioformat) { - case ENCODING_PCM_8BIT: - audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy); - break; - case ENCODING_PCM_16BIT: - audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy); - break; - case ENCODING_PCM_FLOAT: - audioBufferPinned = (*env)->GetFloatArrayElements(env, (jfloatArray)audioBuffer, &isCopy); - break; - default: - return SDL_SetError("Unexpected audio format from Java: %d\n", audioformat); - } - } - return 0; -} - -SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void) -{ - return displayNaturalOrientation; -} - -SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void) -{ - return displayCurrentOrientation; -} - -void *Android_JNI_GetAudioBuffer(void) -{ - return audioBufferPinned; -} - -void Android_JNI_WriteAudioBuffer(void) -{ - JNIEnv *env = Android_JNI_GetEnv(); - - switch (audioBufferFormat) { - case ENCODING_PCM_8BIT: - (*env)->ReleaseByteArrayElements(env, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT); - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer); - break; - case ENCODING_PCM_16BIT: - (*env)->ReleaseShortArrayElements(env, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT); - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer); - break; - case ENCODING_PCM_FLOAT: - (*env)->ReleaseFloatArrayElements(env, (jfloatArray)audioBuffer, (jfloat *)audioBufferPinned, JNI_COMMIT); - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioWriteFloatBuffer, (jfloatArray)audioBuffer); - break; - default: - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled audio buffer format"); - break; - } - - /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */ -} - -int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen) -{ - JNIEnv *env = Android_JNI_GetEnv(); - jboolean isCopy = JNI_FALSE; - jint br = -1; - - switch (captureBufferFormat) { - case ENCODING_PCM_8BIT: - SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen); - br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE); - if (br > 0) { - jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy); - SDL_memcpy(buffer, ptr, br); - (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, ptr, JNI_ABORT); - } - break; - case ENCODING_PCM_16BIT: - SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / sizeof(Sint16))); - br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE); - if (br > 0) { - jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy); - br *= sizeof(Sint16); - SDL_memcpy(buffer, ptr, br); - (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, ptr, JNI_ABORT); - } - break; - case ENCODING_PCM_FLOAT: - SDL_assert((*env)->GetArrayLength(env, (jfloatArray)captureBuffer) == (buflen / sizeof(float))); - br = (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_TRUE); - if (br > 0) { - jfloat *ptr = (*env)->GetFloatArrayElements(env, (jfloatArray)captureBuffer, &isCopy); - br *= sizeof(float); - SDL_memcpy(buffer, ptr, br); - (*env)->ReleaseFloatArrayElements(env, (jfloatArray)captureBuffer, ptr, JNI_ABORT); - } - break; - default: - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: unhandled capture buffer format"); - break; - } - return br; -} - -void Android_JNI_FlushCapturedAudio(void) -{ - JNIEnv *env = Android_JNI_GetEnv(); -#if 0 /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */ - switch (captureBufferFormat) { - case ENCODING_PCM_8BIT: - { - const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer); - while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } - } - break; - case ENCODING_PCM_16BIT: - { - const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer); - while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } - } - break; - case ENCODING_PCM_FLOAT: - { - const jint len = (*env)->GetArrayLength(env, (jfloatArray)captureBuffer); - while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE) == len) { /* spin */ } - } - break; - default: - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format"); - break; - } -#else - switch (captureBufferFormat) { - case ENCODING_PCM_8BIT: - (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE); - break; - case ENCODING_PCM_16BIT: - (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE); - break; - case ENCODING_PCM_FLOAT: - (*env)->CallStaticIntMethod(env, mAudioManagerClass, midCaptureReadFloatBuffer, (jfloatArray)captureBuffer, JNI_FALSE); - break; - default: - __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: flushing unhandled capture buffer format"); - break; - } -#endif -} - -void Android_JNI_CloseAudioDevice(const int iscapture) -{ - JNIEnv *env = Android_JNI_GetEnv(); - - if (iscapture) { - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midCaptureClose); - if (captureBuffer) { - (*env)->DeleteGlobalRef(env, captureBuffer); - captureBuffer = NULL; - } - } else { - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioClose); - if (audioBuffer) { - (*env)->DeleteGlobalRef(env, audioBuffer); - audioBuffer = NULL; - audioBufferPinned = NULL; - } - } -} - -static void Android_JNI_AudioSetThreadPriority(int iscapture, int device_id) -{ - JNIEnv *env = Android_JNI_GetEnv(); - (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioSetThreadPriority, iscapture, device_id); + (*env)->CallStaticVoidMethod(env, mAudioManagerClass, midAudioSetThreadPriority, recording, device_id); } void Android_AudioThreadInit(SDL_AudioDevice *device) { - Android_JNI_AudioSetThreadPriority((int) device->iscapture, (int)device->instance_id); + Android_JNI_AudioSetThreadPriority((int) device->recording, (int)device->instance_id); } -/* Test for an exception and call SDL_SetError with its detail if one occurs */ -/* If the parameter silent is truthy then SDL_SetError() will not be called. */ -static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent) +// Test for an exception and call SDL_SetError with its detail if one occurs +// If the parameter silent is truthy then SDL_SetError() will not be called. +static bool Android_JNI_ExceptionOccurred(bool silent) { JNIEnv *env = Android_JNI_GetEnv(); jthrowable exception; - /* Detect mismatch LocalReferenceHolder_Init/Cleanup */ - SDL_assert(SDL_AtomicGet(&s_active) > 0); + // Detect mismatch LocalReferenceHolder_Init/Cleanup + SDL_assert(SDL_GetAtomicInt(&s_active) > 0); exception = (*env)->ExceptionOccurred(env); if (exception != NULL) { jmethodID mid; - /* Until this happens most JNI operations have undefined behaviour */ + // Until this happens most JNI operations have undefined behaviour (*env)->ExceptionClear(env); if (!silent) { @@ -1901,13 +1726,13 @@ static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent) (*env)->ReleaseStringUTFChars(env, exceptionName, exceptionNameUTF8); } - return SDL_TRUE; + return true; } - return SDL_FALSE; + return false; } -static void Internal_Android_Create_AssetManager() +static void Internal_Android_Create_AssetManager(void) { struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); @@ -1921,10 +1746,10 @@ static void Internal_Android_Create_AssetManager() return; } - /* context = SDLActivity.getContext(); */ + // context = SDLActivity.getContext(); context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); - /* javaAssetManager = context.getAssets(); */ + // javaAssetManager = context.getAssets(); mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), "getAssets", "()Landroid/content/res/AssetManager;"); javaAssetManager = (*env)->CallObjectMethod(env, context, mid); @@ -1940,13 +1765,13 @@ static void Internal_Android_Create_AssetManager() if (!asset_manager) { (*env)->DeleteGlobalRef(env, javaAssetManagerRef); - Android_JNI_ExceptionOccurred(SDL_TRUE); + Android_JNI_ExceptionOccurred(true); } LocalReferenceHolder_Cleanup(&refs); } -static void Internal_Android_Destroy_AssetManager() +static void Internal_Android_Destroy_AssetManager(void) { JNIEnv *env = Android_JNI_GetEnv(); @@ -1956,7 +1781,7 @@ static void Internal_Android_Destroy_AssetManager() } } -int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode) +bool Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode) { SDL_assert(puserdata != NULL); @@ -1977,7 +1802,7 @@ int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mod } *puserdata = (void *)asset; - return 0; + return true; } size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status) @@ -1992,7 +1817,8 @@ size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOSta size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status) { - return SDL_SetError("Cannot write to Android package filesystem"); + SDL_SetError("Cannot write to Android package filesystem"); + return 0; } Sint64 Android_JNI_FileSize(void *userdata) @@ -2000,24 +1826,24 @@ Sint64 Android_JNI_FileSize(void *userdata) return (Sint64) AAsset_getLength64((AAsset *)userdata); } -Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, int whence) +Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, SDL_IOWhence whence) { - return (Sint64) AAsset_seek64((AAsset *)userdata, offset, whence); + return (Sint64) AAsset_seek64((AAsset *)userdata, offset, (int)whence); } -int Android_JNI_FileClose(void *userdata) +bool Android_JNI_FileClose(void *userdata) { AAsset_close((AAsset *)userdata); - return 0; + return true; } -int Android_JNI_SetClipboardText(const char *text) +bool Android_JNI_SetClipboardText(const char *text) { JNIEnv *env = Android_JNI_GetEnv(); jstring string = (*env)->NewStringUTF(env, text); (*env)->CallStaticVoidMethod(env, mActivityClass, midClipboardSetText, string); (*env)->DeleteLocalRef(env, string); - return 0; + return true; } char *Android_JNI_GetClipboardText(void) @@ -2039,7 +1865,7 @@ char *Android_JNI_GetClipboardText(void) return (!text) ? SDL_strdup("") : text; } -SDL_bool Android_JNI_HasClipboardText(void) +bool Android_JNI_HasClipboardText(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midClipboardHasText); @@ -2068,7 +1894,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco return -1; } - /* context = SDLActivity.getContext(); */ + // context = SDLActivity.getContext(); context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED"); @@ -2089,7 +1915,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I"); - /* Watch out for C89 scoping rules because of the macro */ + // Watch out for C89 scoping rules because of the macro #define GET_INT_EXTRA(var, key) \ int var; \ iname = (*env)->NewStringUTF(env, key); \ @@ -2098,7 +1924,7 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z"); - /* Watch out for C89 scoping rules because of the macro */ + // Watch out for C89 scoping rules because of the macro #define GET_BOOL_EXTRA(var, key) \ int var; \ bname = (*env)->NewStringUTF(env, key); \ @@ -2106,49 +1932,49 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco (*env)->DeleteLocalRef(env, bname); if (plugged) { - /* Watch out for C89 scoping rules because of the macro */ - GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */ + // Watch out for C89 scoping rules because of the macro + GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5) if (plug == -1) { LocalReferenceHolder_Cleanup(&refs); return -1; } - /* 1 == BatteryManager.BATTERY_PLUGGED_AC */ - /* 2 == BatteryManager.BATTERY_PLUGGED_USB */ + // 1 == BatteryManager.BATTERY_PLUGGED_AC + // 2 == BatteryManager.BATTERY_PLUGGED_USB *plugged = (0 < plug) ? 1 : 0; } if (charged) { - /* Watch out for C89 scoping rules because of the macro */ - GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */ + // Watch out for C89 scoping rules because of the macro + GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5) if (status == -1) { LocalReferenceHolder_Cleanup(&refs); return -1; } - /* 5 == BatteryManager.BATTERY_STATUS_FULL */ + // 5 == BatteryManager.BATTERY_STATUS_FULL *charged = (status == 5) ? 1 : 0; } if (battery) { - GET_BOOL_EXTRA(present, "present") /* == BatteryManager.EXTRA_PRESENT (API 5) */ + GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5) *battery = present ? 1 : 0; } if (seconds) { - *seconds = -1; /* not possible */ + *seconds = -1; // not possible } if (percent) { int level; int scale; - /* Watch out for C89 scoping rules because of the macro */ + // Watch out for C89 scoping rules because of the macro { - GET_INT_EXTRA(level_temp, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */ + GET_INT_EXTRA(level_temp, "level") // == BatteryManager.EXTRA_LEVEL (API 5) level = level_temp; } - /* Watch out for C89 scoping rules because of the macro */ + // Watch out for C89 scoping rules because of the macro { - GET_INT_EXTRA(scale_temp, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */ + GET_INT_EXTRA(scale_temp, "scale") // == BatteryManager.EXTRA_SCALE (API 5) scale = scale_temp; } @@ -2165,8 +1991,8 @@ int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seco return 0; } -/* Add all touch devices */ -void Android_JNI_InitTouch() +// Add all touch devices +void Android_JNI_InitTouch(void) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticVoidMethod(env, mActivityClass, midInitTouch); @@ -2190,41 +2016,46 @@ void Android_JNI_HapticRun(int device_id, float intensity, int length) (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRun, device_id, intensity, length); } +void Android_JNI_HapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) +{ + JNIEnv *env = Android_JNI_GetEnv(); + (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticRumble, device_id, low_frequency_intensity, high_frequency_intensity, length); +} + void Android_JNI_HapticStop(int device_id) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticVoidMethod(env, mControllerManagerClass, midHapticStop, device_id); } -/* See SDLActivity.java for constants. */ +// See SDLActivity.java for constants. #define COMMAND_SET_KEEP_SCREEN_ON 5 -int SDL_AndroidSendMessage(Uint32 command, int param) +bool SDL_SendAndroidMessage(Uint32 command, int param) { - if (command >= 0x8000) { - return Android_JNI_SendMessage(command, param); + if (command < 0x8000) { + return SDL_InvalidParamError("command"); } - return -1; + return Android_JNI_SendMessage(command, param); } -/* sends message to be handled on the UI event dispatch thread */ -int Android_JNI_SendMessage(int command, int param) +// sends message to be handled on the UI event dispatch thread +bool Android_JNI_SendMessage(int command, int param) { JNIEnv *env = Android_JNI_GetEnv(); - jboolean success; - success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midSendMessage, command, param); - return success ? 0 : -1; + return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSendMessage, command, param); } -int Android_JNI_SuspendScreenSaver(SDL_bool suspend) +bool Android_JNI_SuspendScreenSaver(bool suspend) { - return Android_JNI_SendMessage(COMMAND_SET_KEEP_SCREEN_ON, (suspend == SDL_FALSE) ? 0 : 1); + return Android_JNI_SendMessage(COMMAND_SET_KEEP_SCREEN_ON, (suspend == false) ? 0 : 1); } -void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect) +void Android_JNI_ShowScreenKeyboard(int input_type, SDL_Rect *inputRect) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowTextInput, + input_type, inputRect->x, inputRect->y, inputRect->w, @@ -2233,12 +2064,12 @@ void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect) void Android_JNI_HideScreenKeyboard(void) { - /* has to match Activity constant */ + // has to match Activity constant const int COMMAND_TEXTEDIT_HIDE = 3; Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0); } -SDL_bool Android_JNI_IsScreenKeyboardShown(void) +bool Android_JNI_IsScreenKeyboardShown(void) { JNIEnv *env = Android_JNI_GetEnv(); jboolean is_shown = 0; @@ -2246,7 +2077,7 @@ SDL_bool Android_JNI_IsScreenKeyboardShown(void) return is_shown; } -int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) +bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) { JNIEnv *env; jclass clazz; @@ -2264,7 +2095,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu env = Android_JNI_GetEnv(); - /* convert parameters */ + // convert parameters clazz = (*env)->FindClass(env, "java/lang/String"); @@ -2294,8 +2125,8 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu } if (messageboxdata->colorScheme) { - colors = (*env)->NewIntArray(env, SDL_MESSAGEBOX_COLOR_MAX); - for (i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; ++i) { + colors = (*env)->NewIntArray(env, SDL_MESSAGEBOX_COLOR_COUNT); + for (i = 0; i < SDL_MESSAGEBOX_COLOR_COUNT; ++i) { temp = (0xFFU << 24) | (messageboxdata->colorScheme->colors[i].r << 16) | (messageboxdata->colorScheme->colors[i].g << 8) | @@ -2308,7 +2139,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu (*env)->DeleteLocalRef(env, clazz); - /* context = SDLActivity.getContext(); */ + // context = SDLActivity.getContext(); context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); clazz = (*env)->GetObjectClass(env, context); @@ -2327,7 +2158,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu (*env)->DeleteLocalRef(env, context); (*env)->DeleteLocalRef(env, clazz); - /* delete parameters */ + // delete parameters (*env)->DeleteLocalRef(env, title); (*env)->DeleteLocalRef(env, message); @@ -2336,7 +2167,7 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu (*env)->DeleteLocalRef(env, button_texts); (*env)->DeleteLocalRef(env, colors); - return 0; + return true; } /* @@ -2346,21 +2177,21 @@ int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *bu ////////////////////////////////////////////////////////////////////////////// */ -void *SDL_AndroidGetJNIEnv(void) +void *SDL_GetAndroidJNIEnv(void) { return Android_JNI_GetEnv(); } -void *SDL_AndroidGetActivity(void) +void *SDL_GetAndroidActivity(void) { - /* See SDL_system.h for caveats on using this function. */ + // See SDL_system.h for caveats on using this function. JNIEnv *env = Android_JNI_GetEnv(); if (!env) { return NULL; } - /* return SDLActivity.getContext(); */ + // return SDLActivity.getContext(); return (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); } @@ -2376,37 +2207,37 @@ int SDL_GetAndroidSDKVersion(void) return sdk_version; } -SDL_bool SDL_IsAndroidTablet(void) +bool SDL_IsAndroidTablet(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsTablet); } -SDL_bool SDL_IsAndroidTV(void) +bool SDL_IsAndroidTV(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsAndroidTV); } -SDL_bool SDL_IsChromebook(void) +bool SDL_IsChromebook(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsChromebook); } -SDL_bool SDL_IsDeXMode(void) +bool SDL_IsDeXMode(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midIsDeXMode); } -void SDL_AndroidBackButton(void) +void SDL_SendAndroidBackButton(void) { JNIEnv *env = Android_JNI_GetEnv(); (*env)->CallStaticVoidMethod(env, mActivityClass, midManualBackButton); } -const char *SDL_AndroidGetInternalStoragePath(void) +const char *SDL_GetAndroidInternalStoragePath(void) { static char *s_AndroidInternalFilesPath = NULL; @@ -2424,7 +2255,7 @@ const char *SDL_AndroidGetInternalStoragePath(void) return NULL; } - /* context = SDLActivity.getContext(); */ + // context = SDLActivity.getContext(); context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); if (!context) { SDL_SetError("Couldn't get Android context!"); @@ -2432,7 +2263,7 @@ const char *SDL_AndroidGetInternalStoragePath(void) return NULL; } - /* fileObj = context.getFilesDir(); */ + // fileObj = context.getFilesDir(); mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), "getFilesDir", "()Ljava/io/File;"); fileObject = (*env)->CallObjectMethod(env, context, mid); @@ -2442,11 +2273,11 @@ const char *SDL_AndroidGetInternalStoragePath(void) return NULL; } - /* path = fileObject.getCanonicalPath(); */ + // path = fileObject.getCanonicalPath(); mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject), "getCanonicalPath", "()Ljava/lang/String;"); pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid); - if (Android_JNI_ExceptionOccurred(SDL_FALSE)) { + if (Android_JNI_ExceptionOccurred(false)) { LocalReferenceHolder_Cleanup(&refs); return NULL; } @@ -2460,22 +2291,19 @@ const char *SDL_AndroidGetInternalStoragePath(void) return s_AndroidInternalFilesPath; } -int SDL_AndroidGetExternalStorageState(Uint32 *state) +Uint32 SDL_GetAndroidExternalStorageState(void) { struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); jmethodID mid; jclass cls; jstring stateString; const char *state_string; - int stateFlags; + Uint32 stateFlags; JNIEnv *env = Android_JNI_GetEnv(); if (!LocalReferenceHolder_Init(&refs, env)) { LocalReferenceHolder_Cleanup(&refs); - if (state) { - *state = 0; - } - return -1; + return 0; } cls = (*env)->FindClass(env, "android/os/Environment"); @@ -2485,7 +2313,7 @@ int SDL_AndroidGetExternalStorageState(Uint32 *state) state_string = (*env)->GetStringUTFChars(env, stateString, NULL); - /* Print an info message so people debugging know the storage state */ + // Print an info message so people debugging know the storage state __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state_string); if (SDL_strcmp(state_string, "mounted") == 0) { @@ -2499,13 +2327,11 @@ int SDL_AndroidGetExternalStorageState(Uint32 *state) (*env)->ReleaseStringUTFChars(env, stateString, state_string); LocalReferenceHolder_Cleanup(&refs); - if (state) { - *state = stateFlags; - } - return 0; + + return stateFlags; } -const char *SDL_AndroidGetExternalStoragePath(void) +const char *SDL_GetAndroidExternalStoragePath(void) { static char *s_AndroidExternalFilesPath = NULL; @@ -2523,10 +2349,10 @@ const char *SDL_AndroidGetExternalStoragePath(void) return NULL; } - /* context = SDLActivity.getContext(); */ + // context = SDLActivity.getContext(); context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); - /* fileObj = context.getExternalFilesDir(); */ + // fileObj = context.getExternalFilesDir(); mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); fileObject = (*env)->CallObjectMethod(env, context, mid, NULL); @@ -2536,7 +2362,7 @@ const char *SDL_AndroidGetExternalStoragePath(void) return NULL; } - /* path = fileObject.getAbsolutePath(); */ + // path = fileObject.getAbsolutePath(); mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject), "getAbsolutePath", "()Ljava/lang/String;"); pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid); @@ -2550,7 +2376,53 @@ const char *SDL_AndroidGetExternalStoragePath(void) return s_AndroidExternalFilesPath; } -int SDL_AndroidShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset) +const char *SDL_GetAndroidCachePath(void) +{ + // !!! FIXME: lots of duplication with SDL_GetAndroidExternalStoragePath and SDL_GetAndroidInternalStoragePath; consolidate these functions! + static char *s_AndroidCachePath = NULL; + + if (!s_AndroidCachePath) { + struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); + jmethodID mid; + jobject context; + jobject fileObject; + jstring pathString; + const char *path; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!LocalReferenceHolder_Init(&refs, env)) { + LocalReferenceHolder_Cleanup(&refs); + return NULL; + } + + // context = SDLActivity.getContext(); + context = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetContext); + + // fileObj = context.getExternalFilesDir(); + mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context), + "getCacheDir", "(Ljava/lang/String;)Ljava/io/File;"); + fileObject = (*env)->CallObjectMethod(env, context, mid, NULL); + if (!fileObject) { + SDL_SetError("Couldn't get cache directory"); + LocalReferenceHolder_Cleanup(&refs); + return NULL; + } + + // path = fileObject.getAbsolutePath(); + mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject), + "getAbsolutePath", "()Ljava/lang/String;"); + pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid); + + path = (*env)->GetStringUTFChars(env, pathString, NULL); + s_AndroidCachePath = SDL_strdup(path); + (*env)->ReleaseStringUTFChars(env, pathString, path); + + LocalReferenceHolder_Cleanup(&refs); + } + return s_AndroidCachePath; +} + +bool SDL_ShowAndroidToast(const char *message, int duration, int gravity, int xOffset, int yOffset) { return Android_JNI_ShowToast(message, duration, gravity, xOffset, yOffset); } @@ -2564,9 +2436,9 @@ void Android_JNI_GetManifestEnvironmentVariables(void) if (!bHasEnvironmentVariables) { JNIEnv *env = Android_JNI_GetEnv(); - SDL_bool ret = (*env)->CallStaticBooleanMethod(env, mActivityClass, midGetManifestEnvironmentVariables); + bool ret = (*env)->CallStaticBooleanMethod(env, mActivityClass, midGetManifestEnvironmentVariables); if (ret) { - bHasEnvironmentVariables = SDL_TRUE; + bHasEnvironmentVariables = true; } } } @@ -2593,25 +2465,25 @@ void Android_JNI_DestroyCustomCursor(int cursorID) (*env)->CallStaticVoidMethod(env, mActivityClass, midDestroyCustomCursor, cursorID); } -SDL_bool Android_JNI_SetCustomCursor(int cursorID) +bool Android_JNI_SetCustomCursor(int cursorID) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetCustomCursor, cursorID); } -SDL_bool Android_JNI_SetSystemCursor(int cursorID) +bool Android_JNI_SetSystemCursor(int cursorID) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetSystemCursor, cursorID); } -SDL_bool Android_JNI_SupportsRelativeMouse(void) +bool Android_JNI_SupportsRelativeMouse(void) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSupportsRelativeMouse); } -SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled) +bool Android_JNI_SetRelativeMouseEnabled(bool enabled) { JNIEnv *env = Android_JNI_GetEnv(); return (*env)->CallStaticBooleanMethod(env, mActivityClass, midSetRelativeMouseEnabled, (enabled == 1)); @@ -2621,7 +2493,7 @@ typedef struct NativePermissionRequestInfo { int request_code; char *permission; - SDL_AndroidRequestPermissionCallback callback; + SDL_RequestAndroidPermissionCallback callback; void *userdata; struct NativePermissionRequestInfo *next; } NativePermissionRequestInfo; @@ -2638,7 +2510,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)( if (info->request_code == (int) requestCode) { prev->next = info->next; SDL_UnlockMutex(Android_ActivityMutex); - info->callback(info->userdata, info->permission, result ? SDL_TRUE : SDL_FALSE); + info->callback(info->userdata, info->permission, result ? true : false); SDL_free(info->permission); SDL_free(info); return; @@ -2647,10 +2519,9 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(nativePermissionResult)( } SDL_UnlockMutex(Android_ActivityMutex); - SDL_assert(!"Shouldn't have hit this code"); // we had a permission response for a request we never made...? } -int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermissionCallback cb, void *userdata) +bool SDL_RequestAndroidPermission(const char *permission, SDL_RequestAndroidPermissionCallback cb, void *userdata) { if (!permission) { return SDL_InvalidParamError("permission"); @@ -2660,17 +2531,17 @@ int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermi NativePermissionRequestInfo *info = (NativePermissionRequestInfo *) SDL_calloc(1, sizeof (NativePermissionRequestInfo)); if (!info) { - return -1; + return false; } info->permission = SDL_strdup(permission); if (!info->permission) { SDL_free(info); - return -1; + return false; } static SDL_AtomicInt next_request_code; - info->request_code = SDL_AtomicAdd(&next_request_code, 1); + info->request_code = SDL_AddAtomicInt(&next_request_code, 1); info->callback = cb; info->userdata = userdata; @@ -2685,27 +2556,27 @@ int SDL_AndroidRequestPermission(const char *permission, SDL_AndroidRequestPermi (*env)->CallStaticVoidMethod(env, mActivityClass, midRequestPermission, jpermission, info->request_code); (*env)->DeleteLocalRef(env, jpermission); - return 0; + return true; } -/* Show toast notification */ -int Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset) +// Show toast notification +bool Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset) { - int result = 0; + bool result; JNIEnv *env = Android_JNI_GetEnv(); jstring jmessage = (*env)->NewStringUTF(env, message); - result = (*env)->CallStaticIntMethod(env, mActivityClass, midShowToast, jmessage, duration, gravity, xOffset, yOffset); + result = (*env)->CallStaticBooleanMethod(env, mActivityClass, midShowToast, jmessage, duration, gravity, xOffset, yOffset); (*env)->DeleteLocalRef(env, jmessage); return result; } -int Android_JNI_GetLocale(char *buf, size_t buflen) +bool Android_JNI_GetLocale(char *buf, size_t buflen) { AConfiguration *cfg; SDL_assert(buflen > 6); - /* Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED) */ + // Need to re-create the asset manager if locale has changed (SDL_EVENT_LOCALE_CHANGED) Internal_Android_Destroy_AssetManager(); if (!asset_manager) { @@ -2713,12 +2584,12 @@ int Android_JNI_GetLocale(char *buf, size_t buflen) } if (!asset_manager) { - return -1; + return false; } cfg = AConfiguration_new(); if (!cfg) { - return -1; + return false; } { @@ -2730,7 +2601,7 @@ int Android_JNI_GetLocale(char *buf, size_t buflen) AConfiguration_getLanguage(cfg, language); AConfiguration_getCountry(cfg, country); - /* copy language (not null terminated) */ + // copy language (not null terminated) if (language[0]) { buf[id++] = language[0]; if (language[1]) { @@ -2740,7 +2611,7 @@ int Android_JNI_GetLocale(char *buf, size_t buflen) buf[id++] = '_'; - /* copy country (not null terminated) */ + // copy country (not null terminated) if (country[0]) { buf[id++] = country[0]; if (country[1]) { @@ -2754,16 +2625,198 @@ int Android_JNI_GetLocale(char *buf, size_t buflen) AConfiguration_delete(cfg); - return 0; + return true; } -int Android_JNI_OpenURL(const char *url) +bool Android_JNI_OpenURL(const char *url) { + bool result; JNIEnv *env = Android_JNI_GetEnv(); jstring jurl = (*env)->NewStringUTF(env, url); - const int ret = (*env)->CallStaticIntMethod(env, mActivityClass, midOpenURL, jurl); + result = (*env)->CallStaticBooleanMethod(env, mActivityClass, midOpenURL, jurl); (*env)->DeleteLocalRef(env, jurl); - return ret; + return result; +} + +int Android_JNI_OpenFileDescriptor(const char *uri, const char *mode) +{ + // Get fopen-style modes + int moderead = 0, modewrite = 0, modeappend = 0, modeupdate = 0; + + for (const char *cmode = mode; *cmode; cmode++) { + switch (*cmode) { + case 'a': + modeappend = 1; + break; + case 'r': + moderead = 1; + break; + case 'w': + modewrite = 1; + break; + case '+': + modeupdate = 1; + break; + default: + break; + } + } + + // Translate fopen-style modes to ContentResolver modes. + // Android only allows "r", "w", "wt", "wa", "rw" or "rwt". + const char *contentResolverMode = "r"; + + if (moderead) { + if (modewrite) { + contentResolverMode = "rwt"; + } else { + contentResolverMode = modeupdate ? "rw" : "r"; + } + } else if (modewrite) { + contentResolverMode = modeupdate ? "rwt" : "wt"; + } else if (modeappend) { + contentResolverMode = modeupdate ? "rw" : "wa"; + } + + JNIEnv *env = Android_JNI_GetEnv(); + jstring jstringUri = (*env)->NewStringUTF(env, uri); + jstring jstringMode = (*env)->NewStringUTF(env, contentResolverMode); + jint fd = (*env)->CallStaticIntMethod(env, mActivityClass, midOpenFileDescriptor, jstringUri, jstringMode); + (*env)->DeleteLocalRef(env, jstringUri); + (*env)->DeleteLocalRef(env, jstringMode); + + if (fd == -1) { + SDL_SetError("Unspecified error in JNI"); + } + + return fd; +} + +static struct AndroidFileDialog +{ + int request_code; + SDL_DialogFileCallback callback; + void *userdata; +} mAndroidFileDialogData; + +JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeFileDialog)( + JNIEnv *env, jclass jcls, + jint requestCode, jobjectArray fileList, jint filter) +{ + if (mAndroidFileDialogData.callback != NULL && mAndroidFileDialogData.request_code == requestCode) { + if (fileList == NULL) { + SDL_SetError("Unspecified error in JNI"); + mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1); + mAndroidFileDialogData.callback = NULL; + return; + } + + // Convert fileList to string + size_t count = (*env)->GetArrayLength(env, fileList); + char **charFileList = SDL_calloc(count + 1, sizeof(char*)); + + if (charFileList == NULL) { + mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1); + mAndroidFileDialogData.callback = NULL; + return; + } + + // Convert to UTF-8 + // TODO: Fix modified UTF-8 to classic UTF-8 + for (int i = 0; i < count; i++) { + jstring string = (*env)->GetObjectArrayElement(env, fileList, i); + if (!string) { + continue; + } + + const char *utf8string = (*env)->GetStringUTFChars(env, string, NULL); + if (!utf8string) { + (*env)->DeleteLocalRef(env, string); + continue; + } + + char *newFile = SDL_strdup(utf8string); + if (!newFile) { + (*env)->ReleaseStringUTFChars(env, string, utf8string); + (*env)->DeleteLocalRef(env, string); + mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, NULL, -1); + mAndroidFileDialogData.callback = NULL; + + // Cleanup memory + for (int j = 0; j < i; j++) { + SDL_free(charFileList[j]); + } + SDL_free(charFileList); + return; + } + + charFileList[i] = newFile; + (*env)->ReleaseStringUTFChars(env, string, utf8string); + (*env)->DeleteLocalRef(env, string); + } + + // Call user-provided callback + SDL_ClearError(); + mAndroidFileDialogData.callback(mAndroidFileDialogData.userdata, (const char *const *) charFileList, filter); + mAndroidFileDialogData.callback = NULL; + + // Cleanup memory + for (int i = 0; i < count; i++) { + SDL_free(charFileList[i]); + } + SDL_free(charFileList); + } +} + +bool Android_JNI_OpenFileDialog( + SDL_DialogFileCallback callback, void* userdata, + const SDL_DialogFileFilter *filters, int nfilters, bool forwrite, + bool multiple) +{ + if (mAndroidFileDialogData.callback != NULL) { + SDL_SetError("Only one file dialog can be run at a time."); + return false; + } + + if (forwrite) { + multiple = false; + } + + JNIEnv *env = Android_JNI_GetEnv(); + + // Setup filters + jobjectArray filtersArray = NULL; + if (filters) { + jclass stringClass = (*env)->FindClass(env, "java/lang/String"); + filtersArray = (*env)->NewObjectArray(env, nfilters, stringClass, NULL); + + // Convert to string + for (int i = 0; i < nfilters; i++) { + jstring str = (*env)->NewStringUTF(env, filters[i].pattern); + (*env)->SetObjectArrayElement(env, filtersArray, i, str); + (*env)->DeleteLocalRef(env, str); + } + } + + // Setup data + static SDL_AtomicInt next_request_code; + mAndroidFileDialogData.request_code = SDL_AddAtomicInt(&next_request_code, 1); + mAndroidFileDialogData.userdata = userdata; + mAndroidFileDialogData.callback = callback; + + // Invoke JNI + jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, + midShowFileDialog, filtersArray, (jboolean) multiple, (jboolean) forwrite, mAndroidFileDialogData.request_code); + (*env)->DeleteLocalRef(env, filtersArray); + if (!success) { + mAndroidFileDialogData.callback = NULL; + SDL_AddAtomicInt(&next_request_code, -1); + SDL_SetError("Unspecified error in JNI"); + + return false; + } + + return true; } -#endif /* SDL_PLATFORM_ANDROID */ +#endif // SDL_PLATFORM_ANDROID diff --git a/libs/SDL3/src/core/android/SDL_android.h b/libs/SDL3/src/core/android/SDL_android.h index b323722e2..4d810c99c 100644 --- a/libs/SDL3/src/core/android/SDL_android.h +++ b/libs/SDL3/src/core/android/SDL_android.h @@ -20,7 +20,10 @@ */ #include "SDL_internal.h" -/* Set up for C function definitions, even when using C++ */ +#ifndef SDL_android_h +#define SDL_android_h + +// Set up for C function definitions, even when using C++ #ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { @@ -35,115 +38,125 @@ extern "C" { // this appears to be broken right now (on Android, not SDL, I think...?). #define ALLOW_MULTIPLE_ANDROID_AUDIO_DEVICES 0 -/* Interface from the SDL library into the Android Java activity */ +// Life cycle +typedef enum +{ + SDL_ANDROID_LIFECYCLE_WAKE, + SDL_ANDROID_LIFECYCLE_PAUSE, + SDL_ANDROID_LIFECYCLE_RESUME, + SDL_ANDROID_LIFECYCLE_LOWMEMORY, + SDL_ANDROID_LIFECYCLE_DESTROY, + SDL_NUM_ANDROID_LIFECYCLE_EVENTS +} SDL_AndroidLifecycleEvent; + +void Android_SendLifecycleEvent(SDL_AndroidLifecycleEvent event); +bool Android_WaitLifecycleEvent(SDL_AndroidLifecycleEvent *event, Sint64 timeoutNS); + +void Android_LockActivityMutex(void); +void Android_UnlockActivityMutex(void); + +// Interface from the SDL library into the Android Java activity extern void Android_JNI_SetActivityTitle(const char *title); -extern void Android_JNI_SetWindowStyle(SDL_bool fullscreen); +extern void Android_JNI_SetWindowStyle(bool fullscreen); extern void Android_JNI_SetOrientation(int w, int h, int resizable, const char *hint); extern void Android_JNI_MinizeWindow(void); -extern SDL_bool Android_JNI_ShouldMinimizeOnFocusLoss(void); +extern bool Android_JNI_ShouldMinimizeOnFocusLoss(void); -extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]); -extern void Android_JNI_ShowScreenKeyboard(SDL_Rect *inputRect); +extern bool Android_JNI_GetAccelerometerValues(float values[3]); +extern void Android_JNI_ShowScreenKeyboard(int input_type, SDL_Rect *inputRect); extern void Android_JNI_HideScreenKeyboard(void); -extern SDL_bool Android_JNI_IsScreenKeyboardShown(void); +extern bool Android_JNI_IsScreenKeyboardShown(void); extern ANativeWindow *Android_JNI_GetNativeWindow(void); extern SDL_DisplayOrientation Android_JNI_GetDisplayNaturalOrientation(void); extern SDL_DisplayOrientation Android_JNI_GetDisplayCurrentOrientation(void); -/* Audio support */ -void Android_StartAudioHotplug(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); +// Audio support +void Android_StartAudioHotplug(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording); void Android_StopAudioHotplug(void); extern void Android_AudioThreadInit(SDL_AudioDevice *device); -extern int Android_JNI_OpenAudioDevice(SDL_AudioDevice *device); -extern void *Android_JNI_GetAudioBuffer(void); -extern void Android_JNI_WriteAudioBuffer(void); -extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen); -extern void Android_JNI_FlushCapturedAudio(void); -extern void Android_JNI_CloseAudioDevice(const int iscapture); - -/* Detecting device type */ -extern SDL_bool Android_IsDeXMode(void); -extern SDL_bool Android_IsChromebook(void); - -int Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode); + +// Detecting device type +extern bool Android_IsDeXMode(void); +extern bool Android_IsChromebook(void); + +bool Android_JNI_FileOpen(void **puserdata, const char *fileName, const char *mode); Sint64 Android_JNI_FileSize(void *userdata); -Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, int whence); +Sint64 Android_JNI_FileSeek(void *userdata, Sint64 offset, SDL_IOWhence whence); size_t Android_JNI_FileRead(void *userdata, void *buffer, size_t size, SDL_IOStatus *status); size_t Android_JNI_FileWrite(void *userdata, const void *buffer, size_t size, SDL_IOStatus *status); -int Android_JNI_FileClose(void *userdata); +bool Android_JNI_FileClose(void *userdata); -/* Environment support */ +// Environment support void Android_JNI_GetManifestEnvironmentVariables(void); +int Android_JNI_OpenFileDescriptor(const char *uri, const char *mode); -/* Clipboard support */ -int Android_JNI_SetClipboardText(const char *text); +// Clipboard support +bool Android_JNI_SetClipboardText(const char *text); char *Android_JNI_GetClipboardText(void); -SDL_bool Android_JNI_HasClipboardText(void); +bool Android_JNI_HasClipboardText(void); -/* Power support */ +// Power support int Android_JNI_GetPowerInfo(int *plugged, int *charged, int *battery, int *seconds, int *percent); -/* Joystick support */ +// Joystick support void Android_JNI_PollInputDevices(void); -/* Haptic support */ +// Haptic support void Android_JNI_PollHapticDevices(void); void Android_JNI_HapticRun(int device_id, float intensity, int length); +void Android_JNI_HapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length); void Android_JNI_HapticStop(int device_id); -/* Video */ -int Android_JNI_SuspendScreenSaver(SDL_bool suspend); +// Video +bool Android_JNI_SuspendScreenSaver(bool suspend); -/* Touch support */ +// Touch support void Android_JNI_InitTouch(void); -/* Threads */ +// Threads #include JNIEnv *Android_JNI_GetEnv(void); -int Android_JNI_SetupThread(void); +bool Android_JNI_SetupThread(void); -/* Locale */ -int Android_JNI_GetLocale(char *buf, size_t buflen); +// Locale +bool Android_JNI_GetLocale(char *buf, size_t buflen); -/* Generic messages */ -int Android_JNI_SendMessage(int command, int param); +// Generic messages +bool Android_JNI_SendMessage(int command, int param); -/* Init */ -JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv *mEnv, jclass cls); +// MessageBox +bool Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID); -/* MessageBox */ -int Android_JNI_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID); - -/* Cursor support */ +// Cursor support int Android_JNI_CreateCustomCursor(SDL_Surface *surface, int hot_x, int hot_y); void Android_JNI_DestroyCustomCursor(int cursorID); -SDL_bool Android_JNI_SetCustomCursor(int cursorID); -SDL_bool Android_JNI_SetSystemCursor(int cursorID); +bool Android_JNI_SetCustomCursor(int cursorID); +bool Android_JNI_SetSystemCursor(int cursorID); -/* Relative mouse support */ -SDL_bool Android_JNI_SupportsRelativeMouse(void); -SDL_bool Android_JNI_SetRelativeMouseEnabled(SDL_bool enabled); +// Relative mouse support +bool Android_JNI_SupportsRelativeMouse(void); +bool Android_JNI_SetRelativeMouseEnabled(bool enabled); -/* Show toast notification */ -int Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset); +// Show toast notification +bool Android_JNI_ShowToast(const char *message, int duration, int gravity, int xOffset, int yOffset); -int Android_JNI_OpenURL(const char *url); +bool Android_JNI_OpenURL(const char *url); int SDL_GetAndroidSDKVersion(void); -SDL_bool SDL_IsAndroidTablet(void); -SDL_bool SDL_IsAndroidTV(void); -SDL_bool SDL_IsChromebook(void); -SDL_bool SDL_IsDeXMode(void); +bool SDL_IsAndroidTablet(void); -void Android_ActivityMutex_Lock(void); -void Android_ActivityMutex_Unlock(void); -void Android_ActivityMutex_Lock_Running(void); +// File Dialogs +bool Android_JNI_OpenFileDialog(SDL_DialogFileCallback callback, void* userdata, + const SDL_DialogFileFilter *filters, int nfilters, bool forwrite, + bool multiple); -/* Ends C function definitions when using C++ */ +// Ends C function definitions when using C++ #ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ #endif + +#endif // SDL_android_h diff --git a/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h b/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h index 8cb7430ab..fc6e5e8bf 100644 --- a/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h +++ b/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_default_keyaccmap.h @@ -1,6 +1,6 @@ #include -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off /* * Automatically generated from /usr/share/vt/keymaps/us.acc.kbd. * DO NOT EDIT! @@ -123,45 +123,45 @@ static keymap_t keymap_default_us_acc = { 0x6d, { } }; static accentmap_t accentmap_default_us_acc = { 11, { - /* dgra=0 */ + // dgra=0 { '`', { { 'a',0xe0 }, { 'A',0xc0 }, { 'e',0xe8 }, { 'E',0xc8 }, { 'i',0xec }, { 'I',0xcc }, { 'o',0xf2 }, { 'O',0xd2 }, { 'u',0xf9 }, { 'U',0xd9 }, }, }, - /* dacu=1 */ + // dacu=1 { 0xb4, { { 'a',0xe1 }, { 'A',0xc1 }, { 'e',0xe9 }, { 'E',0xc9 }, { 'i',0xed }, { 'I',0xcd }, { 'o',0xf3 }, { 'O',0xd3 }, { 'u',0xfa }, { 'U',0xda }, { 'y',0xfd }, { 'Y',0xdd }, }, }, - /* dcir=2 */ + // dcir=2 { '^', { { 'a',0xe2 }, { 'A',0xc2 }, { 'e',0xea }, { 'E',0xca }, { 'i',0xee }, { 'I',0xce }, { 'o',0xf4 }, { 'O',0xd4 }, { 'u',0xfb }, { 'U',0xdb }, }, }, - /* dtil=3 */ + // dtil=3 { '~', { { 'a',0xe3 }, { 'A',0xc3 }, { 'n',0xf1 }, { 'N',0xd1 }, { 'o',0xf5 }, { 'O',0xd5 }, }, }, - /* dmac=4 */ - { 0x00 }, - /* dbre=5 */ - { 0x00 }, - /* ddot=6 */ - { 0x00 }, - /* duml=7 */ + // dmac=4 + { 0x00 }, + // dbre=5 + { 0x00 }, + // ddot=6 + { 0x00 }, + // duml=7 { 0xa8, { { 'a',0xe4 }, { 'A',0xc4 }, { 'e',0xeb }, { 'E',0xcb }, { 'i',0xef }, { 'I',0xcf }, { 'o',0xf6 }, { 'O',0xd6 }, { 'u',0xfc }, { 'U',0xdc }, { 'y',0xff }, }, }, - /* dsla=8 */ - { 0x00 }, - /* drin=9 */ + // dsla=8 + { 0x00 }, + // drin=9 { 0xb0, { { 'a',0xe5 }, { 'A',0xc5 }, }, }, - /* dced=10 */ + // dced=10 { 0xb8, { { 'c',0xe7 }, { 'C',0xc7 }, }, }, - /* dapo=11 */ - { 0x00 }, - /* ddac=12 */ - { 0x00 }, - /* dogo=13 */ - { 0x00 }, - /* dcar=14 */ - { 0x00 }, + // dapo=11 + { 0x00 }, + // ddac=12 + { 0x00 }, + // dogo=13 + { 0x00 }, + // dcar=14 + { 0x00 }, } }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on diff --git a/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_freebsd.c index 22d02bf54..6f076b100 100644 --- a/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_freebsd.c +++ b/libs/SDL3/src/core/freebsd/SDL_evdev_kbd_freebsd.c @@ -25,7 +25,7 @@ #ifdef SDL_INPUT_FBSDKBIO -/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD */ +// This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD #include #include @@ -52,12 +52,12 @@ struct SDL_EVDEV_keyboard_state unsigned short **key_maps; keymap_t *key_map; keyboard_info_t *kbInfo; - unsigned char shift_down[4]; /* shift state counters.. */ - SDL_bool dead_key_next; - int npadch; /* -1 or number assembled on pad */ + unsigned char shift_down[4]; // shift state counters.. + bool dead_key_next; + int npadch; // -1 or number assembled on pad accentmap_t *accents; unsigned int diacr; - SDL_bool rep; /* flag telling character repeat */ + bool rep; // flag telling character repeat unsigned char lockstate; unsigned char ledflagstate; char shift_state; @@ -65,7 +65,7 @@ struct SDL_EVDEV_keyboard_state unsigned int text_len; }; -static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd) +static bool SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd) { return ioctl(kbd->keyboard_fd, GIO_KEYMAP, kbd->key_map) >= 0; } @@ -77,7 +77,7 @@ static int kbd_cleanup_atexit_installed = 0; static struct sigaction old_sigaction[NSIG]; static int fatal_signals[] = { - /* Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. */ + // Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. SIGHUP, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGPIPE, SIGBUS, SIGSYS @@ -114,26 +114,26 @@ static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontex struct sigaction *old_action_p = &(old_sigaction[signum]); sigset_t sigset; - /* Restore original signal handler before going any further. */ + // Restore original signal handler before going any further. sigaction(signum, old_action_p, NULL); - /* Unmask current signal. */ + // Unmask current signal. sigemptyset(&sigset); sigaddset(&sigset, signum); sigprocmask(SIG_UNBLOCK, &sigset, NULL); - /* Save original signal info and context for archeologists. */ + // Save original signal info and context for archeologists. SDL_EVDEV_kdb_cleanup_siginfo = info; SDL_EVDEV_kdb_cleanup_ucontext = ucontext; - /* Restore keyboard. */ + // Restore keyboard. kbd_cleanup(); - /* Reraise signal. */ + // Reraise signal. SDL_EVDEV_kbd_reraise_signal(signum); } -static void kbd_unregister_emerg_cleanup() +static void kbd_unregister_emerg_cleanup(void) { int tabidx; @@ -150,27 +150,27 @@ static void kbd_unregister_emerg_cleanup() int signum = fatal_signals[tabidx]; old_action_p = &(old_sigaction[signum]); - /* Examine current signal action */ + // Examine current signal action if (sigaction(signum, NULL, &cur_action)) { continue; } - /* Check if action installed and not modified */ + // Check if action installed and not modified if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) { continue; } - /* Restore original action */ + // Restore original action sigaction(signum, old_action_p, NULL); } } static void kbd_cleanup_atexit(void) { - /* Restore keyboard. */ + // Restore keyboard. kbd_cleanup(); - /* Try to restore signal handlers in case shared library is being unloaded */ + // Try to restore signal handlers in case shared library is being unloaded kbd_unregister_emerg_cleanup(); } @@ -236,14 +236,14 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) kbd->npadch = -1; - /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */ + // This might fail if we're not connected to a tty (e.g. on the Steam Link) kbd->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC); kbd->shift_state = 0; - kbd->accents = SDL_calloc(sizeof(accentmap_t), 1); - kbd->key_map = SDL_calloc(sizeof(keymap_t), 1); - kbd->kbInfo = SDL_calloc(sizeof(keyboard_info_t), 1); + kbd->accents = SDL_calloc(1, sizeof(accentmap_t)); + kbd->key_map = SDL_calloc(1, sizeof(keymap_t)); + kbd->kbInfo = SDL_calloc(1, sizeof(keyboard_info_t)); ioctl(kbd->console_fd, KDGKBINFO, kbd->kbInfo); ioctl(kbd->console_fd, CONS_MOUSECTL, &mData); @@ -258,14 +258,14 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) } if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) { - /* Set the keyboard in XLATE mode and load the keymaps */ + // Set the keyboard in XLATE mode and load the keymaps ioctl(kbd->console_fd, KDSKBMODE, (unsigned long)(K_XLATE)); if (!SDL_EVDEV_kbd_load_keymaps(kbd)) { SDL_free(kbd->key_map); kbd->key_map = &keymap_default_us_acc; } - /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ - if (SDL_getenv("SDL_INPUT_FREEBSD_KEEP_KBD") == NULL) { + + if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) { /* Take keyboard from console and open the actual keyboard device. * Ensures that the keystrokes do not leak through to the console. */ @@ -281,7 +281,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) /* Make sure to restore keyboard if application fails to call * SDL_Quit before exit or fatal signal is raised. */ - if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { + if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { kbd_register_emerg_cleanup(kbd); } SDL_free(devicePath); @@ -306,7 +306,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) kbd_unregister_emerg_cleanup(); if (kbd->keyboard_fd >= 0) { - /* Restore the original keyboard mode */ + // Restore the original keyboard mode ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode); close(kbd->keyboard_fd); @@ -320,7 +320,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) SDL_free(kbd); } -void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted) { } @@ -337,7 +337,7 @@ void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) */ static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c) { - /* c is already part of a UTF-8 sequence and safe to add as a character */ + // c is already part of a UTF-8 sequence and safe to add as a character if (kbd->text_len < (sizeof(kbd->text) - 1)) { kbd->text[kbd->text_len++] = (char)c; } @@ -389,7 +389,7 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) for (i = 0; i < kbd->accents->n_accs; i++) { if (kbd->accents->acc[i].accchar == d) { for (j = 0; j < NUM_ACCENTCHARS; ++j) { - if (kbd->accents->acc[i].map[j][0] == 0) { /* end of table */ + if (kbd->accents->acc[i].map[j][0] == 0) { // end of table break; } if (kbd->accents->acc[i].map[j][0] == ch) { @@ -408,7 +408,7 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) return ch; } -static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) +static bool vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) { return (kbd->ledflagstate & flag) != 0; } @@ -426,7 +426,7 @@ static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag) { if (up_flag) { - return; /* no action, if this is a key release */ + return; // no action, if this is a key release } if (kbd->diacr) { @@ -434,7 +434,7 @@ static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_fl } if (kbd->dead_key_next) { - kbd->dead_key_next = SDL_FALSE; + kbd->dead_key_next = false; kbd->diacr = value; return; } @@ -472,7 +472,7 @@ static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ else kbd->shift_state &= ~(1 << value); - /* kludge */ + // kludge if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) { put_utf8(kbd, kbd->npadch); kbd->npadch = -1; @@ -496,7 +496,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, if (keycode < NUM_KEYS) { if (keycode >= 89 && keycode <= 95) { - /* These constitute unprintable language-related keys, so ignore them. */ + // These constitute unprintable language-related keys, so ignore them. return; } if (keycode > 95) { @@ -520,69 +520,69 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, map_from_key_sym = keysym.map[final_key_state]; if ((keysym.spcl & (0x80 >> final_key_state)) || (map_from_key_sym & SPCLKEY)) { - /* Special function.*/ + // Special function. if (map_from_key_sym == 0) - return; /* Nothing to do. */ + return; // Nothing to do. if (map_from_key_sym & SPCLKEY) { map_from_key_sym &= ~SPCLKEY; } if (map_from_key_sym >= F_ACC && map_from_key_sym <= L_ACC) { - /* Accent function.*/ + // Accent function. unsigned int accent_index = map_from_key_sym - F_ACC; if (kbd->accents->acc[accent_index].accchar != 0) { k_deadunicode(kbd, kbd->accents->acc[accent_index].accchar, !down); } } else { switch (map_from_key_sym) { - case ASH: /* alt/meta shift */ + case ASH: // alt/meta shift k_shift(kbd, 3, down == 0); break; - case LSHA: /* left shift + alt lock */ - case RSHA: /* right shift + alt lock */ + case LSHA: // left shift + alt lock + case RSHA: // right shift + alt lock if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } SDL_FALLTHROUGH; - case LSH: /* left shift */ - case RSH: /* right shift */ + case LSH: // left shift + case RSH: // right shift k_shift(kbd, 0, down == 0); break; - case LCTRA: /* left ctrl + alt lock */ - case RCTRA: /* right ctrl + alt lock */ + case LCTRA: // left ctrl + alt lock + case RCTRA: // right ctrl + alt lock if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } SDL_FALLTHROUGH; - case LCTR: /* left ctrl */ - case RCTR: /* right ctrl */ + case LCTR: // left ctrl + case RCTR: // right ctrl k_shift(kbd, 1, down == 0); break; - case LALTA: /* left alt + alt lock */ - case RALTA: /* right alt + alt lock */ + case LALTA: // left alt + alt lock + case RALTA: // right alt + alt lock if (down == 0) { chg_vc_kbd_led(kbd, ALKED); } SDL_FALLTHROUGH; - case LALT: /* left alt */ - case RALT: /* right alt */ + case LALT: // left alt + case RALT: // right alt k_shift(kbd, 2, down == 0); break; - case ALK: /* alt lock */ + case ALK: // alt lock if (down == 1) { chg_vc_kbd_led(kbd, ALKED); } break; - case CLK: /* caps lock*/ + case CLK: // caps lock if (down == 1) { chg_vc_kbd_led(kbd, CLKED); } break; - case NLK: /* num lock */ + case NLK: // num lock if (down == 1) { chg_vc_kbd_led(kbd, NLKED); } break; - case SLK: /* scroll lock */ + case SLK: // scroll lock if (down == 1) { chg_vc_kbd_led(kbd, SLKED); } @@ -610,4 +610,4 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, } } -#endif /* SDL_INPUT_FBSDKBIO */ +#endif // SDL_INPUT_FBSDKBIO diff --git a/libs/SDL3/src/core/gdk/SDL_gdk.cpp b/libs/SDL3/src/core/gdk/SDL_gdk.cpp index af018d36b..efd56f315 100644 --- a/libs/SDL3/src/core/gdk/SDL_gdk.cpp +++ b/libs/SDL3/src/core/gdk/SDL_gdk.cpp @@ -26,18 +26,18 @@ extern "C" { } #include #include -#include /* CommandLineToArgvW() */ #include static XTaskQueueHandle GDK_GlobalTaskQueue; PAPPSTATE_REGISTRATION hPLM = {}; +PAPPCONSTRAIN_REGISTRATION hCPLM = {}; HANDLE plmSuspendComplete = nullptr; -extern "C" DECLSPEC int -SDL_GDKGetTaskQueue(XTaskQueueHandle *outTaskQueue) +extern "C" +bool SDL_GetGDKTaskQueue(XTaskQueueHandle *outTaskQueue) { - /* If this is the first call, first create the global task queue. */ + // If this is the first call, first create the global task queue. if (!GDK_GlobalTaskQueue) { HRESULT hr; @@ -48,175 +48,98 @@ SDL_GDKGetTaskQueue(XTaskQueueHandle *outTaskQueue) return SDL_SetError("[GDK] Could not create global task queue"); } - /* The initial call gets the non-duplicated handle so they can clean it up */ + // The initial call gets the non-duplicated handle so they can clean it up *outTaskQueue = GDK_GlobalTaskQueue; } else { - /* Duplicate the global task queue handle into outTaskQueue */ + // Duplicate the global task queue handle into outTaskQueue if (FAILED(XTaskQueueDuplicateHandle(GDK_GlobalTaskQueue, outTaskQueue))) { return SDL_SetError("[GDK] Unable to acquire global task queue"); } } - return 0; + return true; } -extern "C" void -GDK_DispatchTaskQueue(void) +extern "C" +void GDK_DispatchTaskQueue(void) { /* If there is no global task queue, don't do anything. * This gives the option to opt-out for those who want to handle everything themselves. */ if (GDK_GlobalTaskQueue) { - /* Dispatch any callbacks which are ready. */ + // Dispatch any callbacks which are ready. while (XTaskQueueDispatch(GDK_GlobalTaskQueue, XTaskQueuePort::Completion, 0)) ; } } -/* Pop up an out of memory message, returns to Windows */ -extern "C" static BOOL -OutOfMemory(void) +extern "C" +bool GDK_RegisterChangeNotifications(void) { - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL); - return FALSE; -} - -/* Gets the arguments with GetCommandLine, converts them to argc and argv - and calls SDL_main */ -extern "C" DECLSPEC int -SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved) -{ - LPWSTR *argvw; - char **argv; - int i, argc, result; - HRESULT hr; - XTaskQueueHandle taskQueue; - - argvw = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argvw == NULL) { - return OutOfMemory(); + // Register suspend/resume handling + plmSuspendComplete = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE); + if (!plmSuspendComplete) { + return SDL_SetError("[GDK] Unable to create plmSuspendComplete event"); } + auto rascn = [](BOOLEAN quiesced, PVOID context) { + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler"); + if (quiesced) { + ResetEvent(plmSuspendComplete); + SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); - /* Note that we need to be careful about how we allocate/free memory here. - * If the application calls SDL_SetMemoryFunctions(), we can't rely on - * SDL_free() to use the same allocator after SDL_main() returns. - */ + // To defer suspension, we must wait to exit this callback. + // IMPORTANT: The app must call SDL_GDKSuspendComplete() to release this lock. + (void)WaitForSingleObject(plmSuspendComplete, INFINITE); - /* Parse it into argv and argc */ - argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv)); - if (argv == NULL) { - return OutOfMemory(); - } - for (i = 0; i < argc; ++i) { - DWORD len; - char *arg = WIN_StringToUTF8W(argvw[i]); - if (arg == NULL) { - return OutOfMemory(); - } - len = (DWORD)SDL_strlen(arg); - argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1); - if (!argv[i]) { - return OutOfMemory(); - } - SDL_memcpy(argv[i], arg, len); - SDL_free(arg); - } - argv[i] = NULL; - LocalFree(argvw); - - hr = XGameRuntimeInitialize(); - - if (SUCCEEDED(hr) && SDL_GDKGetTaskQueue(&taskQueue) == 0) { - Uint32 titleid = 0; - char scidBuffer[64]; - XblInitArgs xblArgs; - - XTaskQueueSetCurrentProcessTaskQueue(taskQueue); - - /* Try to get the title ID and initialize Xbox Live */ - hr = XGameGetXboxTitleId(&titleid); - if (SUCCEEDED(hr)) { - SDL_zero(xblArgs); - xblArgs.queue = taskQueue; - SDL_snprintf(scidBuffer, 64, "00000000-0000-0000-0000-0000%08X", titleid); - xblArgs.scid = scidBuffer; - hr = XblInitialize(&xblArgs); + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler: plmSuspendComplete event signaled."); } else { - SDL_SetError("[GDK] Unable to get titleid. Will not call XblInitialize. Check MicrosoftGame.config!"); - } - - SDL_SetMainReady(); - - /* Register suspend/resume handling */ - plmSuspendComplete = CreateEventEx(nullptr, nullptr, 0, EVENT_MODIFY_STATE | SYNCHRONIZE); - if (!plmSuspendComplete) { - SDL_SetError("[GDK] Unable to create plmSuspendComplete event"); - return -1; + SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); } - auto rascn = [](BOOLEAN quiesced, PVOID context) { - SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler"); - if (quiesced) { - ResetEvent(plmSuspendComplete); - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); - - // To defer suspension, we must wait to exit this callback. - // IMPORTANT: The app must call SDL_GDKSuspendComplete() to release this lock. - (void)WaitForSingleObject(plmSuspendComplete, INFINITE); + }; + if (RegisterAppStateChangeNotification(rascn, NULL, &hPLM)) { + return SDL_SetError("[GDK] Unable to call RegisterAppStateChangeNotification"); + } - SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppStateChangeNotification handler: plmSuspendComplete event signaled."); + // Register constrain/unconstrain handling + auto raccn = [](BOOLEAN constrained, PVOID context) { + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler"); + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (_this) { + if (constrained) { + SDL_SetKeyboardFocus(NULL); } else { - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); + SDL_SetKeyboardFocus(_this->windows); } - }; - if (RegisterAppStateChangeNotification(rascn, NULL, &hPLM)) { - SDL_SetError("[GDK] Unable to call RegisterAppStateChangeNotification"); - return -1; } - - /* Run the application main() code */ - result = mainFunction(argc, argv); - - /* Unregister suspend/resume handling */ - UnregisterAppStateChangeNotification(hPLM); - CloseHandle(plmSuspendComplete); - - /* !!! FIXME: This follows the docs exactly, but for some reason still leaks handles on exit? */ - /* Terminate the task queue and dispatch any pending tasks */ - XTaskQueueTerminate(taskQueue, false, nullptr, nullptr); - while (XTaskQueueDispatch(taskQueue, XTaskQueuePort::Completion, 0)) - ; - - XTaskQueueCloseHandle(taskQueue); - - XGameRuntimeUninitialize(); - } else { -#ifdef SDL_PLATFORM_WINGDK - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "[GDK] Could not initialize - aborting", NULL); -#else - SDL_assert_always(0 && "[GDK] Could not initialize - aborting"); -#endif - result = -1; + }; + if (RegisterAppConstrainedChangeNotification(raccn, NULL, &hCPLM)) { + return SDL_SetError("[GDK] Unable to call RegisterAppConstrainedChangeNotification"); } - /* Free argv, to avoid memory leak */ - for (i = 0; i < argc; ++i) { - HeapFree(GetProcessHeap(), 0, argv[i]); - } - HeapFree(GetProcessHeap(), 0, argv); + return true; +} + +extern "C" +void GDK_UnregisterChangeNotifications(void) +{ + // Unregister suspend/resume handling + UnregisterAppStateChangeNotification(hPLM); + CloseHandle(plmSuspendComplete); - return result; + // Unregister constrain/unconstrain handling + UnregisterAppConstrainedChangeNotification(hCPLM); } -extern "C" DECLSPEC void -SDL_GDKSuspendComplete() +extern "C" +void SDL_GDKSuspendComplete() { if (plmSuspendComplete) { SetEvent(plmSuspendComplete); } } -extern "C" DECLSPEC int -SDL_GDKGetDefaultUser(XUserHandle *outUserHandle) +extern "C" +bool SDL_GetGDKDefaultUser(XUserHandle *outUserHandle) { XAsyncBlock block = { 0 }; HRESULT result; @@ -232,5 +155,5 @@ SDL_GDKGetDefaultUser(XUserHandle *outUserHandle) return WIN_SetErrorFromHRESULT("XUserAddResult", result); } - return 0; + return true; } diff --git a/libs/SDL3/src/core/gdk/SDL_gdk.h b/libs/SDL3/src/core/gdk/SDL_gdk.h index d500c41fd..db2affa33 100644 --- a/libs/SDL3/src/core/gdk/SDL_gdk.h +++ b/libs/SDL3/src/core/gdk/SDL_gdk.h @@ -20,5 +20,8 @@ */ #include "SDL_internal.h" -/* This is called from WIN_PumpEvents on GDK */ +// This is called from WIN_PumpEvents on GDK extern void GDK_DispatchTaskQueue(void); + +extern bool GDK_RegisterChangeNotifications(void); +extern void GDK_UnregisterChangeNotifications(void); diff --git a/libs/SDL3/src/core/haiku/SDL_BApp.h b/libs/SDL3/src/core/haiku/SDL_BApp.h index 8af12eec5..14b69055a 100644 --- a/libs/SDL3/src/core/haiku/SDL_BApp.h +++ b/libs/SDL3/src/core/haiku/SDL_BApp.h @@ -36,7 +36,7 @@ extern "C" { #include "SDL_internal.h" -/* Local includes */ +// Local includes #include "../../events/SDL_events_c.h" #include "../../video/haiku/SDL_bframebuffer.h" @@ -47,27 +47,27 @@ extern "C" { #include -/* Forward declarations */ +// Forward declarations class SDL_BLooper; class SDL_BWin; -/* Message constants */ +// Message constants enum ToSDL { - /* Intercepted by BWindow on its way to BView */ + // Intercepted by BWindow on its way to BView BAPP_MOUSE_MOVED, BAPP_MOUSE_BUTTON, BAPP_MOUSE_WHEEL, BAPP_KEY, - BAPP_REPAINT, /* from _UPDATE_ */ - /* From BWindow */ - BAPP_MAXIMIZE, /* from B_ZOOM */ + BAPP_REPAINT, // from _UPDATE_ + // From BWindow + BAPP_MAXIMIZE, // from B_ZOOM BAPP_MINIMIZE, - BAPP_RESTORE, /* TODO: IMPLEMENT! */ + BAPP_RESTORE, // TODO: IMPLEMENT! BAPP_SHOW, BAPP_HIDE, - BAPP_MOUSE_FOCUS, /* caused by MOUSE_MOVE */ - BAPP_KEYBOARD_FOCUS, /* from WINDOW_ACTIVATED */ + BAPP_MOUSE_FOCUS, // caused by MOUSE_MOVE + BAPP_KEYBOARD_FOCUS, // from WINDOW_ACTIVATED BAPP_WINDOW_CLOSE_REQUESTED, BAPP_WINDOW_MOVED, BAPP_WINDOW_RESIZED, @@ -78,7 +78,7 @@ enum ToSDL extern "C" SDL_BLooper *SDL_Looper; -/* Create a descendant of BLooper */ +// Create a descendant of BLooper class SDL_BLooper : public BLooper { public: @@ -93,10 +93,10 @@ class SDL_BLooper : public BLooper { } - /* Event-handling functions */ + // Event-handling functions virtual void MessageReceived(BMessage *message) { - /* Sort out SDL-related messages */ + // Sort out SDL-related messages switch (message->what) { case BAPP_MOUSE_MOVED: _HandleMouseMove(message); @@ -159,7 +159,7 @@ class SDL_BLooper : public BLooper break; case BAPP_SCREEN_CHANGED: - /* TODO: Handle screen resize or workspace change */ + // TODO: Handle screen resize or workspace change break; default: @@ -168,7 +168,7 @@ class SDL_BLooper : public BLooper } } - /* Window creation/destruction methods */ + // Window creation/destruction methods int32 GetID(SDL_Window *win) { int32 i; @@ -179,19 +179,19 @@ class SDL_BLooper : public BLooper } } - /* Expand the vector if all slots are full */ + // Expand the vector if all slots are full if (i == _GetNumWindowSlots()) { _PushBackWindow(win); return i; } - /* TODO: error handling */ + // TODO: error handling return 0; } /* FIXME: Bad coding practice, but I can't include SDL_BWin.h here. Is there another way to do this? */ - void ClearID(SDL_BWin *bwin); /* Defined in SDL_BeApp.cc */ + void ClearID(SDL_BWin *bwin); // Defined in SDL_BeApp.cc SDL_Window *GetSDLWindow(int32 winID) { @@ -215,7 +215,7 @@ class SDL_BLooper : public BLooper #endif private: - /* Event management */ + // Event management void _HandleBasicWindowEvent(BMessage *msg, SDL_EventType sdlEventType) { SDL_Window *win; @@ -235,8 +235,8 @@ class SDL_BLooper : public BLooper int32 x = 0, y = 0; if ( !_GetWinID(msg, &winID) || - msg->FindInt32("x", &x) != B_OK || /* x movement */ - msg->FindInt32("y", &y) != B_OK /* y movement */ + msg->FindInt32("x", &x) != B_OK || // x movement + msg->FindInt32("y", &y) != B_OK // y movement ) { return; } @@ -254,7 +254,7 @@ class SDL_BLooper : public BLooper if (!be_app->IsCursorHidden()) be_app->HideCursor(); } else { - SDL_SendMouseMotion(0, win, SDL_DEFAULT_MOUSE_ID, SDL_FALSE, (float)x, (float)y); + SDL_SendMouseMotion(0, win, SDL_DEFAULT_MOUSE_ID, false, (float)x, (float)y); if (SDL_CursorVisible() && be_app->IsCursorHidden()) be_app->ShowCursor(); } @@ -264,15 +264,16 @@ class SDL_BLooper : public BLooper { SDL_Window *win; int32 winID; - int32 button, state; /* left/middle/right, pressed/released */ + int32 button; + bool down; if ( !_GetWinID(msg, &winID) || msg->FindInt32("button-id", &button) != B_OK || - msg->FindInt32("button-state", &state) != B_OK) { + msg->FindBool("button-down", &down) != B_OK) { return; } win = GetSDLWindow(winID); - SDL_SendMouseButton(0, win, SDL_DEFAULT_MOUSE_ID, state, button); + SDL_SendMouseButton(0, win, SDL_DEFAULT_MOUSE_ID, button, down); } void _HandleMouseWheel(BMessage *msg) @@ -292,21 +293,21 @@ class SDL_BLooper : public BLooper void _HandleKey(BMessage *msg) { - int32 scancode, state; /* scancode, pressed/released */ + SDL_Window *win; + int32 winID; + int32 scancode; + bool down; if ( - msg->FindInt32("key-state", &state) != B_OK || - msg->FindInt32("key-scancode", &scancode) != B_OK) { + !_GetWinID(msg, &winID) || + msg->FindInt32("key-scancode", &scancode) != B_OK || + msg->FindBool("key-down", &down) != B_OK) { return; } - /* Make sure this isn't a repeated event (key pressed and held) */ - if (state == SDL_PRESSED && HAIKU_GetKeyState(scancode) == SDL_PRESSED) { - return; - } - HAIKU_SetKeyState(scancode, state); - SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, state, HAIKU_GetScancodeFromBeKey(scancode)); + SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, scancode, HAIKU_GetScancodeFromBeKey(scancode), down); - if (state == SDL_PRESSED && SDL_TextInputActive()) { + win = GetSDLWindow(winID); + if (down && SDL_TextInputActive(win)) { const int8 *keyUtf8; ssize_t count; if (msg->FindData("key-utf8", B_INT8_TYPE, (const void **)&keyUtf8, &count) == B_OK) { @@ -322,7 +323,7 @@ class SDL_BLooper : public BLooper { SDL_Window *win; int32 winID; - bool bSetFocus; /* If false, lose focus */ + bool bSetFocus; // If false, lose focus if ( !_GetWinID(msg, &winID) || msg->FindBool("focusGained", &bSetFocus) != B_OK) { @@ -332,7 +333,7 @@ class SDL_BLooper : public BLooper if (bSetFocus) { SDL_SetMouseFocus(win); } else if (SDL_GetMouseFocus() == win) { - /* Only lose all focus if this window was the current focus */ + // Only lose all focus if this window was the current focus SDL_SetMouseFocus(NULL); } } @@ -341,7 +342,7 @@ class SDL_BLooper : public BLooper { SDL_Window *win; int32 winID; - bool bSetFocus; /* If false, lose focus */ + bool bSetFocus; // If false, lose focus if ( !_GetWinID(msg, &winID) || msg->FindBool("focusGained", &bSetFocus) != B_OK) { @@ -351,7 +352,7 @@ class SDL_BLooper : public BLooper if (bSetFocus) { SDL_SetKeyboardFocus(win); } else if (SDL_GetKeyboardFocus() == win) { - /* Only lose all focus if this window was the current focus */ + // Only lose all focus if this window was the current focus SDL_SetKeyboardFocus(NULL); } } @@ -361,7 +362,7 @@ class SDL_BLooper : public BLooper SDL_Window *win; int32 winID; int32 xPos, yPos; - /* Get the window id and new x/y position of the window */ + // Get the window id and new x/y position of the window if ( !_GetWinID(msg, &winID) || msg->FindInt32("window-x", &xPos) != B_OK || @@ -377,7 +378,7 @@ class SDL_BLooper : public BLooper SDL_Window *win; int32 winID; int32 w, h; - /* Get the window id ]and new x/y position of the window */ + // Get the window id ]and new x/y position of the window if ( !_GetWinID(msg, &winID) || msg->FindInt32("window-w", &w) != B_OK || @@ -415,8 +416,8 @@ class SDL_BLooper : public BLooper _window_map.push_back(win); } - /* Members */ - std::vector _window_map; /* Keeps track of SDL_Windows by index-id */ + // Members + std::vector _window_map; // Keeps track of SDL_Windows by index-id #ifdef SDL_VIDEO_OPENGL BGLView *_current_context; diff --git a/libs/SDL3/src/core/haiku/SDL_BeApp.cc b/libs/SDL3/src/core/haiku/SDL_BeApp.cc index 68a79f4e3..39612b8c5 100644 --- a/libs/SDL3/src/core/haiku/SDL_BeApp.cc +++ b/libs/SDL3/src/core/haiku/SDL_BeApp.cc @@ -22,7 +22,7 @@ #ifdef SDL_PLATFORM_HAIKU -/* Handle the BeApp specific portions of the application */ +// Handle the BeApp specific portions of the application #include #include @@ -32,7 +32,7 @@ #include #include -#include "SDL_BApp.h" /* SDL_BLooper class definition */ +#include "SDL_BApp.h" // SDL_BLooper class definition #include "SDL_BeApp.h" #include "../../video/haiku/SDL_BWin.h" @@ -43,17 +43,17 @@ extern "C" { #include "../../thread/SDL_systhread.h" -/* Flag to tell whether or not the Be application and looper are active or not */ +// Flag to tell whether or not the Be application and looper are active or not static int SDL_BeAppActive = 0; static SDL_Thread *SDL_AppThread = NULL; SDL_BLooper *SDL_Looper = NULL; -/* Default application signature */ +// Default application signature const char *SDL_signature = "application/x-SDL-executable"; -/* Create a descendant of BApplication */ +// Create a descendant of BApplication class SDL_BApp : public BApplication { public: SDL_BApp(const char* signature) : @@ -104,10 +104,10 @@ static int StartBeApp(void *unused) } -static int StartBeLooper() +static bool StartBeLooper() { if (!be_app) { - SDL_AppThread = SDL_CreateThreadInternal(StartBeApp, "SDLApplication", 0, NULL); + SDL_AppThread = SDL_CreateThread(StartBeApp, "SDLApplication", NULL); if (!SDL_AppThread) { return SDL_SetError("Couldn't create BApplication thread"); } @@ -117,64 +117,51 @@ static int StartBeLooper() } while ((!be_app) || be_app->IsLaunching()); } - /* Change working directory to that of executable */ - app_info info; - if (B_OK == be_app->GetAppInfo(&info)) { - entry_ref ref = info.ref; - BEntry entry; - if (B_OK == entry.SetTo(&ref)) { - BPath path; - if (B_OK == path.SetTo(&entry)) { - if (B_OK == path.GetParent(&path)) { - chdir(path.Path()); - } - } - } - } - SDL_Looper = new SDL_BLooper("SDLLooper"); SDL_Looper->Run(); - return (0); + return true; } -/* Initialize the Be Application, if it's not already started */ -int SDL_InitBeApp(void) +// Initialize the Be Application, if it's not already started +bool SDL_InitBeApp(void) { - /* Create the BApplication that handles appserver interaction */ + // Create the BApplication that handles appserver interaction if (SDL_BeAppActive <= 0) { - StartBeLooper(); + if (!StartBeLooper()) { + return false; + } - /* Mark the application active */ + // Mark the application active SDL_BeAppActive = 0; } - /* Increment the application reference count */ + // Increment the application reference count ++SDL_BeAppActive; - /* The app is running, and we're ready to go */ - return 0; + // The app is running, and we're ready to go + return true; } -/* Quit the Be Application, if there's nothing left to do */ +// Quit the Be Application, if there's nothing left to do void SDL_QuitBeApp(void) { - /* Decrement the application reference count */ + // Decrement the application reference count --SDL_BeAppActive; - /* If the reference count reached zero, clean up the app */ + // If the reference count reached zero, clean up the app if (SDL_BeAppActive == 0) { SDL_Looper->Lock(); SDL_Looper->Quit(); SDL_Looper = NULL; if (SDL_AppThread) { - if (be_app != NULL) { /* Not tested */ + if (be_app != NULL) { // Not tested be_app->PostMessage(B_QUIT_REQUESTED); } SDL_WaitThread(SDL_AppThread, NULL); SDL_AppThread = NULL; } - /* be_app should now be NULL since be_app has quit */ + // be_app should now be NULL since be_app has quit } } @@ -182,7 +169,7 @@ void SDL_QuitBeApp(void) } #endif -/* SDL_BApp functions */ +// SDL_BApp functions void SDL_BLooper::ClearID(SDL_BWin *bwin) { _SetSDLWindow(NULL, bwin->GetID()); int32 i = _GetNumWindowSlots() - 1; @@ -192,4 +179,4 @@ void SDL_BLooper::ClearID(SDL_BWin *bwin) { } } -#endif /* SDL_PLATFORM_HAIKU */ +#endif // SDL_PLATFORM_HAIKU diff --git a/libs/SDL3/src/core/haiku/SDL_BeApp.h b/libs/SDL3/src/core/haiku/SDL_BeApp.h index fde331aec..b45e10eab 100644 --- a/libs/SDL3/src/core/haiku/SDL_BeApp.h +++ b/libs/SDL3/src/core/haiku/SDL_BeApp.h @@ -23,15 +23,15 @@ #ifdef __cplusplus extern "C" { #endif -/* Handle the BeApp specific portions of the application */ +// Handle the BeApp specific portions of the application -/* Initialize the Be Application, if it's not already started */ -extern int SDL_InitBeApp(void); +// Initialize the Be Application, if it's not already started +extern bool SDL_InitBeApp(void); -/* Quit the Be Application, if there's nothing left to do */ +// Quit the Be Application, if there's nothing left to do extern void SDL_QuitBeApp(void); -/* Be Application Signature*/ +// Be Application Signature extern const char *SDL_signature; diff --git a/libs/SDL3/src/core/linux/SDL_dbus.c b/libs/SDL3/src/core/linux/SDL_dbus.c index 9e6a56b65..e3f132d86 100644 --- a/libs/SDL3/src/core/linux/SDL_dbus.c +++ b/libs/SDL3/src/core/linux/SDL_dbus.c @@ -24,21 +24,21 @@ #include "../../stdlib/SDL_vacopy.h" #ifdef SDL_USE_LIBDBUS -/* we never link directly to libdbus. */ +// we never link directly to libdbus. static const char *dbus_library = "libdbus-1.so.3"; -static void *dbus_handle = NULL; +static SDL_SharedObject *dbus_handle = NULL; static char *inhibit_handle = NULL; static unsigned int screensaver_cookie = 0; static SDL_DBusContext dbus; -static int LoadDBUSSyms(void) +static bool LoadDBUSSyms(void) { #define SDL_DBUS_SYM2_OPTIONAL(TYPE, x, y) \ dbus.x = (TYPE)SDL_LoadFunction(dbus_handle, #y) #define SDL_DBUS_SYM2(TYPE, x, y) \ if (!(dbus.x = (TYPE)SDL_LoadFunction(dbus_handle, #y))) \ - return -1 + return false #define SDL_DBUS_SYM_OPTIONAL(TYPE, x) \ SDL_DBUS_SYM2_OPTIONAL(TYPE, x, dbus_##x) @@ -93,7 +93,7 @@ static int LoadDBUSSyms(void) #undef SDL_DBUS_SYM #undef SDL_DBUS_SYM2 - return 0; + return true; } static void UnloadDBUSLibrary(void) @@ -104,79 +104,79 @@ static void UnloadDBUSLibrary(void) } } -static int LoadDBUSLibrary(void) +static bool LoadDBUSLibrary(void) { - int retval = 0; + bool result = true; if (!dbus_handle) { dbus_handle = SDL_LoadObject(dbus_library); if (!dbus_handle) { - retval = -1; - /* Don't call SDL_SetError(): SDL_LoadObject already did. */ + result = false; + // Don't call SDL_SetError(): SDL_LoadObject already did. } else { - retval = LoadDBUSSyms(); - if (retval < 0) { + result = LoadDBUSSyms(); + if (!result) { UnloadDBUSLibrary(); } } } - - return retval; + return result; } -static SDL_SpinLock spinlock_dbus_init = 0; +static SDL_InitState dbus_init; -/* you must hold spinlock_dbus_init before calling this! */ -static void SDL_DBus_Init_Spinlocked(void) +void SDL_DBus_Init(void) { - static SDL_bool is_dbus_available = SDL_TRUE; + static bool is_dbus_available = true; + if (!is_dbus_available) { - return; /* don't keep trying if this fails. */ + return; // don't keep trying if this fails. } - if (!dbus.session_conn) { - DBusError err; - - if (LoadDBUSLibrary() == -1) { - is_dbus_available = SDL_FALSE; /* can't load at all? Don't keep trying. */ - return; - } - - if (!dbus.threads_init_default()) { - is_dbus_available = SDL_FALSE; - return; - } + if (!SDL_ShouldInit(&dbus_init)) { + return; + } - dbus.error_init(&err); - /* session bus is required */ + if (!LoadDBUSLibrary()) { + goto error; + } - dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err); - if (dbus.error_is_set(&err)) { - dbus.error_free(&err); - SDL_DBus_Quit(); - is_dbus_available = SDL_FALSE; - return; /* oh well */ - } - dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0); + if (!dbus.threads_init_default()) { + goto error; + } - /* system bus is optional */ - dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err); - if (!dbus.error_is_set(&err)) { - dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0); - } + DBusError err; + dbus.error_init(&err); + // session bus is required + dbus.session_conn = dbus.bus_get_private(DBUS_BUS_SESSION, &err); + if (dbus.error_is_set(&err)) { dbus.error_free(&err); + goto error; } -} + dbus.connection_set_exit_on_disconnect(dbus.session_conn, 0); -void SDL_DBus_Init(void) -{ - SDL_LockSpinlock(&spinlock_dbus_init); /* make sure two threads can't init at same time, since this can happen before SDL_Init. */ - SDL_DBus_Init_Spinlocked(); - SDL_UnlockSpinlock(&spinlock_dbus_init); + // system bus is optional + dbus.system_conn = dbus.bus_get_private(DBUS_BUS_SYSTEM, &err); + if (!dbus.error_is_set(&err)) { + dbus.connection_set_exit_on_disconnect(dbus.system_conn, 0); + } + + dbus.error_free(&err); + SDL_SetInitialized(&dbus_init, true); + return; + +error: + is_dbus_available = false; + SDL_SetInitialized(&dbus_init, true); + SDL_DBus_Quit(); } void SDL_DBus_Quit(void) { + if (!SDL_ShouldQuit(&dbus_init)) { + return; + } + if (dbus.system_conn) { dbus.connection_close(dbus.system_conn); dbus.connection_unref(dbus.system_conn); @@ -186,7 +186,7 @@ void SDL_DBus_Quit(void) dbus.connection_unref(dbus.session_conn); } - if (SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, SDL_FALSE)) { + if (SDL_GetHintBoolean(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, false)) { if (dbus.shutdown) { dbus.shutdown(); } @@ -194,8 +194,12 @@ void SDL_DBus_Quit(void) SDL_zero(dbus); UnloadDBUSLibrary(); - SDL_free(inhibit_handle); - inhibit_handle = NULL; + if (inhibit_handle) { + SDL_free(inhibit_handle); + inhibit_handle = NULL; + } + + SDL_SetInitialized(&dbus_init, false); } SDL_DBusContext *SDL_DBus_GetContext(void) @@ -207,23 +211,23 @@ SDL_DBusContext *SDL_DBus_GetContext(void) return (dbus_handle && dbus.session_conn) ? &dbus : NULL; } -static SDL_bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) +static bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) { - SDL_bool retval = SDL_FALSE; + bool result = false; if (conn) { DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method); if (msg) { int firstarg; va_list ap_reply; - va_copy(ap_reply, ap); /* copy the arg list so we don't compete with D-Bus for it */ + va_copy(ap_reply, ap); // copy the arg list so we don't compete with D-Bus for it firstarg = va_arg(ap, int); if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) { DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); if (reply) { - /* skip any input args, get to output args. */ + // skip any input args, get to output args. while ((firstarg = va_arg(ap_reply, int)) != DBUS_TYPE_INVALID) { - /* we assume D-Bus already validated all this. */ + // we assume D-Bus already validated all this. { void *dumpptr = va_arg(ap_reply, void *); (void)dumpptr; @@ -237,7 +241,7 @@ static SDL_bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *no } firstarg = va_arg(ap_reply, int); if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_get_args_valist(reply, NULL, firstarg, ap_reply)) { - retval = SDL_TRUE; + result = true; } dbus.message_unref(reply); } @@ -247,32 +251,32 @@ static SDL_bool SDL_DBus_CallMethodInternal(DBusConnection *conn, const char *no } } - return retval; + return result; } -SDL_bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) { - SDL_bool retval; + bool result; va_list ap; va_start(ap, method); - retval = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap); + result = SDL_DBus_CallMethodInternal(conn, node, path, interface, method, ap); va_end(ap); - return retval; + return result; } -SDL_bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...) { - SDL_bool retval; + bool result; va_list ap; va_start(ap, method); - retval = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap); + result = SDL_DBus_CallMethodInternal(dbus.session_conn, node, path, interface, method, ap); va_end(ap); - return retval; + return result; } -static SDL_bool SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) +static bool SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) { - SDL_bool retval = SDL_FALSE; + bool result = false; if (conn) { DBusMessage *msg = dbus.message_new_method_call(node, path, interface, method); @@ -281,7 +285,7 @@ static SDL_bool SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char if ((firstarg == DBUS_TYPE_INVALID) || dbus.message_append_args_valist(msg, firstarg, ap)) { if (dbus.connection_send(conn, msg, NULL)) { dbus.connection_flush(conn); - retval = SDL_TRUE; + result = true; } } @@ -289,12 +293,12 @@ static SDL_bool SDL_DBus_CallVoidMethodInternal(DBusConnection *conn, const char } } - return retval; + return result; } -static SDL_bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *msg, const int expectedtype, void *result) +static bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *msg, const int expectedtype, void *result) { - SDL_bool retval = SDL_FALSE; + bool retval = false; DBusMessage *reply = dbus.connection_send_with_reply_and_block(conn, msg, 300, NULL); if (reply) { @@ -308,7 +312,7 @@ static SDL_bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *m if (dbus.message_iter_get_arg_type(&actual_iter) == expectedtype) { dbus.message_iter_get_basic(&actual_iter, result); - retval = SDL_TRUE; + retval = true; } dbus.message_unref(reply); @@ -317,29 +321,29 @@ static SDL_bool SDL_DBus_CallWithBasicReply(DBusConnection *conn, DBusMessage *m return retval; } -SDL_bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) { - SDL_bool retval; + bool result; va_list ap; va_start(ap, method); - retval = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap); + result = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap); va_end(ap); - return retval; + return result; } -SDL_bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...) +bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...) { - SDL_bool retval; + bool result; va_list ap; va_start(ap, method); - retval = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap); + result = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap); va_end(ap); - return retval; + return result; } -SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result) +bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) { - SDL_bool retval = SDL_FALSE; + bool retval = false; if (conn) { DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get"); @@ -354,21 +358,21 @@ SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *no return retval; } -SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result) +bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result) { return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result); } void SDL_DBus_ScreensaverTickle(void) { - if (screensaver_cookie == 0 && !inhibit_handle) { /* no need to tickle if we're inhibiting. */ - /* org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. */ + if (screensaver_cookie == 0 && !inhibit_handle) { // no need to tickle if we're inhibiting. + // org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now. SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID); SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID); } } -static SDL_bool SDL_DBus_AppendDictWithKeysAndValues(DBusMessageIter *iterInit, const char **keys, const char **values, int count) +static bool SDL_DBus_AppendDictWithKeysAndValues(DBusMessageIter *iterInit, const char **keys, const char **values, int count) { DBusMessageIter iterDict; @@ -406,16 +410,16 @@ static SDL_bool SDL_DBus_AppendDictWithKeysAndValues(DBusMessageIter *iterInit, goto failed; } - return SDL_TRUE; + return true; failed: /* message_iter_abandon_container_if_open() and message_iter_abandon_container() might be * missing if libdbus is too old. Instead, we just return without cleaning up any eventual * open container */ - return SDL_FALSE; + return false; } -static SDL_bool SDL_DBus_AppendDictWithKeyValue(DBusMessageIter *iterInit, const char *key, const char *value) +static bool SDL_DBus_AppendDictWithKeyValue(DBusMessageIter *iterInit, const char *key, const char *value) { const char *keys[1]; const char *values[1]; @@ -425,31 +429,31 @@ static SDL_bool SDL_DBus_AppendDictWithKeyValue(DBusMessageIter *iterInit, const return SDL_DBus_AppendDictWithKeysAndValues(iterInit, keys, values, 1); } -SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) +bool SDL_DBus_ScreensaverInhibit(bool inhibit) { const char *default_inhibit_reason = "Playing a game"; if ((inhibit && (screensaver_cookie != 0 || inhibit_handle)) || (!inhibit && (screensaver_cookie == 0 && !inhibit_handle))) { - return SDL_TRUE; + return true; } if (!dbus.session_conn) { /* We either lost connection to the session bus or were not able to * load the D-Bus library at all. */ - return SDL_FALSE; + return false; } if (SDL_DetectSandbox() != SDL_SANDBOX_NONE) { const char *bus_name = "org.freedesktop.portal.Desktop"; const char *path = "/org/freedesktop/portal/desktop"; const char *interface = "org.freedesktop.portal.Inhibit"; - const char *window = ""; /* As a future improvement we could gather the X11 XID or Wayland surface identifier */ - static const unsigned int INHIBIT_IDLE = 8; /* Taken from the portal API reference */ + const char *window = ""; // As a future improvement we could gather the X11 XID or Wayland surface identifier + static const unsigned int INHIBIT_IDLE = 8; // Taken from the portal API reference DBusMessageIter iterInit; if (inhibit) { DBusMessage *msg; - SDL_bool retval = SDL_FALSE; + bool result = false; const char *key = "reason"; const char *reply = NULL; const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME); @@ -459,32 +463,32 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) msg = dbus.message_new_method_call(bus_name, path, interface, "Inhibit"); if (!msg) { - return SDL_FALSE; + return false; } if (!dbus.message_append_args(msg, DBUS_TYPE_STRING, &window, DBUS_TYPE_UINT32, &INHIBIT_IDLE, DBUS_TYPE_INVALID)) { dbus.message_unref(msg); - return SDL_FALSE; + return false; } dbus.message_iter_init_append(msg, &iterInit); - /* a{sv} */ + // a{sv} if (!SDL_DBus_AppendDictWithKeyValue(&iterInit, key, reason)) { dbus.message_unref(msg); - return SDL_FALSE; + return false; } if (SDL_DBus_CallWithBasicReply(dbus.session_conn, msg, DBUS_TYPE_OBJECT_PATH, &reply)) { inhibit_handle = SDL_strdup(reply); - retval = SDL_TRUE; + result = true; } dbus.message_unref(msg); - return retval; + return result; } else { if (!SDL_DBus_CallVoidMethod(bus_name, inhibit_handle, "org.freedesktop.portal.Request", "Close", DBUS_TYPE_INVALID)) { - return SDL_FALSE; + return false; } SDL_free(inhibit_handle); inhibit_handle = NULL; @@ -495,11 +499,8 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) const char *interface = "org.freedesktop.ScreenSaver"; if (inhibit) { - const char *app = SDL_GetHint(SDL_HINT_APP_NAME); + const char *app = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); const char *reason = SDL_GetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME); - if (!app || !app[0]) { - app = "My SDL application"; - } if (!reason || !reason[0]) { reason = default_inhibit_reason; } @@ -507,18 +508,18 @@ SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit) if (!SDL_DBus_CallMethod(bus_name, path, interface, "Inhibit", DBUS_TYPE_STRING, &app, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID, DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { - return SDL_FALSE; + return false; } return (screensaver_cookie != 0); } else { if (!SDL_DBus_CallVoidMethod(bus_name, path, interface, "UnInhibit", DBUS_TYPE_UINT32, &screensaver_cookie, DBUS_TYPE_INVALID)) { - return SDL_FALSE; + return false; } screensaver_cookie = 0; } } - return SDL_TRUE; + return true; } void SDL_DBus_PumpEvents(void) @@ -527,7 +528,7 @@ void SDL_DBus_PumpEvents(void) dbus.connection_read_write(dbus.session_conn, 0); while (dbus.connection_dispatch(dbus.session_conn) == DBUS_DISPATCH_DATA_REMAINS) { - /* Do nothing, actual work happens in DBus_MessageFilter */ + // Do nothing, actual work happens in DBus_MessageFilter SDL_DelayNS(SDL_US_TO_NS(10)); } } @@ -544,7 +545,7 @@ char *SDL_DBus_GetLocalMachineId(void) dbus.error_init(&err); if (dbus.try_get_local_machine_id) { - /* Available since dbus 1.12.0, has proper error-handling */ + // Available since dbus 1.12.0, has proper error-handling result = dbus.try_get_local_machine_id(&err); } else { /* Available since time immemorial, but has no error-handling: @@ -578,12 +579,12 @@ char **SDL_DBus_DocumentsPortalRetrieveFiles(const char *key, int *path_count) DBusMessageIter iter, iterDict; char **paths = NULL; DBusMessage *reply = NULL; - DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.portal.Documents", /* Node */ - "/org/freedesktop/portal/documents", /* Path */ - "org.freedesktop.portal.FileTransfer", /* Interface */ - "RetrieveFiles"); /* Method */ + DBusMessage *msg = dbus.message_new_method_call("org.freedesktop.portal.Documents", // Node + "/org/freedesktop/portal/documents", // Path + "org.freedesktop.portal.FileTransfer", // Interface + "RetrieveFiles"); // Method - /* Make sure we have a connection to the dbus session bus */ + // Make sure we have a connection to the dbus session bus if (!SDL_DBus_GetContext() || !dbus.session_conn) { /* We either cannot connect to the session bus or were unable to * load the D-Bus library at all. */ @@ -592,7 +593,7 @@ char **SDL_DBus_DocumentsPortalRetrieveFiles(const char *key, int *path_count) dbus.error_init(&err); - /* First argument is a "application/vnd.portal.filetransfer" key from a DnD or clipboard event */ + // First argument is a "application/vnd.portal.filetransfer" key from a DnD or clipboard event if (!dbus.message_append_args(msg, DBUS_TYPE_STRING, &key, DBUS_TYPE_INVALID)) { SDL_OutOfMemory(); dbus.message_unref(msg); diff --git a/libs/SDL3/src/core/linux/SDL_dbus.h b/libs/SDL3/src/core/linux/SDL_dbus.h index 0be866b36..55fb8ac7a 100644 --- a/libs/SDL3/src/core/linux/SDL_dbus.h +++ b/libs/SDL3/src/core/linux/SDL_dbus.h @@ -91,24 +91,24 @@ extern void SDL_DBus_Init(void); extern void SDL_DBus_Quit(void); extern SDL_DBusContext *SDL_DBus_GetContext(void); -/* These use the built-in Session connection. */ -extern SDL_bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...); -extern SDL_bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...); -extern SDL_bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result); +// These use the built-in Session connection. +extern bool SDL_DBus_CallMethod(const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); -/* These use whatever connection you like. */ -extern SDL_bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); -extern SDL_bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); -extern SDL_bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, const int expectedtype, void *result); +// These use whatever connection you like. +extern bool SDL_DBus_CallMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...); +extern bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result); extern void SDL_DBus_ScreensaverTickle(void); -extern SDL_bool SDL_DBus_ScreensaverInhibit(SDL_bool inhibit); +extern bool SDL_DBus_ScreensaverInhibit(bool inhibit); extern void SDL_DBus_PumpEvents(void); extern char *SDL_DBus_GetLocalMachineId(void); extern char **SDL_DBus_DocumentsPortalRetrieveFiles(const char *key, int *files_count); -#endif /* HAVE_DBUS_DBUS_H */ +#endif // HAVE_DBUS_DBUS_H -#endif /* SDL_dbus_h_ */ +#endif // SDL_dbus_h_ diff --git a/libs/SDL3/src/core/linux/SDL_evdev.c b/libs/SDL3/src/core/linux/SDL_evdev.c index 0f464e301..c5b62ae78 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev.c +++ b/libs/SDL3/src/core/linux/SDL_evdev.c @@ -22,7 +22,7 @@ #ifdef SDL_INPUT_LINUXEV -/* This is based on the linux joystick driver */ +// This is based on the linux joystick driver /* References: https://www.kernel.org/doc/Documentation/input/input.txt * https://www.kernel.org/doc/Documentation/input/event-codes.txt * /usr/include/linux/input.h @@ -43,7 +43,7 @@ #include "../../core/linux/SDL_evdev_capabilities.h" #include "../../core/linux/SDL_udev.h" -/* These are not defined in older Linux kernel headers */ +// These are not defined in older Linux kernel headers #ifndef SYN_DROPPED #define SYN_DROPPED 3 #endif @@ -59,12 +59,12 @@ #define REL_HWHEEL_HI_RES 0x0c #endif -/* The field to look up in struct input_event for integer seconds */ +// The field to look up in struct input_event for integer seconds #ifndef input_event_sec #define input_event_sec time.tv_sec #endif -/* The field to look up in struct input_event for fractional seconds */ +// The field to look up in struct input_event for fractional seconds #ifndef input_event_usec #define input_event_usec time.tv_usec #endif @@ -75,13 +75,13 @@ typedef struct SDL_evdevlist_item int fd; int udev_class; - /* TODO: use this for every device, not just touchscreen */ - SDL_bool out_of_sync; + // TODO: use this for every device, not just touchscreen + bool out_of_sync; /* TODO: expand on this to have data for every possible class (mouse, keyboard, touchpad, etc.). Also there's probably some things in here we can pull out to the SDL_evdevlist_item i.e. name */ - SDL_bool is_touchscreen; + bool is_touchscreen; struct { char *name; @@ -107,10 +107,10 @@ typedef struct SDL_evdevlist_item } *touchscreen_data; - /* Mouse state */ - SDL_bool high_res_wheel; - SDL_bool high_res_hwheel; - SDL_bool relative_mouse; + // Mouse state + bool high_res_wheel; + bool high_res_hwheel; + bool relative_mouse; int mouse_x, mouse_y; int mouse_wheel, mouse_hwheel; int min_x, max_x, range_x; @@ -132,63 +132,62 @@ static SDL_EVDEV_PrivateData *_this = NULL; static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode); static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item); -static int SDL_EVDEV_device_removed(const char *dev_path); - -static int SDL_EVDEV_device_added(const char *dev_path, int udev_class); +static bool SDL_EVDEV_device_removed(const char *dev_path); +static bool SDL_EVDEV_device_added(const char *dev_path, int udev_class); #ifdef SDL_USE_LIBUDEV static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class, const char *dev_path); -#endif /* SDL_USE_LIBUDEV */ +#endif // SDL_USE_LIBUDEV static Uint8 EVDEV_MouseButtons[] = { - SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */ - SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */ - SDL_BUTTON_MIDDLE, /* BTN_MIDDLE 0x112 */ - SDL_BUTTON_X1, /* BTN_SIDE 0x113 */ - SDL_BUTTON_X2, /* BTN_EXTRA 0x114 */ - SDL_BUTTON_X2 + 1, /* BTN_FORWARD 0x115 */ - SDL_BUTTON_X2 + 2, /* BTN_BACK 0x116 */ - SDL_BUTTON_X2 + 3 /* BTN_TASK 0x117 */ + SDL_BUTTON_LEFT, // BTN_LEFT 0x110 + SDL_BUTTON_RIGHT, // BTN_RIGHT 0x111 + SDL_BUTTON_MIDDLE, // BTN_MIDDLE 0x112 + SDL_BUTTON_X1, // BTN_SIDE 0x113 + SDL_BUTTON_X2, // BTN_EXTRA 0x114 + SDL_BUTTON_X2 + 1, // BTN_FORWARD 0x115 + SDL_BUTTON_X2 + 2, // BTN_BACK 0x116 + SDL_BUTTON_X2 + 3 // BTN_TASK 0x117 }; -static int SDL_EVDEV_SetRelativeMouseMode(SDL_bool enabled) +static bool SDL_EVDEV_SetRelativeMouseMode(bool enabled) { - /* Mice already send relative events through this interface */ - return 0; + // Mice already send relative events through this interface + return true; } static void SDL_EVDEV_UpdateKeyboardMute(void) { if (SDL_EVDEV_GetDeviceCount(SDL_UDEV_DEVICE_KEYBOARD) > 0) { - SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_TRUE); + SDL_EVDEV_kbd_set_muted(_this->kbd, true); } else { - SDL_EVDEV_kbd_set_muted(_this->kbd, SDL_FALSE); + SDL_EVDEV_kbd_set_muted(_this->kbd, false); } } -int SDL_EVDEV_Init(void) +bool SDL_EVDEV_Init(void) { if (!_this) { _this = (SDL_EVDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); if (!_this) { - return -1; + return false; } #ifdef SDL_USE_LIBUDEV - if (SDL_UDEV_Init() < 0) { + if (!SDL_UDEV_Init()) { SDL_free(_this); _this = NULL; - return -1; + return false; } - /* Set up the udev callback */ - if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) { + // Set up the udev callback + if (!SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback)) { SDL_UDEV_Quit(); SDL_free(_this); _this = NULL; - return -1; + return false; } - /* Force a scan to build the initial device list */ + // Force a scan to build the initial device list SDL_UDEV_Scan(); #else { @@ -198,7 +197,7 @@ int SDL_EVDEV_Init(void) where device class is an integer representing the SDL_UDEV_deviceclass and path is the full path to the event device. */ - const char *devices = SDL_getenv("SDL_EVDEV_DEVICES"); + const char *devices = SDL_GetHint(SDL_HINT_EVDEV_DEVICES); if (devices) { /* Assume this is the old use of the env var and it is not in ROM. */ @@ -212,10 +211,10 @@ int SDL_EVDEV_Init(void) } } } else { - /* TODO: Scan the devices manually, like a caveman */ + // TODO: Scan the devices manually, like a caveman } } -#endif /* SDL_USE_LIBUDEV */ +#endif // SDL_USE_LIBUDEV _this->kbd = SDL_EVDEV_kbd_init(); @@ -226,7 +225,7 @@ int SDL_EVDEV_Init(void) _this->ref_count += 1; - return 0; + return true; } void SDL_EVDEV_Quit(void) @@ -241,9 +240,9 @@ void SDL_EVDEV_Quit(void) #ifdef SDL_USE_LIBUDEV SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback); SDL_UDEV_Quit(); -#endif /* SDL_USE_LIBUDEV */ +#endif // SDL_USE_LIBUDEV - /* Remove existing devices */ + // Remove existing devices while (_this->first) { SDL_EVDEV_device_removed(_this->first->path); } @@ -286,7 +285,7 @@ static void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_cl break; } } -#endif /* SDL_USE_LIBUDEV */ +#endif // SDL_USE_LIBUDEV void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data) @@ -314,7 +313,7 @@ void SDL_EVDEV_Poll(void) struct input_event events[32]; int i, j, len; SDL_evdevlist_item *item; - SDL_Scancode scan_code; + SDL_Scancode scancode; int mouse_button; SDL_Mouse *mouse; float norm_x, norm_y, norm_pressure; @@ -348,18 +347,14 @@ void SDL_EVDEV_Poll(void) case EV_KEY: if (event->code >= BTN_MOUSE && event->code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) { mouse_button = event->code - BTN_MOUSE; - if (event->value == 0) { - SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, SDL_RELEASED, EVDEV_MouseButtons[mouse_button]); - } else if (event->value == 1) { - SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, SDL_PRESSED, EVDEV_MouseButtons[mouse_button]); - } + SDL_SendMouseButton(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, EVDEV_MouseButtons[mouse_button], (event->value != 0)); break; } /* BTN_TOUCH event value 1 indicates there is contact with - a touchscreen or trackpad (earlist finger's current + a touchscreen or trackpad (earliest finger's current position is sent in EV_ABS ABS_X/ABS_Y, switching to - next finger after earlist is released) */ + next finger after earliest is released) */ if (item->is_touchscreen && event->code == BTN_TOUCH) { if (item->touchscreen_data->max_slots == 1) { if (event->value) { @@ -371,27 +366,25 @@ void SDL_EVDEV_Poll(void) break; } - /* Probably keyboard */ - scan_code = SDL_EVDEV_translate_keycode(event->code); - if (scan_code != SDL_SCANCODE_UNKNOWN) { - if (event->value == 0) { - SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, SDL_RELEASED, scan_code); - } else if (event->value == 1 || event->value == 2 /* key repeated */) { - SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, SDL_PRESSED, scan_code); - } + // Probably keyboard + scancode = SDL_EVDEV_translate_keycode(event->code); + if (event->value == 0) { + SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, event->code, scancode, false); + } else if (event->value == 1 || event->value == 2 /* key repeated */) { + SDL_SendKeyboardKey(SDL_EVDEV_GetEventTimestamp(event), (SDL_KeyboardID)item->fd, event->code, scancode, true); } SDL_EVDEV_kbd_keycode(_this->kbd, event->code, event->value); break; case EV_ABS: switch (event->code) { case ABS_MT_SLOT: - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } item->touchscreen_data->current_slot = event->value; break; case ABS_MT_TRACKING_ID: - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } if (event->value >= 0) { @@ -402,7 +395,7 @@ void SDL_EVDEV_Poll(void) } break; case ABS_MT_POSITION_X: - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = event->value; @@ -411,7 +404,7 @@ void SDL_EVDEV_Poll(void) } break; case ABS_MT_POSITION_Y: - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = event->value; @@ -420,7 +413,7 @@ void SDL_EVDEV_Poll(void) } break; case ABS_MT_PRESSURE: - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } item->touchscreen_data->slots[item->touchscreen_data->current_slot].pressure = event->value; @@ -489,7 +482,7 @@ void SDL_EVDEV_Poll(void) case EV_SYN: switch (event->code) { case SYN_REPORT: - /* Send mouse axis changes together to ensure consistency and reduce event processing overhead */ + // Send mouse axis changes together to ensure consistency and reduce event processing overhead if (item->relative_mouse) { if (item->mouse_x != 0 || item->mouse_y != 0) { SDL_SendMouseMotion(SDL_EVDEV_GetEventTimestamp(event), mouse->focus, (SDL_MouseID)item->fd, item->relative_mouse, (float)item->mouse_x, (float)item->mouse_y); @@ -523,7 +516,7 @@ void SDL_EVDEV_Poll(void) item->mouse_wheel = item->mouse_hwheel = 0; } - if (!item->is_touchscreen) { /* FIXME: temp hack */ + if (!item->is_touchscreen) { // FIXME: temp hack break; } @@ -537,7 +530,7 @@ void SDL_EVDEV_Poll(void) norm_pressure = (float)(item->touchscreen_data->slots[j].pressure - item->touchscreen_data->min_pressure) / (float)item->touchscreen_data->range_pressure; } else { - /* This touchscreen does not support pressure */ + // This touchscreen does not support pressure norm_pressure = 1.0f; } @@ -546,11 +539,11 @@ void SDL_EVDEV_Poll(void) * be window-relative in that case. */ switch (item->touchscreen_data->slots[j].delta) { case EVDEV_TOUCH_SLOTDELTA_DOWN: - SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_TRUE, norm_x, norm_y, norm_pressure); + SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, true, norm_x, norm_y, norm_pressure); item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; case EVDEV_TOUCH_SLOTDELTA_UP: - SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, SDL_FALSE, norm_x, norm_y, norm_pressure); + SDL_SendTouch(SDL_EVDEV_GetEventTimestamp(event), item->fd, item->touchscreen_data->slots[j].tracking_id, NULL, false, norm_x, norm_y, norm_pressure); item->touchscreen_data->slots[j].tracking_id = 0; item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE; break; @@ -564,12 +557,12 @@ void SDL_EVDEV_Poll(void) } if (item->out_of_sync) { - item->out_of_sync = SDL_FALSE; + item->out_of_sync = false; } break; case SYN_DROPPED: if (item->is_touchscreen) { - item->out_of_sync = SDL_TRUE; + item->out_of_sync = true; } SDL_EVDEV_sync_device(item); break; @@ -600,29 +593,29 @@ static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode) keycode); } } -#endif /* DEBUG_SCANCODES */ +#endif // DEBUG_SCANCODES return scancode; } -static int SDL_EVDEV_init_keyboard(SDL_evdevlist_item *item, int udev_class) +static bool SDL_EVDEV_init_keyboard(SDL_evdevlist_item *item, int udev_class) { char name[128]; name[0] = '\0'; ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); - SDL_AddKeyboard((SDL_KeyboardID)item->fd, name, SDL_TRUE); + SDL_AddKeyboard((SDL_KeyboardID)item->fd, name, true); - return 0; + return true; } static void SDL_EVDEV_destroy_keyboard(SDL_evdevlist_item *item) { - SDL_RemoveKeyboard((SDL_KeyboardID)item->fd); + SDL_RemoveKeyboard((SDL_KeyboardID)item->fd, true); } -static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) +static bool SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) { char name[128]; int ret; @@ -631,12 +624,12 @@ static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) name[0] = '\0'; ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); - SDL_AddMouse((SDL_MouseID)item->fd, name, SDL_TRUE); + SDL_AddMouse((SDL_MouseID)item->fd, name, true); ret = ioctl(item->fd, EVIOCGABS(ABS_X), &abs_info); if (ret < 0) { // no absolute mode info, continue - return 0; + return true; } item->min_x = abs_info.minimum; item->max_x = abs_info.maximum; @@ -645,21 +638,21 @@ static int SDL_EVDEV_init_mouse(SDL_evdevlist_item *item, int udev_class) ret = ioctl(item->fd, EVIOCGABS(ABS_Y), &abs_info); if (ret < 0) { // no absolute mode info, continue - return 0; + return true; } item->min_y = abs_info.minimum; item->max_y = abs_info.maximum; item->range_y = abs_info.maximum - abs_info.minimum; - return 0; + return true; } static void SDL_EVDEV_destroy_mouse(SDL_evdevlist_item *item) { - SDL_RemoveMouse((SDL_MouseID)item->fd); + SDL_RemoveMouse((SDL_MouseID)item->fd, true); } -static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) +static bool SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) { int ret; unsigned long xreq, yreq; @@ -667,12 +660,12 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) struct input_absinfo abs_info; if (!item->is_touchscreen) { - return 0; + return true; } item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data)); if (!item->touchscreen_data) { - return -1; + return false; } ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name); @@ -684,7 +677,7 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) item->touchscreen_data->name = SDL_strdup(name); if (!item->touchscreen_data->name) { SDL_free(item->touchscreen_data); - return -1; + return false; } ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info); @@ -740,20 +733,20 @@ static int SDL_EVDEV_init_touchscreen(SDL_evdevlist_item *item, int udev_class) if (!item->touchscreen_data->slots) { SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); - return -1; + return false; } - ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */ + ret = SDL_AddTouch(item->fd, // I guess our fd is unique enough (udev_class & SDL_UDEV_DEVICE_TOUCHPAD) ? SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE : SDL_TOUCH_DEVICE_DIRECT, item->touchscreen_data->name); if (ret < 0) { SDL_free(item->touchscreen_data->slots); SDL_free(item->touchscreen_data->name); SDL_free(item->touchscreen_data); - return ret; + return false; } - return 0; + return true; } static void SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item *item) @@ -785,7 +778,7 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) Sint32 *mt_req_values; size_t mt_req_size; - /* TODO: sync devices other than touchscreen */ + // TODO: sync devices other than touchscreen if (!item->is_touchscreen) { return; } @@ -890,24 +883,24 @@ static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item) SDL_free(mt_req_code); -#endif /* EVIOCGMTSLOTS */ +#endif // EVIOCGMTSLOTS } -static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) +static bool SDL_EVDEV_device_added(const char *dev_path, int udev_class) { SDL_evdevlist_item *item; unsigned long relbit[NBITS(REL_MAX)] = { 0 }; - /* Check to make sure it's not already in list. */ + // Check to make sure it's not already in list. for (item = _this->first; item; item = item->next) { if (SDL_strcmp(dev_path, item->path) == 0) { - return -1; /* already have this one */ + return false; // already have this one } } item = (SDL_evdevlist_item *)SDL_calloc(1, sizeof(SDL_evdevlist_item)); if (!item) { - return -1; + return false; } item->fd = open(dev_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); @@ -920,7 +913,7 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) if (!item->path) { close(item->fd); SDL_free(item); - return -1; + return false; } item->udev_class = udev_class; @@ -931,32 +924,28 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) item->high_res_hwheel = test_bit(REL_HWHEEL_HI_RES, relbit); } - /* For now, we just treat a touchpad like a touchscreen */ + // For now, we just treat a touchpad like a touchscreen if (udev_class & (SDL_UDEV_DEVICE_TOUCHSCREEN | SDL_UDEV_DEVICE_TOUCHPAD)) { - int ret; - item->is_touchscreen = SDL_TRUE; - ret = SDL_EVDEV_init_touchscreen(item, udev_class); - if (ret < 0) { + item->is_touchscreen = true; + if (!SDL_EVDEV_init_touchscreen(item, udev_class)) { close(item->fd); SDL_free(item->path); SDL_free(item); - return ret; + return false; } } else if (udev_class & SDL_UDEV_DEVICE_MOUSE) { - int ret = SDL_EVDEV_init_mouse(item, udev_class); - if (ret < 0) { + if (!SDL_EVDEV_init_mouse(item, udev_class)) { close(item->fd); SDL_free(item->path); SDL_free(item); - return ret; + return false; } } else if (udev_class & SDL_UDEV_DEVICE_KEYBOARD) { - int ret = SDL_EVDEV_init_keyboard(item, udev_class); - if (ret < 0) { + if (!SDL_EVDEV_init_keyboard(item, udev_class)) { close(item->fd); SDL_free(item->path); SDL_free(item); - return ret; + return false; } } @@ -971,16 +960,17 @@ static int SDL_EVDEV_device_added(const char *dev_path, int udev_class) SDL_EVDEV_UpdateKeyboardMute(); - return _this->num_devices++; + ++_this->num_devices; + return true; } -static int SDL_EVDEV_device_removed(const char *dev_path) +static bool SDL_EVDEV_device_removed(const char *dev_path) { SDL_evdevlist_item *item; SDL_evdevlist_item *prev = NULL; for (item = _this->first; item; item = item->next) { - /* found it, remove it. */ + // found it, remove it. if (SDL_strcmp(dev_path, item->path) == 0) { if (prev) { prev->next = item->next; @@ -1003,12 +993,12 @@ static int SDL_EVDEV_device_removed(const char *dev_path) SDL_free(item); SDL_EVDEV_UpdateKeyboardMute(); _this->num_devices--; - return 0; + return true; } prev = item; } - return -1; + return false; } Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event) @@ -1035,4 +1025,4 @@ Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event) return timestamp; } -#endif /* SDL_INPUT_LINUXEV */ +#endif // SDL_INPUT_LINUXEV diff --git a/libs/SDL3/src/core/linux/SDL_evdev.h b/libs/SDL3/src/core/linux/SDL_evdev.h index fc7c4bd53..0eaa60067 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev.h +++ b/libs/SDL3/src/core/linux/SDL_evdev.h @@ -28,7 +28,7 @@ struct input_event; -extern int SDL_EVDEV_Init(void); +extern bool SDL_EVDEV_Init(void); extern void SDL_EVDEV_Quit(void); extern void SDL_EVDEV_SetVTSwitchCallbacks(void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data); @@ -36,6 +36,6 @@ extern int SDL_EVDEV_GetDeviceCount(int device_class); extern void SDL_EVDEV_Poll(void); extern Uint64 SDL_EVDEV_GetEventTimestamp(struct input_event *event); -#endif /* SDL_INPUT_LINUXEV */ +#endif // SDL_INPUT_LINUXEV -#endif /* SDL_evdev_h_ */ +#endif // SDL_evdev_h_ diff --git a/libs/SDL3/src/core/linux/SDL_evdev_capabilities.c b/libs/SDL3/src/core/linux/SDL_evdev_capabilities.c index 865abf4fe..1a04f6b59 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev_capabilities.c +++ b/libs/SDL3/src/core/linux/SDL_evdev_capabilities.c @@ -25,7 +25,7 @@ #ifdef HAVE_LINUX_INPUT_H -/* missing defines in older Linux kernel headers */ +// missing defines in older Linux kernel headers #ifndef BTN_TRIGGER_HAPPY #define BTN_TRIGGER_HAPPY 0x2c0 #endif @@ -49,7 +49,7 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA unsigned end; }; - /* key code ranges above BTN_MISC (start is inclusive, stop is exclusive)*/ + // key code ranges above BTN_MISC (start is inclusive, stop is exclusive) static const struct range high_key_blocks[] = { { KEY_OK, BTN_DPAD_UP }, { KEY_ALS_TOGGLE, BTN_TRIGGER_HAPPY } @@ -58,23 +58,24 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA int devclass = 0; unsigned long keyboard_mask; - /* If the kernel specifically says it's an accelerometer, believe it */ + // If the kernel specifically says it's an accelerometer, believe it if (test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props)) { return SDL_UDEV_DEVICE_ACCELEROMETER; } - /* We treat pointing sticks as indistinguishable from mice */ + // We treat pointing sticks as indistinguishable from mice if (test_bit(INPUT_PROP_POINTING_STICK, bitmask_props)) { return SDL_UDEV_DEVICE_MOUSE; } - /* We treat buttonpads as equivalent to touchpads */ + // We treat buttonpads as equivalent to touchpads if (test_bit(INPUT_PROP_TOPBUTTONPAD, bitmask_props) || - test_bit(INPUT_PROP_BUTTONPAD, bitmask_props)) { + test_bit(INPUT_PROP_BUTTONPAD, bitmask_props) || + test_bit(INPUT_PROP_SEMI_MT, bitmask_props)) { return SDL_UDEV_DEVICE_TOUCHPAD; } - /* X, Y, Z axes but no buttons probably means an accelerometer */ + // X, Y, Z axes but no buttons probably means an accelerometer if (test_bit(EV_ABS, bitmask_ev) && test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs) && @@ -96,15 +97,15 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA if (test_bit(EV_ABS, bitmask_ev) && test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs)) { if (test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key)) { - ; /* ID_INPUT_TABLET */ + ; // ID_INPUT_TABLET } else if (test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key)) { - devclass |= SDL_UDEV_DEVICE_TOUCHPAD; /* ID_INPUT_TOUCHPAD */ + devclass |= SDL_UDEV_DEVICE_TOUCHPAD; // ID_INPUT_TOUCHPAD } else if (test_bit(BTN_MOUSE, bitmask_key)) { - devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ + devclass |= SDL_UDEV_DEVICE_MOUSE; // ID_INPUT_MOUSE } else if (test_bit(BTN_TOUCH, bitmask_key)) { /* TODO: better determining between touchscreen and multitouch touchpad, see https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-input_id.c */ - devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; /* ID_INPUT_TOUCHSCREEN */ + devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; // ID_INPUT_TOUCHSCREEN } if (test_bit(BTN_TRIGGER, bitmask_key) || @@ -118,14 +119,14 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA test_bit(ABS_WHEEL, bitmask_abs) || test_bit(ABS_GAS, bitmask_abs) || test_bit(ABS_BRAKE, bitmask_abs)) { - devclass |= SDL_UDEV_DEVICE_JOYSTICK; /* ID_INPUT_JOYSTICK */ + devclass |= SDL_UDEV_DEVICE_JOYSTICK; // ID_INPUT_JOYSTICK } } if (test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel) && test_bit(BTN_MOUSE, bitmask_key)) { - devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */ + devclass |= SDL_UDEV_DEVICE_MOUSE; // ID_INPUT_MOUSE } if (test_bit(EV_KEY, bitmask_ev)) { @@ -135,7 +136,7 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA for (i = 0; i < BTN_MISC / BITS_PER_LONG; ++i) { found |= bitmask_key[i]; } - /* If there are no keys in the lower block, check the higher blocks */ + // If there are no keys in the lower block, check the higher blocks if (!found) { unsigned block; for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) { @@ -149,7 +150,7 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA } if (found > 0) { - devclass |= SDL_UDEV_DEVICE_HAS_KEYS; /* ID_INPUT_KEY */ + devclass |= SDL_UDEV_DEVICE_HAS_KEYS; // ID_INPUT_KEY } } @@ -158,10 +159,10 @@ SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(INPUT_PROP_MA * do not test KEY_RESERVED, though */ keyboard_mask = 0xFFFFFFFE; if ((bitmask_key[0] & keyboard_mask) == keyboard_mask) { - devclass |= SDL_UDEV_DEVICE_KEYBOARD; /* ID_INPUT_KEYBOARD */ + devclass |= SDL_UDEV_DEVICE_KEYBOARD; // ID_INPUT_KEYBOARD } return devclass; } -#endif /* HAVE_LINUX_INPUT_H */ +#endif // HAVE_LINUX_INPUT_H diff --git a/libs/SDL3/src/core/linux/SDL_evdev_capabilities.h b/libs/SDL3/src/core/linux/SDL_evdev_capabilities.h index 49df8da79..57667d257 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev_capabilities.h +++ b/libs/SDL3/src/core/linux/SDL_evdev_capabilities.h @@ -28,6 +28,9 @@ #include +#ifndef INPUT_PROP_SEMI_MT +#define INPUT_PROP_SEMI_MT 0x03 +#endif #ifndef INPUT_PROP_TOPBUTTONPAD #define INPUT_PROP_TOPBUTTONPAD 0x04 #endif @@ -41,7 +44,7 @@ #define INPUT_PROP_MAX 0x1f #endif -/* A device can be any combination of these classes */ +// A device can be any combination of these classes typedef enum { SDL_UDEV_DEVICE_UNKNOWN = 0x0000, @@ -68,6 +71,6 @@ extern int SDL_EVDEV_GuessDeviceClass(const unsigned long bitmask_props[NBITS(IN const unsigned long bitmask_key[NBITS(KEY_MAX)], const unsigned long bitmask_rel[NBITS(REL_MAX)]); -#endif /* HAVE_LINUX_INPUT_H */ +#endif // HAVE_LINUX_INPUT_H -#endif /* SDL_evdev_capabilities_h_ */ +#endif // SDL_evdev_capabilities_h_ diff --git a/libs/SDL3/src/core/linux/SDL_evdev_kbd.c b/libs/SDL3/src/core/linux/SDL_evdev_kbd.c index bf4832983..5ea7b5552 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev_kbd.c +++ b/libs/SDL3/src/core/linux/SDL_evdev_kbd.c @@ -24,7 +24,7 @@ #ifdef SDL_INPUT_LINUXKD -/* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source */ +// This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source #include #include @@ -32,7 +32,7 @@ #include #include #include -#include /* for TIOCL_GETSHIFTSTATE */ +#include // for TIOCL_GETSHIFTSTATE #include @@ -40,7 +40,7 @@ #include "SDL_evdev_kbd_default_accents.h" #include "SDL_evdev_kbd_default_keymap.h" -/* These are not defined in older Linux kernel headers */ +// These are not defined in older Linux kernel headers #ifndef K_UNICODE #define K_UNICODE 0x03 #endif @@ -84,15 +84,15 @@ static fn_handler_fn *fn_handler[] = { struct SDL_EVDEV_keyboard_state { int console_fd; - SDL_bool muted; + bool muted; int old_kbd_mode; unsigned short **key_maps; - unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ - SDL_bool dead_key_next; - int npadch; /* -1 or number assembled on pad */ + unsigned char shift_down[NR_SHIFT]; // shift state counters.. + bool dead_key_next; + int npadch; // -1 or number assembled on pad struct kbdiacrs *accents; unsigned int diacr; - SDL_bool rep; /* flag telling character repeat */ + bool rep; // flag telling character repeat unsigned char lockstate; unsigned char slockstate; unsigned char ledflagstate; @@ -125,7 +125,7 @@ static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd) printf(" }\n"); printf("};\n"); } -#endif /* DUMP_ACCENTS */ +#endif // DUMP_ACCENTS #ifdef DUMP_KEYMAP static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd) @@ -155,7 +155,7 @@ static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd) } printf("};\n"); } -#endif /* DUMP_KEYMAP */ +#endif // DUMP_KEYMAP static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL; static int kbd_cleanup_sigactions_installed = 0; @@ -164,7 +164,7 @@ static int kbd_cleanup_atexit_installed = 0; static struct sigaction old_sigaction[NSIG]; static int fatal_signals[] = { - /* Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. */ + // Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. SIGHUP, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV, SIGPIPE, SIGBUS, SIGSYS @@ -194,22 +194,22 @@ static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontex struct sigaction *old_action_p = &(old_sigaction[signum]); sigset_t sigset; - /* Restore original signal handler before going any further. */ + // Restore original signal handler before going any further. sigaction(signum, old_action_p, NULL); - /* Unmask current signal. */ + // Unmask current signal. sigemptyset(&sigset); sigaddset(&sigset, signum); sigprocmask(SIG_UNBLOCK, &sigset, NULL); - /* Save original signal info and context for archeologists. */ + // Save original signal info and context for archeologists. SDL_EVDEV_kdb_cleanup_siginfo = info; SDL_EVDEV_kdb_cleanup_ucontext = ucontext; - /* Restore keyboard. */ + // Restore keyboard. kbd_cleanup(); - /* Reraise signal. */ + // Reraise signal. SDL_EVDEV_kbd_reraise_signal(signum); } @@ -230,27 +230,27 @@ static void kbd_unregister_emerg_cleanup(void) int signum = fatal_signals[tabidx]; old_action_p = &(old_sigaction[signum]); - /* Examine current signal action */ + // Examine current signal action if (sigaction(signum, NULL, &cur_action)) { continue; } - /* Check if action installed and not modified */ + // Check if action installed and not modified if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) { continue; } - /* Restore original action */ + // Restore original action sigaction(signum, old_action_p, NULL); } } static void kbd_cleanup_atexit(void) { - /* Restore keyboard. */ + // Restore keyboard. kbd_cleanup(); - /* Try to restore signal handlers in case shared library is being unloaded */ + // Try to restore signal handlers in case shared library is being unloaded kbd_unregister_emerg_cleanup(); } @@ -313,15 +313,15 @@ typedef void (*signal_handler)(int signum); static void kbd_vt_release_signal_action(int signum) { - SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_RELEASE); + SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_RELEASE); } static void kbd_vt_acquire_signal_action(int signum) { - SDL_AtomicSet(&vt_signal_pending, VT_SIGNAL_ACQUIRE); + SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_ACQUIRE); } -static SDL_bool setup_vt_signal(int signum, signal_handler handler) +static bool setup_vt_signal(int signum, signal_handler handler) { struct sigaction *old_action_p; struct sigaction new_action; @@ -330,14 +330,14 @@ static SDL_bool setup_vt_signal(int signum, signal_handler handler) new_action.sa_handler = handler; new_action.sa_flags = SA_RESTART; if (sigaction(signum, &new_action, old_action_p) < 0) { - return SDL_FALSE; + return false; } if (old_action_p->sa_handler != SIG_DFL) { - /* This signal is already in use */ + // This signal is already in use sigaction(signum, old_action_p, NULL); - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } static int find_free_signal(signal_handler handler) @@ -378,7 +378,7 @@ static void kbd_vt_quit(int console_fd) ioctl(console_fd, VT_SETMODE, &mode); } -static int kbd_vt_init(int console_fd) +static bool kbd_vt_init(int console_fd) { struct vt_mode mode; @@ -386,7 +386,7 @@ static int kbd_vt_init(int console_fd) vt_acquire_signal = find_free_signal(kbd_vt_acquire_signal_action); if (!vt_release_signal || !vt_acquire_signal ) { kbd_vt_quit(console_fd); - return -1; + return false; } SDL_zero(mode); @@ -396,14 +396,14 @@ static int kbd_vt_init(int console_fd) mode.frsig = SIGIO; if (ioctl(console_fd, VT_SETMODE, &mode) < 0) { kbd_vt_quit(console_fd); - return -1; + return false; } - return 0; + return true; } static void kbd_vt_update(SDL_EVDEV_keyboard_state *state) { - int signal_pending = SDL_AtomicGet(&vt_signal_pending); + int signal_pending = SDL_GetAtomicInt(&vt_signal_pending); if (signal_pending != VT_SIGNAL_NONE) { if (signal_pending == VT_SIGNAL_RELEASE) { if (state->vt_release_callback) { @@ -416,7 +416,7 @@ static void kbd_vt_update(SDL_EVDEV_keyboard_state *state) } ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ); } - SDL_AtomicCompareAndSwap(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); + SDL_CompareAndSwapAtomicInt(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); } } @@ -432,7 +432,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) return NULL; } - /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */ + // This might fail if we're not connected to a tty (e.g. on the Steam Link) kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC); if (!((ioctl(kbd->console_fd, KDGKBTYPE, &kbtype) == 0) && ((kbtype == KB_101) || (kbtype == KB_84)))) { close(kbd->console_fd); @@ -453,7 +453,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) kbd->key_maps = default_key_maps; if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) { - /* Set the keyboard in UNICODE mode and load the keymaps */ + // Set the keyboard in UNICODE mode and load the keymaps ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE); } @@ -462,7 +462,7 @@ SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) return kbd; } -void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted) { if (!state) { return; @@ -473,8 +473,7 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) } if (muted) { - /* Allow inhibiting keyboard mute with env. variable for debugging etc. */ - if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) { + if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) { /* Mute the keyboard so keystrokes only generate evdev events * and do not leak through to the console */ @@ -483,14 +482,14 @@ void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) /* Make sure to restore keyboard if application fails to call * SDL_Quit before exit or fatal signal is raised. */ - if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { + if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { kbd_register_emerg_cleanup(state); } } } else { kbd_unregister_emerg_cleanup(); - /* Restore the original keyboard mode */ + // Restore the original keyboard mode ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); } state->muted = muted; @@ -523,7 +522,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) return; } - SDL_EVDEV_kbd_set_muted(state, SDL_FALSE); + SDL_EVDEV_kbd_set_muted(state, false); kbd_vt_quit(state->console_fd); @@ -550,7 +549,7 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) */ static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c) { - /* c is already part of a UTF-8 sequence and safe to add as a character */ + // c is already part of a UTF-8 sequence and safe to add as a character if (kbd->text_len < (sizeof(kbd->text) - 1)) { kbd->text[kbd->text_len++] = (char)c; } @@ -600,7 +599,7 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) if (kbd->console_fd >= 0) if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) { - /* No worries, we'll use the default accent table */ + // No worries, we'll use the default accent table } for (i = 0; i < kbd->accents->kb_cnt; i++) { @@ -619,7 +618,7 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) return ch; } -static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) +static bool vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) { return (kbd->ledflagstate & flag) != 0; } @@ -691,7 +690,7 @@ static void fn_num(SDL_EVDEV_keyboard_state *kbd) static void fn_compose(SDL_EVDEV_keyboard_state *kbd) { - kbd->dead_key_next = SDL_TRUE; + kbd->dead_key_next = true; } /* @@ -722,7 +721,7 @@ static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag) { if (up_flag) { - return; /* no action, if this is a key release */ + return; // no action, if this is a key release } if (kbd->diacr) { @@ -730,7 +729,7 @@ static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_f } if (kbd->dead_key_next) { - kbd->dead_key_next = SDL_FALSE; + kbd->dead_key_next = false; kbd->diacr = value; return; } @@ -775,11 +774,11 @@ static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_fl static const char pad_chars[] = "0123456789+-*/\015,.?()#"; if (up_flag) { - return; /* no action, if this is a key release */ + return; // no action, if this is a key release } if (!vc_kbd_led(kbd, K_NUMLOCK)) { - /* unprintable action */ + // unprintable action return; } @@ -822,7 +821,7 @@ static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ kbd->shift_state &= ~(1 << value); } - /* kludge */ + // kludge if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) { put_utf8(kbd, kbd->npadch); kbd->npadch = -1; @@ -842,10 +841,10 @@ static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ } if (value < 10) { - /* decimal input of code, while Alt depressed */ + // decimal input of code, while Alt depressed base = 10; } else { - /* hexadecimal input of code, while AltGr depressed */ + // hexadecimal input of code, while AltGr depressed value -= 10; base = 16; } @@ -874,7 +873,7 @@ static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_ } chg_vc_kbd_slock(kbd, value); - /* try to make Alt, oops, AltGr and such work */ + // try to make Alt, oops, AltGr and such work if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) { kbd->slockstate = 0; chg_vc_kbd_slock(kbd, value); @@ -901,7 +900,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode shift_final = (state->shift_state | state->slockstate) ^ state->lockstate; key_map = state->key_maps[shift_final]; if (!key_map) { - /* Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state */ + // Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state state->shift_state = 0; state->slockstate = 0; state->lockstate = 0; @@ -933,7 +932,7 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode } else { type -= 0xf0; - /* if type is KT_LETTER then it can be affected by Caps Lock */ + // if type is KT_LETTER then it can be affected by Caps Lock if (type == KT_LETTER) { type = KT_LATIN; @@ -968,14 +967,14 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode } } -#elif !defined(SDL_INPUT_FBSDKBIO) /* !SDL_INPUT_LINUXKD */ +#elif !defined(SDL_INPUT_FBSDKBIO) // !SDL_INPUT_LINUXKD SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) { return NULL; } -void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted) +void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted) { } @@ -995,4 +994,4 @@ void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state) { } -#endif /* SDL_INPUT_LINUXKD */ +#endif // SDL_INPUT_LINUXKD diff --git a/libs/SDL3/src/core/linux/SDL_evdev_kbd.h b/libs/SDL3/src/core/linux/SDL_evdev_kbd.h index 7c38bc9d5..39f1d7223 100644 --- a/libs/SDL3/src/core/linux/SDL_evdev_kbd.h +++ b/libs/SDL3/src/core/linux/SDL_evdev_kbd.h @@ -26,10 +26,10 @@ struct SDL_EVDEV_keyboard_state; typedef struct SDL_EVDEV_keyboard_state SDL_EVDEV_keyboard_state; extern SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void); -extern void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted); +extern void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted); extern void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void*), void *release_callback_data, void (*acquire_callback)(void*), void *acquire_callback_data); extern void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state); extern void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down); extern void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state); -#endif /* SDL_evdev_kbd_h_ */ +#endif // SDL_evdev_kbd_h_ diff --git a/libs/SDL3/src/core/linux/SDL_fcitx.c b/libs/SDL3/src/core/linux/SDL_fcitx.c index 808054a05..72451e038 100644 --- a/libs/SDL3/src/core/linux/SDL_fcitx.c +++ b/libs/SDL3/src/core/linux/SDL_fcitx.c @@ -23,6 +23,7 @@ #include #include "SDL_fcitx.h" +#include "../../video/SDL_sysvideo.h" #include "../../events/SDL_keyboard_c.h" #include "SDL_dbus.h" @@ -75,7 +76,7 @@ static char *GetAppName(void) return SDL_strdup(linkfile); } } -#endif /* SDL_PLATFORM_LINUX || SDL_PLATFORM_FREEBSD */ +#endif // SDL_PLATFORM_LINUX || SDL_PLATFORM_FREEBSD return SDL_strdup("SDL_App"); } @@ -93,10 +94,10 @@ static size_t Fcitx_GetPreeditString(SDL_DBusContext *dbus, Sint32 p_end_pos = -1; dbus->message_iter_init(msg, &iter); - /* Message type is a(si)i, we only need string part */ + // Message type is a(si)i, we only need string part if (dbus->message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) { size_t pos = 0; - /* First pass: calculate string length */ + // First pass: calculate string length dbus->message_iter_recurse(&iter, &array); while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { dbus->message_iter_recurse(&array, &sub); @@ -109,12 +110,12 @@ static size_t Fcitx_GetPreeditString(SDL_DBusContext *dbus, } dbus->message_iter_next(&sub); if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_INT32 && p_end_pos == -1) { - /* Type is a bit field defined as follows: */ - /* bit 3: Underline, bit 4: HighLight, bit 5: DontCommit, */ - /* bit 6: Bold, bit 7: Strike, bit 8: Italic */ + // Type is a bit field defined as follows: + // bit 3: Underline, bit 4: HighLight, bit 5: DontCommit, + // bit 6: Bold, bit 7: Strike, bit 8: Italic Sint32 type; dbus->message_iter_get_basic(&sub, &type); - /* We only consider highlight */ + // We only consider highlight if (type & (1 << 4)) { if (p_start_pos == -1) { p_start_pos = pos; @@ -137,7 +138,7 @@ static size_t Fcitx_GetPreeditString(SDL_DBusContext *dbus, if (text) { char *pivot = text; - /* Second pass: join all the sub string */ + // Second pass: join all the sub string dbus->message_iter_recurse(&iter, &array); while (dbus->message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { dbus->message_iter_recurse(&array, &sub); @@ -211,7 +212,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m SDL_SendEditingText("", 0, 0); } - SDL_Fcitx_UpdateTextRect(NULL); + SDL_Fcitx_UpdateTextInputArea(SDL_GetKeyboardFocus()); return DBUS_HANDLER_RESULT_HANDLED; } @@ -229,7 +230,7 @@ static void FcitxClientICCallMethod(FcitxClient *client, const char *method) static void SDLCALL Fcitx_SetCapabilities(void *data, const char *name, const char *old_val, - const char *internal_editing) + const char *hint) { FcitxClient *client = (FcitxClient *)data; Uint64 caps = 0; @@ -237,18 +238,21 @@ static void SDLCALL Fcitx_SetCapabilities(void *data, return; } - if (!(internal_editing && *internal_editing == '1')) { - caps |= (1 << 1); /* Preedit Flag */ - caps |= (1 << 4); /* Formatted Preedit Flag */ + if (hint && SDL_strstr(hint, "composition")) { + caps |= (1 << 1); // Preedit Flag + caps |= (1 << 4); // Formatted Preedit Flag + } + if (hint && SDL_strstr(hint, "candidates")) { + // FIXME, turn off native candidate rendering } SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, "SetCapability", DBUS_TYPE_UINT64, &caps, DBUS_TYPE_INVALID); } -static SDL_bool FcitxCreateInputContext(SDL_DBusContext *dbus, const char *appname, char **ic_path) +static bool FcitxCreateInputContext(SDL_DBusContext *dbus, const char *appname, char **ic_path) { const char *program = "program"; - SDL_bool retval = SDL_FALSE; + bool result = false; if (dbus && dbus->session_conn) { DBusMessage *msg = dbus->message_new_method_call(FCITX_DBUS_SERVICE, FCITX_IM_DBUS_PATH, FCITX_IM_DBUS_INTERFACE, "CreateInputContext"); @@ -265,25 +269,25 @@ static SDL_bool FcitxCreateInputContext(SDL_DBusContext *dbus, const char *appna reply = dbus->connection_send_with_reply_and_block(dbus->session_conn, msg, 300, NULL); if (reply) { if (dbus->message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, ic_path, DBUS_TYPE_INVALID)) { - retval = SDL_TRUE; + result = true; } dbus->message_unref(reply); } dbus->message_unref(msg); } } - return retval; + return result; } -static SDL_bool FcitxClientCreateIC(FcitxClient *client) +static bool FcitxClientCreateIC(FcitxClient *client) { char *appname = GetAppName(); char *ic_path = NULL; SDL_DBusContext *dbus = client->dbus; - /* SDL_DBus_CallMethod cannot handle a(ss) type, call dbus function directly */ + // SDL_DBus_CallMethod cannot handle a(ss) type, call dbus function directly if (!FcitxCreateInputContext(dbus, appname, &ic_path)) { - ic_path = NULL; /* just in case. */ + ic_path = NULL; // just in case. } SDL_free(appname); @@ -300,11 +304,11 @@ static SDL_bool FcitxClientCreateIC(FcitxClient *client) NULL); dbus->connection_flush(dbus->session_conn); - SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, Fcitx_SetCapabilities, client); - return SDL_TRUE; + SDL_AddHintCallback(SDL_HINT_IME_IMPLEMENTED_UI, Fcitx_SetCapabilities, client); + return true; } - return SDL_FALSE; + return false; } static Uint32 Fcitx_ModState(void) @@ -340,7 +344,7 @@ static Uint32 Fcitx_ModState(void) return fcitx_mods; } -SDL_bool SDL_Fcitx_Init(void) +bool SDL_Fcitx_Init(void) { fcitx_client.dbus = SDL_DBus_GetContext(); @@ -361,7 +365,7 @@ void SDL_Fcitx_Quit(void) } } -void SDL_Fcitx_SetFocus(SDL_bool focused) +void SDL_Fcitx_SetFocus(bool focused) { if (focused) { FcitxClientICCallMethod(&fcitx_client, "FocusIn"); @@ -375,50 +379,50 @@ void SDL_Fcitx_Reset(void) FcitxClientICCallMethod(&fcitx_client, "Reset"); } -SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) +bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) { Uint32 mod_state = Fcitx_ModState(); - Uint32 handled = SDL_FALSE; - Uint32 is_release = (state == SDL_RELEASED); + Uint32 handled = false; + Uint32 is_release = !down; Uint32 event_time = 0; if (!fcitx_client.ic_path) { - return SDL_FALSE; + return false; } if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent", DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID, DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) { if (handled) { - SDL_Fcitx_UpdateTextRect(NULL); - return SDL_TRUE; + SDL_Fcitx_UpdateTextInputArea(SDL_GetKeyboardFocus()); + return true; } } - return SDL_FALSE; + return false; } -void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) +void SDL_Fcitx_UpdateTextInputArea(SDL_Window *window) { - SDL_Window *focused_win = NULL; int x = 0, y = 0; SDL_Rect *cursor = &fcitx_client.cursor_rect; - if (rect) { - SDL_copyp(cursor, rect); - } - - focused_win = SDL_GetKeyboardFocus(); - if (!focused_win) { + if (!window) { return; } - SDL_GetWindowPosition(focused_win, &x, &y); + // We'll use a square at the text input cursor location for the cursor_rect + cursor->x = window->text_input_rect.x + window->text_input_cursor; + cursor->y = window->text_input_rect.y; + cursor->w = window->text_input_rect.h; + cursor->h = window->text_input_rect.h; + + SDL_GetWindowPosition(window, &x, &y); #ifdef SDL_VIDEO_DRIVER_X11 { - SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); + SDL_PropertiesID props = SDL_GetWindowProperties(window); + Display *x_disp = (Display *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); int x_screen = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, 0); Window x_win = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); Window unused; @@ -429,9 +433,9 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) #endif if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) { - /* move to bottom left */ + // move to bottom left int w = 0, h = 0; - SDL_GetWindowSize(focused_win, &w, &h); + SDL_GetWindowSize(window, &w, &h); cursor->x = 0; cursor->y = h; } @@ -451,7 +455,6 @@ void SDL_Fcitx_PumpEvents(void) dbus->connection_read_write(conn, 0); while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) { - /* Do nothing, actual work happens in DBus_MessageFilter */ - usleep(10); + // Do nothing, actual work happens in DBus_MessageFilter } } diff --git a/libs/SDL3/src/core/linux/SDL_fcitx.h b/libs/SDL3/src/core/linux/SDL_fcitx.h index 44ee05330..59dc91353 100644 --- a/libs/SDL3/src/core/linux/SDL_fcitx.h +++ b/libs/SDL3/src/core/linux/SDL_fcitx.h @@ -24,12 +24,12 @@ #include "SDL_internal.h" -extern SDL_bool SDL_Fcitx_Init(void); +extern bool SDL_Fcitx_Init(void); extern void SDL_Fcitx_Quit(void); -extern void SDL_Fcitx_SetFocus(SDL_bool focused); +extern void SDL_Fcitx_SetFocus(bool focused); extern void SDL_Fcitx_Reset(void); -extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state); -extern void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect); +extern bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down); +extern void SDL_Fcitx_UpdateTextInputArea(SDL_Window *window); extern void SDL_Fcitx_PumpEvents(void); -#endif /* SDL_fcitx_h_ */ +#endif // SDL_fcitx_h_ diff --git a/libs/SDL3/src/core/linux/SDL_ibus.c b/libs/SDL3/src/core/linux/SDL_ibus.c index 9e514c302..dbbc3e174 100644 --- a/libs/SDL3/src/core/linux/SDL_ibus.c +++ b/libs/SDL3/src/core/linux/SDL_ibus.c @@ -53,7 +53,7 @@ static const char *ibus_input_interface = NULL; static char *input_ctx_path = NULL; static SDL_Rect ibus_cursor_rect = { 0, 0, 0, 0 }; static DBusConnection *ibus_conn = NULL; -static SDL_bool ibus_is_portal_interface = SDL_FALSE; +static bool ibus_is_portal_interface = false; static char *ibus_addr_file = NULL; static int inotify_fd = -1, inotify_wd = -1; @@ -62,7 +62,7 @@ static Uint32 IBus_ModState(void) Uint32 ibus_mods = 0; SDL_Keymod sdl_mods = SDL_GetModState(); - /* Not sure about MOD3, MOD4 and HYPER mappings */ + // Not sure about MOD3, MOD4 and HYPER mappings if (sdl_mods & SDL_KMOD_LSHIFT) { ibus_mods |= IBUS_SHIFT_MASK; } @@ -91,40 +91,40 @@ static Uint32 IBus_ModState(void) return ibus_mods; } -static SDL_bool IBus_EnterVariant(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, +static bool IBus_EnterVariant(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, DBusMessageIter *inside, const char *struct_id, size_t id_size) { DBusMessageIter sub; if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) { - return SDL_FALSE; + return false; } dbus->message_iter_recurse(iter, &sub); if (dbus->message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { - return SDL_FALSE; + return false; } dbus->message_iter_recurse(&sub, inside); if (dbus->message_iter_get_arg_type(inside) != DBUS_TYPE_STRING) { - return SDL_FALSE; + return false; } dbus->message_iter_get_basic(inside, &struct_id); if (!struct_id || SDL_strncmp(struct_id, struct_id, id_size) != 0) { - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } -static SDL_bool IBus_GetDecorationPosition(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, +static bool IBus_GetDecorationPosition(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, Uint32 *start_pos, Uint32 *end_pos) { DBusMessageIter sub1, sub2, array; if (!IBus_EnterVariant(conn, iter, dbus, &sub1, "IBusText", sizeof("IBusText"))) { - return SDL_FALSE; + return false; } dbus->message_iter_next(&sub1); @@ -132,14 +132,14 @@ static SDL_bool IBus_GetDecorationPosition(DBusConnection *conn, DBusMessageIter dbus->message_iter_next(&sub1); if (!IBus_EnterVariant(conn, &sub1, dbus, &sub2, "IBusAttrList", sizeof("IBusAttrList"))) { - return SDL_FALSE; + return false; } dbus->message_iter_next(&sub2); dbus->message_iter_next(&sub2); if (dbus->message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY) { - return SDL_FALSE; + return false; } dbus->message_iter_recurse(&sub2, &array); @@ -152,16 +152,16 @@ static SDL_bool IBus_GetDecorationPosition(DBusConnection *conn, DBusMessageIter dbus->message_iter_next(&sub); dbus->message_iter_next(&sub); - /* From here on, the structure looks like this: */ - /* Uint32 type: 1=underline, 2=foreground, 3=background */ - /* Uint32 value: for underline it's 0=NONE, 1=SINGLE, 2=DOUBLE, */ - /* 3=LOW, 4=ERROR */ - /* for foreground and background it's a color */ - /* Uint32 start_index: starting position for the style (utf8-char) */ - /* Uint32 end_index: end position for the style (utf8-char) */ + // From here on, the structure looks like this: + // Uint32 type: 1=underline, 2=foreground, 3=background + // Uint32 value: for underline it's 0=NONE, 1=SINGLE, 2=DOUBLE, + // 3=LOW, 4=ERROR + // for foreground and background it's a color + // Uint32 start_index: starting position for the style (utf8-char) + // Uint32 end_index: end position for the style (utf8-char) dbus->message_iter_get_basic(&sub, &type); - /* We only use the background type to determine the selection */ + // We only use the background type to determine the selection if (type == 3) { Uint32 start = -1; dbus->message_iter_next(&sub); @@ -172,19 +172,19 @@ static SDL_bool IBus_GetDecorationPosition(DBusConnection *conn, DBusMessageIter if (dbus->message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) { dbus->message_iter_get_basic(&sub, end_pos); *start_pos = start; - return SDL_TRUE; + return true; } } } } dbus->message_iter_next(&array); } - return SDL_FALSE; + return false; } static const char *IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus) { - /* The text we need is nested weirdly, use dbus-monitor to see the structure better */ + // The text we need is nested weirdly, use dbus-monitor to see the structure better const char *text = NULL; DBusMessageIter sub; @@ -203,18 +203,18 @@ static const char *IBus_GetVariantText(DBusConnection *conn, DBusMessageIter *it return text; } -static SDL_bool IBus_GetVariantCursorPos(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, +static bool IBus_GetVariantCursorPos(DBusConnection *conn, DBusMessageIter *iter, SDL_DBusContext *dbus, Uint32 *pos) { dbus->message_iter_next(iter); if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_UINT32) { - return SDL_FALSE; + return false; } dbus->message_iter_get_basic(iter, pos); - return SDL_TRUE; + return true; } static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage *msg, void *user_data) @@ -242,8 +242,8 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * if (text) { Uint32 pos, start_pos, end_pos; - SDL_bool has_pos = SDL_FALSE; - SDL_bool has_dec_pos = SDL_FALSE; + bool has_pos = false; + bool has_dec_pos = false; dbus->message_iter_init(msg, &iter); has_dec_pos = IBus_GetDecorationPosition(conn, &iter, dbus, &start_pos, &end_pos); @@ -261,7 +261,7 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * } } - SDL_IBus_UpdateTextRect(NULL); + SDL_IBus_UpdateTextInputArea(SDL_GetKeyboardFocus()); return DBUS_HANDLER_RESULT_HANDLED; } @@ -277,7 +277,7 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * static char *IBus_ReadAddressFromFile(const char *file_path) { char addr_buf[1024]; - SDL_bool success = SDL_FALSE; + bool success = false; FILE *addr_file; addr_file = fopen(file_path, "r"); @@ -294,7 +294,7 @@ static char *IBus_ReadAddressFromFile(const char *file_path) if (addr_buf[sz - 2] == '\r') { addr_buf[sz - 2] = 0; } - success = SDL_TRUE; + success = true; break; } } @@ -330,7 +330,7 @@ static char *IBus_GetDBusAddressFilename(void) return NULL; } - /* Use this environment variable if it exists. */ + // Use this environment variable if it exists. addr = SDL_getenv("IBUS_ADDRESS"); if (addr && *addr) { return SDL_strdup(addr); @@ -401,29 +401,33 @@ static char *IBus_GetDBusAddressFilename(void) return SDL_strdup(file_path); } -static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus); +static bool IBus_CheckConnection(SDL_DBusContext *dbus); static void SDLCALL IBus_SetCapabilities(void *data, const char *name, const char *old_val, - const char *internal_editing) + const char *hint) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); if (IBus_CheckConnection(dbus)) { Uint32 caps = IBUS_CAP_FOCUS; - if (!(internal_editing && *internal_editing == '1')) { + + if (hint && SDL_strstr(hint, "composition")) { caps |= IBUS_CAP_PREEDIT_TEXT; } + if (hint && SDL_strstr(hint, "candidates")) { + // FIXME, turn off native candidate rendering + } SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID); } } -static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) +static bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) { const char *client_name = "SDL3_Application"; const char *path = NULL; - SDL_bool result = SDL_FALSE; + bool result = false; DBusObjectPathVTable ibus_vtable; SDL_zero(ibus_vtable); @@ -432,7 +436,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) /* try the portal interface first. Modern systems have this in general, and sandbox things like FlakPak and Snaps, etc, require it. */ - ibus_is_portal_interface = SDL_TRUE; + ibus_is_portal_interface = true; ibus_service = IBUS_PORTAL_SERVICE; ibus_interface = IBUS_PORTAL_INTERFACE; ibus_input_interface = IBUS_PORTAL_INPUT_INTERFACE; @@ -442,21 +446,21 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); if (!result) { - ibus_is_portal_interface = SDL_FALSE; + ibus_is_portal_interface = false; ibus_service = IBUS_SERVICE; ibus_interface = IBUS_INTERFACE; ibus_input_interface = IBUS_INPUT_INTERFACE; ibus_conn = dbus->connection_open_private(addr, NULL); if (!ibus_conn) { - return SDL_FALSE; /* oh well. */ + return false; // oh well. } dbus->connection_flush(ibus_conn); if (!dbus->bus_register(ibus_conn, NULL)) { ibus_conn = NULL; - return SDL_FALSE; + return false; } dbus->connection_flush(ibus_conn); @@ -465,7 +469,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); } else { - /* re-using dbus->session_conn */ + // re-using dbus->session_conn dbus->connection_ref(ibus_conn); } @@ -474,26 +478,30 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) (void)SDL_snprintf(matchstr, sizeof(matchstr), "type='signal',interface='%s'", ibus_input_interface); SDL_free(input_ctx_path); input_ctx_path = SDL_strdup(path); - SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL); + SDL_AddHintCallback(SDL_HINT_IME_IMPLEMENTED_UI, IBus_SetCapabilities, NULL); dbus->bus_add_match(ibus_conn, matchstr, NULL); dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus, NULL); dbus->connection_flush(ibus_conn); } - SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL); - SDL_IBus_UpdateTextRect(NULL); - + SDL_Window *window = SDL_GetKeyboardFocus(); + if (SDL_TextInputActive(window)) { + SDL_IBus_SetFocus(true); + SDL_IBus_UpdateTextInputArea(window); + } else { + SDL_IBus_SetFocus(false); + } return result; } -static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) +static bool IBus_CheckConnection(SDL_DBusContext *dbus) { if (!dbus) { - return SDL_FALSE; + return false; } if (ibus_conn && dbus->connection_get_is_connected(ibus_conn)) { - return SDL_TRUE; + return true; } if (inotify_fd > 0 && inotify_wd > 0) { @@ -502,18 +510,18 @@ static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) if (readsize > 0) { char *p; - SDL_bool file_updated = SDL_FALSE; + bool file_updated = false; for (p = buf; p < buf + readsize; /**/) { struct inotify_event *event = (struct inotify_event *)p; if (event->len > 0) { char *addr_file_no_path = SDL_strrchr(ibus_addr_file, '/'); if (!addr_file_no_path) { - return SDL_FALSE; + return false; } if (SDL_strcmp(addr_file_no_path + 1, event->name) == 0) { - file_updated = SDL_TRUE; + file_updated = true; break; } } @@ -524,7 +532,7 @@ static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) if (file_updated) { char *addr = IBus_ReadAddressFromFile(ibus_addr_file); if (addr) { - SDL_bool result = IBus_SetupConnection(dbus, addr); + bool result = IBus_SetupConnection(dbus, addr); SDL_free(addr); return result; } @@ -532,12 +540,12 @@ static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus) } } - return SDL_FALSE; + return false; } -SDL_bool SDL_IBus_Init(void) +bool SDL_IBus_Init(void) { - SDL_bool result = SDL_FALSE; + bool result = false; SDL_DBusContext *dbus = SDL_DBus_GetContext(); if (dbus) { @@ -546,13 +554,13 @@ SDL_bool SDL_IBus_Init(void) char *addr_file_dir; if (!addr_file) { - return SDL_FALSE; + return false; } addr = IBus_ReadAddressFromFile(addr_file); if (!addr) { SDL_free(addr_file); - return SDL_FALSE; + return false; } if (ibus_addr_file) { @@ -576,7 +584,7 @@ SDL_bool SDL_IBus_Init(void) result = IBus_SetupConnection(dbus, addr); SDL_free(addr); - /* don't use the addr_file if using the portal interface. */ + // don't use the addr_file if using the portal interface. if (result && ibus_is_portal_interface) { if (inotify_fd > 0) { if (inotify_wd > 0) { @@ -608,7 +616,7 @@ void SDL_IBus_Quit(void) dbus = SDL_DBus_GetContext(); - /* if using portal, ibus_conn == session_conn; don't release it here. */ + // if using portal, ibus_conn == session_conn; don't release it here. if (dbus && ibus_conn && !ibus_is_portal_interface) { dbus->connection_close(ibus_conn); dbus->connection_unref(ibus_conn); @@ -618,16 +626,16 @@ void SDL_IBus_Quit(void) ibus_service = NULL; ibus_interface = NULL; ibus_input_interface = NULL; - ibus_is_portal_interface = SDL_FALSE; + ibus_is_portal_interface = false; if (inotify_fd > 0 && inotify_wd > 0) { inotify_rm_watch(inotify_fd, inotify_wd); inotify_wd = -1; } - /* !!! FIXME: should we close(inotify_fd) here? */ + // !!! FIXME: should we close(inotify_fd) here? - SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL); + SDL_RemoveHintCallback(SDL_HINT_IME_IMPLEMENTED_UI, IBus_SetCapabilities, NULL); SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect)); } @@ -641,7 +649,7 @@ static void IBus_SimpleMessage(const char *method) } } -void SDL_IBus_SetFocus(SDL_bool focused) +void SDL_IBus_SetFocus(bool focused) { const char *method = focused ? "FocusIn" : "FocusOut"; IBus_SimpleMessage(method); @@ -652,7 +660,7 @@ void SDL_IBus_Reset(void) IBus_SimpleMessage("Reset"); } -SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) +bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) { Uint32 result = 0; SDL_DBusContext *dbus = SDL_DBus_GetContext(); @@ -660,7 +668,7 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) if (IBus_CheckConnection(dbus)) { Uint32 mods = IBus_ModState(); Uint32 ibus_keycode = keycode - 8; - if (state == SDL_RELEASED) { + if (!down) { mods |= (1 << 30); // IBUS_RELEASE_MASK } if (!SDL_DBus_CallMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "ProcessKeyEvent", @@ -670,32 +678,32 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) } } - SDL_IBus_UpdateTextRect(NULL); + SDL_IBus_UpdateTextInputArea(SDL_GetKeyboardFocus()); return (result != 0); } -void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) +void SDL_IBus_UpdateTextInputArea(SDL_Window *window) { - SDL_Window *focused_win; int x = 0, y = 0; SDL_DBusContext *dbus; - if (rect) { - SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect)); - } - - focused_win = SDL_GetKeyboardFocus(); - if (!focused_win) { + if (!window) { return; } - SDL_GetWindowPosition(focused_win, &x, &y); + // We'll use a square at the text input cursor location for the ibus_cursor + ibus_cursor_rect.x = window->text_input_rect.x + window->text_input_cursor; + ibus_cursor_rect.y = window->text_input_rect.y; + ibus_cursor_rect.w = window->text_input_rect.h; + ibus_cursor_rect.h = window->text_input_rect.h; + + SDL_GetWindowPosition(window, &x, &y); #ifdef SDL_VIDEO_DRIVER_X11 { - SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); - Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); + SDL_PropertiesID props = SDL_GetWindowProperties(window); + Display *x_disp = (Display *)SDL_GetPointerProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); int x_screen = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, 0); Window x_win = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); Window unused; @@ -725,7 +733,7 @@ void SDL_IBus_PumpEvents(void) dbus->connection_read_write(ibus_conn, 0); while (dbus->connection_dispatch(ibus_conn) == DBUS_DISPATCH_DATA_REMAINS) { - /* Do nothing, actual work happens in IBus_MessageHandler */ + // Do nothing, actual work happens in IBus_MessageHandler } } } diff --git a/libs/SDL3/src/core/linux/SDL_ibus.h b/libs/SDL3/src/core/linux/SDL_ibus.h index 377a9fc2b..ffd7e8e5e 100644 --- a/libs/SDL3/src/core/linux/SDL_ibus.h +++ b/libs/SDL3/src/core/linux/SDL_ibus.h @@ -26,30 +26,30 @@ #ifdef HAVE_IBUS_IBUS_H #define SDL_USE_IBUS 1 -#include +#include -extern SDL_bool SDL_IBus_Init(void); +extern bool SDL_IBus_Init(void); extern void SDL_IBus_Quit(void); -/* Lets the IBus server know about changes in window focus */ -extern void SDL_IBus_SetFocus(SDL_bool focused); +// Lets the IBus server know about changes in window focus +extern void SDL_IBus_SetFocus(bool focused); -/* Closes the candidate list and resets any text currently being edited */ +// Closes the candidate list and resets any text currently being edited extern void SDL_IBus_Reset(void); -/* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to +/* Sends a keypress event to IBus, returns true if IBus used this event to update its candidate list or change input methods. PumpEvents should be called some time after this, to receive the TextInput / TextEditing event back. */ -extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state); +extern bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down); /* Update the position of IBus' candidate list. If rect is NULL then this will just reposition it relative to the focused window's new position. */ -extern void SDL_IBus_UpdateTextRect(const SDL_Rect *window_relative_rect); +extern void SDL_IBus_UpdateTextInputArea(SDL_Window *window); /* Checks DBus for new IBus events, and calls SDL_SendKeyboardText / SDL_SendEditingText for each event it finds */ extern void SDL_IBus_PumpEvents(void); -#endif /* HAVE_IBUS_IBUS_H */ +#endif // HAVE_IBUS_IBUS_H -#endif /* SDL_ibus_h_ */ +#endif // SDL_ibus_h_ diff --git a/libs/SDL3/src/core/linux/SDL_ime.c b/libs/SDL3/src/core/linux/SDL_ime.c index 752c3ab9b..a853618bb 100644 --- a/libs/SDL3/src/core/linux/SDL_ime.c +++ b/libs/SDL3/src/core/linux/SDL_ime.c @@ -24,12 +24,12 @@ #include "SDL_ibus.h" #include "SDL_fcitx.h" -typedef SDL_bool (*SDL_IME_Init_t)(void); +typedef bool (*SDL_IME_Init_t)(void); typedef void (*SDL_IME_Quit_t)(void); -typedef void (*SDL_IME_SetFocus_t)(SDL_bool); +typedef void (*SDL_IME_SetFocus_t)(bool); typedef void (*SDL_IME_Reset_t)(void); -typedef SDL_bool (*SDL_IME_ProcessKeyEvent_t)(Uint32, Uint32, Uint8 state); -typedef void (*SDL_IME_UpdateTextRect_t)(const SDL_Rect *); +typedef bool (*SDL_IME_ProcessKeyEvent_t)(Uint32, Uint32, bool down); +typedef void (*SDL_IME_UpdateTextInputArea_t)(SDL_Window *window); typedef void (*SDL_IME_PumpEvents_t)(void); static SDL_IME_Init_t SDL_IME_Init_Real = NULL; @@ -37,24 +37,24 @@ static SDL_IME_Quit_t SDL_IME_Quit_Real = NULL; static SDL_IME_SetFocus_t SDL_IME_SetFocus_Real = NULL; static SDL_IME_Reset_t SDL_IME_Reset_Real = NULL; static SDL_IME_ProcessKeyEvent_t SDL_IME_ProcessKeyEvent_Real = NULL; -static SDL_IME_UpdateTextRect_t SDL_IME_UpdateTextRect_Real = NULL; +static SDL_IME_UpdateTextInputArea_t SDL_IME_UpdateTextInputArea_Real = NULL; static SDL_IME_PumpEvents_t SDL_IME_PumpEvents_Real = NULL; static void InitIME(void) { - static SDL_bool inited = SDL_FALSE; + static bool inited = false; #ifdef HAVE_FCITX const char *im_module = SDL_getenv("SDL_IM_MODULE"); const char *xmodifiers = SDL_getenv("XMODIFIERS"); #endif - if (inited == SDL_TRUE) { + if (inited == true) { return; } - inited = SDL_TRUE; + inited = true; - /* See if fcitx IME support is being requested */ + // See if fcitx IME support is being requested #ifdef HAVE_FCITX if (!SDL_IME_Init_Real && ((im_module && SDL_strcmp(im_module, "fcitx") == 0) || @@ -64,12 +64,12 @@ static void InitIME(void) SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus; SDL_IME_Reset_Real = SDL_Fcitx_Reset; SDL_IME_ProcessKeyEvent_Real = SDL_Fcitx_ProcessKeyEvent; - SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect; + SDL_IME_UpdateTextInputArea_Real = SDL_Fcitx_UpdateTextInputArea; SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents; } -#endif /* HAVE_FCITX */ +#endif // HAVE_FCITX - /* default to IBus */ + // default to IBus #ifdef HAVE_IBUS_IBUS_H if (!SDL_IME_Init_Real) { SDL_IME_Init_Real = SDL_IBus_Init; @@ -77,32 +77,32 @@ static void InitIME(void) SDL_IME_SetFocus_Real = SDL_IBus_SetFocus; SDL_IME_Reset_Real = SDL_IBus_Reset; SDL_IME_ProcessKeyEvent_Real = SDL_IBus_ProcessKeyEvent; - SDL_IME_UpdateTextRect_Real = SDL_IBus_UpdateTextRect; + SDL_IME_UpdateTextInputArea_Real = SDL_IBus_UpdateTextInputArea; SDL_IME_PumpEvents_Real = SDL_IBus_PumpEvents; } -#endif /* HAVE_IBUS_IBUS_H */ +#endif // HAVE_IBUS_IBUS_H } -SDL_bool SDL_IME_Init(void) +bool SDL_IME_Init(void) { InitIME(); if (SDL_IME_Init_Real) { if (SDL_IME_Init_Real()) { - return SDL_TRUE; + return true; } - /* uhoh, the IME implementation's init failed! Disable IME support. */ + // uhoh, the IME implementation's init failed! Disable IME support. SDL_IME_Init_Real = NULL; SDL_IME_Quit_Real = NULL; SDL_IME_SetFocus_Real = NULL; SDL_IME_Reset_Real = NULL; SDL_IME_ProcessKeyEvent_Real = NULL; - SDL_IME_UpdateTextRect_Real = NULL; + SDL_IME_UpdateTextInputArea_Real = NULL; SDL_IME_PumpEvents_Real = NULL; } - return SDL_FALSE; + return false; } void SDL_IME_Quit(void) @@ -112,7 +112,7 @@ void SDL_IME_Quit(void) } } -void SDL_IME_SetFocus(SDL_bool focused) +void SDL_IME_SetFocus(bool focused) { if (SDL_IME_SetFocus_Real) { SDL_IME_SetFocus_Real(focused); @@ -126,19 +126,19 @@ void SDL_IME_Reset(void) } } -SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) +bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down) { if (SDL_IME_ProcessKeyEvent_Real) { - return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state); + return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, down); } - return SDL_FALSE; + return false; } -void SDL_IME_UpdateTextRect(const SDL_Rect *rect) +void SDL_IME_UpdateTextInputArea(SDL_Window *window) { - if (SDL_IME_UpdateTextRect_Real) { - SDL_IME_UpdateTextRect_Real(rect); + if (SDL_IME_UpdateTextInputArea_Real) { + SDL_IME_UpdateTextInputArea_Real(window); } } diff --git a/libs/SDL3/src/core/linux/SDL_ime.h b/libs/SDL3/src/core/linux/SDL_ime.h index f0ac77825..2b75cdd37 100644 --- a/libs/SDL3/src/core/linux/SDL_ime.h +++ b/libs/SDL3/src/core/linux/SDL_ime.h @@ -24,12 +24,12 @@ #include "SDL_internal.h" -extern SDL_bool SDL_IME_Init(void); +extern bool SDL_IME_Init(void); extern void SDL_IME_Quit(void); -extern void SDL_IME_SetFocus(SDL_bool focused); +extern void SDL_IME_SetFocus(bool focused); extern void SDL_IME_Reset(void); -extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state); -extern void SDL_IME_UpdateTextRect(const SDL_Rect *rect); +extern bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, bool down); +extern void SDL_IME_UpdateTextInputArea(SDL_Window *window); extern void SDL_IME_PumpEvents(void); -#endif /* SDL_ime_h_ */ +#endif // SDL_ime_h_ diff --git a/libs/SDL3/src/core/linux/SDL_sandbox.c b/libs/SDL3/src/core/linux/SDL_sandbox.c index 413148fc7..5a8df8487 100644 --- a/libs/SDL3/src/core/linux/SDL_sandbox.c +++ b/libs/SDL3/src/core/linux/SDL_sandbox.c @@ -33,7 +33,9 @@ SDL_Sandbox SDL_DetectSandbox(void) /* For Snap, we check multiple variables because they might be set for * unrelated reasons. This is the same thing WebKitGTK does. */ - if (SDL_getenv("SNAP") != NULL && SDL_getenv("SNAP_NAME") != NULL && SDL_getenv("SNAP_REVISION") != NULL) { + if (SDL_getenv("SNAP") != NULL && + SDL_getenv("SNAP_NAME") != NULL && + SDL_getenv("SNAP_REVISION") != NULL) { return SDL_SANDBOX_SNAP; } diff --git a/libs/SDL3/src/core/linux/SDL_sandbox.h b/libs/SDL3/src/core/linux/SDL_sandbox.h index 8339c90b4..d480658ce 100644 --- a/libs/SDL3/src/core/linux/SDL_sandbox.h +++ b/libs/SDL3/src/core/linux/SDL_sandbox.h @@ -31,7 +31,7 @@ typedef enum SDL_SANDBOX_SNAP, } SDL_Sandbox; -/* Return the sandbox type currently in use, if any */ +// Return the sandbox type currently in use, if any SDL_Sandbox SDL_DetectSandbox(void); -#endif /* SDL_SANDBOX_H */ +#endif // SDL_SANDBOX_H diff --git a/libs/SDL3/src/core/linux/SDL_system_theme.c b/libs/SDL3/src/core/linux/SDL_system_theme.c index 1623775af..570d93251 100644 --- a/libs/SDL3/src/core/linux/SDL_system_theme.c +++ b/libs/SDL3/src/core/linux/SDL_system_theme.c @@ -44,16 +44,16 @@ typedef struct SystemThemeData static SystemThemeData system_theme_data; -static SDL_bool DBus_ExtractThemeVariant(DBusMessageIter *iter, SDL_SystemTheme *theme) { +static bool DBus_ExtractThemeVariant(DBusMessageIter *iter, SDL_SystemTheme *theme) { SDL_DBusContext *dbus = system_theme_data.dbus; Uint32 color_scheme; DBusMessageIter variant_iter; if (dbus->message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) - return SDL_FALSE; + return false; dbus->message_iter_recurse(iter, &variant_iter); if (dbus->message_iter_get_arg_type(&variant_iter) != DBUS_TYPE_UINT32) - return SDL_FALSE; + return false; dbus->message_iter_get_basic(&variant_iter, &color_scheme); switch (color_scheme) { case 0: @@ -66,7 +66,7 @@ static SDL_bool DBus_ExtractThemeVariant(DBusMessageIter *iter, SDL_SystemTheme *theme = SDL_SYSTEM_THEME_LIGHT; break; } - return SDL_TRUE; + return true; } static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -77,7 +77,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m const char *namespace, *key; dbus->message_iter_init(msg, &signal_iter); - /* Check if the parameters are what we expect */ + // Check if the parameters are what we expect if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_STRING) goto not_our_signal; dbus->message_iter_get_basic(&signal_iter, &namespace); @@ -106,7 +106,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -SDL_bool SDL_SystemTheme_Init(void) +bool SDL_SystemTheme_Init(void) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); DBusMessage *msg; @@ -116,7 +116,7 @@ SDL_bool SDL_SystemTheme_Init(void) system_theme_data.theme = SDL_SYSTEM_THEME_UNKNOWN; system_theme_data.dbus = dbus; if (!dbus) { - return SDL_FALSE; + return false; } msg = dbus->message_new_method_call(PORTAL_DESTINATION, PORTAL_PATH, PORTAL_INTERFACE, PORTAL_METHOD); @@ -127,7 +127,7 @@ SDL_bool SDL_SystemTheme_Init(void) DBusMessageIter reply_iter, variant_outer_iter; dbus->message_iter_init(reply, &reply_iter); - /* The response has signature <> */ + // The response has signature <> if (dbus->message_iter_get_arg_type(&reply_iter) != DBUS_TYPE_VARIANT) goto incorrect_type; dbus->message_iter_recurse(&reply_iter, &variant_outer_iter); @@ -147,7 +147,7 @@ SDL_bool SDL_SystemTheme_Init(void) dbus->connection_add_filter(dbus->session_conn, &DBus_MessageFilter, dbus, NULL); dbus->connection_flush(dbus->session_conn); - return SDL_TRUE; + return true; } SDL_SystemTheme SDL_SystemTheme_Get(void) diff --git a/libs/SDL3/src/core/linux/SDL_system_theme.h b/libs/SDL3/src/core/linux/SDL_system_theme.h index 396b3a76e..2693e5d07 100644 --- a/libs/SDL3/src/core/linux/SDL_system_theme.h +++ b/libs/SDL3/src/core/linux/SDL_system_theme.h @@ -24,7 +24,7 @@ #include "SDL_internal.h" -extern SDL_bool SDL_SystemTheme_Init(void); +extern bool SDL_SystemTheme_Init(void); extern SDL_SystemTheme SDL_SystemTheme_Get(void); -#endif /* SDL_system_theme_h_ */ +#endif // SDL_system_theme_h_ diff --git a/libs/SDL3/src/core/linux/SDL_threadprio.c b/libs/SDL3/src/core/linux/SDL_threadprio.c index 106894947..fb5b27be7 100644 --- a/libs/SDL3/src/core/linux/SDL_threadprio.c +++ b/libs/SDL3/src/core/linux/SDL_threadprio.c @@ -29,11 +29,11 @@ #include #include -/* RLIMIT_RTTIME requires kernel >= 2.6.25 and is in glibc >= 2.14 */ +// RLIMIT_RTTIME requires kernel >= 2.6.25 and is in glibc >= 2.14 #ifndef RLIMIT_RTTIME #define RLIMIT_RTTIME 15 #endif -/* SCHED_RESET_ON_FORK is in kernel >= 2.6.32. */ +// SCHED_RESET_ON_FORK is in kernel >= 2.6.32. #ifndef SCHED_RESET_ON_FORK #define SCHED_RESET_ON_FORK 0x40000000 #endif @@ -42,17 +42,17 @@ #ifdef SDL_USE_LIBDBUS -/* d-bus queries to org.freedesktop.RealtimeKit1. */ +// d-bus queries to org.freedesktop.RealtimeKit1. #define RTKIT_DBUS_NODE "org.freedesktop.RealtimeKit1" #define RTKIT_DBUS_PATH "/org/freedesktop/RealtimeKit1" #define RTKIT_DBUS_INTERFACE "org.freedesktop.RealtimeKit1" -/* d-bus queries to the XDG portal interface to RealtimeKit1 */ +// d-bus queries to the XDG portal interface to RealtimeKit1 #define XDG_PORTAL_DBUS_NODE "org.freedesktop.portal.Desktop" #define XDG_PORTAL_DBUS_PATH "/org/freedesktop/portal/desktop" #define XDG_PORTAL_DBUS_INTERFACE "org.freedesktop.portal.Realtime" -static SDL_bool rtkit_use_session_conn; +static bool rtkit_use_session_conn; static const char *rtkit_dbus_node; static const char *rtkit_dbus_path; static const char *rtkit_dbus_interface; @@ -67,7 +67,7 @@ static Sint64 rtkit_max_rttime_usec = 200000; * - The desktop portal exists and supports the realtime interface. * - The realtime interface is new enough to have the required bug fixes applied. */ -static SDL_bool realtime_portal_supported(DBusConnection *conn) +static bool realtime_portal_supported(DBusConnection *conn) { Sint64 res; return SDL_DBus_QueryPropertyOnConnection(conn, XDG_PORTAL_DBUS_NODE, XDG_PORTAL_DBUS_PATH, XDG_PORTAL_DBUS_INTERFACE, @@ -78,14 +78,14 @@ static void set_rtkit_interface(void) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); - /* xdg-desktop-portal works in all instances, so check for it first. */ + // xdg-desktop-portal works in all instances, so check for it first. if (dbus && realtime_portal_supported(dbus->session_conn)) { - rtkit_use_session_conn = SDL_TRUE; + rtkit_use_session_conn = true; rtkit_dbus_node = XDG_PORTAL_DBUS_NODE; rtkit_dbus_path = XDG_PORTAL_DBUS_PATH; rtkit_dbus_interface = XDG_PORTAL_DBUS_INTERFACE; - } else { /* Fall back to the standard rtkit interface in all other cases. */ - rtkit_use_session_conn = SDL_FALSE; + } else { // Fall back to the standard rtkit interface in all other cases. + rtkit_use_session_conn = false; rtkit_dbus_node = RTKIT_DBUS_NODE; rtkit_dbus_path = RTKIT_DBUS_PATH; rtkit_dbus_interface = RTKIT_DBUS_INTERFACE; @@ -110,26 +110,26 @@ static void rtkit_initialize(void) set_rtkit_interface(); dbus_conn = get_rtkit_dbus_connection(); - /* Try getting minimum nice level: this is often greater than PRIO_MIN (-20). */ + // Try getting minimum nice level: this is often greater than PRIO_MIN (-20). if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MinNiceLevel", DBUS_TYPE_INT32, &rtkit_min_nice_level)) { rtkit_min_nice_level = -20; } - /* Try getting maximum realtime priority: this can be less than the POSIX default (99). */ + // Try getting maximum realtime priority: this can be less than the POSIX default (99). if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MaxRealtimePriority", DBUS_TYPE_INT32, &rtkit_max_realtime_priority)) { rtkit_max_realtime_priority = 99; } - /* Try getting maximum rttime allowed by rtkit: exceeding this value will result in SIGKILL */ + // Try getting maximum rttime allowed by rtkit: exceeding this value will result in SIGKILL if (!dbus_conn || !SDL_DBus_QueryPropertyOnConnection(dbus_conn, rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "RTTimeUSecMax", DBUS_TYPE_INT64, &rtkit_max_rttime_usec)) { rtkit_max_rttime_usec = 200000; } } -static SDL_bool rtkit_initialize_realtime_thread(void) +static bool rtkit_initialize_realtime_thread(void) { // Following is an excerpt from rtkit README that outlines the requirements // a thread must meet before making rtkit requests: @@ -163,7 +163,7 @@ static SDL_bool rtkit_initialize_realtime_thread(void) // Requirement #1: Set RLIMIT_RTTIME err = getrlimit(nLimit, &rlimit); if (err) { - return SDL_FALSE; + return false; } // Current rtkit allows a max of 200ms right now @@ -171,24 +171,24 @@ static SDL_bool rtkit_initialize_realtime_thread(void) rlimit.rlim_cur = rlimit.rlim_max / 2; err = setrlimit(nLimit, &rlimit); if (err) { - return SDL_FALSE; + return false; } // Requirement #2: Add SCHED_RESET_ON_FORK to the scheduler policy err = sched_getparam(nPid, &schedParam); if (err) { - return SDL_FALSE; + return false; } err = sched_setscheduler(nPid, nSchedPolicy, &schedParam); if (err) { - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } -static SDL_bool rtkit_setpriority_nice(pid_t thread, int nice_level) +static bool rtkit_setpriority_nice(pid_t thread, int nice_level) { DBusConnection *dbus_conn; Uint64 pid = (Uint64)getpid(); @@ -206,12 +206,12 @@ static SDL_bool rtkit_setpriority_nice(pid_t thread, int nice_level) rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadHighPriorityWithPID", DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_INT32, &nice, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID)) { - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } -static SDL_bool rtkit_setpriority_realtime(pid_t thread, int rt_priority) +static bool rtkit_setpriority_realtime(pid_t thread, int rt_priority) { DBusConnection *dbus_conn; Uint64 pid = (Uint64)getpid(); @@ -237,25 +237,25 @@ static SDL_bool rtkit_setpriority_realtime(pid_t thread, int rt_priority) rtkit_dbus_node, rtkit_dbus_path, rtkit_dbus_interface, "MakeThreadRealtimeWithPID", DBUS_TYPE_UINT64, &pid, DBUS_TYPE_UINT64, &tid, DBUS_TYPE_UINT32, &priority, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID)) { - return SDL_FALSE; + return false; } - return SDL_TRUE; + return true; } #else #define rtkit_max_realtime_priority 99 -#endif /* dbus */ -#endif /* threads */ +#endif // dbus +#endif // threads -/* this is a public symbol, so it has to exist even if threads are disabled. */ -int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) +// this is a public symbol, so it has to exist even if threads are disabled. +bool SDL_SetLinuxThreadPriority(Sint64 threadID, int priority) { #ifdef SDL_THREADS_DISABLED return SDL_Unsupported(); #else if (setpriority(PRIO_PROCESS, (id_t)threadID, priority) == 0) { - return 0; + return true; } #ifdef SDL_USE_LIBDBUS @@ -272,7 +272,7 @@ int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) README and sample code at: http://git.0pointer.net/rtkit.git */ if (rtkit_setpriority_nice((pid_t)threadID, priority)) { - return 0; + return true; } #endif @@ -280,8 +280,8 @@ int SDL_LinuxSetThreadPriority(Sint64 threadID, int priority) #endif } -/* this is a public symbol, so it has to exist even if threads are disabled. */ -int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy) +// this is a public symbol, so it has to exist even if threads are disabled. +bool SDL_SetLinuxThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int schedPolicy) { #ifdef SDL_THREADS_DISABLED return SDL_Unsupported(); @@ -310,7 +310,7 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc } if (setpriority(PRIO_PROCESS, (id_t)threadID, osPriority) == 0) { - return 0; + return true; } } @@ -329,11 +329,11 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc */ if (schedPolicy == SCHED_RR || schedPolicy == SCHED_FIFO) { if (rtkit_setpriority_realtime((pid_t)threadID, osPriority)) { - return 0; + return true; } } else { if (rtkit_setpriority_nice((pid_t)threadID, osPriority)) { - return 0; + return true; } } #endif @@ -342,4 +342,4 @@ int SDL_LinuxSetThreadPriorityAndPolicy(Sint64 threadID, int sdlPriority, int sc #endif } -#endif /* SDL_PLATFORM_LINUX */ +#endif // SDL_PLATFORM_LINUX diff --git a/libs/SDL3/src/core/linux/SDL_udev.c b/libs/SDL3/src/core/linux/SDL_udev.c index fb9921382..ada5a26b7 100644 --- a/libs/SDL3/src/core/linux/SDL_udev.c +++ b/libs/SDL3/src/core/linux/SDL_udev.c @@ -40,31 +40,31 @@ static const char *SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" }; static SDL_UDEV_PrivateData *_this = NULL; -static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr); -static int SDL_UDEV_load_syms(void); -static SDL_bool SDL_UDEV_hotplug_update_available(void); +static bool SDL_UDEV_load_sym(const char *fn, void **addr); +static bool SDL_UDEV_load_syms(void); +static bool SDL_UDEV_hotplug_update_available(void); static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len); static int guess_device_class(struct udev_device *dev); static int device_class(struct udev_device *dev); static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev); -static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr) +static bool SDL_UDEV_load_sym(const char *fn, void **addr) { *addr = SDL_LoadFunction(_this->udev_handle, fn); if (!*addr) { - /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ - return SDL_FALSE; + // Don't call SDL_SetError(): SDL_LoadFunction already did. + return false; } - return SDL_TRUE; + return true; } -static int SDL_UDEV_load_syms(void) +static bool SDL_UDEV_load_syms(void) { /* cast funcs to char* first, to please GCC's strict aliasing rules. */ #define SDL_UDEV_SYM(x) \ if (!SDL_UDEV_load_sym(#x, (void **)(char *)&_this->syms.x)) \ - return -1 + return false SDL_UDEV_SYM(udev_device_get_action); SDL_UDEV_SYM(udev_device_get_devnode); @@ -95,34 +95,31 @@ static int SDL_UDEV_load_syms(void) SDL_UDEV_SYM(udev_device_get_devnum); #undef SDL_UDEV_SYM - return 0; + return true; } -static SDL_bool SDL_UDEV_hotplug_update_available(void) +static bool SDL_UDEV_hotplug_update_available(void) { if (_this->udev_mon) { const int fd = _this->syms.udev_monitor_get_fd(_this->udev_mon); if (SDL_IOReady(fd, SDL_IOR_READ, 0)) { - return SDL_TRUE; + return true; } } - return SDL_FALSE; + return false; } -int SDL_UDEV_Init(void) +bool SDL_UDEV_Init(void) { - int retval = 0; - if (!_this) { _this = (SDL_UDEV_PrivateData *)SDL_calloc(1, sizeof(*_this)); if (!_this) { - return -1; + return false; } - retval = SDL_UDEV_LoadLibrary(); - if (retval < 0) { + if (!SDL_UDEV_LoadLibrary()) { SDL_UDEV_Quit(); - return retval; + return false; } /* Set up udev monitoring @@ -146,13 +143,13 @@ int SDL_UDEV_Init(void) _this->syms.udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "video4linux", NULL); _this->syms.udev_monitor_enable_receiving(_this->udev_mon); - /* Do an initial scan of existing devices */ + // Do an initial scan of existing devices SDL_UDEV_Scan(); } _this->ref_count += 1; - return retval; + return true; } void SDL_UDEV_Quit(void) @@ -174,7 +171,7 @@ void SDL_UDEV_Quit(void) _this->udev = NULL; } - /* Remove existing devices */ + // Remove existing devices while (_this->first) { SDL_UDEV_CallbackList *item = _this->first; _this->first = _this->first->next; @@ -187,14 +184,14 @@ void SDL_UDEV_Quit(void) } } -int SDL_UDEV_Scan(void) +bool SDL_UDEV_Scan(void) { struct udev_enumerate *enumerate = NULL; struct udev_list_entry *devs = NULL; struct udev_list_entry *item = NULL; if (!_this) { - return 0; + return true; } enumerate = _this->syms.udev_enumerate_new(_this->udev); @@ -219,10 +216,10 @@ int SDL_UDEV_Scan(void) } _this->syms.udev_enumerate_unref(enumerate); - return 0; + return true; } -SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class) +bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class) { struct stat statbuf; char type; @@ -231,11 +228,11 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 int class_temp; if (!_this) { - return SDL_FALSE; + return false; } if (stat(device_path, &statbuf) == -1) { - return SDL_FALSE; + return false; } if (S_ISBLK(statbuf.st_mode)) { @@ -245,13 +242,13 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 type = 'c'; } else { - return SDL_FALSE; + return false; } dev = _this->syms.udev_device_new_from_devnum(_this->udev, type, statbuf.st_rdev); if (!dev) { - return SDL_FALSE; + return false; } val = _this->syms.udev_device_get_property_value(dev, "ID_VENDOR_ID"); @@ -276,7 +273,7 @@ SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 _this->syms.udev_device_unref(dev); - return SDL_TRUE; + return true; } void SDL_UDEV_UnloadLibrary(void) @@ -291,26 +288,26 @@ void SDL_UDEV_UnloadLibrary(void) } } -int SDL_UDEV_LoadLibrary(void) +bool SDL_UDEV_LoadLibrary(void) { - int retval = 0, i; + bool result = true; if (!_this) { return SDL_SetError("UDEV not initialized"); } - /* See if there is a udev library already loaded */ - if (SDL_UDEV_load_syms() == 0) { - return 0; + // See if there is a udev library already loaded + if (SDL_UDEV_load_syms()) { + return true; } #ifdef SDL_UDEV_DYNAMIC - /* Check for the build environment's libudev first */ + // Check for the build environment's libudev first if (!_this->udev_handle) { _this->udev_handle = SDL_LoadObject(SDL_UDEV_DYNAMIC); if (_this->udev_handle) { - retval = SDL_UDEV_load_syms(); - if (retval < 0) { + result = SDL_UDEV_load_syms(); + if (!result) { SDL_UDEV_UnloadLibrary(); } } @@ -318,11 +315,11 @@ int SDL_UDEV_LoadLibrary(void) #endif if (!_this->udev_handle) { - for (i = 0; i < SDL_arraysize(SDL_UDEV_LIBS); i++) { + for (int i = 0; i < SDL_arraysize(SDL_UDEV_LIBS); i++) { _this->udev_handle = SDL_LoadObject(SDL_UDEV_LIBS[i]); if (_this->udev_handle) { - retval = SDL_UDEV_load_syms(); - if (retval < 0) { + result = SDL_UDEV_load_syms(); + if (!result) { SDL_UDEV_UnloadLibrary(); } else { break; @@ -331,12 +328,12 @@ int SDL_UDEV_LoadLibrary(void) } if (!_this->udev_handle) { - retval = -1; - /* Don't call SDL_SetError(): SDL_LoadObject already did. */ + result = false; + // Don't call SDL_SetError(): SDL_LoadObject already did. } } - return retval; + return result; } static void get_caps(struct udev_device *dev, struct udev_device *pdev, const char *attr, unsigned long *bitmask, size_t bitmask_len) @@ -420,7 +417,7 @@ static int device_class(struct udev_device *dev) devclass = SDL_UDEV_DEVICE_VIDEO_CAPTURE; } } else if (SDL_strcmp(subsystem, "input") == 0) { - /* udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c */ + // udev rules reference: http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-input_id.c val = _this->syms.udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"); if (val && SDL_strcmp(val, "1") == 0) { @@ -459,7 +456,7 @@ static int device_class(struct udev_device *dev) } if (devclass == 0) { - /* Fall back to old style input classes */ + // Fall back to old style input classes val = _this->syms.udev_device_get_property_value(dev, "ID_CLASS"); if (val) { if (SDL_strcmp(val, "joystick") == 0) { @@ -470,7 +467,7 @@ static int device_class(struct udev_device *dev) devclass = SDL_UDEV_DEVICE_HAS_KEYS | SDL_UDEV_DEVICE_KEYBOARD; } } else { - /* We could be linked with libudev on a system that doesn't have udev running */ + // We could be linked with libudev on a system that doesn't have udev running devclass = guess_device_class(dev); } } @@ -495,7 +492,7 @@ static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) return; } - /* Process callbacks */ + // Process callbacks for (item = _this->first; item; item = item->next) { item->callback(type, devclass, path); } @@ -529,12 +526,12 @@ void SDL_UDEV_Poll(void) } } -int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) +bool SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) { SDL_UDEV_CallbackList *item; item = (SDL_UDEV_CallbackList *)SDL_calloc(1, sizeof(SDL_UDEV_CallbackList)); if (!item) { - return -1; + return false; } item->callback = cb; @@ -546,7 +543,7 @@ int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb) _this->last = item; } - return 0; + return true; } void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb) @@ -559,7 +556,7 @@ void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb) } for (item = _this->first; item; item = item->next) { - /* found it, remove it. */ + // found it, remove it. if (item->callback == cb) { if (prev) { prev->next = item->next; @@ -579,7 +576,7 @@ void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb) const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void) { - if (SDL_UDEV_Init() < 0) { + if (!SDL_UDEV_Init()) { SDL_SetError("Could not initialize UDEV"); return NULL; } @@ -592,4 +589,4 @@ void SDL_UDEV_ReleaseUdevSyms(void) SDL_UDEV_Quit(); } -#endif /* SDL_USE_LIBUDEV */ +#endif // SDL_USE_LIBUDEV diff --git a/libs/SDL3/src/core/linux/SDL_udev.h b/libs/SDL3/src/core/linux/SDL_udev.h index b3972d675..c165bfecb 100644 --- a/libs/SDL3/src/core/linux/SDL_udev.h +++ b/libs/SDL3/src/core/linux/SDL_udev.h @@ -86,28 +86,28 @@ typedef struct SDL_UDEV_Symbols typedef struct SDL_UDEV_PrivateData { const char *udev_library; - void *udev_handle; + SDL_SharedObject *udev_handle; struct udev *udev; struct udev_monitor *udev_mon; int ref_count; SDL_UDEV_CallbackList *first, *last; - /* Function pointers */ + // Function pointers SDL_UDEV_Symbols syms; } SDL_UDEV_PrivateData; -extern int SDL_UDEV_Init(void); +extern bool SDL_UDEV_Init(void); extern void SDL_UDEV_Quit(void); extern void SDL_UDEV_UnloadLibrary(void); -extern int SDL_UDEV_LoadLibrary(void); +extern bool SDL_UDEV_LoadLibrary(void); extern void SDL_UDEV_Poll(void); -extern int SDL_UDEV_Scan(void); -extern SDL_bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class); -extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb); +extern bool SDL_UDEV_Scan(void); +extern bool SDL_UDEV_GetProductInfo(const char *device_path, Uint16 *vendor, Uint16 *product, Uint16 *version, int *class); +extern bool SDL_UDEV_AddCallback(SDL_UDEV_Callback cb); extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb); extern const SDL_UDEV_Symbols *SDL_UDEV_GetUdevSyms(void); extern void SDL_UDEV_ReleaseUdevSyms(void); -#endif /* HAVE_LIBUDEV_H && HAVE_LINUX_INPUT_H */ +#endif // HAVE_LIBUDEV_H && HAVE_LINUX_INPUT_H -#endif /* SDL_udev_h_ */ +#endif // SDL_udev_h_ diff --git a/libs/SDL3/src/core/openbsd/SDL_wscons.h b/libs/SDL3/src/core/openbsd/SDL_wscons.h index 40e102d00..c56b1098c 100644 --- a/libs/SDL3/src/core/openbsd/SDL_wscons.h +++ b/libs/SDL3/src/core/openbsd/SDL_wscons.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -void SDL_WSCONS_Init(); -void SDL_WSCONS_Quit(); +void SDL_WSCONS_Init(void); +void SDL_WSCONS_Quit(void); -void SDL_WSCONS_PumpEvents(); +void SDL_WSCONS_PumpEvents(void); diff --git a/libs/SDL3/src/core/openbsd/SDL_wscons_kbd.c b/libs/SDL3/src/core/openbsd/SDL_wscons_kbd.c index 81f94448c..79566ef5b 100644 --- a/libs/SDL3/src/core/openbsd/SDL_wscons_kbd.c +++ b/libs/SDL3/src/core/openbsd/SDL_wscons_kbd.c @@ -49,48 +49,48 @@ } typedef struct SDL_WSCONS_mouse_input_data SDL_WSCONS_mouse_input_data; -extern SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(); +extern SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(void); extern void updateMouse(SDL_WSCONS_mouse_input_data *input); extern void SDL_WSCONS_Quit_Mouse(SDL_WSCONS_mouse_input_data *input); -/* Conversion table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */ +// Conversion table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c static const unsigned char latin1_to_upper[256] = { - /* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */ - 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */ - 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */ - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */ - 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */ - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */ - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */ - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */ - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */ + // 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 5 + 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', // 6 + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', // 6 + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', // 7 + 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, // 7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // a + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // b + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // b + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // c + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // c + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // d + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, // e + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, // e + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, // f + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, // f }; -/* Compose table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c */ +// Compose table courtesy of /usr/src/sys/dev/wscons/wskbdutil.c static struct SDL_wscons_compose_tab_s { keysym_t elem[2]; @@ -433,9 +433,9 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) } input->keyboardID = SDL_GetNextObjectID(); - SDL_AddKeyboard(input->keyboardID, NULL, SDL_FALSE); + SDL_AddKeyboard(input->keyboardID, NULL, false); - input->keymap.map = SDL_calloc(sizeof(struct wscons_keymap), KS_NUMKEYCODES); + input->keymap.map = SDL_calloc(KS_NUMKEYCODES, sizeof(struct wscons_keymap)); if (!input->keymap.map) { SDL_free(input); return NULL; @@ -452,7 +452,7 @@ static SDL_WSCONS_input_data *SDL_WSCONS_Init_Keyboard(const char *dev) return input; } -void SDL_WSCONS_Init() +void SDL_WSCONS_Init(void) { inputs[0] = SDL_WSCONS_Init_Keyboard("/dev/wskbd0"); inputs[1] = SDL_WSCONS_Init_Keyboard("/dev/wskbd1"); @@ -463,7 +463,7 @@ void SDL_WSCONS_Init() return; } -void SDL_WSCONS_Quit() +void SDL_WSCONS_Quit(void) { int i = 0; SDL_WSCONS_input_data *input = NULL; @@ -487,7 +487,7 @@ void SDL_WSCONS_Quit() static void put_queue(SDL_WSCONS_input_data *kbd, uint c) { - /* c is already part of a UTF-8 sequence and safe to add as a character */ + // c is already part of a UTF-8 sequence and safe to add as a character if (kbd->text_len < (sizeof(kbd->text) - 1)) { kbd->text[kbd->text_len++] = (char)(c); } @@ -535,7 +535,7 @@ static void Translate_to_text(SDL_WSCONS_input_data *input, keysym_t ksym) case KS_BackSpace: case KS_Return: case KS_Linefeed: - /* All of these are unprintable characters. Ignore them */ + // All of these are unprintable characters. Ignore them break; default: put_utf8(input, ksym); @@ -544,7 +544,7 @@ static void Translate_to_text(SDL_WSCONS_input_data *input, keysym_t ksym) if (input->text_len > 0) { input->text[input->text_len] = '\0'; SDL_SendKeyboardText(input->text); - /*SDL_memset(input->text, 0, sizeof(input->text));*/ + // SDL_memset(input->text, 0, sizeof(input->text)); input->text_len = 0; input->text[0] = 0; } @@ -556,26 +556,26 @@ static void Translate_to_keycode(SDL_WSCONS_input_data *input, int type, keysym_ keysym_t *group = &keyDesc.group1[KS_GROUP(keyDesc.group1[0]) == KS_GROUP_Keypad && IS_NUMLOCK_ON ? !IS_SHIFT_HELD : 0]; int i = 0; - /* Check command first, then group[0]*/ + // Check command first, then group[0] switch (keyDesc.command) { case KS_Cmd_ScrollBack: { - SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEUP); + SDL_SendKeyboardKey(0, input->keyboardID, 0, SDL_SCANCODE_PAGEUP, (type == WSCONS_EVENT_KEY_DOWN)); return; } case KS_Cmd_ScrollFwd: { - SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_PAGEDOWN); + SDL_SendKeyboardKey(0, input->keyboardID, 0, SDL_SCANCODE_PAGEDOWN, (type == WSCONS_EVENT_KEY_DOWN)); return; } } for (i = 0; i < sizeof(conversion_table) / sizeof(struct wscons_keycode_to_SDL); i++) { if (conversion_table[i].sourcekey == group[0]) { - SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, conversion_table[i].targetKey); + SDL_SendKeyboardKey(0, input->keyboardID, group[0], conversion_table[i].targetKey, (type == WSCONS_EVENT_KEY_DOWN)); return; } } - SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_UNKNOWN); + SDL_SendKeyboardKey(0, input->keyboardID, group[0], SDL_SCANCODE_UNKNOWN, (type == WSCONS_EVENT_KEY_DOWN)); } static void updateKeyboard(SDL_WSCONS_input_data *input) @@ -808,14 +808,14 @@ static void updateKeyboard(SDL_WSCONS_input_data *input) } } break; case WSCONS_EVENT_ALL_KEYS_UP: - for (i = 0; i < SDL_NUM_SCANCODES; i++) { - SDL_SendKeyboardKey(0, input->keyboardID, SDL_RELEASED, i); + for (i = 0; i < SDL_SCANCODE_COUNT; i++) { + SDL_SendKeyboardKey(0, input->keyboardID, 0, (SDL_Scancode)i, false); } break; } if (input->type == WSKBD_TYPE_USB && events[i].value <= 0xE7) - SDL_SendKeyboardKey(0, input->keyboardID, type == WSCONS_EVENT_KEY_DOWN ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)events[i].value); + SDL_SendKeyboardKey(0, input->keyboardID, 0, (SDL_Scancode)events[i].value, (type == WSCONS_EVENT_KEY_DOWN)); else Translate_to_keycode(input, type, events[i].value); @@ -924,7 +924,7 @@ static void updateKeyboard(SDL_WSCONS_input_data *input) } } -void SDL_WSCONS_PumpEvents() +void SDL_WSCONS_PumpEvents(void) { int i = 0; for (i = 0; i < 4; i++) { diff --git a/libs/SDL3/src/core/openbsd/SDL_wscons_mouse.c b/libs/SDL3/src/core/openbsd/SDL_wscons_mouse.c index 6b0c96261..5ba7a5007 100644 --- a/libs/SDL3/src/core/openbsd/SDL_wscons_mouse.c +++ b/libs/SDL3/src/core/openbsd/SDL_wscons_mouse.c @@ -35,7 +35,7 @@ typedef struct SDL_WSCONS_mouse_input_data SDL_MouseID mouseID; } SDL_WSCONS_mouse_input_data; -SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse() +SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse(void) { #ifdef WSMOUSEIO_SETVERSION int version = WSMOUSE_EVENT_VERSION; @@ -52,7 +52,7 @@ SDL_WSCONS_mouse_input_data *SDL_WSCONS_Init_Mouse() } input->mouseID = SDL_GetNextObjectID(); - SDL_AddMouse(input->mouseID, NULL, SDL_FALSE); + SDL_AddMouse(input->mouseID, NULL, false); #ifdef WSMOUSEIO_SETMODE ioctl(input->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT); @@ -78,28 +78,28 @@ void updateMouse(SDL_WSCONS_mouse_input_data *input) case WSCONS_EVENT_MOUSE_DOWN: { switch (events[i].value) { - case 0: /* Left Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_LEFT); + case 0: // Left Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_LEFT, true); break; - case 1: /* Middle Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_MIDDLE); + case 1: // Middle Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_MIDDLE, true); break; - case 2: /* Right Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_PRESSED, SDL_BUTTON_RIGHT); + case 2: // Right Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_RIGHT, true); break; } } break; case WSCONS_EVENT_MOUSE_UP: { switch (events[i].value) { - case 0: /* Left Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_LEFT); + case 0: // Left Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_LEFT, false); break; - case 1: /* Middle Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_MIDDLE); + case 1: // Middle Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_MIDDLE, false); break; - case 2: /* Right Mouse Button. */ - SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_RELEASED, SDL_BUTTON_RIGHT); + case 2: // Right Mouse Button. + SDL_SendMouseButton(0, mouse->focus, input->mouseID, SDL_BUTTON_RIGHT, false); break; } } break; diff --git a/libs/SDL3/src/core/unix/SDL_appid.c b/libs/SDL3/src/core/unix/SDL_appid.c index 67a44330d..046b88244 100644 --- a/libs/SDL3/src/core/unix/SDL_appid.c +++ b/libs/SDL3/src/core/unix/SDL_appid.c @@ -24,11 +24,11 @@ #include "SDL_appid.h" #include -const char *SDL_GetExeName() +const char *SDL_GetExeName(void) { static const char *proc_name = NULL; - /* TODO: Use a fallback if BSD has no mounted procfs (OpenBSD has no procfs at all) */ + // TODO: Use a fallback if BSD has no mounted procfs (OpenBSD has no procfs at all) if (!proc_name) { #if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD) || defined (SDL_PLATFORM_NETBSD) static char linkfile[1024]; @@ -57,18 +57,17 @@ const char *SDL_GetExeName() return proc_name; } -const char *SDL_GetAppID() +const char *SDL_GetAppID(void) { - /* Always check the hint, as it may have changed */ - const char *id_str = SDL_GetHint(SDL_HINT_APP_ID); + const char *id_str = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING); if (!id_str) { - /* If the hint isn't set, try to use the application's executable name */ + // If the hint isn't set, try to use the application's executable name id_str = SDL_GetExeName(); } if (!id_str) { - /* Finally, use the default we've used forever */ + // Finally, use the default we've used forever id_str = "SDL_App"; } diff --git a/libs/SDL3/src/core/unix/SDL_appid.h b/libs/SDL3/src/core/unix/SDL_appid.h index 976788cb1..37c9e11fc 100644 --- a/libs/SDL3/src/core/unix/SDL_appid.h +++ b/libs/SDL3/src/core/unix/SDL_appid.h @@ -24,7 +24,7 @@ freely, subject to the following restrictions: #ifndef SDL_appid_h_ #define SDL_appid_h_ -extern const char *SDL_GetExeName(); -extern const char *SDL_GetAppID(); +extern const char *SDL_GetExeName(void); +extern const char *SDL_GetAppID(void); -#endif /* SDL_appid_h_ */ +#endif // SDL_appid_h_ diff --git a/libs/SDL3/src/core/unix/SDL_poll.c b/libs/SDL3/src/core/unix/SDL_poll.c index 2ff460997..b164efd4d 100644 --- a/libs/SDL3/src/core/unix/SDL_poll.c +++ b/libs/SDL3/src/core/unix/SDL_poll.c @@ -38,7 +38,7 @@ int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) SDL_assert(flags & (SDL_IOR_READ | SDL_IOR_WRITE)); - /* Note: We don't bother to account for elapsed time if we get EINTR */ + // Note: We don't bother to account for elapsed time if we get EINTR do { #ifdef HAVE_POLL struct pollfd info; @@ -52,7 +52,7 @@ int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) if (flags & SDL_IOR_WRITE) { info.events |= POLLOUT; } - /* FIXME: Add support for ppoll() for nanosecond precision */ + // FIXME: Add support for ppoll() for nanosecond precision if (timeoutNS > 0) { timeoutMS = (int)SDL_NS_TO_MS(timeoutNS); } else if (timeoutNS == 0) { @@ -66,7 +66,7 @@ int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) fd_set wfdset, *wfdp = NULL; struct timeval tv, *tvp = NULL; - /* If this assert triggers we'll corrupt memory here */ + // If this assert triggers we'll corrupt memory here SDL_assert(fd >= 0 && fd < FD_SETSIZE); if (flags & SDL_IOR_READ) { @@ -87,7 +87,7 @@ int SDL_IOReady(int fd, int flags, Sint64 timeoutNS) } result = select(fd + 1, rfdp, wfdp, NULL, tvp); -#endif /* HAVE_POLL */ +#endif // HAVE_POLL } while (result < 0 && errno == EINTR && !(flags & SDL_IOR_NO_RETRY)); diff --git a/libs/SDL3/src/core/unix/SDL_poll.h b/libs/SDL3/src/core/unix/SDL_poll.h index eef1d64b2..8034b1dc0 100644 --- a/libs/SDL3/src/core/unix/SDL_poll.h +++ b/libs/SDL3/src/core/unix/SDL_poll.h @@ -30,4 +30,4 @@ extern int SDL_IOReady(int fd, int flags, Sint64 timeoutNS); -#endif /* SDL_poll_h_ */ +#endif // SDL_poll_h_ diff --git a/libs/SDL3/src/core/windows/SDL_directx.h b/libs/SDL3/src/core/windows/SDL_directx.h index 6736d8d7b..3acf0ae46 100644 --- a/libs/SDL3/src/core/windows/SDL_directx.h +++ b/libs/SDL3/src/core/windows/SDL_directx.h @@ -23,7 +23,7 @@ #ifndef SDL_directx_h_ #define SDL_directx_h_ -/* Include all of the DirectX 8.0 headers and adds any necessary tweaks */ +// Include all of the DirectX 8.0 headers and adds any necessary tweaks #include "SDL_windows.h" #include @@ -32,12 +32,12 @@ #endif #undef WINNT -/* Far pointers don't exist in 32-bit code */ +// Far pointers don't exist in 32-bit code #ifndef FAR #define FAR #endif -/* Error codes not yet included in Win32 API header files */ +// Error codes not yet included in Win32 API header files #ifndef MAKE_HRESULT #define MAKE_HRESULT(sev, fac, code) \ ((HRESULT)(((unsigned long)(sev) << 31) | ((unsigned long)(fac) << 16) | ((unsigned long)(code)))) @@ -73,12 +73,12 @@ #define REGDB_E_CLASSNOTREG (HRESULT)0x80040154L #endif -/* Severity codes */ +// Severity codes #ifndef SEVERITY_ERROR #define SEVERITY_ERROR 1 #endif -/* Error facility codes */ +// Error facility codes #ifndef FACILITY_WIN32 #define FACILITY_WIN32 7 #endif @@ -89,10 +89,10 @@ /* DirectX headers (if it isn't included, I haven't tested it yet) */ -/* We need these defines to mark what version of DirectX API we use */ +// We need these defines to mark what version of DirectX API we use #define DIRECTDRAW_VERSION 0x0700 #define DIRECTSOUND_VERSION 0x0800 -#define DIRECTINPUT_VERSION 0x0800 /* Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... */ +#define DIRECTINPUT_VERSION 0x0800 // Need version 7 for force feedback. Need version 8 so IDirectInput8_EnumDevices doesn't leak like a sieve... #ifdef HAVE_DDRAW_H #include @@ -109,4 +109,4 @@ typedef struct } DIDEVICEINSTANCE; #endif -#endif /* SDL_directx_h_ */ +#endif // SDL_directx_h_ diff --git a/libs/SDL3/src/core/windows/SDL_hid.c b/libs/SDL3/src/core/windows/SDL_hid.c index 0e42bb667..419cb7270 100644 --- a/libs/SDL3/src/core/windows/SDL_hid.c +++ b/libs/SDL3/src/core/windows/SDL_hid.c @@ -20,8 +20,6 @@ */ #include "SDL_internal.h" -#ifndef SDL_PLATFORM_WINRT - #include "SDL_hid.h" HidD_GetString_t SDL_HidD_GetManufacturerString; @@ -36,17 +34,17 @@ static HMODULE s_pHIDDLL = 0; static int s_HIDDLLRefCount = 0; -int WIN_LoadHIDDLL(void) +bool WIN_LoadHIDDLL(void) { if (s_pHIDDLL) { SDL_assert(s_HIDDLLRefCount > 0); s_HIDDLLRefCount++; - return 0; /* already loaded */ + return true; // already loaded } s_pHIDDLL = LoadLibrary(TEXT("hid.dll")); if (!s_pHIDDLL) { - return -1; + return false; } SDL_assert(s_HIDDLLRefCount == 0); @@ -63,10 +61,10 @@ int WIN_LoadHIDDLL(void) !SDL_HidP_GetCaps || !SDL_HidP_GetButtonCaps || !SDL_HidP_GetValueCaps || !SDL_HidP_MaxDataListLength || !SDL_HidP_GetData) { WIN_UnloadHIDDLL(); - return -1; + return false; } - return 0; + return true; } void WIN_UnloadHIDDLL(void) @@ -82,11 +80,9 @@ void WIN_UnloadHIDDLL(void) } } -#endif /* !SDL_PLATFORM_WINRT */ - -#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) -/* CM_Register_Notification definitions */ +// CM_Register_Notification definitions #define CR_SUCCESS 0 @@ -224,7 +220,7 @@ void WIN_QuitDeviceNotification(void) if (--s_DeviceNotificationsRequested > 0) { return; } - /* Make sure we have balanced calls to init/quit */ + // Make sure we have balanced calls to init/quit SDL_assert(s_DeviceNotificationsRequested == 0); if (cfgmgr32_lib_handle) { @@ -253,4 +249,4 @@ void WIN_QuitDeviceNotification(void) { } -#endif // !SDL_PLATFORM_WINRT && !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES +#endif // !SDL_PLATFORM_XBOXONE && !SDL_PLATFORM_XBOXSERIES diff --git a/libs/SDL3/src/core/windows/SDL_hid.h b/libs/SDL3/src/core/windows/SDL_hid.h index 3d7821126..50c5d38c0 100644 --- a/libs/SDL3/src/core/windows/SDL_hid.h +++ b/libs/SDL3/src/core/windows/SDL_hid.h @@ -25,8 +25,6 @@ #include "SDL_windows.h" -#ifndef SDL_PLATFORM_WINRT - typedef LONG NTSTATUS; typedef USHORT USAGE; typedef struct _HIDP_PREPARSED_DATA *PHIDP_PREPARSED_DATA; @@ -190,7 +188,7 @@ typedef struct #define HIDP_STATUS_REPORT_DOES_NOT_EXIST HIDP_ERROR_CODES(0xC, 0x0010) #define HIDP_STATUS_NOT_IMPLEMENTED HIDP_ERROR_CODES(0xC, 0x0020) -extern int WIN_LoadHIDDLL(void); +extern bool WIN_LoadHIDDLL(void); extern void WIN_UnloadHIDDLL(void); typedef BOOLEAN (WINAPI *HidD_GetString_t)(HANDLE HidDeviceObject, PVOID Buffer, ULONG BufferLength); @@ -208,11 +206,8 @@ extern HidP_GetValueCaps_t SDL_HidP_GetValueCaps; extern HidP_MaxDataListLength_t SDL_HidP_MaxDataListLength; extern HidP_GetData_t SDL_HidP_GetData; -#endif /* !SDL_PLATFORM_WINRT */ - - void WIN_InitDeviceNotification(void); Uint64 WIN_GetLastDeviceNotification(void); void WIN_QuitDeviceNotification(void); -#endif /* SDL_hid_h_ */ +#endif // SDL_hid_h_ diff --git a/libs/SDL3/src/core/windows/SDL_immdevice.c b/libs/SDL3/src/core/windows/SDL_immdevice.c index 77911e64c..ddf55cdaa 100644 --- a/libs/SDL3/src/core/windows/SDL_immdevice.c +++ b/libs/SDL3/src/core/windows/SDL_immdevice.c @@ -20,12 +20,12 @@ */ #include "SDL_internal.h" -#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && defined(HAVE_MMDEVICEAPI_H) +#if defined(SDL_PLATFORM_WINDOWS) && defined(HAVE_MMDEVICEAPI_H) #include "SDL_windows.h" #include "SDL_immdevice.h" #include "../../audio/SDL_sysaudio.h" -#include /* For CLSIDFromString */ +#include // For CLSIDFromString typedef struct SDL_IMMDevice_HandleData { @@ -33,20 +33,20 @@ typedef struct SDL_IMMDevice_HandleData GUID directsound_guid; } SDL_IMMDevice_HandleData; -static const ERole SDL_IMMDevice_role = eConsole; /* !!! FIXME: should this be eMultimedia? Should be a hint? */ +static const ERole SDL_IMMDevice_role = eConsole; // !!! FIXME: should this be eMultimedia? Should be a hint? -/* This is global to the WASAPI target, to handle hotplug and default device lookup. */ +// This is global to the WASAPI target, to handle hotplug and default device lookup. static IMMDeviceEnumerator *enumerator = NULL; static SDL_IMMDevice_callbacks immcallbacks; -/* PropVariantInit() is an inline function/macro in PropIdl.h that calls the C runtime's memset() directly. Use ours instead, to avoid dependency. */ +// PropVariantInit() is an inline function/macro in PropIdl.h that calls the C runtime's memset() directly. Use ours instead, to avoid dependency. #ifdef PropVariantInit #undef PropVariantInit #endif #define PropVariantInit(p) SDL_zerop(p) -/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */ -/* *INDENT-OFF* */ /* clang-format off */ +// Some GUIDs we need to know without linking to libraries that aren't available before Vista. +/* *INDENT-OFF* */ // clang-format off static const CLSID SDL_CLSID_MMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c,{ 0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e } }; static const IID SDL_IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35,{ 0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6 } }; static const IID SDL_IID_IMMNotificationClient = { 0x7991eec9, 0x7e89, 0x4d85,{ 0x83, 0x90, 0x6c, 0x70, 0x3c, 0xec, 0x60, 0xc0 } }; @@ -54,18 +54,18 @@ static const IID SDL_IID_IMMEndpoint = { 0x1be09788, 0x6894, 0x4089,{ 0x85, 0x86 static const PROPERTYKEY SDL_PKEY_Device_FriendlyName = { { 0xa45c254e, 0xdf1c, 0x4efd,{ 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, } }, 14 }; static const PROPERTYKEY SDL_PKEY_AudioEngine_DeviceFormat = { { 0xf19f064d, 0x82c, 0x4e27,{ 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, } }, 0 }; static const PROPERTYKEY SDL_PKEY_AudioEndpoint_GUID = { { 0x1da5d803, 0xd492, 0x4edd,{ 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, } }, 4 }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on -static SDL_bool FindByDevIDCallback(SDL_AudioDevice *device, void *userdata) +static bool FindByDevIDCallback(SDL_AudioDevice *device, void *userdata) { LPCWSTR devid = (LPCWSTR)userdata; if (devid && device && device->handle) { const SDL_IMMDevice_HandleData *handle = (const SDL_IMMDevice_HandleData *)device->handle; if (handle->immdevice_id && SDL_wcscmp(handle->immdevice_id, devid) == 0) { - return SDL_TRUE; + return true; } } - return SDL_FALSE; + return false; } static SDL_AudioDevice *SDL_IMMDevice_FindByDevID(LPCWSTR devid) @@ -120,7 +120,7 @@ void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device) } } -static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid) +static SDL_AudioDevice *SDL_IMMDevice_Add(const bool recording, const char *devname, WAVEFORMATEXTENSIBLE *fmt, LPCWSTR devid, GUID *dsoundguid) { /* You can have multiple endpoints on a device that are mutually exclusive ("Speakers" vs "Line Out" or whatever). In a perfect world, things that are unplugged won't be in this collection. The only gotcha is probably for @@ -134,7 +134,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * // see if we already have this one first. SDL_AudioDevice *device = SDL_IMMDevice_FindByDevID(devid); if (device) { - if (SDL_AtomicGet(&device->zombie)) { + if (SDL_GetAtomicInt(&device->zombie)) { // whoa, it came back! This can happen if you unplug and replug USB headphones while we're still keeping the SDL object alive. // Kill this device's IMMDevice id; the device will go away when the app closes it, or maybe a new default device is chosen // (possibly this reconnected device), so we just want to make sure IMMDevice doesn't try to find the old device by the existing ID string. @@ -164,7 +164,7 @@ static SDL_AudioDevice *SDL_IMMDevice_Add(const SDL_bool iscapture, const char * spec.freq = fmt->Format.nSamplesPerSec; spec.format = SDL_WaveFormatExToSDLFormat((WAVEFORMATEX *)fmt); - device = SDL_AddAudioDevice(iscapture, devname, &spec, handle); + device = SDL_AddAudioDevice(recording, devname, &spec, handle); if (!device) { SDL_free(handle->immdevice_id); SDL_free(handle); @@ -205,14 +205,14 @@ static ULONG STDMETHODCALLTYPE SDLMMNotificationClient_AddRef(IMMNotificationCli static ULONG STDMETHODCALLTYPE SDLMMNotificationClient_Release(IMMNotificationClient *iclient) { - /* client is a static object; we don't ever free it. */ + // client is a static object; we don't ever free it. SDLMMNotificationClient *client = (SDLMMNotificationClient *)iclient; - const ULONG retval = SDL_AtomicDecRef(&client->refcount); - if (retval == 0) { - SDL_AtomicSet(&client->refcount, 0); /* uhh... */ + const ULONG rc = SDL_AtomicDecRef(&client->refcount); + if (rc == 0) { + SDL_SetAtomicInt(&client->refcount, 0); // uhh... return 0; } - return retval - 1; + return rc - 1; } // These are the entry points called when WASAPI device endpoints change. @@ -248,14 +248,14 @@ static HRESULT STDMETHODCALLTYPE SDLMMNotificationClient_OnDeviceStateChanged(IM if (SUCCEEDED(IMMDevice_QueryInterface(device, &SDL_IID_IMMEndpoint, (void **)&endpoint))) { EDataFlow flow; if (SUCCEEDED(IMMEndpoint_GetDataFlow(endpoint, &flow))) { - const SDL_bool iscapture = (flow == eCapture); + const bool recording = (flow == eCapture); if (dwNewState == DEVICE_STATE_ACTIVE) { char *utf8dev; WAVEFORMATEXTENSIBLE fmt; GUID dsoundguid; GetMMDeviceInfo(device, &utf8dev, &fmt, &dsoundguid); if (utf8dev) { - SDL_IMMDevice_Add(iscapture, utf8dev, &fmt, pwstrDeviceId, &dsoundguid); + SDL_IMMDevice_Add(recording, utf8dev, &fmt, pwstrDeviceId, &dsoundguid); SDL_free(utf8dev); } } else { @@ -288,11 +288,11 @@ static const IMMNotificationClientVtbl notification_client_vtbl = { static SDLMMNotificationClient notification_client = { ¬ification_client_vtbl, { 1 } }; -int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks) +bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks) { HRESULT ret; - /* just skip the discussion with COM here. */ + // just skip the discussion with COM here. if (!WIN_IsWindowsVistaOrGreater()) { return SDL_SetError("IMMDevice support requires Windows Vista or later"); } @@ -320,7 +320,7 @@ int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks) immcallbacks.default_audio_device_changed = SDL_DefaultAudioDeviceChanged; } - return 0; + return true; } void SDL_IMMDevice_Quit(void) @@ -336,9 +336,9 @@ void SDL_IMMDevice_Quit(void) WIN_CoUninitialize(); } -int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture) +bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool recording) { - const Uint64 timeout = SDL_GetTicks() + 8000; /* intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. */ + const Uint64 timeout = SDL_GetTicks() + 8000; // intel's audio drivers can fail for up to EIGHT SECONDS after a device is connected or we wake from sleep. SDL_assert(device != NULL); SDL_assert(immdevice != NULL); @@ -351,23 +351,25 @@ int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool i const Uint64 now = SDL_GetTicks(); if (timeout > now) { const Uint64 ticksleft = timeout - now; - SDL_Delay((Uint32)SDL_min(ticksleft, 300)); /* wait awhile and try again. */ + SDL_Delay((Uint32)SDL_min(ticksleft, 300)); // wait awhile and try again. continue; } break; } - return SUCCEEDED(ret) ? 0 : WIN_SetErrorFromHRESULT("WASAPI can't find requested audio endpoint", ret); - + if (!SUCCEEDED(ret)) { + return WIN_SetErrorFromHRESULT("WASAPI can't find requested audio endpoint", ret); + } + return true; } -static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice **default_device) +static void EnumerateEndpointsForFlow(const bool recording, SDL_AudioDevice **default_device) { /* Note that WASAPI separates "adapter devices" from "audio endpoint devices" ...one adapter device ("SoundBlaster Pro") might have multiple endpoint devices ("Speakers", "Line-Out"). */ IMMDeviceCollection *collection = NULL; - if (FAILED(IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, iscapture ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection))) { + if (FAILED(IMMDeviceEnumerator_EnumAudioEndpoints(enumerator, recording ? eCapture : eRender, DEVICE_STATE_ACTIVE, &collection))) { return; } @@ -380,7 +382,7 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice LPWSTR default_devid = NULL; if (default_device) { IMMDevice *default_immdevice = NULL; - const EDataFlow dataflow = iscapture ? eCapture : eRender; + const EDataFlow dataflow = recording ? eCapture : eRender; if (SUCCEEDED(IMMDeviceEnumerator_GetDefaultAudioEndpoint(enumerator, dataflow, SDL_IMMDevice_role, &default_immdevice))) { LPWSTR devid = NULL; if (SUCCEEDED(IMMDevice_GetId(default_immdevice, &devid))) { @@ -403,7 +405,7 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice SDL_zero(dsoundguid); GetMMDeviceInfo(immdevice, &devname, &fmt, &dsoundguid); if (devname) { - SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(iscapture, devname, &fmt, devid, &dsoundguid); + SDL_AudioDevice *sdldevice = SDL_IMMDevice_Add(recording, devname, &fmt, devid, &dsoundguid); if (default_device && default_devid && SDL_wcscmp(default_devid, devid) == 0) { *default_device = sdldevice; } @@ -420,13 +422,13 @@ static void EnumerateEndpointsForFlow(const SDL_bool iscapture, SDL_AudioDevice IMMDeviceCollection_Release(collection); } -void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture) +void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording) { - EnumerateEndpointsForFlow(SDL_FALSE, default_output); /* playback */ - EnumerateEndpointsForFlow(SDL_TRUE, default_capture); /* capture */ + EnumerateEndpointsForFlow(false, default_playback); + EnumerateEndpointsForFlow(true, default_recording); - /* if this fails, we just won't get hotplug events. Carry on anyhow. */ + // if this fails, we just won't get hotplug events. Carry on anyhow. IMMDeviceEnumerator_RegisterEndpointNotificationCallback(enumerator, (IMMNotificationClient *)¬ification_client); } -#endif /* (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && defined(HAVE_MMDEVICEAPI_H) */ +#endif // defined(SDL_PLATFORM_WINDOWS) && defined(HAVE_MMDEVICEAPI_H) diff --git a/libs/SDL3/src/core/windows/SDL_immdevice.h b/libs/SDL3/src/core/windows/SDL_immdevice.h index 3dcd45ebc..9ebd142e9 100644 --- a/libs/SDL3/src/core/windows/SDL_immdevice.h +++ b/libs/SDL3/src/core/windows/SDL_immdevice.h @@ -34,12 +34,12 @@ typedef struct SDL_IMMDevice_callbacks void (*default_audio_device_changed)(SDL_AudioDevice *new_default_device); } SDL_IMMDevice_callbacks; -int SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks); +bool SDL_IMMDevice_Init(const SDL_IMMDevice_callbacks *callbacks); void SDL_IMMDevice_Quit(void); -int SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, SDL_bool iscapture); -void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_output, SDL_AudioDevice **default_capture); +bool SDL_IMMDevice_Get(SDL_AudioDevice *device, IMMDevice **immdevice, bool recording); +void SDL_IMMDevice_EnumerateEndpoints(SDL_AudioDevice **default_playback, SDL_AudioDevice **default_recording); LPGUID SDL_IMMDevice_GetDirectSoundGUID(SDL_AudioDevice *device); LPCWSTR SDL_IMMDevice_GetDevID(SDL_AudioDevice *device); void SDL_IMMDevice_FreeDeviceHandle(SDL_AudioDevice *device); -#endif /* SDL_IMMDEVICE_H */ +#endif // SDL_IMMDEVICE_H diff --git a/libs/SDL3/src/core/windows/SDL_windows.c b/libs/SDL3/src/core/windows/SDL_windows.c index bc06f4d5e..c8a157c7a 100644 --- a/libs/SDL3/src/core/windows/SDL_windows.c +++ b/libs/SDL3/src/core/windows/SDL_windows.c @@ -20,13 +20,13 @@ */ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "SDL_windows.h" -#include /* for CoInitialize/CoUninitialize (Win32 only) */ +#include // for CoInitialize/CoUninitialize (Win32 only) #ifdef HAVE_ROAPI_H -#include /* For RoInitialize/RoUninitialize (Win32 only) */ +#include // For RoInitialize/RoUninitialize (Win32 only) #else typedef enum RO_INIT_TYPE { @@ -53,8 +53,8 @@ typedef enum RO_INIT_TYPE #define WC_ERR_INVALID_CHARS 0x00000080 #endif -/* Sets an error message based on an HRESULT */ -int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) +// Sets an error message based on an HRESULT +bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) { TCHAR buffer[1024]; char *message; @@ -62,7 +62,7 @@ int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) DWORD c = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, 0, buffer, SDL_arraysize(buffer), NULL); buffer[c] = 0; - /* kill CR/LF that FormatMessage() sticks at the end */ + // kill CR/LF that FormatMessage() sticks at the end while (*p) { if (*p == '\r') { *p = 0; @@ -73,11 +73,11 @@ int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr) message = WIN_StringToUTF8(buffer); SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message); SDL_free(message); - return -1; + return false; } -/* Sets an error message based on GetLastError() */ -int WIN_SetError(const char *prefix) +// Sets an error message based on GetLastError() +bool WIN_SetError(const char *prefix) { return WIN_SetErrorFromHRESULT(prefix, GetLastError()); } @@ -90,15 +90,8 @@ WIN_CoInitialize(void) If you need multi-threaded mode, call CoInitializeEx() before SDL_Init() */ -#ifdef SDL_PLATFORM_WINRT - /* DLudwig: On WinRT, it is assumed that COM was initialized in main(). - CoInitializeEx is available (not CoInitialize though), however - on WinRT, main() is typically declared with the [MTAThread] - attribute, which, AFAIK, should initialize COM. - */ - return S_OK; -#elif defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) - /* On Xbox, there's no need to call CoInitializeEx (and it's not implemented) */ +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) + // On Xbox, there's no need to call CoInitializeEx (and it's not implemented) return S_OK; #else HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); @@ -106,8 +99,8 @@ WIN_CoInitialize(void) hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); } - /* S_FALSE means success, but someone else already initialized. */ - /* You still need to call CoUninitialize in this case! */ + // S_FALSE means success, but someone else already initialized. + // You still need to call CoUninitialize in this case! if (hr == S_FALSE) { return S_OK; } @@ -118,20 +111,17 @@ WIN_CoInitialize(void) void WIN_CoUninitialize(void) { -#ifndef SDL_PLATFORM_WINRT CoUninitialize(); -#endif } -#ifndef SDL_PLATFORM_WINRT FARPROC WIN_LoadComBaseFunction(const char *name) { - static SDL_bool s_bLoaded; + static bool s_bLoaded; static HMODULE s_hComBase; if (!s_bLoaded) { s_hComBase = LoadLibraryEx(TEXT("combase.dll"), NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); - s_bLoaded = SDL_TRUE; + s_bLoaded = true; } if (s_hComBase) { return GetProcAddress(s_hComBase, name); @@ -139,25 +129,21 @@ FARPROC WIN_LoadComBaseFunction(const char *name) return NULL; } } -#endif HRESULT WIN_RoInitialize(void) { -#ifdef SDL_PLATFORM_WINRT - return S_OK; -#else typedef HRESULT(WINAPI * RoInitialize_t)(RO_INIT_TYPE initType); RoInitialize_t RoInitializeFunc = (RoInitialize_t)WIN_LoadComBaseFunction("RoInitialize"); if (RoInitializeFunc) { - /* RO_INIT_SINGLETHREADED is equivalent to COINIT_APARTMENTTHREADED */ + // RO_INIT_SINGLETHREADED is equivalent to COINIT_APARTMENTTHREADED HRESULT hr = RoInitializeFunc(RO_INIT_SINGLETHREADED); if (hr == RPC_E_CHANGED_MODE) { hr = RoInitializeFunc(RO_INIT_MULTITHREADED); } - /* S_FALSE means success, but someone else already initialized. */ - /* You still need to call RoUninitialize in this case! */ + // S_FALSE means success, but someone else already initialized. + // You still need to call RoUninitialize in this case! if (hr == S_FALSE) { return S_OK; } @@ -166,21 +152,18 @@ WIN_RoInitialize(void) } else { return E_NOINTERFACE; } -#endif } void WIN_RoUninitialize(void) { -#ifndef SDL_PLATFORM_WINRT typedef void(WINAPI * RoUninitialize_t)(void); RoUninitialize_t RoUninitializeFunc = (RoUninitialize_t)WIN_LoadComBaseFunction("RoUninitialize"); if (RoUninitializeFunc) { RoUninitializeFunc(); } -#endif } -#if !defined(SDL_PLATFORM_WINRT) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor) { OSVERSIONINFOEXW osvi; @@ -202,17 +185,17 @@ static BOOL IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion, WO #endif // apply some static variables so we only call into the Win32 API once per process for each check. -#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) #define CHECKWINVER(notdesktop_platform_result, test) return (notdesktop_platform_result); #else #define CHECKWINVER(notdesktop_platform_result, test) \ - static SDL_bool checked = SDL_FALSE; \ - static BOOL retval = FALSE; \ + static bool checked = false; \ + static BOOL result = FALSE; \ if (!checked) { \ - retval = (test); \ - checked = SDL_TRUE; \ + result = (test); \ + checked = true; \ } \ - return retval; + return result; #endif // this is the oldest thing we run on (and we may lose support for this in SDL3 at any time!), @@ -265,20 +248,20 @@ WASAPI doesn't need this. This is just for DirectSound/WinMM. */ char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) { -#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) - return WIN_StringToUTF8(name); /* No registry access on WinRT/UWP and Xbox, go with what we've got. */ +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) + return WIN_StringToUTF8W(name); // No registry access on Xbox, go with what we've got. #else static const GUID nullguid = { 0 }; const unsigned char *ptr; char keystr[128]; WCHAR *strw = NULL; - SDL_bool rc; + bool rc; HKEY hkey; DWORD len = 0; - char *retval = NULL; + char *result = NULL; if (WIN_IsEqualGUID(guid, &nullguid)) { - return WIN_StringToUTF8(name); /* No GUID, go with what we've got. */ + return WIN_StringToUTF8(name); // No GUID, go with what we've got. } ptr = (const unsigned char *)guid; @@ -291,44 +274,44 @@ char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid) rc = (RegOpenKeyExW(HKEY_LOCAL_MACHINE, strw, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS); SDL_free(strw); if (!rc) { - return WIN_StringToUTF8(name); /* oh well. */ + return WIN_StringToUTF8(name); // oh well. } rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, NULL, &len) == ERROR_SUCCESS); if (!rc) { RegCloseKey(hkey); - return WIN_StringToUTF8(name); /* oh well. */ + return WIN_StringToUTF8(name); // oh well. } strw = (WCHAR *)SDL_malloc(len + sizeof(WCHAR)); if (!strw) { RegCloseKey(hkey); - return WIN_StringToUTF8(name); /* oh well. */ + return WIN_StringToUTF8(name); // oh well. } rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, (LPBYTE)strw, &len) == ERROR_SUCCESS); RegCloseKey(hkey); if (!rc) { SDL_free(strw); - return WIN_StringToUTF8(name); /* oh well. */ + return WIN_StringToUTF8(name); // oh well. } - strw[len / 2] = 0; /* make sure it's null-terminated. */ + strw[len / 2] = 0; // make sure it's null-terminated. - retval = WIN_StringToUTF8(strw); + result = WIN_StringToUTF8(strw); SDL_free(strw); - return retval ? retval : WIN_StringToUTF8(name); -#endif /* if SDL_PLATFORM_WINRT / else */ + return result ? result : WIN_StringToUTF8(name); +#endif } BOOL WIN_IsEqualGUID(const GUID *a, const GUID *b) { - return SDL_memcmp(a, b, sizeof(*a)) == 0; + return (SDL_memcmp(a, b, sizeof(*a)) == 0); } BOOL WIN_IsEqualIID(REFIID a, REFIID b) { - return SDL_memcmp(a, b, sizeof(*a)) == 0; + return (SDL_memcmp(a, b, sizeof(*a)) == 0); } void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect) @@ -349,15 +332,15 @@ void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect) BOOL WIN_IsRectEmpty(const RECT *rect) { - /* Calculating this manually because UWP and Xbox do not support Win32 IsRectEmpty. */ + // Calculating this manually because Xbox does not support Win32 IsRectEmpty. return (rect->right <= rect->left) || (rect->bottom <= rect->top); } -/* Some GUIDs we need to know without linking to libraries that aren't available before Vista. */ -/* *INDENT-OFF* */ /* clang-format off */ +// Some GUIDs we need to know without linking to libraries that aren't available before Vista. +/* *INDENT-OFF* */ // clang-format off static const GUID SDL_KSDATAFORMAT_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; static const GUID SDL_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010,{ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat) { @@ -377,7 +360,7 @@ SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat) return SDL_AUDIO_S32; } } - return 0; + return SDL_AUDIO_UNKNOWN; } @@ -389,78 +372,4 @@ int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, return WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar); } - -/* Win32-specific SDL_RunApp(), which does most of the SDL_main work, - based on SDL_windows_main.c, placed in the public domain by Sam Lantinga 4/13/98 */ -#ifdef SDL_PLATFORM_WIN32 - -#include /* CommandLineToArgvW() */ - -/* Pop up an out of memory message, returns to Windows */ -static int OutOfMemory(void) -{ - SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Out of memory - aborting", NULL); - return -1; -} - -DECLSPEC int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_func mainFunction, void * reserved) -{ - - /* Gets the arguments with GetCommandLine, converts them to argc and argv - and calls SDL_main */ - - LPWSTR *argvw; - char **argv; - int i, argc, result; - - (void)_argc; (void)_argv; (void)reserved; - - argvw = CommandLineToArgvW(GetCommandLineW(), &argc); - if (!argvw) { - return OutOfMemory(); - } - - /* Note that we need to be careful about how we allocate/free memory here. - * If the application calls SDL_SetMemoryFunctions(), we can't rely on - * SDL_free() to use the same allocator after SDL_main() returns. - */ - - /* Parse it into argv and argc */ - argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv)); - if (!argv) { - return OutOfMemory(); - } - for (i = 0; i < argc; ++i) { - DWORD len; - char *arg = WIN_StringToUTF8W(argvw[i]); - if (!arg) { - return OutOfMemory(); - } - len = (DWORD)SDL_strlen(arg); - argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1); - if (!argv[i]) { - return OutOfMemory(); - } - SDL_memcpy(argv[i], arg, len); - SDL_free(arg); - } - argv[i] = NULL; - LocalFree(argvw); - - SDL_SetMainReady(); - - /* Run the application main() code */ - result = mainFunction(argc, argv); - - /* Free argv, to avoid memory leak */ - for (i = 0; i < argc; ++i) { - HeapFree(GetProcessHeap(), 0, argv[i]); - } - HeapFree(GetProcessHeap(), 0, argv); - - return result; -} - -#endif /* SDL_PLATFORM_WIN32 */ - -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) */ +#endif // defined(SDL_PLATFORM_WINDOWS) diff --git a/libs/SDL3/src/core/windows/SDL_windows.h b/libs/SDL3/src/core/windows/SDL_windows.h index e4a25f95a..854c072ce 100644 --- a/libs/SDL3/src/core/windows/SDL_windows.h +++ b/libs/SDL3/src/core/windows/SDL_windows.h @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -/* This is an include file for windows.h with the SDL build settings */ +// This is an include file for windows.h with the SDL build settings #ifndef _INCLUDED_WINDOWS_H #define _INCLUDED_WINDOWS_H @@ -36,12 +36,12 @@ #endif #undef WINVER #undef _WIN32_WINNT -#if SDL_VIDEO_RENDER_D3D12 -#define _WIN32_WINNT 0xA00 /* For D3D12, 0xA00 is required */ +#if defined(SDL_VIDEO_RENDER_D3D12) || defined(HAVE_DXGI1_6_H) +#define _WIN32_WINNT 0xA00 // For D3D12, 0xA00 is required #elif defined(HAVE_SHELLSCALINGAPI_H) -#define _WIN32_WINNT 0x603 /* For DPI support */ +#define _WIN32_WINNT 0x603 // For DPI support #else -#define _WIN32_WINNT 0x501 /* Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input */ +#define _WIN32_WINNT 0x501 // Need 0x410 for AlphaBlend() and 0x500 for EnumDisplayDevices(), 0x501 for raw input #endif #define WINVER _WIN32_WINNT @@ -76,8 +76,8 @@ #define WINVER _WIN32_WINNT #endif -/* See https://github.com/libsdl-org/SDL/pull/7607 */ -/* force_align_arg_pointer attribute requires gcc >= 4.2.x. */ +// See https://github.com/libsdl-org/SDL/pull/7607 +// force_align_arg_pointer attribute requires gcc >= 4.2.x. #if defined(__clang__) #define HAVE_FORCE_ALIGN_ARG_POINTER #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) @@ -90,13 +90,13 @@ #endif #include -#include /* for REFIID with broken mingw.org headers */ +#include // for REFIID with broken mingw.org headers #include -/* Routines to convert from UTF8 to native Windows text */ +// Routines to convert from UTF8 to native Windows text #define WIN_StringToUTF8W(S) SDL_iconv_string("UTF-8", "UTF-16LE", (const char *)(S), (SDL_wcslen(S) + 1) * sizeof(WCHAR)) #define WIN_UTF8ToStringW(S) (WCHAR *)SDL_iconv_string("UTF-16LE", "UTF-8", (const char *)(S), SDL_strlen(S) + 1) -/* !!! FIXME: UTF8ToString() can just be a SDL_strdup() here. */ +// !!! FIXME: UTF8ToString() can just be a SDL_strdup() here. #define WIN_StringToUTF8A(S) SDL_iconv_string("UTF-8", "ASCII", (const char *)(S), (SDL_strlen(S) + 1)) #define WIN_UTF8ToStringA(S) SDL_iconv_string("ASCII", "UTF-8", (const char *)(S), SDL_strlen(S) + 1) #if UNICODE @@ -111,64 +111,62 @@ #define SDL_tcsstr SDL_strstr #endif -/* Set up for C function definitions, even when using C++ */ +// Set up for C function definitions, even when using C++ #ifdef __cplusplus extern "C" { #endif -/* Sets an error message based on a given HRESULT */ -extern int WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr); +// Sets an error message based on a given HRESULT +extern bool WIN_SetErrorFromHRESULT(const char *prefix, HRESULT hr); -/* Sets an error message based on GetLastError(). Always return -1. */ -extern int WIN_SetError(const char *prefix); +// Sets an error message based on GetLastError(). Always return -1. +extern bool WIN_SetError(const char *prefix); -#ifndef SDL_PLATFORM_WINRT -/* Load a function from combase.dll */ +// Load a function from combase.dll FARPROC WIN_LoadComBaseFunction(const char *name); -#endif -/* Wrap up the oddities of CoInitialize() into a common function. */ +// Wrap up the oddities of CoInitialize() into a common function. extern HRESULT WIN_CoInitialize(void); extern void WIN_CoUninitialize(void); -/* Wrap up the oddities of RoInitialize() into a common function. */ +// Wrap up the oddities of RoInitialize() into a common function. extern HRESULT WIN_RoInitialize(void); extern void WIN_RoUninitialize(void); -/* Returns SDL_TRUE if we're running on Windows XP (any service pack). DOES NOT CHECK XP "OR GREATER"! */ +// Returns true if we're running on Windows XP (any service pack). DOES NOT CHECK XP "OR GREATER"! extern BOOL WIN_IsWindowsXP(void); -/* Returns SDL_TRUE if we're running on Windows Vista and newer */ +// Returns true if we're running on Windows Vista and newer extern BOOL WIN_IsWindowsVistaOrGreater(void); -/* Returns SDL_TRUE if we're running on Windows 7 and newer */ +// Returns true if we're running on Windows 7 and newer extern BOOL WIN_IsWindows7OrGreater(void); -/* Returns SDL_TRUE if we're running on Windows 8 and newer */ +// Returns true if we're running on Windows 8 and newer extern BOOL WIN_IsWindows8OrGreater(void); -/* You need to SDL_free() the result of this call. */ +// You need to SDL_free() the result of this call. extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid); -/* Checks to see if two GUID are the same. */ +// Checks to see if two GUID are the same. extern BOOL WIN_IsEqualGUID(const GUID *a, const GUID *b); extern BOOL WIN_IsEqualIID(REFIID a, REFIID b); -/* Convert between SDL_rect and RECT */ +// Convert between SDL_rect and RECT extern void WIN_RECTToRect(const RECT *winrect, SDL_Rect *sdlrect); extern void WIN_RectToRECT(const SDL_Rect *sdlrect, RECT *winrect); -/* Returns SDL_TRUE if the rect is empty */ +// Returns true if the rect is empty extern BOOL WIN_IsRectEmpty(const RECT *rect); extern SDL_AudioFormat SDL_WaveFormatExToSDLFormat(WAVEFORMATEX *waveformat); -/* WideCharToMultiByte, but with some WinXP manangement. */ +// WideCharToMultiByte, but with some WinXP management. extern int WIN_WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWCH lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCCH lpDefaultChar, LPBOOL lpUsedDefaultChar); -/* Ends C function definitions when using C++ */ +// Ends C function definitions when using C++ #ifdef __cplusplus } #endif -#endif /* _INCLUDED_WINDOWS_H */ +#endif // _INCLUDED_WINDOWS_H diff --git a/libs/SDL3/src/core/windows/SDL_xinput.c b/libs/SDL3/src/core/windows/SDL_xinput.c index 13c06bde4..76b5bd2c1 100644 --- a/libs/SDL3/src/core/windows/SDL_xinput.c +++ b/libs/SDL3/src/core/windows/SDL_xinput.c @@ -22,7 +22,7 @@ #include "SDL_xinput.h" -/* Set up for C function definitions, even when using C++ */ +// Set up for C function definitions, even when using C++ #ifdef __cplusplus extern "C" { #endif @@ -37,47 +37,43 @@ DWORD SDL_XInputVersion = 0; static HMODULE s_pXInputDLL = NULL; static int s_XInputDLLRefCount = 0; -#if defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) +#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) -int WIN_LoadXInputDLL(void) +bool WIN_LoadXInputDLL(void) { /* Getting handles to system dlls (via LoadLibrary and its variants) is not - * supported on WinRT, thus, pointers to XInput's functions can't be + * supported on Xbox, thus, pointers to XInput's functions can't be * retrieved via GetProcAddress. * - * When on WinRT, assume that XInput is already loaded, and directly map + * When on Xbox, assume that XInput is already loaded, and directly map * its XInput.h-declared functions to the SDL_XInput* set of function * pointers. - * - * Side-note: XInputGetStateEx is not available for use in WinRT. - * This seems to mean that support for the guide button is not available - * in WinRT, unfortunately. */ SDL_XInputGetState = (XInputGetState_t)XInputGetState; SDL_XInputSetState = (XInputSetState_t)XInputSetState; SDL_XInputGetCapabilities = (XInputGetCapabilities_t)XInputGetCapabilities; SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)XInputGetBatteryInformation; - /* XInput 1.4 ships with Windows 8 and 8.1: */ + // XInput 1.4 ships with Windows 8 and 8.1: SDL_XInputVersion = (1 << 16) | 4; - return 0; + return true; } void WIN_UnloadXInputDLL(void) { } -#else /* !(defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) */ +#else // !(defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) -int WIN_LoadXInputDLL(void) +bool WIN_LoadXInputDLL(void) { DWORD version = 0; if (s_pXInputDLL) { SDL_assert(s_XInputDLLRefCount > 0); s_XInputDLLRefCount++; - return 0; /* already loaded */ + return true; // already loaded } /* NOTE: Don't load XinputUap.dll @@ -85,42 +81,42 @@ int WIN_LoadXInputDLL(void) * limitations of that API (no devices at startup, no background input, etc.) */ version = (1 << 16) | 4; - s_pXInputDLL = LoadLibrary(TEXT("XInput1_4.dll")); /* 1.4 Ships with Windows 8. */ + s_pXInputDLL = LoadLibrary(TEXT("XInput1_4.dll")); // 1.4 Ships with Windows 8. if (!s_pXInputDLL) { version = (1 << 16) | 3; - s_pXInputDLL = LoadLibrary(TEXT("XInput1_3.dll")); /* 1.3 can be installed as a redistributable component. */ + s_pXInputDLL = LoadLibrary(TEXT("XInput1_3.dll")); // 1.3 can be installed as a redistributable component. } if (!s_pXInputDLL) { s_pXInputDLL = LoadLibrary(TEXT("bin\\XInput1_3.dll")); } if (!s_pXInputDLL) { - /* "9.1.0" Ships with Vista and Win7, and is more limited than 1.3+ (e.g. XInputGetStateEx is not available.) */ + // "9.1.0" Ships with Vista and Win7, and is more limited than 1.3+ (e.g. XInputGetStateEx is not available.) s_pXInputDLL = LoadLibrary(TEXT("XInput9_1_0.dll")); } if (!s_pXInputDLL) { - return -1; + return false; } SDL_assert(s_XInputDLLRefCount == 0); SDL_XInputVersion = version; s_XInputDLLRefCount = 1; - /* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */ + // 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... SDL_XInputGetState = (XInputGetState_t)GetProcAddress(s_pXInputDLL, (LPCSTR)100); if (!SDL_XInputGetState) { SDL_XInputGetState = (XInputGetState_t)GetProcAddress(s_pXInputDLL, "XInputGetState"); } SDL_XInputSetState = (XInputSetState_t)GetProcAddress(s_pXInputDLL, "XInputSetState"); SDL_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress(s_pXInputDLL, "XInputGetCapabilities"); - /* 108 is the ordinal for _XInputGetCapabilitiesEx, which additionally returns VID/PID of the controller. */ + // 108 is the ordinal for _XInputGetCapabilitiesEx, which additionally returns VID/PID of the controller. SDL_XInputGetCapabilitiesEx = (XInputGetCapabilitiesEx_t)GetProcAddress(s_pXInputDLL, (LPCSTR)108); SDL_XInputGetBatteryInformation = (XInputGetBatteryInformation_t)GetProcAddress(s_pXInputDLL, "XInputGetBatteryInformation"); if (!SDL_XInputGetState || !SDL_XInputSetState || !SDL_XInputGetCapabilities) { WIN_UnloadXInputDLL(); - return -1; + return false; } - return 0; + return true; } void WIN_UnloadXInputDLL(void) @@ -136,9 +132,9 @@ void WIN_UnloadXInputDLL(void) } } -#endif /* SDL_PLATFORM_WINRT */ +#endif -/* Ends C function definitions when using C++ */ +// Ends C function definitions when using C++ #ifdef __cplusplus } #endif diff --git a/libs/SDL3/src/core/windows/SDL_xinput.h b/libs/SDL3/src/core/windows/SDL_xinput.h index 200c8b6fe..ff72b2398 100644 --- a/libs/SDL3/src/core/windows/SDL_xinput.h +++ b/libs/SDL3/src/core/windows/SDL_xinput.h @@ -27,14 +27,14 @@ #ifdef HAVE_XINPUT_H #if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES) -/* Xbox supports an XInput wrapper which is a C++-only header... */ -#include /* Required to compile with recent MSVC... */ +// Xbox supports an XInput wrapper which is a C++-only header... +#include // Required to compile with recent MSVC... #include using namespace XInputOnGameInput; #else #include #endif -#endif /* HAVE_XINPUT_H */ +#endif // HAVE_XINPUT_H #ifndef XUSER_MAX_COUNT #define XUSER_MAX_COUNT 4 @@ -160,15 +160,15 @@ using namespace XInputOnGameInput; #define BATTERY_LEVEL_FULL 0x03 #endif -/* Set up for C function definitions, even when using C++ */ +// Set up for C function definitions, even when using C++ #ifdef __cplusplus extern "C" { #endif -/* typedef's for XInput structs we use */ +// typedef's for XInput structs we use -/* This is the same as XINPUT_BATTERY_INFORMATION, but always defined instead of just if WIN32_WINNT >= _WIN32_WINNT_WIN8 */ +// This is the same as XINPUT_BATTERY_INFORMATION, but always defined instead of just if WIN32_WINNT >= _WIN32_WINNT_WIN8 typedef struct { BYTE BatteryType; @@ -209,9 +209,9 @@ typedef struct XINPUT_VIBRATION Vibration; } XINPUT_CAPABILITIES; -#endif /* HAVE_XINPUT_H */ +#endif // HAVE_XINPUT_H -/* This struct is not defined in XInput headers. */ +// This struct is not defined in XInput headers. typedef struct { XINPUT_CAPABILITIES Capabilities; @@ -222,29 +222,29 @@ typedef struct DWORD unk2; } SDL_XINPUT_CAPABILITIES_EX; -/* Forward decl's for XInput API's we load dynamically and use if available */ +// Forward decl's for XInput API's we load dynamically and use if available typedef DWORD(WINAPI *XInputGetState_t)( - DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ - XINPUT_STATE *pState /* [out] Receives the current state */ + DWORD dwUserIndex, // [in] Index of the gamer associated with the device + XINPUT_STATE *pState // [out] Receives the current state ); typedef DWORD(WINAPI *XInputSetState_t)( - DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ - XINPUT_VIBRATION *pVibration /* [in, out] The vibration information to send to the controller */ + DWORD dwUserIndex, // [in] Index of the gamer associated with the device + XINPUT_VIBRATION *pVibration // [in, out] The vibration information to send to the controller ); typedef DWORD(WINAPI *XInputGetCapabilities_t)( - DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ - DWORD dwFlags, /* [in] Input flags that identify the device type */ - XINPUT_CAPABILITIES *pCapabilities /* [out] Receives the capabilities */ + DWORD dwUserIndex, // [in] Index of the gamer associated with the device + DWORD dwFlags, // [in] Input flags that identify the device type + XINPUT_CAPABILITIES *pCapabilities // [out] Receives the capabilities ); -/* Only available in XInput 1.4 that is shipped with Windows 8 and newer. */ +// Only available in XInput 1.4 that is shipped with Windows 8 and newer. typedef DWORD(WINAPI *XInputGetCapabilitiesEx_t)( - DWORD dwReserved, /* [in] Must be 1 */ - DWORD dwUserIndex, /* [in] Index of the gamer associated with the device */ - DWORD dwFlags, /* [in] Input flags that identify the device type */ - SDL_XINPUT_CAPABILITIES_EX *pCapabilitiesEx /* [out] Receives the capabilities */ + DWORD dwReserved, // [in] Must be 1 + DWORD dwUserIndex, // [in] Index of the gamer associated with the device + DWORD dwFlags, // [in] Input flags that identify the device type + SDL_XINPUT_CAPABILITIES_EX *pCapabilitiesEx // [out] Receives the capabilities ); typedef DWORD(WINAPI *XInputGetBatteryInformation_t)( @@ -252,7 +252,7 @@ typedef DWORD(WINAPI *XInputGetBatteryInformation_t)( BYTE devType, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation); -extern int WIN_LoadXInputDLL(void); +extern bool WIN_LoadXInputDLL(void); extern void WIN_UnloadXInputDLL(void); extern XInputGetState_t SDL_XInputGetState; @@ -260,9 +260,9 @@ extern XInputSetState_t SDL_XInputSetState; extern XInputGetCapabilities_t SDL_XInputGetCapabilities; extern XInputGetCapabilitiesEx_t SDL_XInputGetCapabilitiesEx; extern XInputGetBatteryInformation_t SDL_XInputGetBatteryInformation; -extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */ +extern DWORD SDL_XInputVersion; // ((major << 16) & 0xFF00) | (minor & 0xFF) -/* Ends C function definitions when using C++ */ +// Ends C function definitions when using C++ #ifdef __cplusplus } #endif @@ -273,4 +273,4 @@ extern DWORD SDL_XInputVersion; /* ((major << 16) & 0xFF00) | (minor & 0xFF) */ #define XINPUTGETCAPABILITIESEX SDL_XInputGetCapabilitiesEx #define XINPUTGETBATTERYINFORMATION SDL_XInputGetBatteryInformation -#endif /* SDL_xinput_h_ */ +#endif // SDL_xinput_h_ diff --git a/libs/SDL3/src/core/windows/version.rc b/libs/SDL3/src/core/windows/version.rc index 476f2a91e..6deeea36d 100644 --- a/libs/SDL3/src/core/windows/version.rc +++ b/libs/SDL3/src/core/windows/version.rc @@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,1,1,0 - PRODUCTVERSION 3,1,1,0 + FILEVERSION 3,1,3,0 + PRODUCTVERSION 3,1,3,0 FILEFLAGSMASK 0x3fL FILEFLAGS 0x0L FILEOS 0x40004L @@ -23,12 +23,12 @@ BEGIN BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "SDL\0" - VALUE "FileVersion", "3, 1, 1, 0\0" + VALUE "FileVersion", "3, 1, 3, 0\0" VALUE "InternalName", "SDL\0" VALUE "LegalCopyright", "Copyright (C) 2024 Sam Lantinga\0" VALUE "OriginalFilename", "SDL3.dll\0" VALUE "ProductName", "Simple DirectMedia Layer\0" - VALUE "ProductVersion", "3, 1, 1, 0\0" + VALUE "ProductVersion", "3, 1, 3, 0\0" END END BLOCK "VarFileInfo" diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_common.cpp b/libs/SDL3/src/core/winrt/SDL_winrtapp_common.cpp deleted file mode 100644 index c20f52420..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_common.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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" - -#include "SDL_winrtapp_direct3d.h" -#include "SDL_winrtapp_xaml.h" - -#include - -int (*WINRT_SDLAppEntryPoint)(int, char **) = NULL; - -extern "C" DECLSPEC int -SDL_RunApp(int, char**, SDL_main_func mainFunction, void * xamlBackgroundPanel) -{ - if (xamlBackgroundPanel) { - return SDL_WinRTInitXAMLApp(mainFunction, xamlBackgroundPanel); - } else { - if (FAILED(Windows::Foundation::Initialize(RO_INIT_MULTITHREADED))) { - return 1; - } - return SDL_WinRTInitNonXAMLApp(mainFunction); - } -} - -extern "C" DECLSPEC SDL_WinRT_DeviceFamily -SDL_WinRTGetDeviceFamily() -{ -#if NTDDI_VERSION >= NTDDI_WIN10 /* !!! FIXME: I have no idea if this is the right test. This is a UWP API, I think. Older windows should...just return "mobile"? I don't know. --ryan. */ - Platform::String ^ deviceFamily = Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily; - - if (deviceFamily->Equals("Windows.Desktop")) { - return SDL_WINRT_DEVICEFAMILY_DESKTOP; - } else if (deviceFamily->Equals("Windows.Mobile")) { - return SDL_WINRT_DEVICEFAMILY_MOBILE; - } else if (deviceFamily->Equals("Windows.Xbox")) { - return SDL_WINRT_DEVICEFAMILY_XBOX; - } -#endif - - return SDL_WINRT_DEVICEFAMILY_UNKNOWN; -} diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_common.h b/libs/SDL3/src/core/winrt/SDL_winrtapp_common.h deleted file mode 100644 index 83cfd7762..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_common.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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_winrtapp_common_h_ -#define SDL_winrtapp_common_h_ - -/* A pointer to the app's C-style main() function (which is a different - function than the WinRT app's actual entry point). - */ -extern int (*WINRT_SDLAppEntryPoint)(int, char **); - -#endif // SDL_winrtapp_common_h_ diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.cpp b/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.cpp deleted file mode 100644 index 013d03e2e..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ /dev/null @@ -1,758 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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" - -/* Windows includes */ -#include "ppltasks.h" -using namespace concurrency; -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::ApplicationModel::Activation; -using namespace Windows::Devices::Input; -using namespace Windows::Graphics::Display; -using namespace Windows::Foundation; -using namespace Windows::System; -using namespace Windows::UI::Core; -using namespace Windows::UI::Input; - -#if SDL_WINAPI_FAMILY_PHONE -using namespace Windows::Phone::UI::Input; -#endif - -/* SDL includes */ -extern "C" { -#include "../../video/SDL_sysvideo.h" -#include "../../events/SDL_events_c.h" -#include "../../events/SDL_keyboard_c.h" -#include "../../events/SDL_mouse_c.h" -#include "../../events/SDL_windowevents_c.h" -#include "../../render/SDL_sysrender.h" -#include "../windows/SDL_windows.h" -} - -#include "../../video/winrt/SDL_winrtevents_c.h" -#include "../../video/winrt/SDL_winrtvideo_cpp.h" -#include "SDL_winrtapp_common.h" -#include "SDL_winrtapp_direct3d.h" - -#if SDL_VIDEO_RENDER_D3D11 -/* Calling IDXGIDevice3::Trim on the active Direct3D 11.x device is necessary - * when Windows 8.1 apps are about to get suspended. - */ -extern "C" void D3D11_Trim(SDL_Renderer *); -#endif - -// Compile-time debugging options: -// To enable, uncomment; to disable, comment them out. -// #define LOG_POINTER_EVENTS 1 -// #define LOG_WINDOW_EVENTS 1 -// #define LOG_ORIENTATION_EVENTS 1 - -// HACK, DLudwig: record a reference to the global, WinRT 'app'/view. -// SDL/WinRT will use this throughout its code. -// -// TODO, WinRT: consider replacing SDL_WinRTGlobalApp with something -// non-global, such as something created inside -// SDL_InitSubSystem(SDL_INIT_VIDEO), or something inside -// SDL_CreateWindow(). -SDL_WinRTApp ^ SDL_WinRTGlobalApp = nullptr; - -ref class SDLApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource -{ - public: - virtual Windows::ApplicationModel::Core::IFrameworkView ^ CreateView(); -}; - -IFrameworkView ^ SDLApplicationSource::CreateView() -{ - // TODO, WinRT: see if this function (CreateView) can ever get called - // more than once. For now, just prevent it from ever assigning - // SDL_WinRTGlobalApp more than once. - SDL_assert(!SDL_WinRTGlobalApp); - SDL_WinRTApp ^ app = ref new SDL_WinRTApp(); - if (!SDL_WinRTGlobalApp) { - SDL_WinRTGlobalApp = app; - } - return app; -} - -int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **)) -{ - WINRT_SDLAppEntryPoint = mainFunction; - auto direct3DApplicationSource = ref new SDLApplicationSource(); - CoreApplication::Run(direct3DApplicationSource); - return 0; -} - -static void WINRT_ProcessWindowSizeChange() // TODO: Pass an SDL_Window-identifying thing into WINRT_ProcessWindowSizeChange() -{ - CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread(); - if (coreWindow) { - if (WINRT_GlobalSDLWindow) { - SDL_Window *window = WINRT_GlobalSDLWindow; - SDL_WindowData *data = window->driverdata; - - int x = (int)SDL_lroundf(data->coreWindow->Bounds.Left); - int y = (int)SDL_lroundf(data->coreWindow->Bounds.Top); - int w = (int)SDL_floorf(data->coreWindow->Bounds.Width); - int h = (int)SDL_floorf(data->coreWindow->Bounds.Height); - -#if SDL_WINAPI_FAMILY_PHONE && NTDDI_VERSION == NTDDI_WIN8 - /* WinPhone 8.0 always keeps its native window size in portrait, - regardless of orientation. This changes in WinPhone 8.1, - in which the native window's size changes along with - orientation. - - Attempt to emulate WinPhone 8.1's behavior on WinPhone 8.0, with - regards to window size. This fixes a rendering bug that occurs - when a WinPhone 8.0 app is rotated to either 90 or 270 degrees. - */ - const DisplayOrientations currentOrientation = WINRT_DISPLAY_PROPERTY(CurrentOrientation); - switch (currentOrientation) { - case DisplayOrientations::Landscape: - case DisplayOrientations::LandscapeFlipped: - { - int tmp = w; - w = h; - h = tmp; - } break; - } -#endif - - const Uint32 latestFlags = WINRT_DetectWindowFlags(window); - if (latestFlags & SDL_WINDOW_MAXIMIZED) { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } else { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESTORED, 0, 0); - } - - WINRT_UpdateWindowFlags(window, SDL_WINDOW_FULLSCREEN); - - /* The window can move during a resize event, such as when maximizing - or resizing from a corner */ - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_MOVED, x, y); - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_RESIZED, w, h); - } - } -} - -SDL_WinRTApp::SDL_WinRTApp() : m_windowClosed(false), - m_windowVisible(true) -{ -} - -void SDL_WinRTApp::Initialize(CoreApplicationView ^ applicationView) -{ - applicationView->Activated += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnAppActivated); - - CoreApplication::Suspending += - ref new EventHandler(this, &SDL_WinRTApp::OnSuspending); - - CoreApplication::Resuming += - ref new EventHandler(this, &SDL_WinRTApp::OnResuming); - - CoreApplication::Exiting += - ref new EventHandler(this, &SDL_WinRTApp::OnExiting); - -#if NTDDI_VERSION >= NTDDI_WIN10 - /* HACK ALERT! Xbox One doesn't seem to detect gamepads unless something - gets registered to receive Win10's Windows.Gaming.Input.Gamepad.GamepadAdded - events. We'll register an event handler for these events here, to make - sure that gamepad detection works later on, if requested. - */ - Windows::Gaming::Input::Gamepad::GamepadAdded += - ref new Windows::Foundation::EventHandler( - this, &SDL_WinRTApp::OnGamepadAdded); -#endif -} - -#if NTDDI_VERSION > NTDDI_WIN8 -void SDL_WinRTApp::OnOrientationChanged(DisplayInformation ^ sender, Object ^ args) -#else -void SDL_WinRTApp::OnOrientationChanged(Object ^ sender) -#endif -{ -#if LOG_ORIENTATION_EVENTS == 1 - { - CoreWindow ^ window = CoreWindow::GetForCurrentThread(); - if (window) { - SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, CoreWindow Bounds={%f,%f,%f,%f}\n", - __FUNCTION__, - WINRT_DISPLAY_PROPERTY(CurrentOrientation), - WINRT_DISPLAY_PROPERTY(NativeOrientation), - WINRT_DISPLAY_PROPERTY(AutoRotationPreferences), - window->Bounds.X, - window->Bounds.Y, - window->Bounds.Width, - window->Bounds.Height); - } else { - SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d\n", - __FUNCTION__, - WINRT_DISPLAY_PROPERTY(CurrentOrientation), - WINRT_DISPLAY_PROPERTY(NativeOrientation), - WINRT_DISPLAY_PROPERTY(AutoRotationPreferences)); - } - } -#endif - - WINRT_ProcessWindowSizeChange(); - -#if SDL_WINAPI_FAMILY_PHONE - // HACK: Make sure that orientation changes - // lead to the Direct3D renderer's viewport getting updated: - // - // For some reason, this doesn't seem to need to be done on Windows 8.x, - // even when going from Landscape to LandscapeFlipped. It only seems to - // be needed on Windows Phone, at least when I tested on my devices. - // I'm not currently sure why this is, but it seems to work fine. -- David L. - // - // TODO, WinRT: do more extensive research into why orientation changes on Win 8.x don't need D3D changes, or if they might, in some cases - SDL_Window *window = WINRT_GlobalSDLWindow; - if (window) { - SDL_WindowData *data = window->driverdata; - int w = (int)SDL_floorf(data->coreWindow->Bounds.Width); - int h = (int)SDL_floorf(data->coreWindow->Bounds.Height); - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_RESIZED, w, h); - } -#endif -} - -void SDL_WinRTApp::SetWindow(CoreWindow ^ window) -{ -#if LOG_WINDOW_EVENTS == 1 - SDL_Log("%s, current orientation=%d, native orientation=%d, auto rot. pref=%d, window bounds={%f, %f, %f,%f}\n", - __FUNCTION__, - WINRT_DISPLAY_PROPERTY(CurrentOrientation), - WINRT_DISPLAY_PROPERTY(NativeOrientation), - WINRT_DISPLAY_PROPERTY(AutoRotationPreferences), - window->Bounds.X, - window->Bounds.Y, - window->Bounds.Width, - window->Bounds.Height); -#endif - - window->SizeChanged += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnWindowSizeChanged); - - window->VisibilityChanged += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnVisibilityChanged); - - window->Activated += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnWindowActivated); - - window->Closed += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnWindowClosed); - -#if !SDL_WINAPI_FAMILY_PHONE - window->PointerCursor = ref new CoreCursor(CoreCursorType::Arrow, 0); -#endif - - window->PointerPressed += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerPressed); - - window->PointerMoved += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerMoved); - - window->PointerReleased += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerReleased); - - window->PointerEntered += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerEntered); - - window->PointerExited += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerExited); - - window->PointerWheelChanged += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnPointerWheelChanged); - -#if !SDL_WINAPI_FAMILY_PHONE - // Retrieves relative-only mouse movements: - Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnMouseMoved); -#endif - - window->Dispatcher->AcceleratorKeyActivated += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnAcceleratorKeyActivated); - - window->CharacterReceived += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnCharacterReceived); - -#if NTDDI_VERSION >= NTDDI_WIN10 - Windows::UI::Core::SystemNavigationManager::GetForCurrentView()->BackRequested += - ref new EventHandler(this, &SDL_WinRTApp::OnBackButtonPressed); -#elif SDL_WINAPI_FAMILY_PHONE - HardwareButtons::BackPressed += - ref new EventHandler(this, &SDL_WinRTApp::OnBackButtonPressed); -#endif - -#if NTDDI_VERSION > NTDDI_WIN8 - DisplayInformation::GetForCurrentView()->OrientationChanged += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnOrientationChanged); -#else - DisplayProperties::OrientationChanged += - ref new DisplayPropertiesEventHandler(this, &SDL_WinRTApp::OnOrientationChanged); -#endif - -#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps) - // Make sure we know when a user has opened the app's settings pane. - // This is needed in order to display a privacy policy, which needs - // to be done for network-enabled apps, as per Windows Store requirements. - using namespace Windows::UI::ApplicationSettings; - SettingsPane::GetForCurrentView()->CommandsRequested += - ref new TypedEventHandler(this, &SDL_WinRTApp::OnSettingsPaneCommandsRequested); -#endif -} - -void SDL_WinRTApp::Load(Platform::String ^ entryPoint) -{ -} - -void SDL_WinRTApp::Run() -{ - SDL_SetMainReady(); - if (WINRT_SDLAppEntryPoint) { - // TODO, WinRT: pass the C-style main() a reasonably realistic - // representation of command line arguments. - int argc = 1; - char **argv = (char **)SDL_malloc(2 * sizeof(*argv)); - if (!argv) { - return; - } - argv[0] = SDL_strdup("WinRTApp"); - argv[1] = NULL; - WINRT_SDLAppEntryPoint(argc, argv); - SDL_free(argv[0]); - SDL_free(argv); - } -} - -static bool IsSDLWindowEventPending(SDL_EventType windowEventID) -{ - SDL_Event events[128]; - const int count = SDL_PeepEvents(events, sizeof(events) / sizeof(SDL_Event), SDL_PEEKEVENT, windowEventID, windowEventID); - return (count > 0); -} - -bool SDL_WinRTApp::ShouldWaitForAppResumeEvents() -{ - /* Don't wait if the app is visible: */ - if (m_windowVisible) { - return false; - } - - /* Don't wait until the window-hide events finish processing. - * Do note that if an app-suspend event is sent (as indicated - * by SDL_EVENT_WILL_ENTER_BACKGROUND and SDL_EVENT_DID_ENTER_BACKGROUND - * events), then this code may be a moot point, as WinRT's - * own event pump (aka ProcessEvents()) will pause regardless - * of what we do here. This happens on Windows Phone 8, to note. - * Windows 8.x apps, on the other hand, may get a chance to run - * these. - */ - if (IsSDLWindowEventPending(SDL_EVENT_WINDOW_HIDDEN)) { - return false; - } else if (IsSDLWindowEventPending(SDL_EVENT_WINDOW_FOCUS_LOST)) { - return false; - } else if (IsSDLWindowEventPending(SDL_EVENT_WINDOW_MINIMIZED)) { - return false; - } - - return true; -} - -void SDL_WinRTApp::PumpEvents() -{ - if (!m_windowClosed) { - if (!ShouldWaitForAppResumeEvents()) { - /* This is the normal way in which events should be pumped. - * 'ProcessAllIfPresent' will make ProcessEvents() process anywhere - * from zero to N events, and will then return. - */ - CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - } else { - /* This style of event-pumping, with 'ProcessOneAndAllPending', - * will cause anywhere from one to N events to be processed. If - * at least one event is processed, the call will return. If - * no events are pending, then the call will wait until one is - * available, and will not return (to the caller) until this - * happens! This should only occur when the app is hidden. - */ - CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); - } - } -} - -void SDL_WinRTApp::Uninitialize() -{ -} - -#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) -void SDL_WinRTApp::OnSettingsPaneCommandsRequested( - Windows::UI::ApplicationSettings::SettingsPane ^ p, - Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^ args) -{ - using namespace Platform; - using namespace Windows::UI::ApplicationSettings; - using namespace Windows::UI::Popups; - - String ^ privacyPolicyURL = nullptr; // a URL to an app's Privacy Policy - String ^ privacyPolicyLabel = nullptr; // label/link text - const char *tmpHintValue = NULL; // SDL_GetHint-retrieved value, used immediately - wchar_t *tmpStr = NULL; // used for UTF8 to UCS2 conversion - - // Setup a 'Privacy Policy' link, if one is available (via SDL_GetHint): - tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_URL); - if (tmpHintValue && tmpHintValue[0] != '\0') { - // Convert the privacy policy's URL to UCS2: - tmpStr = WIN_UTF8ToString(tmpHintValue); - privacyPolicyURL = ref new String(tmpStr); - SDL_free(tmpStr); - - // Optionally retrieve custom label-text for the link. If this isn't - // available, a default value will be used instead. - tmpHintValue = SDL_GetHint(SDL_HINT_WINRT_PRIVACY_POLICY_LABEL); - if (tmpHintValue && tmpHintValue[0] != '\0') { - tmpStr = WIN_UTF8ToString(tmpHintValue); - privacyPolicyLabel = ref new String(tmpStr); - SDL_free(tmpStr); - } else { - privacyPolicyLabel = ref new String(L"Privacy Policy"); - } - - // Register the link, along with a handler to be called if and when it is - // clicked: - auto cmd = ref new SettingsCommand(L"privacyPolicy", privacyPolicyLabel, - ref new UICommandInvokedHandler([=](IUICommand ^) { - Windows::System::Launcher::LaunchUriAsync(ref new Uri(privacyPolicyURL)); - })); - args->Request->ApplicationCommands->Append(cmd); - } -} -#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) - -void SDL_WinRTApp::OnWindowSizeChanged(CoreWindow ^ sender, WindowSizeChangedEventArgs ^ args) -{ -#if LOG_WINDOW_EVENTS == 1 - SDL_Log("%s, size={%f,%f}, bounds={%f,%f,%f,%f}, current orientation=%d, native orientation=%d, auto rot. pref=%d, WINRT_GlobalSDLWindow?=%s\n", - __FUNCTION__, - args->Size.Width, args->Size.Height, - sender->Bounds.X, sender->Bounds.Y, sender->Bounds.Width, sender->Bounds.Height, - WINRT_DISPLAY_PROPERTY(CurrentOrientation), - WINRT_DISPLAY_PROPERTY(NativeOrientation), - WINRT_DISPLAY_PROPERTY(AutoRotationPreferences), - (WINRT_GlobalSDLWindow ? "yes" : "no")); -#endif - - WINRT_ProcessWindowSizeChange(); -} - -void SDL_WinRTApp::OnVisibilityChanged(CoreWindow ^ sender, VisibilityChangedEventArgs ^ args) -{ -#if LOG_WINDOW_EVENTS == 1 - SDL_Log("%s, visible?=%s, bounds={%f,%f,%f,%f}, WINRT_GlobalSDLWindow?=%s\n", - __FUNCTION__, - (args->Visible ? "yes" : "no"), - sender->Bounds.X, sender->Bounds.Y, - sender->Bounds.Width, sender->Bounds.Height, - (WINRT_GlobalSDLWindow ? "yes" : "no")); -#endif - - m_windowVisible = args->Visible; - if (WINRT_GlobalSDLWindow) { - SDL_bool wasSDLWindowSurfaceValid = WINRT_GlobalSDLWindow->surface_valid; - Uint32 latestWindowFlags = WINRT_DetectWindowFlags(WINRT_GlobalSDLWindow); - if (args->Visible) { - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_SHOWN, 0, 0); - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0); - if (latestWindowFlags & SDL_WINDOW_MAXIMIZED) { - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0); - } else { - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_RESTORED, 0, 0); - } - } else { - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_HIDDEN, 0, 0); - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0); - SDL_SendWindowEvent(WINRT_GlobalSDLWindow, SDL_EVENT_WINDOW_MINIMIZED, 0, 0); - } - - // HACK: Prevent SDL's window-hide handling code, which currently - // triggers a fake window resize (possibly erroneously), from - // marking the SDL window's surface as invalid. - // - // A better solution to this probably involves figuring out if the - // fake window resize can be prevented. - WINRT_GlobalSDLWindow->surface_valid = wasSDLWindowSurfaceValid; - } -} - -void SDL_WinRTApp::OnWindowActivated(CoreWindow ^ sender, WindowActivatedEventArgs ^ args) -{ -#if LOG_WINDOW_EVENTS == 1 - SDL_Log("%s, WINRT_GlobalSDLWindow?=%s\n\n", - __FUNCTION__, - (WINRT_GlobalSDLWindow ? "yes" : "no")); -#endif - - /* There's no property in Win 8.x to tell whether a window is active or - not. [De]activation events are, however, sent to the app. We'll just - record those, in case the CoreWindow gets wrapped by an SDL_Window at - some future time. - */ - sender->CustomProperties->Insert("SDLHelperWindowActivationState", args->WindowActivationState); - - SDL_Window *window = WINRT_GlobalSDLWindow; - if (window) { - if (args->WindowActivationState != CoreWindowActivationState::Deactivated) { - SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); - if (SDL_GetKeyboardFocus() != window) { - SDL_SetKeyboardFocus(window); - } - - /* Send a mouse-motion event as appropriate. - This doesn't work when called from OnPointerEntered, at least - not in WinRT CoreWindow apps (as OnPointerEntered doesn't - appear to be called after window-reactivation, at least not - in Windows 10, Build 10586.3 (November 2015 update, non-beta). - - Don't do it on WinPhone 8.0 though, as CoreWindow's 'PointerPosition' - property isn't available. - */ -#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION >= NTDDI_WINBLUE - Point cursorPos = WINRT_TransformCursorPosition(window, sender->PointerPosition, TransformToSDLWindowSize); - SDL_SendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, cursorPos.X, cursorPos.Y); -#endif - - /* TODO, WinRT: see if the Win32 bugfix from https://hg.libsdl.org/SDL/rev/d278747da408 needs to be applied (on window activation) */ - // WIN_CheckAsyncMouseRelease(data); - - /* TODO, WinRT: implement clipboard support, if possible */ - ///* - // * FIXME: Update keyboard state - // */ - // WIN_CheckClipboardUpdate(data->videodata); - - // HACK: Resetting the mouse-cursor here seems to fix - // https://bugzilla.libsdl.org/show_bug.cgi?id=3217, whereby a - // WinRT app's mouse cursor may switch to Windows' 'wait' cursor, - // after a user alt-tabs back into a full-screened SDL app. - // This bug does not appear to reproduce 100% of the time. - // It may be a bug in Windows itself (v.10.0.586.36, as tested, - // and the most-recent as of this writing). - SDL_SetCursor(NULL); - } else { - if (SDL_GetKeyboardFocus() == window) { - SDL_SetKeyboardFocus(NULL); - } - } - } -} - -void SDL_WinRTApp::OnWindowClosed(CoreWindow ^ sender, CoreWindowEventArgs ^ args) -{ -#if LOG_WINDOW_EVENTS == 1 - SDL_Log("%s\n", __FUNCTION__); -#endif - m_windowClosed = true; -} - -void SDL_WinRTApp::OnAppActivated(CoreApplicationView ^ applicationView, IActivatedEventArgs ^ args) -{ - CoreWindow::GetForCurrentThread()->Activate(); -} - -void SDL_WinRTApp::OnSuspending(Platform::Object ^ sender, SuspendingEventArgs ^ args) -{ - // Save app state asynchronously after requesting a deferral. Holding a deferral - // indicates that the application is busy performing suspending operations. Be - // aware that a deferral may not be held indefinitely. After about five seconds, - // the app will be forced to exit. - - // ... but first, let the app know it's about to go to the background. - // The separation of events may be important, given that the deferral - // runs in a separate thread. This'll make SDL_EVENT_WILL_ENTER_BACKGROUND - // the only event among the two that runs in the main thread. Given - // that a few WinRT operations can only be done from the main thread - // (things that access the WinRT CoreWindow are one example of this), - // this could be important. - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_BACKGROUND); - - SuspendingDeferral ^ deferral = args->SuspendingOperation->GetDeferral(); - create_task([this, deferral]() { - // Send an app did-enter-background event immediately to observers. - // CoreDispatcher::ProcessEvents, which is the backbone on which - // SDL_WinRTApp::PumpEvents is built, will not return to its caller - // once it sends out a suspend event. Any events posted to SDL's - // event queue won't get received until the WinRT app is resumed. - // SDL_AddEventWatch() may be used to receive app-suspend events on - // WinRT. - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_BACKGROUND); - - // Let the Direct3D 11 renderer prepare for the app to be backgrounded. - // This is necessary for Windows 8.1, possibly elsewhere in the future. - // More details at: http://msdn.microsoft.com/en-us/library/windows/apps/Hh994929.aspx -#if SDL_VIDEO_RENDER_D3D11 - if (WINRT_GlobalSDLWindow) { - SDL_Renderer *renderer = SDL_GetRenderer(WINRT_GlobalSDLWindow); - if (renderer && (SDL_strcmp(renderer->info.name, "direct3d11") == 0)) { - D3D11_Trim(renderer); - } - } -#endif - - deferral->Complete(); - }); -} - -void SDL_WinRTApp::OnResuming(Platform::Object ^ sender, Platform::Object ^ args) -{ - // Restore any data or state that was unloaded on suspend. By default, data - // and state are persisted when resuming from suspend. Note that these events - // do not occur if the app was previously terminated. - SDL_SendAppEvent(SDL_EVENT_WILL_ENTER_FOREGROUND); - SDL_SendAppEvent(SDL_EVENT_DID_ENTER_FOREGROUND); -} - -void SDL_WinRTApp::OnExiting(Platform::Object ^ sender, Platform::Object ^ args) -{ - SDL_SendAppEvent(SDL_EVENT_TERMINATING); -} - -static void WINRT_LogPointerEvent(const char *header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint) -{ - Uint8 button, pressed; - Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint; - WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed); - SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n", - header, - pt->Position.X, pt->Position.Y, - transformedPoint.X, transformedPoint.Y, - pt->Properties->MouseWheelDelta, - pt->FrameId, - pt->PointerId, - button, - pressed); -} - -void SDL_WinRTApp::OnPointerPressed(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer pressed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnPointerMoved(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer moved", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnPointerReleased(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer released", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnPointerEntered(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer entered", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerEnteredEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnPointerExited(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer exited", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerExitedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnPointerWheelChanged(CoreWindow ^ sender, PointerEventArgs ^ args) -{ -#if LOG_POINTER_EVENTS - WINRT_LogPointerEvent("pointer wheel changed", args, WINRT_TransformCursorPosition(WINRT_GlobalSDLWindow, args->CurrentPoint->Position, TransformToSDLWindowSize)); -#endif - - WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->CurrentPoint); -} - -void SDL_WinRTApp::OnMouseMoved(MouseDevice ^ mouseDevice, MouseEventArgs ^ args) -{ - WINRT_ProcessMouseMovedEvent(WINRT_GlobalSDLWindow, args); -} - -void SDL_WinRTApp::OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ sender, Windows::UI::Core::AcceleratorKeyEventArgs ^ args) -{ - WINRT_ProcessAcceleratorKeyActivated(args); -} - -void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args) -{ - WINRT_ProcessCharacterReceivedEvent(WINRT_GlobalSDLWindow, args); -} - -template -static void WINRT_OnBackButtonPressed(BackButtonEventArgs ^ args) -{ - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, SDL_SCANCODE_AC_BACK); - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, SDL_SCANCODE_AC_BACK); - - if (SDL_GetHintBoolean(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, SDL_FALSE)) { - args->Handled = true; - } -} - -#if NTDDI_VERSION >= NTDDI_WIN10 -void SDL_WinRTApp::OnBackButtonPressed(Platform::Object ^ sender, Windows::UI::Core::BackRequestedEventArgs ^ args) - -{ - WINRT_OnBackButtonPressed(args); -} -#elif SDL_WINAPI_FAMILY_PHONE -void SDL_WinRTApp::OnBackButtonPressed(Platform::Object ^ sender, Windows::Phone::UI::Input::BackPressedEventArgs ^ args) - -{ - WINRT_OnBackButtonPressed(args); -} -#endif - -#if NTDDI_VERSION >= NTDDI_WIN10 -void SDL_WinRTApp::OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ gamepad) -{ - /* HACK ALERT: Nothing needs to be done here, as this method currently - only exists to allow something to be registered with Win10's - GamepadAdded event, an operation that seems to be necessary to get - Xinput-based detection to work on Xbox One. - */ -} -#endif diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.h b/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.h deleted file mode 100644 index 9fb21f320..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_direct3d.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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 - -extern int SDL_WinRTInitNonXAMLApp(int (*mainFunction)(int, char **)); - -ref class SDL_WinRTApp sealed : public Windows::ApplicationModel::Core::IFrameworkView -{ - public: - SDL_WinRTApp(); - - // IFrameworkView Methods. - virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView ^ applicationView); - virtual void SetWindow(Windows::UI::Core::CoreWindow ^ window); - virtual void Load(Platform::String ^ entryPoint); - virtual void Run(); - virtual void Uninitialize(); - - internal : - // SDL-specific methods - void - PumpEvents(); - - protected: - bool ShouldWaitForAppResumeEvents(); - - // Event Handlers. - -#if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) // for Windows 8/8.1/RT apps... (and not Phone apps) - void OnSettingsPaneCommandsRequested( - Windows::UI::ApplicationSettings::SettingsPane ^ p, - Windows::UI::ApplicationSettings::SettingsPaneCommandsRequestedEventArgs ^ args); -#endif // if (WINAPI_FAMILY == WINAPI_FAMILY_APP) && (NTDDI_VERSION < NTDDI_WIN10) - -#if NTDDI_VERSION > NTDDI_WIN8 - void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation ^ sender, Platform::Object ^ args); -#else - void OnOrientationChanged(Platform::Object ^ sender); -#endif - void OnWindowSizeChanged(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::WindowSizeChangedEventArgs ^ args); - void OnLogicalDpiChanged(Platform::Object ^ sender); - void OnAppActivated(Windows::ApplicationModel::Core::CoreApplicationView ^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs ^ args); - void OnSuspending(Platform::Object ^ sender, Windows::ApplicationModel::SuspendingEventArgs ^ args); - void OnResuming(Platform::Object ^ sender, Platform::Object ^ args); - void OnExiting(Platform::Object ^ sender, Platform::Object ^ args); - void OnWindowActivated(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::WindowActivatedEventArgs ^ args); - void OnWindowClosed(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CoreWindowEventArgs ^ args); - void OnVisibilityChanged(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::VisibilityChangedEventArgs ^ args); - void OnPointerPressed(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnPointerReleased(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnPointerWheelChanged(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnPointerMoved(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnPointerEntered(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnPointerExited(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::PointerEventArgs ^ args); - void OnMouseMoved(Windows::Devices::Input::MouseDevice ^ mouseDevice, Windows::Devices::Input::MouseEventArgs ^ args); - void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ sender, Windows::UI::Core::AcceleratorKeyEventArgs ^ args); - void OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args); - -#if NTDDI_VERSION >= NTDDI_WIN10 - void OnBackButtonPressed(Platform::Object ^ sender, Windows::UI::Core::BackRequestedEventArgs ^ args); -#elif SDL_WINAPI_FAMILY_PHONE - void OnBackButtonPressed(Platform::Object ^ sender, Windows::Phone::UI::Input::BackPressedEventArgs ^ args); -#endif - -#if NTDDI_VERSION >= NTDDI_WIN10 - void OnGamepadAdded(Platform::Object ^ sender, Windows::Gaming::Input::Gamepad ^ gamepad); -#endif - - private: - bool m_windowClosed; - bool m_windowVisible; -}; - -extern SDL_WinRTApp ^ SDL_WinRTGlobalApp; diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.cpp b/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.cpp deleted file mode 100644 index 81a54515d..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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" - -/* Windows includes */ -#include -#include - -#if WINAPI_FAMILY == WINAPI_FAMILY_APP -#include -#endif - -/* SDL includes */ -#include "../../video/winrt/SDL_winrtevents_c.h" -#include "../../video/winrt/SDL_winrtvideo_cpp.h" -#include "SDL_winrtapp_common.h" -#include "SDL_winrtapp_xaml.h" - -/* SDL-internal globals: */ -SDL_bool WINRT_XAMLWasEnabled = SDL_FALSE; - -#if WINAPI_FAMILY == WINAPI_FAMILY_APP -extern "C" ISwapChainBackgroundPanelNative *WINRT_GlobalSwapChainBackgroundPanelNative = NULL; -static Windows::Foundation::EventRegistrationToken WINRT_XAMLAppEventToken; -#endif - -/* - * Input event handlers (XAML) - */ -#if WINAPI_FAMILY == WINAPI_FAMILY_APP - -static void WINRT_OnPointerPressedViaXAML(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ args) -{ - WINRT_ProcessPointerPressedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr)); -} - -static void WINRT_OnPointerMovedViaXAML(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ args) -{ - WINRT_ProcessPointerMovedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr)); -} - -static void WINRT_OnPointerReleasedViaXAML(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ args) -{ - WINRT_ProcessPointerReleasedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr)); -} - -static void WINRT_OnPointerWheelChangedViaXAML(Platform::Object ^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs ^ args) -{ - WINRT_ProcessPointerWheelChangedEvent(WINRT_GlobalSDLWindow, args->GetCurrentPoint(nullptr)); -} - -#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP - -/* - * XAML-to-SDL Rendering Callback - */ -#if WINAPI_FAMILY == WINAPI_FAMILY_APP - -static void WINRT_OnRenderViaXAML(_In_ Platform::Object ^ sender, _In_ Platform::Object ^ args) -{ - WINRT_CycleXAMLThread(); -} - -#endif // WINAPI_FAMILY == WINAPI_FAMILY_APP - -/* - * SDL + XAML Initialization - */ - -int SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void *backgroundPanelAsIInspectable) -{ -#if SDL_WINAPI_FAMILY_PHONE - return SDL_SetError("XAML support is not yet available in Windows Phone."); -#else - // Declare C++/CX namespaces: - using namespace Platform; - using namespace Windows::Foundation; - using namespace Windows::UI::Core; - using namespace Windows::UI::Xaml; - using namespace Windows::UI::Xaml::Controls; - using namespace Windows::UI::Xaml::Input; - using namespace Windows::UI::Xaml::Media; - - // Make sure we have a valid XAML element (to draw onto): - if (!backgroundPanelAsIInspectable) { - return SDL_InvalidParamError("backgroundPanelAsIInspectable"); - } - - Platform::Object ^ backgroundPanel = reinterpret_cast((IInspectable *)backgroundPanelAsIInspectable); - SwapChainBackgroundPanel ^ swapChainBackgroundPanel = dynamic_cast(backgroundPanel); - if (!swapChainBackgroundPanel) { - return SDL_SetError("An unknown or unsupported type of XAML control was specified."); - } - - // Setup event handlers: - swapChainBackgroundPanel->PointerPressed += ref new PointerEventHandler(WINRT_OnPointerPressedViaXAML); - swapChainBackgroundPanel->PointerReleased += ref new PointerEventHandler(WINRT_OnPointerReleasedViaXAML); - swapChainBackgroundPanel->PointerWheelChanged += ref new PointerEventHandler(WINRT_OnPointerWheelChangedViaXAML); - swapChainBackgroundPanel->PointerMoved += ref new PointerEventHandler(WINRT_OnPointerMovedViaXAML); - - // Setup for rendering: - IInspectable *panelInspectable = (IInspectable *)reinterpret_cast(swapChainBackgroundPanel); - panelInspectable->QueryInterface(__uuidof(ISwapChainBackgroundPanelNative), (void **)&WINRT_GlobalSwapChainBackgroundPanelNative); - - WINRT_XAMLAppEventToken = CompositionTarget::Rendering::add(ref new EventHandler(WINRT_OnRenderViaXAML)); - - // Make sure the app is ready to call the SDL-centric main() function: - WINRT_SDLAppEntryPoint = mainFunction; - SDL_SetMainReady(); - - // Make sure video-init knows that we're initializing XAML: - SDL_bool oldXAMLWasEnabledValue = WINRT_XAMLWasEnabled; - WINRT_XAMLWasEnabled = SDL_TRUE; - - // Make sure video modes are detected now, while we still have access to the WinRT - // CoreWindow. WinRT will not allow the app's CoreWindow to be accessed via the - // SDL/WinRT thread. - if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { - // SDL_InitSubSystem will, on error, set the SDL error. Let that propagate to - // the caller to here: - WINRT_XAMLWasEnabled = oldXAMLWasEnabledValue; - return -1; - } - - // All done, for now. - return 0; -#endif // SDL_WINAPI_FAMILY_PHONE -} diff --git a/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.h b/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.h deleted file mode 100644 index b321cc832..000000000 --- a/libs/SDL3/src/core/winrt/SDL_winrtapp_xaml.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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_winrtapp_xaml_h_ -#define SDL_winrtapp_xaml_h_ - -#ifdef __cplusplus -extern SDL_bool WINRT_XAMLWasEnabled; -extern int SDL_WinRTInitXAMLApp(int (*mainFunction)(int, char **), void *backgroundPanelAsIInspectable); -#endif // ifdef __cplusplus - -#endif // SDL_winrtapp_xaml_h_ diff --git a/libs/SDL3/src/cpuinfo/SDL_cpuinfo.c b/libs/SDL3/src/cpuinfo/SDL_cpuinfo.c index 2270956e1..6fdf3c024 100644 --- a/libs/SDL3/src/cpuinfo/SDL_cpuinfo.c +++ b/libs/SDL3/src/cpuinfo/SDL_cpuinfo.c @@ -21,11 +21,13 @@ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINRT) || defined(SDL_PLATFORM_GDK) +#include "SDL_cpuinfo_c.h" + +#if defined(SDL_PLATFORM_WINDOWS) #include "../core/windows/SDL_windows.h" #endif -/* CPU feature detection for SDL */ +// CPU feature detection for SDL #ifdef HAVE_SYSCONF #include @@ -35,10 +37,10 @@ #include #endif #if defined(SDL_PLATFORM_MACOS) && (defined(__ppc__) || defined(__ppc64__)) -#include /* For AltiVec check */ +#include // For AltiVec check #elif defined(SDL_PLATFORM_OPENBSD) && defined(__powerpc__) #include -#include /* For AltiVec check */ +#include // For AltiVec check #include #elif defined(SDL_PLATFORM_FREEBSD) && defined(__powerpc__) #include @@ -55,7 +57,7 @@ #include #include -/*#include */ +// #include #ifndef AT_HWCAP #define AT_HWCAP 16 #endif @@ -67,6 +69,10 @@ #endif #endif +#if defined (SDL_PLATFORM_FREEBSD) +#include +#endif + #if defined(SDL_PLATFORM_ANDROID) && defined(__arm__) && !defined(HAVE_GETAUXVAL) #include #endif @@ -116,13 +122,13 @@ static void illegal_instruction(int sig) { longjmp(jmpbuf, 1); } -#endif /* HAVE_SETJMP */ +#endif // HAVE_SETJMP static int CPU_haveCPUID(void) { int has_CPUID = 0; -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off #ifndef SDL_PLATFORM_EMSCRIPTEN #if (defined(__GNUC__) || defined(__llvm__)) && defined(__i386__) __asm__ ( @@ -210,8 +216,8 @@ static int CPU_haveCPUID(void) "1: \n" ); #endif -#endif /* !SDL_PLATFORM_EMSCRIPTEN */ -/* *INDENT-ON* */ /* clang-format on */ +#endif // !SDL_PLATFORM_EMSCRIPTEN +/* *INDENT-ON* */ // clang-format on return has_CPUID; } @@ -247,7 +253,7 @@ static int CPU_haveCPUID(void) __asm mov d, edx \ } #elif (defined(_MSC_VER) && defined(_M_X64)) -/* Use __cpuidex instead of __cpuid because ICL does not clear ecx register */ +// Use __cpuidex instead of __cpuid because ICL does not clear ecx register #define cpuid(func, a, b, c, d) \ { \ int CPUInfo[4]; \ @@ -270,14 +276,14 @@ static int CPU_haveCPUID(void) static int CPU_CPUIDFeatures[4]; static int CPU_CPUIDMaxFunction = 0; -static SDL_bool CPU_OSSavesYMM = SDL_FALSE; -static SDL_bool CPU_OSSavesZMM = SDL_FALSE; +static bool CPU_OSSavesYMM = false; +static bool CPU_OSSavesZMM = false; static void CPU_calcCPUIDFeatures(void) { - static SDL_bool checked = SDL_FALSE; + static bool checked = false; if (!checked) { - checked = SDL_TRUE; + checked = true; if (CPU_haveCPUID()) { int a, b, c, d; cpuid(0, a, b, c, d); @@ -289,15 +295,15 @@ static void CPU_calcCPUIDFeatures(void) CPU_CPUIDFeatures[2] = c; CPU_CPUIDFeatures[3] = d; - /* Check to make sure we can call xgetbv */ + // Check to make sure we can call xgetbv if (c & 0x08000000) { - /* Call xgetbv to see if YMM (etc) register state is saved */ + // Call xgetbv to see if YMM (etc) register state is saved #if (defined(__GNUC__) || defined(__llvm__)) && (defined(__i386__) || defined(__x86_64__)) __asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(a) : "c"(0) : "%edx"); -#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) /* VS2010 SP1 */ +#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) && (_MSC_FULL_VER >= 160040219) // VS2010 SP1 a = (int)_xgetbv(0); #elif (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) __asm @@ -307,8 +313,8 @@ static void CPU_calcCPUIDFeatures(void) mov a, eax } #endif - CPU_OSSavesYMM = ((a & 6) == 6) ? SDL_TRUE : SDL_FALSE; - CPU_OSSavesZMM = (CPU_OSSavesYMM && ((a & 0xe0) == 0xe0)) ? SDL_TRUE : SDL_FALSE; + CPU_OSSavesYMM = ((a & 6) == 6) ? true : false; + CPU_OSSavesZMM = (CPU_OSSavesYMM && ((a & 0xe0) == 0xe0)) ? true : false; } } } @@ -441,28 +447,28 @@ static int CPU_haveNEON(void) /* The way you detect NEON is a privileged instruction on ARM, so you have query the OS kernel in a platform-specific way. :/ */ #if defined(SDL_PLATFORM_WINDOWS) && (defined(_M_ARM) || defined(_M_ARM64)) -/* Visual Studio, for ARM, doesn't define __ARM_ARCH. Handle this first. */ -/* Seems to have been removed */ +// Visual Studio, for ARM, doesn't define __ARM_ARCH. Handle this first. +// Seems to have been removed #ifndef PF_ARM_NEON_INSTRUCTIONS_AVAILABLE #define PF_ARM_NEON_INSTRUCTIONS_AVAILABLE 19 #endif - /* All WinRT ARM devices are required to support NEON, but just in case. */ + // All WinRT ARM devices are required to support NEON, but just in case. return IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE) != 0; #elif (defined(__ARM_ARCH) && (__ARM_ARCH >= 8)) || defined(__aarch64__) - return 1; /* ARMv8 always has non-optional NEON support. */ + return 1; // ARMv8 always has non-optional NEON support. #elif defined(SDL_PLATFORM_VITA) return 1; #elif defined(SDL_PLATFORM_3DS) return 0; #elif defined(SDL_PLATFORM_APPLE) && defined(__ARM_ARCH) && (__ARM_ARCH >= 7) - /* (note that sysctlbyname("hw.optional.neon") doesn't work!) */ - return 1; /* all Apple ARMv7 chips and later have NEON. */ + // (note that sysctlbyname("hw.optional.neon") doesn't work!) + return 1; // all Apple ARMv7 chips and later have NEON. #elif defined(SDL_PLATFORM_APPLE) - return 0; /* assume anything else from Apple doesn't have NEON. */ + return 0; // assume anything else from Apple doesn't have NEON. #elif !defined(__arm__) - return 0; /* not an ARM CPU at all. */ + return 0; // not an ARM CPU at all. #elif defined(SDL_PLATFORM_OPENBSD) - return 1; /* OpenBSD only supports ARMv7 CPUs that have NEON. */ + return 1; // OpenBSD only supports ARMv7 CPUs that have NEON. #elif defined(HAVE_ELF_AUX_INFO) unsigned long hasneon = 0; if (elf_aux_info(AT_HWCAP, (void *)&hasneon, (int)sizeof(hasneon)) != 0) { @@ -474,7 +480,7 @@ static int CPU_haveNEON(void) #elif defined(SDL_PLATFORM_LINUX) return readProcAuxvForNeon(); #elif defined(SDL_PLATFORM_ANDROID) - /* Use NDK cpufeatures to read either /proc/self/auxv or /proc/cpuinfo */ + // Use NDK cpufeatures to read either /proc/self/auxv or /proc/cpuinfo { AndroidCpuFamily cpu_family = android_getCpuFamily(); if (cpu_family == ANDROID_CPU_FAMILY_ARM) { @@ -486,7 +492,7 @@ static int CPU_haveNEON(void) return 0; } #elif defined(SDL_PLATFORM_RISCOS) - /* Use the VFPSupport_Features SWI to access the MVFR registers */ + // Use the VFPSupport_Features SWI to access the MVFR registers { _kernel_swi_regs regs; regs.r[0] = 0; @@ -584,7 +590,7 @@ static int CPU_haveAVX2(void) (void)a; (void)b; (void)c; - (void)d; /* compiler warnings... */ + (void)d; // compiler warnings... cpuid(7, a, b, c, d); return b & 0x00000020; } @@ -606,7 +612,7 @@ static int CPU_haveAVX512F(void) (void)a; (void)b; (void)c; - (void)d; /* compiler warnings... */ + (void)d; // compiler warnings... cpuid(7, a, b, c, d); return b & 0x00010000; } @@ -614,35 +620,35 @@ static int CPU_haveAVX512F(void) } #endif -static int SDL_CPUCount = 0; +static int SDL_NumLogicalCPUCores = 0; -int SDL_GetCPUCount(void) +int SDL_GetNumLogicalCPUCores(void) { - if (!SDL_CPUCount) { + if (!SDL_NumLogicalCPUCores) { #if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) - if (SDL_CPUCount <= 0) { - SDL_CPUCount = (int)sysconf(_SC_NPROCESSORS_ONLN); + if (SDL_NumLogicalCPUCores <= 0) { + SDL_NumLogicalCPUCores = (int)sysconf(_SC_NPROCESSORS_ONLN); } #endif #ifdef HAVE_SYSCTLBYNAME - if (SDL_CPUCount <= 0) { - size_t size = sizeof(SDL_CPUCount); - sysctlbyname("hw.ncpu", &SDL_CPUCount, &size, NULL, 0); + if (SDL_NumLogicalCPUCores <= 0) { + size_t size = sizeof(SDL_NumLogicalCPUCores); + sysctlbyname("hw.ncpu", &SDL_NumLogicalCPUCores, &size, NULL, 0); } #endif -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) - if (SDL_CPUCount <= 0) { +#if defined(SDL_PLATFORM_WINDOWS) + if (SDL_NumLogicalCPUCores <= 0) { SYSTEM_INFO info; GetSystemInfo(&info); - SDL_CPUCount = info.dwNumberOfProcessors; + SDL_NumLogicalCPUCores = info.dwNumberOfProcessors; } #endif - /* There has to be at least 1, right? :) */ - if (SDL_CPUCount <= 0) { - SDL_CPUCount = 1; + // There has to be at least 1, right? :) + if (SDL_NumLogicalCPUCores <= 0) { + SDL_NumLogicalCPUCores = 1; } } - return SDL_CPUCount; + return SDL_NumLogicalCPUCores; } #ifdef __e2k__ @@ -656,7 +662,7 @@ SDL_GetCPUType(void) return SDL_CPUType; } #else -/* Oh, such a sweet sweet trick, just not very useful. :) */ +// Oh, such a sweet sweet trick, just not very useful. :) static const char *SDL_GetCPUType(void) { static char SDL_CPUType[13]; @@ -665,7 +671,7 @@ static const char *SDL_GetCPUType(void) int i = 0; CPU_calcCPUIDFeatures(); - if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */ + if (CPU_CPUIDMaxFunction > 0) { // do we have CPUID at all? int a, b, c, d; cpuid(0x00000000, a, b, c, d); (void)a; @@ -723,7 +729,7 @@ static const char *SDL_GetCPUName(void) int a, b, c, d; CPU_calcCPUIDFeatures(); - if (CPU_CPUIDMaxFunction > 0) { /* do we have CPUID at all? */ + if (CPU_CPUIDMaxFunction > 0) { // do we have CPUID at all? cpuid(0x80000000, a, b, c, d); if (a >= 0x80000004) { cpuid(0x80000002, a, b, c, d); @@ -839,6 +845,7 @@ static const char *SDL_GetCPUName(void) int SDL_GetCPUCacheLineSize(void) { const char *cpuType = SDL_GetCPUType(); + int cacheline_size = SDL_CACHELINE_SIZE; // initial guess int a, b, c, d; (void)a; (void)b; @@ -846,14 +853,34 @@ int SDL_GetCPUCacheLineSize(void) (void)d; if (SDL_strcmp(cpuType, "GenuineIntel") == 0 || SDL_strcmp(cpuType, "CentaurHauls") == 0 || SDL_strcmp(cpuType, " Shanghai ") == 0) { cpuid(0x00000001, a, b, c, d); - return ((b >> 8) & 0xff) * 8; + cacheline_size = ((b >> 8) & 0xff) * 8; } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0 || SDL_strcmp(cpuType, "HygonGenuine") == 0) { cpuid(0x80000005, a, b, c, d); - return c & 0xff; + cacheline_size = c & 0xff; } else { - /* Just make a guess here... */ - return SDL_CACHELINE_SIZE; +#if defined(HAVE_SYSCONF) && defined(_SC_LEVEL1_DCACHE_LINESIZE) + if ((cacheline_size = (int)sysconf(_SC_LEVEL1_DCACHE_LINESIZE)) > 0) { + return cacheline_size; + } else { + cacheline_size = SDL_CACHELINE_SIZE; + } +#endif +#if defined(SDL_PLATFORM_LINUX) + { + FILE *f = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r"); + if (f) { + int size; + if (fscanf(f, "%d", &size) == 1) { + cacheline_size = size; + } + fclose(f); + } + } +#elif defined(__FREEBSD__) && defined(CACHE_LINE_SIZE) + cacheline_size = CACHE_LINE_SIZE; +#endif } + return cacheline_size; } #define SDL_CPUFEATURES_RESET_VALUE 0xFFFFFFFF @@ -861,7 +888,7 @@ int SDL_GetCPUCacheLineSize(void) static Uint32 SDL_CPUFeatures = SDL_CPUFEATURES_RESET_VALUE; static Uint32 SDL_SIMDAlignment = 0xFFFFFFFF; -static SDL_bool ref_string_equals(const char *ref, const char *test, const char *end_test) { +static bool ref_string_equals(const char *ref, const char *test, const char *end_test) { size_t len_test = end_test - test; return SDL_strncmp(ref, test, len_test) == 0 && ref[len_test] == '\0' && (test[len_test] == '\0' || test[len_test] == ','); } @@ -876,7 +903,7 @@ static Uint32 SDLCALL SDL_CPUFeatureMaskFromHint(void) for (const char *spot = hint, *next; *spot; spot = next) { const char *end = SDL_strchr(spot, ','); Uint32 spot_mask; - SDL_bool add_spot_mask = SDL_TRUE; + bool add_spot_mask = true; if (end) { next = end + 1; } else { @@ -885,10 +912,10 @@ static Uint32 SDLCALL SDL_CPUFeatureMaskFromHint(void) next = end; } if (spot[0] == '+') { - add_spot_mask = SDL_TRUE; + add_spot_mask = true; spot += 1; } else if (spot[0] == '-') { - add_spot_mask = SDL_FALSE; + add_spot_mask = false; spot += 1; } if (ref_string_equals("all", spot, end)) { @@ -922,7 +949,7 @@ static Uint32 SDLCALL SDL_CPUFeatureMaskFromHint(void) } else if (ref_string_equals("lasx", spot, end)) { spot_mask = CPU_HAS_LASX; } else { - /* Ignore unknown/incorrect cpu feature(s) */ + // Ignore unknown/incorrect cpu feature(s) continue; } if (add_spot_mask) { @@ -940,7 +967,7 @@ static Uint32 SDL_GetCPUFeatures(void) if (SDL_CPUFeatures == SDL_CPUFEATURES_RESET_VALUE) { CPU_calcCPUIDFeatures(); SDL_CPUFeatures = 0; - SDL_SIMDAlignment = sizeof(void *); /* a good safe base value */ + SDL_SIMDAlignment = sizeof(void *); // a good safe base value if (CPU_haveAltiVec()) { SDL_CPUFeatures |= CPU_HAS_ALTIVEC; SDL_SIMDAlignment = SDL_max(SDL_SIMDAlignment, 16); @@ -1006,74 +1033,74 @@ void SDL_QuitCPUInfo(void) { SDL_CPUFeatures = SDL_CPUFEATURES_RESET_VALUE; } -#define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & (f)) ? SDL_TRUE : SDL_FALSE) +#define CPU_FEATURE_AVAILABLE(f) ((SDL_GetCPUFeatures() & (f)) ? true : false) -SDL_bool SDL_HasAltiVec(void) +bool SDL_HasAltiVec(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_ALTIVEC); } -SDL_bool SDL_HasMMX(void) +bool SDL_HasMMX(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_MMX); } -SDL_bool SDL_HasSSE(void) +bool SDL_HasSSE(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE); } -SDL_bool SDL_HasSSE2(void) +bool SDL_HasSSE2(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE2); } -SDL_bool SDL_HasSSE3(void) +bool SDL_HasSSE3(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE3); } -SDL_bool SDL_HasSSE41(void) +bool SDL_HasSSE41(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE41); } -SDL_bool SDL_HasSSE42(void) +bool SDL_HasSSE42(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_SSE42); } -SDL_bool SDL_HasAVX(void) +bool SDL_HasAVX(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX); } -SDL_bool SDL_HasAVX2(void) +bool SDL_HasAVX2(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX2); } -SDL_bool SDL_HasAVX512F(void) +bool SDL_HasAVX512F(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_AVX512F); } -SDL_bool SDL_HasARMSIMD(void) +bool SDL_HasARMSIMD(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_ARM_SIMD); } -SDL_bool SDL_HasNEON(void) +bool SDL_HasNEON(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_NEON); } -SDL_bool SDL_HasLSX(void) +bool SDL_HasLSX(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_LSX); } -SDL_bool SDL_HasLASX(void) +bool SDL_HasLASX(void) { return CPU_FEATURE_AVAILABLE(CPU_HAS_LASX); } @@ -1091,18 +1118,18 @@ int SDL_GetSystemRAM(void) #ifdef HAVE_SYSCTLBYNAME if (SDL_SystemRAM <= 0) { #ifdef HW_PHYSMEM64 - /* (64-bit): NetBSD since 2003, OpenBSD */ + // (64-bit): NetBSD since 2003, OpenBSD int mib[2] = { CTL_HW, HW_PHYSMEM64 }; #elif defined(HW_REALMEM) - /* (64-bit): FreeBSD since 2005, DragonFly */ + // (64-bit): FreeBSD since 2005, DragonFly int mib[2] = { CTL_HW, HW_REALMEM }; #elif defined(HW_MEMSIZE) - /* (64-bit): Darwin */ + // (64-bit): Darwin int mib[2] = { CTL_HW, HW_MEMSIZE }; #else - /* (32-bit): very old BSD, might only report up to 2 GiB */ + // (32-bit): very old BSD, might only report up to 2 GiB int mib[2] = { CTL_HW, HW_PHYSMEM }; -#endif /* HW_PHYSMEM64 */ +#endif // HW_PHYSMEM64 Uint64 memsize = 0; size_t len = sizeof(memsize); @@ -1111,7 +1138,7 @@ int SDL_GetSystemRAM(void) } } #endif -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) if (SDL_SystemRAM <= 0) { MEMORYSTATUSEX stat; stat.dwLength = sizeof(stat); @@ -1138,7 +1165,7 @@ int SDL_GetSystemRAM(void) #endif #ifdef SDL_PLATFORM_PS2 if (SDL_SystemRAM <= 0) { - /* PlayStation 2 has 32MiB however there are some special models with 64 and 128 */ + // PlayStation 2 has 32MiB however there are some special models with 64 and 128 SDL_SystemRAM = GetMemorySize(); } #endif @@ -1156,10 +1183,10 @@ int SDL_GetSystemRAM(void) return SDL_SystemRAM; } -size_t SDL_SIMDGetAlignment(void) +size_t SDL_GetSIMDAlignment(void) { if (SDL_SIMDAlignment == 0xFFFFFFFF) { - SDL_GetCPUFeatures(); /* make sure this has been calculated */ + SDL_GetCPUFeatures(); // make sure this has been calculated } SDL_assert(SDL_SIMDAlignment != 0); return SDL_SIMDAlignment; diff --git a/libs/SDL3/src/cpuinfo/SDL_cpuinfo_c.h b/libs/SDL3/src/cpuinfo/SDL_cpuinfo_c.h index c64a091ed..1e239bd86 100644 --- a/libs/SDL3/src/cpuinfo/SDL_cpuinfo_c.h +++ b/libs/SDL3/src/cpuinfo/SDL_cpuinfo_c.h @@ -24,4 +24,4 @@ extern void SDL_QuitCPUInfo(void); -#endif /* SDL_cpuinfo_c_h_ */ +#endif // SDL_cpuinfo_c_h_ diff --git a/libs/SDL3/src/dialog/SDL_dialog_utils.c b/libs/SDL3/src/dialog/SDL_dialog_utils.c new file mode 100644 index 000000000..ef3fbdf29 --- /dev/null +++ b/libs/SDL3/src/dialog/SDL_dialog_utils.c @@ -0,0 +1,259 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" + +#include "SDL_dialog_utils.h" + +char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters, + NameTransform ntf, const char *prefix, + const char *separator, const char *suffix, + const char *filt_prefix, const char *filt_separator, + const char *filt_suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix) +{ + char *combined; + char *new_combined; + char *converted; + const char *terminator; + size_t new_length; + int i; + + if (!filters) { + SDL_SetError("Called convert_filters() with NULL filters (SDL bug)"); + return NULL; + } + + combined = SDL_strdup(prefix); + + if (!combined) { + return NULL; + } + + for (i = 0; i < nfilters; i++) { + const SDL_DialogFileFilter *f = &filters[i]; + + converted = convert_filter(*f, ntf, filt_prefix, filt_separator, + filt_suffix, ext_prefix, ext_separator, + ext_suffix); + + if (!converted) { + SDL_free(combined); + return NULL; + } + + terminator = f[1].name ? separator : suffix; + new_length = SDL_strlen(combined) + SDL_strlen(converted) + + SDL_strlen(terminator) + 1; + + new_combined = (char *)SDL_realloc(combined, new_length); + + if (!new_combined) { + SDL_free(converted); + SDL_free(combined); + return NULL; + } + + combined = new_combined; + + SDL_strlcat(combined, converted, new_length); + SDL_strlcat(combined, terminator, new_length); + SDL_free(converted); + } + + // If the filter list is empty, put the suffix + if (!filters->name || !filters->pattern) { + new_length = SDL_strlen(combined) + SDL_strlen(suffix) + 1; + + new_combined = (char *)SDL_realloc(combined, new_length); + + if (!new_combined) { + SDL_free(combined); + return NULL; + } + + combined = new_combined; + + SDL_strlcat(combined, suffix, new_length); + } + + return combined; +} + +char *convert_filter(SDL_DialogFileFilter filter, NameTransform ntf, + const char *prefix, const char *separator, + const char *suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix) +{ + char *converted; + char *name_filtered; + size_t total_length; + char *list; + + list = convert_ext_list(filter.pattern, ext_prefix, ext_separator, + ext_suffix); + + if (!list) { + return NULL; + } + + if (ntf) { + name_filtered = ntf(filter.name); + } else { + // Useless strdup, but easier to read and maintain code this way + name_filtered = SDL_strdup(filter.name); + } + + if (!name_filtered) { + SDL_free(list); + return NULL; + } + + total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered) + + SDL_strlen(separator) + SDL_strlen(list) + + SDL_strlen(suffix) + 1; + + converted = (char *) SDL_malloc(total_length); + + if (!converted) { + SDL_free(list); + SDL_free(name_filtered); + return NULL; + } + + SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered, + separator, list, suffix); + + SDL_free(list); + SDL_free(name_filtered); + + return converted; +} + +char *convert_ext_list(const char *list, const char *prefix, + const char *separator, const char *suffix) +{ + char *converted; + int semicolons; + size_t total_length; + + semicolons = 0; + + for (const char *c = list; *c; c++) { + semicolons += (*c == ';'); + } + + total_length = + SDL_strlen(list) - semicolons // length of list contents + + semicolons * SDL_strlen(separator) // length of separators + + SDL_strlen(prefix) + SDL_strlen(suffix) // length of prefix/suffix + + 1; // terminating null byte + + converted = (char *) SDL_malloc(total_length); + + if (!converted) { + return NULL; + } + + *converted = '\0'; + + SDL_strlcat(converted, prefix, total_length); + + /* Some platforms may prefer to handle the asterisk manually, but this + function offers to handle it for ease of use. */ + if (SDL_strcmp(list, "*") == 0) { + SDL_strlcat(converted, "*", total_length); + } else { + for (const char *c = list; *c; c++) { + if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') + || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' + || *c == '.') { + char str[2]; + str[0] = *c; + str[1] = '\0'; + SDL_strlcat(converted, str, total_length); + } else if (*c == ';') { + if (c == list || c[-1] == ';') { + SDL_SetError("Empty pattern not allowed"); + SDL_free(converted); + return NULL; + } + + SDL_strlcat(converted, separator, total_length); + } else { + SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c); + SDL_free(converted); + return NULL; + } + } + } + + if (list[SDL_strlen(list) - 1] == ';') { + SDL_SetError("Empty pattern not allowed"); + SDL_free(converted); + return NULL; + } + + SDL_strlcat(converted, suffix, total_length); + + return converted; +} + +const char *validate_filters(const SDL_DialogFileFilter *filters, int nfilters) +{ + if (filters) { + for (int i = 0; i < nfilters; i++) { + const char *msg = validate_list(filters[i].pattern); + + if (msg) { + return msg; + } + } + } + + return NULL; +} + +const char *validate_list(const char *list) +{ + if (SDL_strcmp(list, "*") == 0) { + return NULL; + } else { + for (const char *c = list; *c; c++) { + if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') + || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' + || *c == '.') { + continue; + } else if (*c == ';') { + if (c == list || c[-1] == ';') { + return "Empty pattern not allowed"; + } + } else { + return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)"; + } + } + } + + if (list[SDL_strlen(list) - 1] == ';') { + return "Empty pattern not allowed"; + } + + return NULL; +} diff --git a/libs/SDL3/src/dialog/SDL_dialog_utils.h b/libs/SDL3/src/dialog/SDL_dialog_utils.h new file mode 100644 index 000000000..1fd71befe --- /dev/null +++ b/libs/SDL3/src/dialog/SDL_dialog_utils.h @@ -0,0 +1,59 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" + +/* The following are utility functions to help implementations. + They are ordered by scope largeness, decreasing. All implementations + should use them, as they check for invalid filters. Where they are unused, + the validate_* function further down below should be used. */ + +/* Transform the name given in argument into something viable for the engine. + Useful if there are special characters to avoid on certain platforms (such + as "|" with Zenity). */ +typedef char *(NameTransform)(const char * name); + +// Converts all the filters into a single string. +// [filter]{[filter]...} +char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters, + NameTransform ntf, const char *prefix, + const char *separator, const char *suffix, + const char *filt_prefix, const char *filt_separator, + const char *filt_suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix); + +// Converts one filter into a single string. +// [filter name][filter extension list] +char *convert_filter(SDL_DialogFileFilter filter, NameTransform ntf, + const char *prefix, const char *separator, + const char *suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix); + +// Converts the extension list of a filter into a single string. +// [extension]{[extension]...} +char *convert_ext_list(const char *list, const char *prefix, + const char *separator, const char *suffix); + +/* Must be used if convert_* functions aren't used */ +// Returns an error message if there's a problem, NULL otherwise +const char *validate_filters(const SDL_DialogFileFilter *filters, + int nfilters); + +const char *validate_list(const char *list); diff --git a/libs/SDL3/src/dialog/android/SDL_androiddialog.c b/libs/SDL3/src/dialog/android/SDL_androiddialog.c new file mode 100644 index 000000000..fd9e102ef --- /dev/null +++ b/libs/SDL3/src/dialog/android/SDL_androiddialog.c @@ -0,0 +1,45 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" +#include "../../core/android/SDL_android.h" + +void SDLCALL SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many) +{ + if (!Android_JNI_OpenFileDialog(callback, userdata, filters, nfilters, false, allow_many)) { + // SDL_SetError is already called when it fails + callback(userdata, NULL, -1); + } +} + +void SDLCALL SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location) +{ + if (!Android_JNI_OpenFileDialog(callback, userdata, filters, nfilters, true, false)) { + // SDL_SetError is already called when it fails + callback(userdata, NULL, -1); + } +} + +void SDLCALL SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char *default_location, bool allow_many) +{ + SDL_Unsupported(); + callback(userdata, NULL, -1); +} diff --git a/libs/SDL3/src/dialog/cocoa/SDL_cocoadialog.m b/libs/SDL3/src/dialog/cocoa/SDL_cocoadialog.m index 970b1884f..eee685e26 100644 --- a/libs/SDL3/src/dialog/cocoa/SDL_cocoadialog.m +++ b/libs/SDL3/src/dialog/cocoa/SDL_cocoadialog.m @@ -19,6 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" +#include "../SDL_dialog_utils.h" #import #import @@ -30,13 +31,29 @@ FDT_OPENFOLDER } cocoa_FileDialogType; -void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { #if defined(SDL_PLATFORM_TVOS) || defined(SDL_PLATFORM_IOS) SDL_SetError("tvOS and iOS don't support path-based file dialogs"); callback(userdata, NULL, -1); #else - /* NSOpenPanel inherits from NSSavePanel */ + if (filters) { + const char *msg = validate_filters(filters, nfilters); + + if (msg) { + SDL_SetError("%s", msg); + callback(userdata, NULL, -1); + return; + } + } + + if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { + SDL_SetError("File dialog driver unsupported"); + callback(userdata, NULL, -1); + return; + } + + // NSOpenPanel inherits from NSSavePanel NSSavePanel *dialog; NSOpenPanel *dialog_as_open; @@ -46,69 +63,64 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback break; case FDT_OPEN: dialog_as_open = [NSOpenPanel openPanel]; - [dialog_as_open setAllowsMultipleSelection:((allow_many == SDL_TRUE) ? YES : NO)]; + [dialog_as_open setAllowsMultipleSelection:((allow_many == true) ? YES : NO)]; dialog = dialog_as_open; break; case FDT_OPENFOLDER: dialog_as_open = [NSOpenPanel openPanel]; [dialog_as_open setCanChooseFiles:NO]; [dialog_as_open setCanChooseDirectories:YES]; - [dialog_as_open setAllowsMultipleSelection:((allow_many == SDL_TRUE) ? YES : NO)]; + [dialog_as_open setAllowsMultipleSelection:((allow_many == true) ? YES : NO)]; dialog = dialog_as_open; break; }; - int n = -1; - while (filters[++n].name && filters[n].pattern); - // On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString - NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:n ]; + if (filters) { + // On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString + NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ]; - int has_all_files = 0; - for (int i = 0; i < n; i++) { - char *pattern = SDL_strdup(filters[i].pattern); - char *pattern_ptr = pattern; + int has_all_files = 0; + for (int i = 0; i < nfilters; i++) { + char *pattern = SDL_strdup(filters[i].pattern); + char *pattern_ptr = pattern; - if (!pattern_ptr) { - SDL_OutOfMemory(); - callback(userdata, NULL, -1); - return; - } + if (!pattern_ptr) { + callback(userdata, NULL, -1); + return; + } - for (char *c = pattern; *c; c++) { - if (*c == ';') { - *c = '\0'; - if(@available(macOS 11.0, *)) { - [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; - } else { - [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; + for (char *c = pattern; *c; c++) { + if (*c == ';') { + *c = '\0'; + if(@available(macOS 11.0, *)) { + [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; + } else { + [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; + } + pattern_ptr = c + 1; + } else if (*c == '*') { + has_all_files = 1; } - pattern_ptr = c + 1; - } else if (!((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9') || *c == '.' || *c == '_' || *c == '-' || (*c == '*' && (c[1] == '\0' || c[1] == ';')))) { - SDL_SetError("Illegal character in pattern name: %c (Only alphanumeric characters, periods, underscores and hyphens allowed)", *c); - callback(userdata, NULL, -1); - SDL_free(pattern); - } else if (*c == '*') { - has_all_files = 1; } - } - if(@available(macOS 11.0, *)) { - [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; - } else { - [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; - } + if(@available(macOS 11.0, *)) { + [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; + } else { + [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; + } - SDL_free(pattern); - } + SDL_free(pattern); + } - if (!has_all_files) { - if (@available(macOS 11.0, *)) { - [dialog setAllowedContentTypes:types]; - } else { - [dialog setAllowedFileTypes:types]; + if (!has_all_files) { + if (@available(macOS 11.0, *)) { + [dialog setAllowedContentTypes:types]; + } else { + [dialog setAllowedFileTypes:types]; + } } } - /* Keep behavior consistent with other platforms */ + // Keep behavior consistent with other platforms [dialog setAllowsOtherFileTypes:YES]; if (default_location) { @@ -118,7 +130,7 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback NSWindow *w = NULL; if (window) { - w = (__bridge NSWindow *)SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); + w = (__bridge NSWindow *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL); } if (w) { @@ -166,17 +178,17 @@ void show_file_dialog(cocoa_FileDialogType type, SDL_DialogFileCallback callback #endif // defined(SDL_PLATFORM_TVOS) || defined(SDL_PLATFORM_IOS) } -void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { - show_file_dialog(FDT_OPEN, callback, userdata, window, filters, default_location, allow_many); + show_file_dialog(FDT_OPEN, callback, userdata, window, filters, nfilters, default_location, allow_many); } -void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { - show_file_dialog(FDT_SAVE, callback, userdata, window, filters, default_location, 0); + show_file_dialog(FDT_SAVE, callback, userdata, window, filters, nfilters, default_location, 0); } -void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { - show_file_dialog(FDT_OPENFOLDER, callback, userdata, window, NULL, default_location, allow_many); + show_file_dialog(FDT_OPENFOLDER, callback, userdata, window, NULL, 0, default_location, allow_many); } diff --git a/libs/SDL3/src/dialog/dummy/SDL_dummydialog.c b/libs/SDL3/src/dialog/dummy/SDL_dummydialog.c index 057bb67d8..209efe766 100644 --- a/libs/SDL3/src/dialog/dummy/SDL_dummydialog.c +++ b/libs/SDL3/src/dialog/dummy/SDL_dummydialog.c @@ -20,19 +20,19 @@ */ #include "SDL_internal.h" -void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { SDL_Unsupported(); callback(userdata, NULL, -1); } -void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { SDL_Unsupported(); callback(userdata, NULL, -1); } -void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { SDL_Unsupported(); callback(userdata, NULL, -1); diff --git a/libs/SDL3/src/dialog/haiku/SDL_haikudialog.cc b/libs/SDL3/src/dialog/haiku/SDL_haikudialog.cc index 3e63fc807..9d6e37303 100644 --- a/libs/SDL3/src/dialog/haiku/SDL_haikudialog.cc +++ b/libs/SDL3/src/dialog/haiku/SDL_haikudialog.cc @@ -19,6 +19,9 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" +extern "C" { +#include "../SDL_dialog_utils.h" +} #include "../../core/haiku/SDL_BeApp.h" #include @@ -40,26 +43,27 @@ bool StringEndsWith(const std::string& str, const std::string& end) std::vector StringSplit(const std::string& str, const std::string& split) { - std::vector retval; + std::vector result; std::string s = str; size_t pos = 0; while ((pos = s.find(split)) != std::string::npos) { - retval.push_back(s.substr(0, pos)); + result.push_back(s.substr(0, pos)); s = s.substr(pos + split.size()); } - retval.push_back(s); + result.push_back(s); - return retval; + return result; } class SDLBRefFilter : public BRefFilter { public: - SDLBRefFilter(const SDL_DialogFileFilter *filters) : + SDLBRefFilter(const SDL_DialogFileFilter *filters, int nfilters) : BRefFilter(), - m_filters(filters) + m_filters(filters), + m_nfilters(nfilters) { } @@ -78,14 +82,12 @@ class SDLBRefFilter : public BRefFilter if (S_ISDIR(info.st_mode)) return true; - const auto *filter = m_filters; - while (filter->name && filter->pattern) { - for (const auto& suffix : StringSplit(filter->pattern, ";")) { + for (int i = 0; i < m_nfilters; i++) { + for (const auto& suffix : StringSplit(m_filters[i].pattern, ";")) { if (StringEndsWith(result, std::string(".") + suffix)) { return true; } } - filter++; } return false; @@ -93,6 +95,7 @@ class SDLBRefFilter : public BRefFilter private: const SDL_DialogFileFilter * const m_filters; + int m_nfilters; }; class CallbackLooper : public BLooper @@ -187,9 +190,9 @@ class CallbackLooper : public BLooper SDLBRefFilter *m_filter; }; -void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool many, bool modal, const SDL_DialogFileFilter *filters, bool folder, const char *location) +void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool many, bool modal, const SDL_DialogFileFilter *filters, int nfilters, bool folder, const char *location) { - if (SDL_InitBeApp()) { + if (!SDL_InitBeApp()) { char* err = SDL_strdup(SDL_GetError()); SDL_SetError("Couldn't init Be app: %s", err); SDL_free(err); @@ -197,10 +200,35 @@ void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool return; } + if (filters) { + const char *msg = validate_filters(filters, nfilters); + + if (msg) { + SDL_SetError("%s", msg); + callback(userdata, NULL, -1); + return; + } + } + + if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { + SDL_SetError("File dialog driver unsupported"); + callback(userdata, NULL, -1); + return; + } + // No unique_ptr's because they need to survive the end of the function - CallbackLooper *looper = new CallbackLooper(callback, userdata); - BMessenger *messenger = new BMessenger(NULL, looper); - SDLBRefFilter *filter = new SDLBRefFilter(filters); + CallbackLooper *looper = new(std::nothrow) CallbackLooper(callback, userdata); + BMessenger *messenger = new(std::nothrow) BMessenger(NULL, looper); + SDLBRefFilter *filter = new(std::nothrow) SDLBRefFilter(filters, nfilters); + + if (looper == NULL || messenger == NULL || filter == NULL) { + SDL_free(looper); + SDL_free(messenger); + SDL_free(filter); + SDL_OutOfMemory(); + callback(userdata, NULL, -1); + return; + } BEntry entry; entry_ref entryref; @@ -215,19 +243,17 @@ void ShowDialog(bool save, SDL_DialogFileCallback callback, void *userdata, bool panel->Show(); } -void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location, SDL_bool allow_many) +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location, bool allow_many) { - ShowDialog(false, callback, userdata, allow_many == SDL_TRUE, !!window, filters, false, default_location); + ShowDialog(false, callback, userdata, allow_many == true, !!window, filters, nfilters, false, default_location); } -void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, const char *default_location) +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const SDL_DialogFileFilter *filters, int nfilters, const char *default_location) { - ShowDialog(true, callback, userdata, false, !!window, filters, false, default_location); + ShowDialog(true, callback, userdata, false, !!window, filters, nfilters, false, default_location); } -void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void *userdata, SDL_Window *window, const char* default_location, bool allow_many) { - // Use a dummy filter to avoid showing files in the dialog - SDL_DialogFileFilter filter[] = {{}}; - ShowDialog(false, callback, userdata, allow_many == SDL_TRUE, !!window, filter, true, default_location); + ShowDialog(false, callback, userdata, allow_many == true, !!window, NULL, 0, true, default_location); } diff --git a/libs/SDL3/src/dialog/unix/SDL_portaldialog.c b/libs/SDL3/src/dialog/unix/SDL_portaldialog.c index e56478bb0..ac6b575c4 100644 --- a/libs/SDL3/src/dialog/unix/SDL_portaldialog.c +++ b/libs/SDL3/src/dialog/unix/SDL_portaldialog.c @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" -#include "./SDL_dialog.h" +#include "../SDL_dialog_utils.h" #include "../../core/linux/SDL_dbus.h" @@ -74,19 +74,18 @@ static void DBus_AppendBoolOption(SDL_DBusContext *dbus, DBusMessageIter *option dbus->message_iter_close_container(options, &options_pair); } -static void DBus_AppendFilter(SDL_DBusContext *dbus, DBusMessageIter *parent, const SDL_DialogFileFilter *filter) +static void DBus_AppendFilter(SDL_DBusContext *dbus, DBusMessageIter *parent, const SDL_DialogFileFilter filter) { DBusMessageIter filter_entry, filter_array, filter_array_entry; char *state = NULL, *patterns, *pattern, *glob_pattern; int zero = 0; dbus->message_iter_open_container(parent, DBUS_TYPE_STRUCT, NULL, &filter_entry); - dbus->message_iter_append_basic(&filter_entry, DBUS_TYPE_STRING, &filter->name); + dbus->message_iter_append_basic(&filter_entry, DBUS_TYPE_STRING, &filter.name); dbus->message_iter_open_container(&filter_entry, DBUS_TYPE_ARRAY, "(us)", &filter_array); - patterns = SDL_strdup(filter->pattern); + patterns = SDL_strdup(filter.pattern); if (!patterns) { - SDL_OutOfMemory(); goto cleanup; } @@ -97,9 +96,8 @@ static void DBus_AppendFilter(SDL_DBusContext *dbus, DBusMessageIter *parent, co dbus->message_iter_open_container(&filter_array, DBUS_TYPE_STRUCT, NULL, &filter_array_entry); dbus->message_iter_append_basic(&filter_array_entry, DBUS_TYPE_UINT32, &zero); - glob_pattern = SDL_calloc(sizeof(char), max_len); + glob_pattern = SDL_calloc(max_len, sizeof(char)); if (!glob_pattern) { - SDL_OutOfMemory(); goto cleanup; } glob_pattern[0] = '*'; @@ -122,7 +120,7 @@ static void DBus_AppendFilter(SDL_DBusContext *dbus, DBusMessageIter *parent, co dbus->message_iter_close_container(parent, &filter_entry); } -static void DBus_AppendFilters(SDL_DBusContext *dbus, DBusMessageIter *options, const SDL_DialogFileFilter *filters) +static void DBus_AppendFilters(SDL_DBusContext *dbus, DBusMessageIter *options, const SDL_DialogFileFilter *filters, int nfilters) { DBusMessageIter options_pair, options_value, options_value_array; static const char *filters_name = "filters"; @@ -131,8 +129,8 @@ static void DBus_AppendFilters(SDL_DBusContext *dbus, DBusMessageIter *options, dbus->message_iter_append_basic(&options_pair, DBUS_TYPE_STRING, &filters_name); dbus->message_iter_open_container(&options_pair, DBUS_TYPE_VARIANT, "a(sa(us))", &options_value); dbus->message_iter_open_container(&options_value, DBUS_TYPE_ARRAY, "(sa(us))", &options_value_array); - for (const SDL_DialogFileFilter *filter = filters; filter && filter->name && filter->pattern; ++filter) { - DBus_AppendFilter(dbus, &options_value_array, filter); + for (int i = 0; i < nfilters; i++) { + DBus_AppendFilter(dbus, &options_value_array, filters[i]); } dbus->message_iter_close_container(&options_value, &options_value_array); dbus->message_iter_close_container(&options_pair, &options_value); @@ -167,19 +165,19 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m const char **path; dbus->message_iter_init(msg, &signal_iter); - /* Check if the parameters are what we expect */ + // Check if the parameters are what we expect if (dbus->message_iter_get_arg_type(&signal_iter) != DBUS_TYPE_UINT32) goto not_our_signal; dbus->message_iter_get_basic(&signal_iter, &result); - if (result == 1) { - /* cancelled */ + if (result == 1 || result == 2) { + // cancelled const char *result_data[] = { NULL }; - signal_data->callback(signal_data->userdata, result_data, -1); /* TODO: Set this to the last selected filter */ + signal_data->callback(signal_data->userdata, result_data, -1); // TODO: Set this to the last selected filter goto handled; } else if (result) { - /* some error occurred */ + // some error occurred signal_data->callback(signal_data->userdata, NULL, -1); goto handled; } @@ -201,7 +199,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m dbus->message_iter_get_basic(&array_entry, &method); if (!SDL_strcmp(method, "uris")) { - /* we only care about the selected file paths */ + // we only care about the selected file paths break; } @@ -222,32 +220,51 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m path = SDL_malloc(sizeof(const char *) * length); if (!path) { - SDL_OutOfMemory(); signal_data->callback(signal_data->userdata, NULL, -1); goto cleanup; } while (dbus->message_iter_get_arg_type(&uri_entry) == DBUS_TYPE_STRING) { + const char *uri = NULL; + if (current >= length - 1) { ++length; path = SDL_realloc(path, sizeof(const char *) * length); if (!path) { - SDL_OutOfMemory(); signal_data->callback(signal_data->userdata, NULL, -1); goto cleanup; } } - dbus->message_iter_get_basic(&uri_entry, path + current); + + dbus->message_iter_get_basic(&uri_entry, &uri); + + // https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.FileChooser.html + // Returned paths will always start with 'file://'; SDL_URIToLocal() truncates it. + char *decoded_uri = SDL_malloc(SDL_strlen(uri) + 1); + if (SDL_URIToLocal(uri, decoded_uri)) { + path[current] = decoded_uri; + } else { + SDL_free(decoded_uri); + SDL_SetError("Portal dialogs: Unsupported protocol: %s", uri); + signal_data->callback(signal_data->userdata, NULL, -1); + goto cleanup; + } dbus->message_iter_next(&uri_entry); ++current; } path[length - 1] = NULL; - signal_data->callback(signal_data->userdata, path, -1); /* TODO: Fetch the index of the filter that was used */ + signal_data->callback(signal_data->userdata, path, -1); // TODO: Fetch the index of the filter that was used cleanup: dbus->connection_remove_filter(conn, &DBus_MessageFilter, signal_data); + if (path) { + for (size_t i = 0; i < current; ++i) { + SDL_free((char *)path[i]); + } + } + SDL_free(path); SDL_free((void *)signal_data->path); SDL_free(signal_data); @@ -258,7 +275,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } -static void DBus_OpenDialog(const char *method, const char *method_title, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many, int open_folders) +static void DBus_OpenDialog(const char *method, const char *method_title, SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many, int open_folders) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); DBusMessage *msg; @@ -270,14 +287,24 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di static char *default_parent_window = ""; SDL_PropertiesID props = SDL_GetWindowProperties(window); + const char *err_msg = validate_filters(filters, nfilters); + + if (err_msg) { + SDL_SetError("%s", err_msg); + callback(userdata, NULL, -1); + return; + } + if (dbus == NULL) { SDL_SetError("Failed to connect to DBus"); + callback(userdata, NULL, -1); return; } msg = dbus->message_new_method_call(PORTAL_DESTINATION, PORTAL_PATH, PORTAL_INTERFACE, method); if (msg == NULL) { SDL_SetError("Failed to send message to portal"); + callback(userdata, NULL, -1); return; } @@ -291,6 +318,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di len += sizeof(WAYLAND_HANDLE_PREFIX) + 1; handle_str = SDL_malloc(len * sizeof(char)); if (!handle_str) { + callback(userdata, NULL, -1); return; } @@ -298,13 +326,14 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di } else { const Uint64 xid = (Uint64)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); if (xid) { - const size_t len = sizeof(X11_HANDLE_PREFIX) + 24; /* A 64-bit number can be 20 characters max. */ + const size_t len = sizeof(X11_HANDLE_PREFIX) + 24; // A 64-bit number can be 20 characters max. handle_str = SDL_malloc(len * sizeof(char)); if (!handle_str) { + callback(userdata, NULL, -1); return; } - /* The portal wants X11 window ID numbers in hex. */ + // The portal wants X11 window ID numbers in hex. SDL_snprintf(handle_str, len, "%s%" SDL_PRIx64, X11_HANDLE_PREFIX, xid); } } @@ -320,6 +349,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di handle_str = SDL_malloc(sizeof(char) * (HANDLE_LEN + 1)); if (!handle_str) { + callback(userdata, NULL, -1); return; } SDL_snprintf(handle_str, HANDLE_LEN, "%u", ++handle_id); @@ -327,14 +357,14 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di SDL_free(handle_str); DBus_AppendBoolOption(dbus, &options, "modal", !!window); - if (allow_many == SDL_TRUE) { + if (allow_many == true) { DBus_AppendBoolOption(dbus, &options, "multiple", 1); } if (open_folders) { DBus_AppendBoolOption(dbus, &options, "directory", 1); } if (filters) { - DBus_AppendFilters(dbus, &options, filters); + DBus_AppendFilters(dbus, &options, filters, nfilters); } if (default_location) { DBus_AppendByteArray(dbus, &options, "current_folder", default_location); @@ -353,6 +383,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di if (!signal_id) { SDL_SetError("Invalid response received by DBus"); + callback(userdata, NULL, -1); goto incorrect_type; } @@ -361,6 +392,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di filter_len = SDL_strlen(SIGNAL_FILTER) + SDL_strlen(signal_id) + 2; filter = SDL_malloc(sizeof(char) * filter_len); if (!filter) { + callback(userdata, NULL, -1); goto incorrect_type; } @@ -370,6 +402,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di SignalCallback *data = SDL_malloc(sizeof(SignalCallback)); if (!data) { + callback(userdata, NULL, -1); goto incorrect_type; } data->callback = callback; @@ -377,6 +410,7 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di data->path = SDL_strdup(signal_id); if (!data->path) { SDL_free(data); + callback(userdata, NULL, -1); goto incorrect_type; } @@ -391,22 +425,22 @@ static void DBus_OpenDialog(const char *method, const char *method_title, SDL_Di dbus->message_unref(reply); } -void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { - DBus_OpenDialog("OpenFile", "Open File", callback, userdata, window, filters, default_location, allow_many, 0); + DBus_OpenDialog("OpenFile", "Open File", callback, userdata, window, filters, nfilters, default_location, allow_many, 0); } -void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { - DBus_OpenDialog("SaveFile", "Save File", callback, userdata, window, filters, default_location, 0, 0); + DBus_OpenDialog("SaveFile", "Save File", callback, userdata, window, filters, nfilters, default_location, 0, 0); } -void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { - DBus_OpenDialog("OpenFile", "Open Folder", callback, userdata, window, NULL, default_location, allow_many, 1); + DBus_OpenDialog("OpenFile", "Open Folder", callback, userdata, window, NULL, 0, default_location, allow_many, 1); } -int SDL_Portal_detect(void) +bool SDL_Portal_detect(void) { SDL_DBusContext *dbus = SDL_DBus_GetContext(); DBusMessage *msg = NULL, *reply = NULL; @@ -414,19 +448,19 @@ int SDL_Portal_detect(void) DBusMessageIter reply_iter; static int portal_present = -1; - /* No need for this if the result is cached. */ + // No need for this if the result is cached. if (portal_present != -1) { - return portal_present; + return (portal_present > 0); } portal_present = 0; if (!dbus) { SDL_SetError("%s", "Failed to connect to DBus!"); - return 0; + return false; } - /* Use introspection to get the available services. */ + // Use introspection to get the available services. msg = dbus->message_new_method_call(PORTAL_DESTINATION, PORTAL_PATH, "org.freedesktop.DBus.Introspectable", "Introspect"); if (!msg) { goto done; @@ -451,7 +485,7 @@ int SDL_Portal_detect(void) */ dbus->message_iter_get_basic(&reply_iter, &reply_str); if (SDL_strstr(reply_str, PORTAL_INTERFACE)) { - portal_present = 1; /* Found it! */ + portal_present = 1; // Found it! } done: @@ -459,34 +493,34 @@ int SDL_Portal_detect(void) dbus->message_unref(reply); } - return portal_present; + return (portal_present > 0); } #else -/* Dummy implementation to avoid compilation problems */ +// Dummy implementation to avoid compilation problems -void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { SDL_Unsupported(); callback(userdata, NULL, -1); } -void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { SDL_Unsupported(); callback(userdata, NULL, -1); } -void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { SDL_Unsupported(); callback(userdata, NULL, -1); } -int SDL_Portal_detect(void) +bool SDL_Portal_detect(void) { - return 0; + return false; } -#endif /* SDL_USE_LIBDBUS */ +#endif // SDL_USE_LIBDBUS diff --git a/libs/SDL3/src/dialog/unix/SDL_portaldialog.h b/libs/SDL3/src/dialog/unix/SDL_portaldialog.h index 71ed3cbed..495933cf6 100644 --- a/libs/SDL3/src/dialog/unix/SDL_portaldialog.h +++ b/libs/SDL3/src/dialog/unix/SDL_portaldialog.h @@ -21,9 +21,9 @@ #include "SDL_internal.h" -void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many); -void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location); -void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many); +void SDL_Portal_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many); +void SDL_Portal_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location); +void SDL_Portal_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many); /** @returns non-zero if available, zero if unavailable */ -int SDL_Portal_detect(void); +bool SDL_Portal_detect(void); diff --git a/libs/SDL3/src/dialog/unix/SDL_unixdialog.c b/libs/SDL3/src/dialog/unix/SDL_unixdialog.c index 29ce2eef0..5e81b70cd 100644 --- a/libs/SDL3/src/dialog/unix/SDL_unixdialog.c +++ b/libs/SDL3/src/dialog/unix/SDL_unixdialog.c @@ -23,60 +23,85 @@ #include "./SDL_portaldialog.h" #include "./SDL_zenitydialog.h" -static void (*detected_open)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) = NULL; -static void (*detected_save)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) = NULL; -static void (*detected_folder)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) = NULL; +static void (*detected_open)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) = NULL; +static void (*detected_save)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) = NULL; +static void (*detected_folder)(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) = NULL; -/* Returns non-zero on success, 0 on failure */ -static int detect_available_methods(void) +static int detect_available_methods(const char *value); + +void SDLCALL hint_callback(void *userdata, const char *name, const char *oldValue, const char *newValue) +{ + detect_available_methods(newValue); +} + +static void set_callback(void) { - if (SDL_Portal_detect()) { - detected_open = SDL_Portal_ShowOpenFileDialog; - detected_save = SDL_Portal_ShowSaveFileDialog; - detected_folder = SDL_Portal_ShowOpenFolderDialog; - return 1; + static bool is_set = false; + + if (is_set == false) { + is_set = true; + SDL_AddHintCallback(SDL_HINT_FILE_DIALOG_DRIVER, hint_callback, NULL); + } +} + +// Returns non-zero on success, 0 on failure +static int detect_available_methods(const char *value) +{ + const char *driver = value ? value : SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER); + + set_callback(); + + if (driver == NULL || SDL_strcmp(driver, "portal") == 0) { + if (SDL_Portal_detect()) { + detected_open = SDL_Portal_ShowOpenFileDialog; + detected_save = SDL_Portal_ShowSaveFileDialog; + detected_folder = SDL_Portal_ShowOpenFolderDialog; + return 1; + } } - if (SDL_Zenity_detect()) { - detected_open = SDL_Zenity_ShowOpenFileDialog; - detected_save = SDL_Zenity_ShowSaveFileDialog; - detected_folder = SDL_Zenity_ShowOpenFolderDialog; - return 2; + if (driver == NULL || SDL_strcmp(driver, "zenity") == 0) { + if (SDL_Zenity_detect()) { + detected_open = SDL_Zenity_ShowOpenFileDialog; + detected_save = SDL_Zenity_ShowSaveFileDialog; + detected_folder = SDL_Zenity_ShowOpenFolderDialog; + return 2; + } } - SDL_SetError("No supported method for file dialogs"); + SDL_SetError("File dialog driver unsupported"); return 0; } -void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { - /* Call detect_available_methods() again each time in case the situation changed */ - if (!detected_open && !detect_available_methods()) { - /* SetError() done by detect_available_methods() */ + // Call detect_available_methods() again each time in case the situation changed + if (!detected_open && !detect_available_methods(NULL)) { + // SetError() done by detect_available_methods() callback(userdata, NULL, -1); return; } - detected_open(callback, userdata, window, filters, default_location, allow_many); + detected_open(callback, userdata, window, filters, nfilters, default_location, allow_many); } -void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { - /* Call detect_available_methods() again each time in case the situation changed */ - if (!detected_save && !detect_available_methods()) { - /* SetError() done by detect_available_methods() */ + // Call detect_available_methods() again each time in case the situation changed + if (!detected_save && !detect_available_methods(NULL)) { + // SetError() done by detect_available_methods() callback(userdata, NULL, -1); return; } - detected_save(callback, userdata, window, filters, default_location); + detected_save(callback, userdata, window, filters, nfilters, default_location); } -void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { - /* Call detect_available_methods() again each time in case the situation changed */ - if (!detected_folder && !detect_available_methods()) { - /* SetError() done by detect_available_methods() */ + // Call detect_available_methods() again each time in case the situation changed + if (!detected_folder && !detect_available_methods(NULL)) { + // SetError() done by detect_available_methods() callback(userdata, NULL, -1); return; } diff --git a/libs/SDL3/src/dialog/unix/SDL_zenitydialog.c b/libs/SDL3/src/dialog/unix/SDL_zenitydialog.c index 5ba8e8dc7..bca4ed1c6 100644 --- a/libs/SDL3/src/dialog/unix/SDL_zenitydialog.c +++ b/libs/SDL3/src/dialog/unix/SDL_zenitydialog.c @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" -#include "./SDL_dialog.h" +#include "../SDL_dialog_utils.h" #include #include @@ -39,6 +39,7 @@ typedef struct void* userdata; const char* filename; const SDL_DialogFileFilter *filters; + int nfilters; Uint32 flags; } zenityArgs; @@ -54,7 +55,6 @@ typedef struct #define CHECK_OOM() \ { \ if (!argv[nextarg - 1]) { \ - SDL_OutOfMemory(); \ CLEAR_AND_RETURN() \ } \ \ @@ -65,6 +65,22 @@ typedef struct } \ } +char *zenity_clean_name(const char *name) +{ + char *newname = SDL_strdup(name); + + /* Filter out "|", which Zenity considers a special character. Let's hope + there aren't others. TODO: find something better. */ + for (char *c = newname; *c; c++) { + if (*c == '|') { + // Zenity doesn't support escaping with '\' + *c = '/'; + } + } + + return newname; +} + /* Exec call format: * * /usr/bin/env zenity --file-selection --separator=\n [--multiple] @@ -77,7 +93,7 @@ static char** generate_args(const zenityArgs* info) int nextarg = 0; char **argv = NULL; - /* ARGC PASS */ + // ARGC PASS if (info->flags & ZENITY_MULTIPLE) { argc++; } @@ -95,18 +111,11 @@ static char** generate_args(const zenityArgs* info) } if (info->filters) { - const SDL_DialogFileFilter *filter_ptr = info->filters; - - while (filter_ptr->name && filter_ptr->pattern) { - argc++; - filter_ptr++; - } + argc += info->nfilters; } argv = SDL_malloc(sizeof(char *) * argc + 1); - if (!argv) { - SDL_OutOfMemory(); return NULL; } @@ -119,7 +128,7 @@ static char** generate_args(const zenityArgs* info) argv[nextarg++] = SDL_strdup("--separator=\n"); CHECK_OOM() - /* ARGV PASS */ + // ARGV PASS if (info->flags & ZENITY_MULTIPLE) { argv[nextarg++] = SDL_strdup("--multiple"); CHECK_OOM() @@ -144,74 +153,18 @@ static char** generate_args(const zenityArgs* info) } if (info->filters) { - const SDL_DialogFileFilter *filter_ptr = info->filters; - - while (filter_ptr->name && filter_ptr->pattern) { - /* *Normally*, no filter arg should exceed 4096 bytes. */ - char buffer[4096]; - - SDL_snprintf(buffer, 4096, "--file-filter=%s | *.", filter_ptr->name); - size_t i_buf = SDL_strlen(buffer); - - /* "|" is a special character for Zenity */ - for (char *c = buffer; *c; c++) { - if (*c == '|') { - *c = ' '; - } - } + for (int i = 0; i < info->nfilters; i++) { + char *filter_str = convert_filter(info->filters[i], + zenity_clean_name, + "--file-filter=", " | ", "", + "*.", " *.", ""); - for (size_t i_pat = 0; i_buf < 4095 && filter_ptr->pattern[i_pat]; i_pat++) { - const char *c = filter_ptr->pattern + i_pat; - - if (*c == ';') { - /* Disallow empty patterns (might bug Zenity) */ - int at_end = (c[1] == '\0'); - int at_mid = (c[1] == ';'); - int at_beg = (i_pat == 0); - if (at_end || at_mid || at_beg) { - const char *pos_str = ""; - - if (at_end) { - pos_str = "end"; - } else if (at_mid) { - pos_str = "middle"; - } else if (at_beg) { - pos_str = "beginning"; - } - - SDL_SetError("Empty pattern file extension (at %s of list)", pos_str); - CLEAR_AND_RETURN() - } - - if (i_buf + 3 >= 4095) { - i_buf += 3; - break; - } - - buffer[i_buf++] = ' '; - buffer[i_buf++] = '*'; - buffer[i_buf++] = '.'; - } else if (*c == '*' && (c[1] == '\0' || c[1] == ';') && (i_pat == 0 || *(c - 1) == ';')) { - buffer[i_buf++] = '*'; - } else if (!((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9') || *c == '.' || *c == '_' || *c == '-')) { - SDL_SetError("Illegal character in pattern name: %c (Only alphanumeric characters, periods, underscores and hyphens allowed)", *c); - CLEAR_AND_RETURN() - } else { - buffer[i_buf++] = *c; - } - } - - if (i_buf >= 4095) { - SDL_SetError("Filter '%s' wouldn't fit in a 4096 byte buffer; please report your use case if you need filters that long", filter_ptr->name); + if (!filter_str) { CLEAR_AND_RETURN() } - buffer[i_buf] = '\0'; - - argv[nextarg++] = SDL_strdup(buffer); + argv[nextarg++] = filter_str; CHECK_OOM() - - filter_ptr++; } } @@ -232,137 +185,101 @@ void free_args(char **argv) SDL_free(argv); } -/* TODO: Zenity survives termination of the parent */ +// TODO: Zenity survives termination of the parent static void run_zenity(zenityArgs* arg_struct) { SDL_DialogFileCallback callback = arg_struct->callback; void* userdata = arg_struct->userdata; - - int out[2]; - pid_t process; + SDL_Process *process = NULL; + char **args = NULL; + SDL_Environment *env = NULL; int status = -1; + size_t bytes_read = 0; + char *container = NULL; + size_t narray = 1; + char **array = NULL; + bool result = false; - if (pipe(out) < 0) { - SDL_SetError("Could not create pipe: %s", strerror(errno)); - callback(userdata, NULL, -1); - return; + args = generate_args(arg_struct); + if (!args) { + goto done; } - /* Args are only needed in the forked process, but generating them early - allows catching the error messages in the main process */ - char **args = generate_args(arg_struct); + env = SDL_CreateEnvironment(true); + if (!env) { + goto done; + } - if (!args) { - /* SDL_SetError will have been called already */ - callback(userdata, NULL, -1); - return; + /* Recent versions of Zenity have different exit codes, but picks up + different codes from the environment */ + SDL_SetEnvironmentVariable(env, "ZENITY_OK", "0", true); + SDL_SetEnvironmentVariable(env, "ZENITY_CANCEL", "1", true); + SDL_SetEnvironmentVariable(env, "ZENITY_ESC", "1", true); + SDL_SetEnvironmentVariable(env, "ZENITY_EXTRA", "2", true); + SDL_SetEnvironmentVariable(env, "ZENITY_ERROR", "2", true); + SDL_SetEnvironmentVariable(env, "ZENITY_TIMEOUT", "2", true); + + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, args); + SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, env); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_NULL); + process = SDL_CreateProcessWithProperties(props); + SDL_DestroyProperties(props); + if (!process) { + goto done; } - process = fork(); + container = SDL_ReadProcess(process, &bytes_read, &status); + if (!container) { + goto done; + } - if (process < 0) { - SDL_SetError("Could not fork process: %s", strerror(errno)); - close(out[0]); - close(out[1]); - free_args(args); - callback(userdata, NULL, -1); - return; - } else if (process == 0){ - dup2(out[1], STDOUT_FILENO); - close(STDERR_FILENO); /* Hide errors from Zenity to stderr */ - close(out[0]); - close(out[1]); - - /* Recent versions of Zenity have different exit codes, but picks up - different codes from the environment */ - SDL_setenv("ZENITY_OK", "0", 1); - SDL_setenv("ZENITY_CANCEL", "1", 1); - SDL_setenv("ZENITY_ESC", "1", 1); - SDL_setenv("ZENITY_EXTRA", "2", 1); - SDL_setenv("ZENITY_ERROR", "2", 1); - SDL_setenv("ZENITY_TIMEOUT", "2", 1); - - execv(args[0], args); - - exit(errno + 128); - } else { - char readbuffer[2048]; - size_t bytes_read = 0, bytes_last_read; - char *container = NULL; - close(out[1]); - free_args(args); - - while ((bytes_last_read = read(out[0], readbuffer, sizeof(readbuffer)))) { - char *new_container = SDL_realloc(container, bytes_read + bytes_last_read); - if (!new_container) { - SDL_OutOfMemory(); - SDL_free(container); - close(out[0]); - callback(userdata, NULL, -1); - return; + array = (char **)SDL_malloc((narray + 1) * sizeof(char *)); + if (!array) { + goto done; + } + array[0] = container; + array[1] = NULL; + + for (int i = 0; i < bytes_read; i++) { + if (container[i] == '\n') { + container[i] = '\0'; + // Reading from a process often leaves a trailing \n, so ignore the last one + if (i < bytes_read - 1) { + array[narray] = container + i + 1; + narray++; + char **new_array = (char **) SDL_realloc(array, (narray + 1) * sizeof(char *)); + if (!new_array) { + goto done; + } + array = new_array; + array[narray] = NULL; } - container = new_container; - SDL_memcpy(container + bytes_read, readbuffer, bytes_last_read); - bytes_read += bytes_last_read; } - close(out[0]); - - if (waitpid(process, &status, 0) == -1) { - SDL_SetError("waitpid failed"); - SDL_free(container); - callback(userdata, NULL, -1); - return; - } - - if (WIFEXITED(status)) { - status = WEXITSTATUS(status); - } - - size_t narray = 1; - char **array = (char **) SDL_malloc((narray + 1) * sizeof(char *)); + } - if (!array) { - SDL_OutOfMemory(); - SDL_free(container); - callback(userdata, NULL, -1); - return; - } + // 0 = the user chose one or more files, 1 = the user canceled the dialog + if (status == 0 || status == 1) { + callback(userdata, (const char * const*)array, -1); + } else { + SDL_SetError("Could not run zenity: exit code %d", status); + callback(userdata, NULL, -1); + } - array[0] = container; - array[1] = NULL; - - for (int i = 0; i < bytes_read; i++) { - if (container[i] == '\n') { - container[i] = '\0'; - /* Reading from a process often leaves a trailing \n, so ignore the last one */ - if (i < bytes_read - 1) { - array[narray] = container + i + 1; - narray++; - char **new_array = (char **) SDL_realloc(array, (narray + 1) * sizeof(char *)); - if (!new_array) { - SDL_OutOfMemory(); - SDL_free(container); - SDL_free(array); - callback(userdata, NULL, -1); - return; - } - array = new_array; - array[narray] = NULL; - } - } - } + result = true; - /* 0 = the user chose one or more files, 1 = the user canceled the dialog */ - if (status == 0 || status == 1) { - callback(userdata, (const char * const*) array, -1); - } else { - SDL_SetError("Could not run zenity: exit code %d (may be zenity or execv+128)", status); - callback(userdata, NULL, -1); - } +done: + SDL_free(array); + SDL_free(container); + free_args(args); + SDL_DestroyEnvironment(env); + SDL_DestroyProcess(process); - SDL_free(array); - SDL_free(container); + if (!result) { + callback(userdata, NULL, -1); } } @@ -373,14 +290,13 @@ static int run_zenity_thread(void* ptr) return 0; } -void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { zenityArgs *args; SDL_Thread *thread; args = SDL_malloc(sizeof(*args)); if (!args) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } @@ -389,7 +305,8 @@ void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userda args->userdata = userdata; args->filename = default_location; args->filters = filters; - args->flags = (allow_many == SDL_TRUE) ? ZENITY_MULTIPLE : 0; + args->nfilters = nfilters; + args->flags = (allow_many == true) ? ZENITY_MULTIPLE : 0; thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowOpenFileDialog", (void *) args); @@ -401,14 +318,13 @@ void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userda SDL_DetachThread(thread); } -void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { zenityArgs *args; SDL_Thread *thread; args = SDL_malloc(sizeof(zenityArgs)); if (args == NULL) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } @@ -417,6 +333,7 @@ void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userda args->userdata = userdata; args->filename = default_location; args->filters = filters; + args->nfilters = nfilters; args->flags = ZENITY_SAVE; thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowSaveFileDialog", (void *) args); @@ -429,14 +346,13 @@ void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userda SDL_DetachThread(thread); } -void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { zenityArgs *args; SDL_Thread *thread; args = SDL_malloc(sizeof(zenityArgs)); if (args == NULL) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } @@ -445,7 +361,8 @@ void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* user args->userdata = userdata; args->filename = default_location; args->filters = NULL; - args->flags = ((allow_many == SDL_TRUE) ? ZENITY_MULTIPLE : 0) | ZENITY_DIRECTORY; + args->nfilters = 0; + args->flags = ((allow_many == true) ? ZENITY_MULTIPLE : 0) | ZENITY_DIRECTORY; thread = SDL_CreateThread(run_zenity_thread, "SDL_ShowOpenFolderDialog", (void *) args); @@ -457,32 +374,23 @@ void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* user SDL_DetachThread(thread); } -int SDL_Zenity_detect(void) +bool SDL_Zenity_detect(void) { - pid_t process; + const char *args[] = { + "/usr/bin/env", "zenity", "--version", NULL + }; int status = -1; - process = fork(); - - if (process < 0) { - SDL_SetError("Could not fork process: %s", strerror(errno)); - return 0; - } else if (process == 0){ - /* Disable output */ - close(STDERR_FILENO); - close(STDOUT_FILENO); - execl("/usr/bin/env", "/usr/bin/env", "zenity", "--version", NULL); - exit(errno + 128); - } else { - if (waitpid(process, &status, 0) == -1) { - SDL_SetError("waitpid failed"); - return 0; - } - - if (WIFEXITED(status)) { - status = WEXITSTATUS(status); - } - - return !status; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, args); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_NULL); + SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_NULL); + SDL_Process *process = SDL_CreateProcessWithProperties(props); + SDL_DestroyProperties(props); + if (process) { + SDL_WaitProcess(process, true, &status); + SDL_DestroyProcess(process); } + return (status == 0); } diff --git a/libs/SDL3/src/dialog/unix/SDL_zenitydialog.h b/libs/SDL3/src/dialog/unix/SDL_zenitydialog.h index 9d7203b67..b17f79f38 100644 --- a/libs/SDL3/src/dialog/unix/SDL_zenitydialog.h +++ b/libs/SDL3/src/dialog/unix/SDL_zenitydialog.h @@ -21,9 +21,9 @@ #include "SDL_internal.h" -void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many); -void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location); -void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many); +extern void SDL_Zenity_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many); +extern void SDL_Zenity_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location); +extern void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many); /** @returns non-zero if available, zero if unavailable */ -int SDL_Zenity_detect(void); +extern bool SDL_Zenity_detect(void); diff --git a/libs/SDL3/src/dialog/windows/SDL_windowsdialog.c b/libs/SDL3/src/dialog/windows/SDL_windowsdialog.c index 61fde649b..9bb6d9918 100644 --- a/libs/SDL3/src/dialog/windows/SDL_windowsdialog.c +++ b/libs/SDL3/src/dialog/windows/SDL_windowsdialog.c @@ -19,18 +19,23 @@ 3. This notice may not be removed or altered from any source distribution. */ #include "SDL_internal.h" +#include "../SDL_dialog_utils.h" #include +#include #include #include "../../core/windows/SDL_windows.h" #include "../../thread/SDL_systhread.h" +// If this number is too small, selecting too many files will give an error +#define SELECTLIST_SIZE 65536 + typedef struct { int is_save; const SDL_DialogFileFilter *filters; + int nfilters; const char* default_file; - const char* default_folder; SDL_Window* parent; DWORD flags; SDL_DialogFileCallback callback; @@ -46,28 +51,19 @@ typedef struct } winFArgs; /** Converts dialog.nFilterIndex to SDL-compatible value */ -int getFilterIndex(int as_reported_by_windows, const SDL_DialogFileFilter *filters) +int getFilterIndex(int as_reported_by_windows) { - int filter_index = as_reported_by_windows - 1; - - if (filter_index < 0) { - filter_index = 0; - for (const SDL_DialogFileFilter *filter = filters; filter && filter->name && filter->pattern; filter++) { - filter_index++; - } - } - - return filter_index; + return as_reported_by_windows - 1; } -/* TODO: The new version of file dialogs */ +// TODO: The new version of file dialogs void windows_ShowFileDialog(void *ptr) { winArgs *args = (winArgs *) ptr; int is_save = args->is_save; const SDL_DialogFileFilter *filters = args->filters; + int nfilters = args->nfilters; const char* default_file = args->default_file; - const char* default_folder = args->default_folder; SDL_Window* parent = args->parent; DWORD flags = args->flags; SDL_DialogFileCallback callback = args->callback; @@ -105,85 +101,101 @@ void windows_ShowFileDialog(void *ptr) HWND window = NULL; if (parent) { - window = (HWND) SDL_GetProperty(SDL_GetWindowProperties(parent), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); + window = (HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(parent), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); } - wchar_t filebuffer[MAX_PATH] = L""; - wchar_t initfolder[MAX_PATH] = L""; + wchar_t *filebuffer; // lpstrFile + wchar_t initfolder[MAX_PATH] = L""; // lpstrInitialDir + + /* If SELECTLIST_SIZE is too large, putting filebuffer on the stack might + cause an overflow */ + filebuffer = (wchar_t *) SDL_malloc(SELECTLIST_SIZE * sizeof(wchar_t)); - /* Necessary for the return code below */ - SDL_memset(filebuffer, 0, MAX_PATH * sizeof(wchar_t)); + // Necessary for the return code below + SDL_memset(filebuffer, 0, SELECTLIST_SIZE * sizeof(wchar_t)); if (default_file) { - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_file, -1, filebuffer, MAX_PATH); - } + /* On Windows 10, 11 and possibly others, lpstrFile can be initialized + with a path and the dialog will start at that location, but *only if + the path contains a filename*. If it ends with a folder (directory + separator), it fails with 0x3002 (12290) FNERR_INVALIDFILENAME. For + that specific case, lpstrInitialDir must be used instead, but just + for that case, because lpstrInitialDir doesn't support file names. - if (default_folder) { - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_folder, -1, filebuffer, MAX_PATH); - } + On top of that, lpstrInitialDir hides a special algorithm that + decides which folder to actually use as starting point, which may or + may not be the one provided, or some other unrelated folder. Also, + the algorithm changes between platforms. Assuming the documentation + is correct, the algorithm is there under 'lpstrInitialDir': - size_t len = 0; - for (const SDL_DialogFileFilter *filter = filters; filter && filter->name && filter->pattern; filter++) { - const char *pattern_ptr = filter->pattern; - len += SDL_strlen(filter->name) + SDL_strlen(filter->pattern) + 4; - while (*pattern_ptr) { - if (*pattern_ptr == ';') { - len += 2; + https://learn.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamew + + Finally, lpstrFile does not support forward slashes. lpstrInitialDir + does, though. */ + + char last_c = default_file[SDL_strlen(default_file) - 1]; + + if (last_c == '\\' || last_c == '/') { + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_file, -1, initfolder, MAX_PATH); + } else { + MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, default_file, -1, filebuffer, MAX_PATH); + + for (int i = 0; i < SELECTLIST_SIZE; i++) { + if (filebuffer[i] == L'/') { + filebuffer[i] = L'\\'; + } } - pattern_ptr++; } } - wchar_t *filterlist = SDL_malloc((len + 1) * sizeof(wchar_t)); - if (!filterlist) { - SDL_OutOfMemory(); - callback(userdata, NULL, -1); - return; - } + wchar_t *filter_wchar = NULL; - wchar_t *filter_ptr = filterlist; - for (const SDL_DialogFileFilter *filter = filters; filter && filter->name && filter->pattern; filter++) { - size_t l = SDL_strlen(filter->name); - const char *pattern_ptr = filter->pattern; - - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filter->name, -1, filter_ptr, MAX_PATH); - filter_ptr += l + 1; - - *filter_ptr++ = L'*'; - *filter_ptr++ = L'.'; - while (*pattern_ptr) { - if (*pattern_ptr == ';') { - *filter_ptr++ = L';'; - *filter_ptr++ = L'*'; - *filter_ptr++ = L'.'; - } else if (*pattern_ptr == '*' && (pattern_ptr[1] == '\0' || pattern_ptr[1] == ';')) { - *filter_ptr++ = L'*'; - } else if (!((*pattern_ptr >= 'a' && *pattern_ptr <= 'z') || (*pattern_ptr >= 'A' && *pattern_ptr <= 'Z') || (*pattern_ptr >= '0' && *pattern_ptr <= '9') || *pattern_ptr == '.' || *pattern_ptr == '_' || *pattern_ptr == '-')) { - SDL_SetError("Illegal character in pattern name: %c (Only alphanumeric characters, periods, underscores and hyphens allowed)", *pattern_ptr); - callback(userdata, NULL, -1); - } else { - MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pattern_ptr, 1, filter_ptr, 1); - filter_ptr++; + if (filters) { + // '\x01' is used in place of a null byte + // suffix needs two null bytes in case the filter list is empty + char *filterlist = convert_filters(filters, nfilters, NULL, "", "", + "\x01\x01", "", "\x01", "\x01", + "*.", ";*.", ""); + + if (!filterlist) { + callback(userdata, NULL, -1); + SDL_free(filebuffer); + return; + } + + int filter_len = (int)SDL_strlen(filterlist); + + for (char *c = filterlist; *c; c++) { + if (*c == '\x01') { + *c = '\0'; } - pattern_ptr++; } - *filter_ptr++ = '\0'; - } - *filter_ptr = '\0'; + int filter_wlen = MultiByteToWideChar(CP_UTF8, 0, filterlist, filter_len, NULL, 0); + filter_wchar = (wchar_t *)SDL_malloc(filter_wlen * sizeof(wchar_t)); + if (!filter_wchar) { + SDL_free(filterlist); + callback(userdata, NULL, -1); + SDL_free(filebuffer); + return; + } + + MultiByteToWideChar(CP_UTF8, 0, filterlist, filter_len, filter_wchar, filter_wlen); + + SDL_free(filterlist); + } OPENFILENAMEW dialog; dialog.lStructSize = sizeof(OPENFILENAME); dialog.hwndOwner = window; dialog.hInstance = 0; - dialog.lpstrFilter = filterlist; + dialog.lpstrFilter = filter_wchar; dialog.lpstrCustomFilter = NULL; dialog.nMaxCustFilter = 0; dialog.nFilterIndex = 0; dialog.lpstrFile = filebuffer; - dialog.nMaxFile = MAX_PATH; - dialog.lpstrFileTitle = *filebuffer ? filebuffer : NULL; - dialog.nMaxFileTitle = MAX_PATH; + dialog.nMaxFile = SELECTLIST_SIZE; + dialog.lpstrFileTitle = NULL; dialog.lpstrInitialDir = *initfolder ? initfolder : NULL; dialog.lpstrTitle = NULL; dialog.Flags = flags | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; @@ -193,19 +205,19 @@ void windows_ShowFileDialog(void *ptr) dialog.lCustData = 0; dialog.lpfnHook = NULL; dialog.lpTemplateName = NULL; - /* Skipped many mac-exclusive and reserved members */ + // Skipped many mac-exclusive and reserved members dialog.FlagsEx = 0; BOOL result = pGetAnyFileName(&dialog); - SDL_free(filterlist); + SDL_free(filter_wchar); if (result) { if (!(flags & OFN_ALLOWMULTISELECT)) { - /* File is a C string stored in dialog.lpstrFile */ + // File is a C string stored in dialog.lpstrFile char *chosen_file = WIN_StringToUTF8W(dialog.lpstrFile); const char* opts[2] = { chosen_file, NULL }; - callback(userdata, opts, getFilterIndex(dialog.nFilterIndex, filters)); + callback(userdata, opts, getFilterIndex(dialog.nFilterIndex)); SDL_free(chosen_file); } else { /* File is either a C string if the user chose a single file, else @@ -223,8 +235,8 @@ void windows_ShowFileDialog(void *ptr) char **chosen_files_list = (char **) SDL_malloc(sizeof(char *) * (nfiles + 1)); if (!chosen_files_list) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); + SDL_free(filebuffer); return; } @@ -234,6 +246,7 @@ void windows_ShowFileDialog(void *ptr) SDL_SetError("Path too long or invalid character in path"); SDL_free(chosen_files_list); callback(userdata, NULL, -1); + SDL_free(filebuffer); return; } @@ -248,14 +261,13 @@ void windows_ShowFileDialog(void *ptr) char **new_cfl = (char **) SDL_realloc(chosen_files_list, sizeof(char*) * (nfiles + 1)); if (!new_cfl) { - SDL_OutOfMemory(); - for (size_t i = 0; i < nfiles - 1; i++) { SDL_free(chosen_files_list[i]); } SDL_free(chosen_files_list); callback(userdata, NULL, -1); + SDL_free(filebuffer); return; } @@ -273,6 +285,7 @@ void windows_ShowFileDialog(void *ptr) SDL_free(chosen_files_list); callback(userdata, NULL, -1); + SDL_free(filebuffer); return; } @@ -281,19 +294,42 @@ void windows_ShowFileDialog(void *ptr) chosen_files_list[nfiles - 1] = SDL_strdup(chosen_file); if (!chosen_files_list[nfiles - 1]) { - SDL_OutOfMemory(); - for (size_t i = 0; i < nfiles - 1; i++) { SDL_free(chosen_files_list[i]); } SDL_free(chosen_files_list); callback(userdata, NULL, -1); + SDL_free(filebuffer); return; } } - callback(userdata, (const char * const*) chosen_files_list, getFilterIndex(dialog.nFilterIndex, filters)); + // If the user chose only one file, it's all just one string + if (nfiles == 0) { + nfiles++; + char **new_cfl = (char **) SDL_realloc(chosen_files_list, sizeof(char*) * (nfiles + 1)); + + if (!new_cfl) { + SDL_free(chosen_files_list); + callback(userdata, NULL, -1); + SDL_free(filebuffer); + return; + } + + chosen_files_list = new_cfl; + chosen_files_list[nfiles] = NULL; + chosen_files_list[nfiles - 1] = SDL_strdup(chosen_folder); + + if (!chosen_files_list[nfiles - 1]) { + SDL_free(chosen_files_list); + callback(userdata, NULL, -1); + SDL_free(filebuffer); + return; + } + } + + callback(userdata, (const char * const*) chosen_files_list, getFilterIndex(dialog.nFilterIndex)); for (size_t i = 0; i < nfiles; i++) { SDL_free(chosen_files_list[i]); @@ -303,19 +339,21 @@ void windows_ShowFileDialog(void *ptr) } } else { DWORD error = pCommDlgExtendedError(); - /* Error code 0 means the user clicked the cancel button. */ + // Error code 0 means the user clicked the cancel button. if (error == 0) { /* Unlike SDL's handling of errors, Windows does reset the error code to 0 after calling GetOpenFileName if another Windows function before set a different error code, so it's safe to check for success. */ const char* opts[1] = { NULL }; - callback(userdata, opts, getFilterIndex(dialog.nFilterIndex, filters)); + callback(userdata, opts, getFilterIndex(dialog.nFilterIndex)); } else { SDL_SetError("Windows error, CommDlgExtendedError: %ld", pCommDlgExtendedError()); callback(userdata, NULL, -1); } } + + SDL_free(filebuffer); } int windows_file_dialog_thread(void* ptr) @@ -325,29 +363,22 @@ int windows_file_dialog_thread(void* ptr) return 0; } -int CALLBACK browse_callback_proc( - HWND hwnd, - UINT uMsg, - LPARAM lParam, - LPARAM lpData) +int CALLBACK browse_callback_proc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { - - switch (uMsg) - { - case BFFM_INITIALIZED : - if(lpData) - { - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); + switch (uMsg) { + case BFFM_INITIALIZED: + if (lpData) { + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData); } - break; - case BFFM_SELCHANGED : - break; - case BFFM_VALIDATEFAILED : - break; - default: - break; - } - return 0; + break; + case BFFM_SELCHANGED: + break; + case BFFM_VALIDATEFAILED: + break; + default: + break; + } + return 0; } void windows_ShowFolderDialog(void* ptr) @@ -356,11 +387,10 @@ void windows_ShowFolderDialog(void* ptr) SDL_Window *window = args->parent; SDL_DialogFileCallback callback = args->callback; void *userdata = args->userdata; - HWND parent = NULL; if (window) { - parent = (HWND) SDL_GetProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); + parent = (HWND) SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); } wchar_t buffer[MAX_PATH]; @@ -368,7 +398,7 @@ void windows_ShowFolderDialog(void* ptr) BROWSEINFOW dialog; dialog.hwndOwner = parent; dialog.pidlRoot = NULL; - /* Windows docs say this is `LPTSTR` - apparently it's actually `LPWSTR`*/ + // Windows docs say this is `LPTSTR` - apparently it's actually `LPWSTR` dialog.pszDisplayName = buffer; dialog.lpszTitle = NULL; dialog.ulFlags = BIF_USENEWUI; @@ -396,76 +426,94 @@ int windows_folder_dialog_thread(void* ptr) return 0; } -void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location, bool allow_many) { winArgs *args; SDL_Thread *thread; - args = SDL_malloc(sizeof(winArgs)); + if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { + SDL_Log("%s", SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER)); + SDL_SetError("File dialog driver unsupported"); + callback(userdata, NULL, -1); + return; + } + + args = (winArgs *)SDL_malloc(sizeof(*args)); if (args == NULL) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } args->is_save = 0; args->filters = filters; + args->nfilters = nfilters; args->default_file = default_location; - args->default_folder = NULL; args->parent = window; - args->flags = (allow_many == SDL_TRUE) ? OFN_ALLOWMULTISELECT : 0; + args->flags = (allow_many != false) ? OFN_ALLOWMULTISELECT : 0; args->callback = callback; args->userdata = userdata; - thread = SDL_CreateThreadInternal(windows_file_dialog_thread, "SDL_ShowOpenFileDialog", 0, (void *) args); + thread = SDL_CreateThread(windows_file_dialog_thread, "SDL_ShowOpenFileDialog", (void *) args); if (thread == NULL) { callback(userdata, NULL, -1); + SDL_free(args); return; } SDL_DetachThread(thread); } -void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, const char* default_location) +void SDL_ShowSaveFileDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const SDL_DialogFileFilter *filters, int nfilters, const char* default_location) { winArgs *args; SDL_Thread *thread; - args = SDL_malloc(sizeof(winArgs)); + if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { + SDL_SetError("File dialog driver unsupported"); + callback(userdata, NULL, -1); + return; + } + + args = (winArgs *)SDL_malloc(sizeof(*args)); if (args == NULL) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } args->is_save = 1; args->filters = filters; + args->nfilters = nfilters; args->default_file = default_location; - args->default_folder = NULL; args->parent = window; args->flags = 0; args->callback = callback; args->userdata = userdata; - thread = SDL_CreateThreadInternal(windows_file_dialog_thread, "SDL_ShowSaveFileDialog", 0, (void *) args); + thread = SDL_CreateThread(windows_file_dialog_thread, "SDL_ShowSaveFileDialog", (void *) args); if (thread == NULL) { callback(userdata, NULL, -1); + SDL_free(args); return; } SDL_DetachThread(thread); } -void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, SDL_bool allow_many) +void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, SDL_Window* window, const char* default_location, bool allow_many) { winFArgs *args; SDL_Thread *thread; - args = SDL_malloc(sizeof(winFArgs)); + if (SDL_GetHint(SDL_HINT_FILE_DIALOG_DRIVER) != NULL) { + SDL_SetError("File dialog driver unsupported"); + callback(userdata, NULL, -1); + return; + } + + args = (winFArgs *)SDL_malloc(sizeof(*args)); if (args == NULL) { - SDL_OutOfMemory(); callback(userdata, NULL, -1); return; } @@ -475,10 +523,11 @@ void SDL_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* userdata, S args->default_folder = default_location; args->userdata = userdata; - thread = SDL_CreateThreadInternal(windows_folder_dialog_thread, "SDL_ShowOpenFolderDialog", 0, (void *) args); + thread = SDL_CreateThread(windows_folder_dialog_thread, "SDL_ShowOpenFolderDialog", (void *) args); if (thread == NULL) { callback(userdata, NULL, -1); + SDL_free(args); return; } diff --git a/libs/SDL3/src/dynapi/SDL_dynapi.c b/libs/SDL3/src/dynapi/SDL_dynapi.c index 8a46fe1f4..c0078ad99 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi.c +++ b/libs/SDL3/src/dynapi/SDL_dynapi.c @@ -19,7 +19,7 @@ 3. This notice may not be removed or altered from any source distribution. */ -#include "build_config/SDL_build_config.h" +#include "SDL_build_config.h" #include "SDL_dynapi.h" #include "SDL_dynapi_unsupported.h" @@ -35,11 +35,11 @@ #endif #include -#define SDL_MAIN_NOIMPL /* don't drag in header-only implementation of SDL_main */ +#define SDL_MAIN_NOIMPL // don't drag in header-only implementation of SDL_main #include -/* These headers have system specific definitions, so aren't included above */ +// These headers have system specific definitions, so aren't included above #include /* This is the version of the dynamic API. This doesn't match the SDL version @@ -60,15 +60,11 @@ extern "C" { static void SDL_InitDynamicAPI(void); /* BE CAREFUL CALLING ANY SDL CODE IN HERE, IT WILL BLOW UP. - Even self-contained stuff might call SDL_Error and break everything. */ + Even self-contained stuff might call SDL_SetError() and break everything. */ -/* behold, the macro salsa! */ +// behold, the macro salsa! -/* !!! FIXME: ...disabled...until we write it. :) */ -#define DISABLE_JUMP_MAGIC 1 - -#if DISABLE_JUMP_MAGIC -/* Can't use the macro for varargs nonsense. This is atrocious. */ +// Can't use the macro for varargs nonsense. This is atrocious. #define SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, logname, prio) \ _static void SDLCALL SDL_Log##logname##name(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ @@ -80,7 +76,7 @@ static void SDL_InitDynamicAPI(void); } #define SDL_DYNAPI_VARARGS(_static, name, initcall) \ - _static int SDLCALL SDL_SetError##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ + _static bool SDLCALL SDL_SetError##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ char buf[128], *str = buf; \ int result; \ @@ -99,62 +95,62 @@ static void SDL_InitDynamicAPI(void); } \ } \ if (result >= 0) { \ - result = jump_table.SDL_SetError("%s", str); \ + jump_table.SDL_SetError("%s", str); \ } \ if (str != buf) { \ jump_table.SDL_free(str); \ } \ - return result; \ + return false; \ } \ _static int SDLCALL SDL_sscanf##name(const char *buf, SDL_SCANF_FORMAT_STRING const char *fmt, ...) \ { \ - int retval; \ + int result; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_vsscanf(buf, fmt, ap); \ + result = jump_table.SDL_vsscanf(buf, fmt, ap); \ va_end(ap); \ - return retval; \ + return result; \ } \ _static int SDLCALL SDL_snprintf##name(SDL_OUT_Z_CAP(maxlen) char *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ - int retval; \ + int result; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_vsnprintf(buf, maxlen, fmt, ap); \ + result = jump_table.SDL_vsnprintf(buf, maxlen, fmt, ap); \ va_end(ap); \ - return retval; \ + return result; \ } \ _static int SDLCALL SDL_swprintf##name(SDL_OUT_Z_CAP(maxlen) wchar_t *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ...) \ { \ - int retval; \ + int result; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_vswprintf(buf, maxlen, fmt, ap); \ + result = jump_table.SDL_vswprintf(buf, maxlen, fmt, ap); \ va_end(ap); \ - return retval; \ + return result; \ } \ _static int SDLCALL SDL_asprintf##name(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ - int retval; \ + int result; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_vasprintf(strp, fmt, ap); \ + result = jump_table.SDL_vasprintf(strp, fmt, ap); \ va_end(ap); \ - return retval; \ + return result; \ } \ _static size_t SDLCALL SDL_IOprintf##name(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ - size_t retval; \ + size_t result; \ va_list ap; \ initcall; \ va_start(ap, fmt); \ - retval = jump_table.SDL_IOvprintf(context, fmt, ap); \ + result = jump_table.SDL_IOvprintf(context, fmt, ap); \ va_end(ap); \ - return retval; \ + return result; \ } \ _static void SDLCALL SDL_Log##name(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) \ { \ @@ -172,17 +168,17 @@ static void SDL_InitDynamicAPI(void); jump_table.SDL_LogMessageV(category, priority, fmt, ap); \ va_end(ap); \ } \ + SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Trace, TRACE) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Verbose, VERBOSE) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Debug, DEBUG) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Info, INFO) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Warn, WARN) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Error, ERROR) \ SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Critical, CRITICAL) -#endif -/* Typedefs for function pointers for jump table, and predeclare funcs */ -/* The DEFAULT funcs will init jump table and then call real function. */ -/* The REAL funcs are the actual functions, name-mangled to not clash. */ +// Typedefs for function pointers for jump table, and predeclare funcs +// The DEFAULT funcs will init jump table and then call real function. +// The REAL funcs are the actual functions, name-mangled to not clash. #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) \ typedef rc (SDLCALL *SDL_DYNAPIFN_##fn) params;\ static rc SDLCALL fn##_DEFAULT params; \ @@ -190,7 +186,7 @@ static void SDL_InitDynamicAPI(void); #include "SDL_dynapi_procs.h" #undef SDL_DYNAPI_PROC -/* The jump table! */ +// The jump table! typedef struct { #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) SDL_DYNAPIFN_##fn fn; @@ -198,20 +194,19 @@ typedef struct #undef SDL_DYNAPI_PROC } SDL_DYNAPI_jump_table; -/* Predeclare the default functions for initializing the jump table. */ +// Predeclare the default functions for initializing the jump table. #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) static rc SDLCALL fn##_DEFAULT params; #include "SDL_dynapi_procs.h" #undef SDL_DYNAPI_PROC -/* The actual jump table. */ +// The actual jump table. static SDL_DYNAPI_jump_table jump_table = { #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) fn##_DEFAULT, #include "SDL_dynapi_procs.h" #undef SDL_DYNAPI_PROC }; -/* Default functions init the function table then call right thing. */ -#if DISABLE_JUMP_MAGIC +// Default functions init the function table then call right thing. #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) \ static rc SDLCALL fn##_DEFAULT params \ { \ @@ -223,13 +218,8 @@ static SDL_DYNAPI_jump_table jump_table = { #undef SDL_DYNAPI_PROC #undef SDL_DYNAPI_PROC_NO_VARARGS SDL_DYNAPI_VARARGS(static, _DEFAULT, SDL_InitDynamicAPI()) -#else -/* !!! FIXME: need the jump magic. */ -#error Write me. -#endif -/* Public API functions to jump into the jump table. */ -#if DISABLE_JUMP_MAGIC +// Public API functions to jump into the jump table. #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) \ rc SDLCALL fn params \ { \ @@ -240,16 +230,12 @@ SDL_DYNAPI_VARARGS(static, _DEFAULT, SDL_InitDynamicAPI()) #undef SDL_DYNAPI_PROC #undef SDL_DYNAPI_PROC_NO_VARARGS SDL_DYNAPI_VARARGS(, , ) -#else -/* !!! FIXME: need the jump magic. */ -#error Write me. -#endif #define ENABLE_SDL_CALL_LOGGING 0 #if ENABLE_SDL_CALL_LOGGING -static int SDLCALL SDL_SetError_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +static bool SDLCALL SDL_SetError_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { - char buf[512]; /* !!! FIXME: dynamic allocation */ + char buf[512]; // !!! FIXME: dynamic allocation va_list ap; SDL_Log_REAL("SDL3CALL SDL_SetError"); va_start(ap, fmt); @@ -259,53 +245,53 @@ static int SDLCALL SDL_SetError_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char } static int SDLCALL SDL_sscanf_LOGSDLCALLS(const char *buf, SDL_SCANF_FORMAT_STRING const char *fmt, ...) { - int retval; + int result; va_list ap; SDL_Log_REAL("SDL3CALL SDL_sscanf"); va_start(ap, fmt); - retval = SDL_vsscanf_REAL(buf, fmt, ap); + result = SDL_vsscanf_REAL(buf, fmt, ap); va_end(ap); - return retval; + return result; } static int SDLCALL SDL_snprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) char *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { - int retval; + int result; va_list ap; SDL_Log_REAL("SDL3CALL SDL_snprintf"); va_start(ap, fmt); - retval = SDL_vsnprintf_REAL(buf, maxlen, fmt, ap); + result = SDL_vsnprintf_REAL(buf, maxlen, fmt, ap); va_end(ap); - return retval; + return result; } static int SDLCALL SDL_asprintf_LOGSDLCALLS(char **strp, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { - int retval; + int result; va_list ap; SDL_Log_REAL("SDL3CALL SDL_asprintf"); va_start(ap, fmt); - retval = SDL_vasprintf_REAL(strp, fmt, ap); + result = SDL_vasprintf_REAL(strp, fmt, ap); va_end(ap); - return retval; + return result; } static int SDLCALL SDL_swprintf_LOGSDLCALLS(SDL_OUT_Z_CAP(maxlen) wchar_t *buf, size_t maxlen, SDL_PRINTF_FORMAT_STRING const wchar_t *fmt, ...) { - int retval; + int result; va_list ap; SDL_Log_REAL("SDL3CALL SDL_swprintf"); va_start(ap, fmt); - retval = SDL_vswprintf_REAL(buf, maxlen, fmt, ap); + result = SDL_vswprintf_REAL(buf, maxlen, fmt, ap); va_end(ap); - return retval; + return result; } -_static size_t SDLCALL SDL_IOprintf_LOGSDLCALLS(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) +static size_t SDLCALL SDL_IOprintf_LOGSDLCALLS(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { - size_t retval; + size_t result; va_list ap; SDL_Log_REAL("SDL3CALL SDL_IOprintf"); va_start(ap, fmt); - retval = SDL_IOvprintf_REAL(context, fmt, ap); + result = SDL_IOvprintf_REAL(context, fmt, ap); va_end(ap); - return retval; + return result; } static void SDLCALL SDL_Log_LOGSDLCALLS(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) { @@ -332,6 +318,7 @@ static void SDLCALL SDL_LogMessage_LOGSDLCALLS(int category, SDL_LogPriority pri SDL_LogMessageV_REAL(category, SDL_LOG_PRIORITY_##prio, fmt, ap); \ va_end(ap); \ } +SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Trace, TRACE) SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Verbose, VERBOSE) SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Debug, DEBUG) SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Info, INFO) @@ -357,17 +344,17 @@ static Sint32 initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize) SDL_DYNAPI_jump_table *output_jump_table = (SDL_DYNAPI_jump_table *)table; if (apiver != SDL_DYNAPI_VERSION) { - /* !!! FIXME: can maybe handle older versions? */ - return -1; /* not compatible. */ + // !!! FIXME: can maybe handle older versions? + return -1; // not compatible. } else if (tablesize > sizeof(jump_table)) { - return -1; /* newer version of SDL with functions we can't provide. */ + return -1; // newer version of SDL with functions we can't provide. } -/* Init our jump table first. */ +// Init our jump table first. #if ENABLE_SDL_CALL_LOGGING { - const char *env = SDL_getenv_REAL("SDL_DYNAPI_LOG_CALLS"); - const SDL_bool log_calls = (env && SDL_atoi_REAL(env)); + const char *env = SDL_getenv_unsafe_REAL("SDL_DYNAPI_LOG_CALLS"); + const bool log_calls = (env && SDL_atoi_REAL(env)); if (log_calls) { #define SDL_DYNAPI_PROC(rc, fn, params, args, ret) jump_table.fn = fn##_LOGSDLCALLS; #include "SDL_dynapi_procs.h" @@ -384,20 +371,20 @@ static Sint32 initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize) #undef SDL_DYNAPI_PROC #endif - /* Then the external table... */ + // Then the external table... if (output_jump_table != &jump_table) { jump_table.SDL_memcpy(output_jump_table, &jump_table, tablesize); } - /* Safe to call SDL functions now; jump table is initialized! */ + // Safe to call SDL functions now; jump table is initialized! - return 0; /* success! */ + return 0; // success! } -/* Here's the exported entry point that fills in the jump table. */ -/* Use specific types when an "int" might suffice to keep this sane. */ +// Here's the exported entry point that fills in the jump table. +// Use specific types when an "int" might suffice to keep this sane. typedef Sint32 (SDLCALL *SDL_DYNAPI_ENTRYFN)(Uint32 apiver, void *table, Uint32 tablesize); -extern DECLSPEC Sint32 SDLCALL SDL_DYNAPI_entry(Uint32, void *, Uint32); +extern SDL_DECLSPEC Sint32 SDLCALL SDL_DYNAPI_entry(Uint32, void *, Uint32); Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) { @@ -408,8 +395,8 @@ Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) } #endif -/* Obviously we can't use SDL_LoadObject() to load SDL. :) */ -/* Also obviously, we never close the loaded library. */ +// Obviously we can't use SDL_LoadObject() to load SDL. :) +// Also obviously, we never close the loaded library. #if defined(WIN32) || defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN 1 @@ -418,14 +405,14 @@ Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) { HMODULE lib = LoadLibraryA(fname); - void *retval = NULL; + void *result = NULL; if (lib) { - retval = (void *) GetProcAddress(lib, sym); - if (!retval) { + result = (void *) GetProcAddress(lib, sym); + if (!result) { FreeLibrary(lib); } } - return retval; + return result; } #elif defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE) || defined(SDL_PLATFORM_HAIKU) @@ -433,14 +420,14 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym) { void *lib = dlopen(fname, RTLD_NOW | RTLD_LOCAL); - void *retval = NULL; + void *result = NULL; if (lib) { - retval = dlsym(lib, sym); - if (!retval) { + result = dlsym(lib, sym); + if (!result) { dlclose(lib); } } - return retval; + return result; } #else @@ -451,7 +438,7 @@ static void dynapi_warn(const char *msg) { const char *caption = "SDL Dynamic API Failure!"; (void)caption; -/* SDL_ShowSimpleMessageBox() is a too heavy for here. */ +// SDL_ShowSimpleMessageBox() is a too heavy for here. #if (defined(WIN32) || defined(_WIN32) || defined(SDL_PLATFORM_CYGWIN)) && !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) MessageBoxA(NULL, msg, caption, MB_OK | MB_ICONERROR); #elif defined(HAVE_STDIO_H) @@ -476,15 +463,16 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode); static void SDL_InitDynamicAPILocked(void) { - char *libname = SDL_getenv_REAL(SDL_DYNAMIC_API_ENVVAR); - SDL_DYNAPI_ENTRYFN entry = NULL; /* funcs from here by default. */ - SDL_bool use_internal = SDL_TRUE; + const char *libname = SDL_getenv_unsafe_REAL(SDL_DYNAMIC_API_ENVVAR); + SDL_DYNAPI_ENTRYFN entry = NULL; // funcs from here by default. + bool use_internal = true; if (libname) { while (*libname && !entry) { - char *ptr = libname; - while (SDL_TRUE) { - const char ch = *ptr; + // This is evil, but we're not making any permanent changes... + char *ptr = (char *)libname; + while (true) { + char ch = *ptr; if ((ch == ',') || (ch == '\0')) { *ptr = '\0'; entry = (SDL_DYNAPI_ENTRYFN)get_sdlapi_entry(libname, "SDL_DYNAPI_entry"); @@ -498,29 +486,29 @@ static void SDL_InitDynamicAPILocked(void) } if (!entry) { dynapi_warn("Couldn't load an overriding SDL library. Please fix or remove the " SDL_DYNAMIC_API_ENVVAR " environment variable. Using the default SDL."); - /* Just fill in the function pointers from this library, later. */ + // Just fill in the function pointers from this library, later. } } if (entry) { if (entry(SDL_DYNAPI_VERSION, &jump_table, sizeof(jump_table)) < 0) { dynapi_warn("Couldn't override SDL library. Using a newer SDL build might help. Please fix or remove the " SDL_DYNAMIC_API_ENVVAR " environment variable. Using the default SDL."); - /* Just fill in the function pointers from this library, later. */ + // Just fill in the function pointers from this library, later. } else { - use_internal = SDL_FALSE; /* We overrode SDL! Don't use the internal version! */ + use_internal = false; // We overrode SDL! Don't use the internal version! } } - /* Just fill in the function pointers from this library. */ + // Just fill in the function pointers from this library. if (use_internal) { if (initialize_jumptable(SDL_DYNAPI_VERSION, &jump_table, sizeof(jump_table)) < 0) { - /* Now we're screwed. Should definitely abort now. */ + // Now we're screwed. Should definitely abort now. dynapi_warn("Failed to initialize internal SDL dynapi. As this would otherwise crash, we have to abort now."); SDL_ExitProcess(86); } } - /* we intentionally never close the newly-loaded lib, of course. */ + // we intentionally never close the newly-loaded lib, of course. } static void SDL_InitDynamicAPI(void) @@ -536,20 +524,20 @@ static void SDL_InitDynamicAPI(void) * SDL_CreateThread() would also call this function before building the * new thread). */ - static SDL_bool already_initialized = SDL_FALSE; + static bool already_initialized = false; static SDL_SpinLock lock = 0; SDL_LockSpinlock_REAL(&lock); if (!already_initialized) { SDL_InitDynamicAPILocked(); - already_initialized = SDL_TRUE; + already_initialized = true; } SDL_UnlockSpinlock_REAL(&lock); } -#else /* SDL_DYNAMIC_API */ +#else // SDL_DYNAMIC_API #include @@ -559,7 +547,7 @@ Sint32 SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize) (void)apiver; (void)table; (void)tablesize; - return -1; /* not compatible. */ + return -1; // not compatible. } -#endif /* SDL_DYNAMIC_API */ +#endif // SDL_DYNAMIC_API diff --git a/libs/SDL3/src/dynapi/SDL_dynapi.h b/libs/SDL3/src/dynapi/SDL_dynapi.h index 43a642419..be52f2c29 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi.h +++ b/libs/SDL3/src/dynapi/SDL_dynapi.h @@ -35,7 +35,7 @@ updated SDL can transparently take advantage of them, but your program will not without this feature. Think hard before turning it off. */ -#ifdef SDL_DYNAMIC_API /* Tried to force it on the command line? */ +#ifdef SDL_DYNAMIC_API // Tried to force it on the command line? #error Nope, you have to edit this file to force this off. #endif @@ -43,33 +43,31 @@ #include "TargetConditionals.h" #endif -#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE /* probably not useful on iOS. */ +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE // probably not useful on iOS. #define SDL_DYNAMIC_API 0 -#elif defined(SDL_PLATFORM_ANDROID) /* probably not useful on Android. */ +#elif defined(SDL_PLATFORM_ANDROID) // probably not useful on Android. #define SDL_DYNAMIC_API 0 -#elif defined(SDL_PLATFORM_EMSCRIPTEN) /* probably not useful on Emscripten. */ -#define SDL_DYNAMIC_API 0 -#elif defined(SDL_BUILDING_WINRT) && SDL_BUILDING_WINRT /* probably not useful on WinRT, given current .dll loading restrictions */ +#elif defined(SDL_PLATFORM_EMSCRIPTEN) // probably not useful on Emscripten. #define SDL_DYNAMIC_API 0 #elif defined(SDL_PLATFORM_PS2) && SDL_PLATFORM_PS2 #define SDL_DYNAMIC_API 0 #elif defined(SDL_PLATFORM_PSP) && SDL_PLATFORM_PSP #define SDL_DYNAMIC_API 0 -#elif defined(SDL_PLATFORM_RISCOS) /* probably not useful on RISC OS, since dlopen() can't be used when using static linking. */ +#elif defined(SDL_PLATFORM_RISCOS) // probably not useful on RISC OS, since dlopen() can't be used when using static linking. #define SDL_DYNAMIC_API 0 -#elif defined(__clang_analyzer__) || defined(SDL_THREAD_SAFETY_ANALYSIS) -#define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ +#elif defined(__clang_analyzer__) || defined(__INTELLISENSE__) || defined(SDL_THREAD_SAFETY_ANALYSIS) +#define SDL_DYNAMIC_API 0 // Turn off for static analysis, so reports are more clear. #elif defined(SDL_PLATFORM_VITA) -#define SDL_DYNAMIC_API 0 /* vitasdk doesn't support dynamic linking */ +#define SDL_DYNAMIC_API 0 // vitasdk doesn't support dynamic linking #elif defined(SDL_PLATFORM_NGAGE) -#define SDL_DYNAMIC_API 0 /* The N-Gage doesn't support dynamic linking either */ +#define SDL_DYNAMIC_API 0 // The N-Gage doesn't support dynamic linking either #elif defined(SDL_PLATFORM_3DS) -#define SDL_DYNAMIC_API 0 /* devkitARM doesn't support dynamic linking */ +#define SDL_DYNAMIC_API 0 // devkitARM doesn't support dynamic linking #elif defined(DYNAPI_NEEDS_DLOPEN) && !defined(HAVE_DLOPEN) -#define SDL_DYNAMIC_API 0 /* we need dlopen(), but don't have it.... */ +#define SDL_DYNAMIC_API 0 // we need dlopen(), but don't have it.... #endif -/* everyone else. This is where we turn on the API if nothing forced it off. */ +// everyone else. This is where we turn on the API if nothing forced it off. #ifndef SDL_DYNAMIC_API #define SDL_DYNAMIC_API 1 #endif diff --git a/libs/SDL3/src/dynapi/SDL_dynapi.sym b/libs/SDL3/src/dynapi/SDL_dynapi.sym index a63155052..ab7704b53 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi.sym +++ b/libs/SDL3/src/dynapi/SDL_dynapi.sym @@ -3,47 +3,56 @@ SDL3_0.0.0 { JNI_OnLoad; SDL_DYNAPI_entry; SDL_AcquireCameraFrame; + SDL_AcquireGPUCommandBuffer; + SDL_AcquireGPUSwapchainTexture; + SDL_AddAtomicInt; SDL_AddEventWatch; SDL_AddGamepadMapping; SDL_AddGamepadMappingsFromFile; SDL_AddGamepadMappingsFromIO; SDL_AddHintCallback; + SDL_AddSurfaceAlternateImage; SDL_AddTimer; + SDL_AddTimerNS; SDL_AddVulkanRenderSemaphores; - SDL_AllocateEventMemory; - SDL_AndroidBackButton; - SDL_AndroidGetActivity; - SDL_AndroidGetExternalStoragePath; - SDL_AndroidGetExternalStorageState; - SDL_AndroidGetInternalStoragePath; - SDL_AndroidGetJNIEnv; - SDL_AndroidRequestPermission; - SDL_AndroidSendMessage; - SDL_AndroidShowToast; - SDL_AtomicAdd; - SDL_AtomicCompareAndSwap; - SDL_AtomicCompareAndSwapPointer; - SDL_AtomicGet; - SDL_AtomicGetPtr; - SDL_AtomicSet; - SDL_AtomicSetPtr; SDL_AttachVirtualJoystick; - SDL_AttachVirtualJoystickEx; SDL_AudioDevicePaused; + SDL_BeginGPUComputePass; + SDL_BeginGPUCopyPass; + SDL_BeginGPURenderPass; SDL_BindAudioStream; SDL_BindAudioStreams; + SDL_BindGPUComputePipeline; + SDL_BindGPUComputeSamplers; + SDL_BindGPUComputeStorageBuffers; + SDL_BindGPUComputeStorageTextures; + SDL_BindGPUFragmentSamplers; + SDL_BindGPUFragmentStorageBuffers; + SDL_BindGPUFragmentStorageTextures; + SDL_BindGPUGraphicsPipeline; + SDL_BindGPUIndexBuffer; + SDL_BindGPUVertexBuffers; + SDL_BindGPUVertexSamplers; + SDL_BindGPUVertexStorageBuffers; + SDL_BindGPUVertexStorageTextures; + SDL_BlitGPUTexture; + SDL_BlitSurface9Grid; SDL_BlitSurface; SDL_BlitSurfaceScaled; + SDL_BlitSurfaceTiled; + SDL_BlitSurfaceTiledWithScale; SDL_BlitSurfaceUnchecked; SDL_BlitSurfaceUncheckedScaled; SDL_BroadcastCondition; SDL_CaptureMouse; + SDL_ClaimWindowForGPUDevice; SDL_CleanupTLS; SDL_ClearAudioStream; SDL_ClearClipboardData; SDL_ClearComposition; SDL_ClearError; SDL_ClearProperty; + SDL_ClearSurface; SDL_CloseAudioDevice; SDL_CloseCamera; SDL_CloseGamepad; @@ -52,25 +61,42 @@ SDL3_0.0.0 { SDL_CloseJoystick; SDL_CloseSensor; SDL_CloseStorage; + SDL_CompareAndSwapAtomicInt; + SDL_CompareAndSwapAtomicPointer; + SDL_CompareAndSwapAtomicU32; SDL_ComposeCustomBlendMode; SDL_ConvertAudioSamples; SDL_ConvertEventToRenderCoordinates; SDL_ConvertPixels; SDL_ConvertPixelsAndColorspace; SDL_ConvertSurface; - SDL_ConvertSurfaceFormat; - SDL_ConvertSurfaceFormatAndColorspace; + SDL_ConvertSurfaceAndColorspace; + SDL_CopyFile; + SDL_CopyGPUBufferToBuffer; + SDL_CopyGPUTextureToTexture; SDL_CopyProperties; + SDL_CopyStorageFile; SDL_CreateAudioStream; SDL_CreateColorCursor; SDL_CreateCondition; SDL_CreateCursor; SDL_CreateDirectory; + SDL_CreateEnvironment; + SDL_CreateGPUBuffer; + SDL_CreateGPUComputePipeline; + SDL_CreateGPUDevice; + SDL_CreateGPUDeviceWithProperties; + SDL_CreateGPUGraphicsPipeline; + SDL_CreateGPUSampler; + SDL_CreateGPUShader; + SDL_CreateGPUTexture; + SDL_CreateGPUTransferBuffer; SDL_CreateHapticEffect; SDL_CreateMutex; SDL_CreatePalette; - SDL_CreatePixelFormat; SDL_CreatePopupWindow; + SDL_CreateProcess; + SDL_CreateProcessWithProperties; SDL_CreateProperties; SDL_CreateRWLock; SDL_CreateRenderer; @@ -80,30 +106,29 @@ SDL3_0.0.0 { SDL_CreateStorageDirectory; SDL_CreateSurface; SDL_CreateSurfaceFrom; + SDL_CreateSurfacePalette; SDL_CreateSystemCursor; - SDL_CreateTLS; SDL_CreateTexture; SDL_CreateTextureFromSurface; SDL_CreateTextureWithProperties; - SDL_CreateThread; - SDL_CreateThreadWithStackSize; + SDL_CreateThreadRuntime; + SDL_CreateThreadWithPropertiesRuntime; SDL_CreateWindow; SDL_CreateWindowAndRenderer; SDL_CreateWindowWithProperties; SDL_CursorVisible; - SDL_DXGIGetOutputInfo; SDL_DateTimeToTime; - SDL_DelEventWatch; - SDL_DelHintCallback; SDL_Delay; SDL_DelayNS; SDL_DestroyAudioStream; SDL_DestroyCondition; SDL_DestroyCursor; + SDL_DestroyEnvironment; + SDL_DestroyGPUDevice; SDL_DestroyHapticEffect; SDL_DestroyMutex; SDL_DestroyPalette; - SDL_DestroyPixelFormat; + SDL_DestroyProcess; SDL_DestroyProperties; SDL_DestroyRWLock; SDL_DestroyRenderer; @@ -114,20 +139,29 @@ SDL3_0.0.0 { SDL_DestroyWindowSurface; SDL_DetachThread; SDL_DetachVirtualJoystick; - SDL_Direct3D9GetAdapterIndex; SDL_DisableScreenSaver; + SDL_DispatchGPUCompute; + SDL_DispatchGPUComputeIndirect; + SDL_DownloadFromGPUBuffer; + SDL_DownloadFromGPUTexture; + SDL_DrawGPUIndexedPrimitives; + SDL_DrawGPUIndexedPrimitivesIndirect; + SDL_DrawGPUPrimitives; + SDL_DrawGPUPrimitivesIndirect; SDL_DuplicateSurface; - SDL_EGL_GetCurrentEGLConfig; - SDL_EGL_GetCurrentEGLDisplay; + SDL_EGL_GetCurrentConfig; + SDL_EGL_GetCurrentDisplay; SDL_EGL_GetProcAddress; - SDL_EGL_GetWindowEGLSurface; - SDL_EGL_SetEGLAttributeCallbacks; + SDL_EGL_GetWindowSurface; + SDL_EGL_SetAttributeCallbacks; SDL_EnableScreenSaver; + SDL_EndGPUComputePass; + SDL_EndGPUCopyPass; + SDL_EndGPURenderPass; SDL_EnterAppMainCallbacks; SDL_EnumerateDirectory; SDL_EnumerateProperties; SDL_EnumerateStorageDirectory; - SDL_Error; SDL_EventEnabled; SDL_FillSurfaceRect; SDL_FillSurfaceRects; @@ -137,12 +171,13 @@ SDL3_0.0.0 { SDL_FlushAudioStream; SDL_FlushEvent; SDL_FlushEvents; + SDL_FlushIO; SDL_FlushRenderer; - SDL_GDKGetDefaultUser; - SDL_GDKGetTaskQueue; + SDL_GDKResumeGPU; SDL_GDKSuspendComplete; + SDL_GDKSuspendGPU; SDL_GL_CreateContext; - SDL_GL_DeleteContext; + SDL_GL_DestroyContext; SDL_GL_ExtensionSupported; SDL_GL_GetAttribute; SDL_GL_GetCurrentContext; @@ -156,7 +191,11 @@ SDL3_0.0.0 { SDL_GL_SetSwapInterval; SDL_GL_SwapWindow; SDL_GL_UnloadLibrary; - SDL_GUIDFromString; + SDL_GPUSupportsProperties; + SDL_GPUSupportsShaderFormats; + SDL_GPUTextureFormatTexelBlockSize; + SDL_GPUTextureSupportsFormat; + SDL_GPUTextureSupportsSampleCount; SDL_GUIDToString; SDL_GamepadConnected; SDL_GamepadEventsEnabled; @@ -164,35 +203,52 @@ SDL3_0.0.0 { SDL_GamepadHasButton; SDL_GamepadHasSensor; SDL_GamepadSensorEnabled; + SDL_GenerateMipmapsForGPUTexture; + SDL_GetAndroidActivity; + SDL_GetAndroidCachePath; + SDL_GetAndroidExternalStoragePath; + SDL_GetAndroidExternalStorageState; + SDL_GetAndroidInternalStoragePath; + SDL_GetAndroidJNIEnv; SDL_GetAndroidSDKVersion; + SDL_GetAppMetadataProperty; SDL_GetAssertionHandler; SDL_GetAssertionReport; - SDL_GetAudioCaptureDevices; + SDL_GetAtomicInt; + SDL_GetAtomicPointer; + SDL_GetAtomicU32; + SDL_GetAudioDeviceChannelMap; SDL_GetAudioDeviceFormat; + SDL_GetAudioDeviceGain; SDL_GetAudioDeviceName; SDL_GetAudioDriver; - SDL_GetAudioOutputDevices; + SDL_GetAudioFormatName; + SDL_GetAudioPlaybackDevices; + SDL_GetAudioRecordingDevices; SDL_GetAudioStreamAvailable; SDL_GetAudioStreamData; SDL_GetAudioStreamDevice; SDL_GetAudioStreamFormat; SDL_GetAudioStreamFrequencyRatio; + SDL_GetAudioStreamGain; + SDL_GetAudioStreamInputChannelMap; + SDL_GetAudioStreamOutputChannelMap; SDL_GetAudioStreamProperties; SDL_GetAudioStreamQueued; SDL_GetBasePath; SDL_GetBooleanProperty; SDL_GetCPUCacheLineSize; - SDL_GetCPUCount; - SDL_GetCameraDeviceName; - SDL_GetCameraDevicePosition; - SDL_GetCameraDeviceSupportedFormats; - SDL_GetCameraDevices; SDL_GetCameraDriver; SDL_GetCameraFormat; - SDL_GetCameraInstanceID; + SDL_GetCameraID; + SDL_GetCameraName; SDL_GetCameraPermissionState; + SDL_GetCameraPosition; SDL_GetCameraProperties; + SDL_GetCameraSupportedFormats; + SDL_GetCameras; SDL_GetClipboardData; + SDL_GetClipboardMimeTypes; SDL_GetClipboardText; SDL_GetClosestFullscreenDisplayMode; SDL_GetCurrentAudioDriver; @@ -204,12 +260,15 @@ SDL3_0.0.0 { SDL_GetCurrentTime; SDL_GetCurrentVideoDriver; SDL_GetCursor; + SDL_GetDXGIOutputInfo; + SDL_GetDateTimeLocalePreferences; SDL_GetDayOfWeek; SDL_GetDayOfYear; SDL_GetDaysInMonth; SDL_GetDefaultAssertionHandler; SDL_GetDefaultCursor; SDL_GetDesktopDisplayMode; + SDL_GetDirect3D9AdapterIndex; SDL_GetDisplayBounds; SDL_GetDisplayContentScale; SDL_GetDisplayForPoint; @@ -219,10 +278,19 @@ SDL3_0.0.0 { SDL_GetDisplayProperties; SDL_GetDisplayUsableBounds; SDL_GetDisplays; + SDL_GetEnvironment; + SDL_GetEnvironmentVariable; + SDL_GetEnvironmentVariables; SDL_GetError; SDL_GetEventFilter; SDL_GetFloatProperty; SDL_GetFullscreenDisplayModes; + SDL_GetGDKDefaultUser; + SDL_GetGDKTaskQueue; + SDL_GetGPUDeviceDriver; + SDL_GetGPUDriver; + SDL_GetGPUShaderFormats; + SDL_GetGPUSwapchainTextureFormat; SDL_GetGamepadAppleSFSymbolsNameForAxis; SDL_GetGamepadAppleSFSymbolsNameForButton; SDL_GetGamepadAxis; @@ -234,28 +302,26 @@ SDL3_0.0.0 { SDL_GetGamepadButtonLabelForType; SDL_GetGamepadConnectionState; SDL_GetGamepadFirmwareVersion; - SDL_GetGamepadFromInstanceID; + SDL_GetGamepadFromID; SDL_GetGamepadFromPlayerIndex; - SDL_GetGamepadInstanceGUID; - SDL_GetGamepadInstanceID; - SDL_GetGamepadInstanceMapping; - SDL_GetGamepadInstanceName; - SDL_GetGamepadInstancePath; - SDL_GetGamepadInstancePlayerIndex; - SDL_GetGamepadInstanceProduct; - SDL_GetGamepadInstanceProductVersion; - SDL_GetGamepadInstanceType; - SDL_GetGamepadInstanceVendor; + SDL_GetGamepadGUIDForID; + SDL_GetGamepadID; SDL_GetGamepadJoystick; SDL_GetGamepadMapping; SDL_GetGamepadMappingForGUID; + SDL_GetGamepadMappingForID; SDL_GetGamepadMappings; SDL_GetGamepadName; + SDL_GetGamepadNameForID; SDL_GetGamepadPath; + SDL_GetGamepadPathForID; SDL_GetGamepadPlayerIndex; + SDL_GetGamepadPlayerIndexForID; SDL_GetGamepadPowerInfo; SDL_GetGamepadProduct; + SDL_GetGamepadProductForID; SDL_GetGamepadProductVersion; + SDL_GetGamepadProductVersionForID; SDL_GetGamepadProperties; SDL_GetGamepadSensorData; SDL_GetGamepadSensorDataRate; @@ -266,18 +332,20 @@ SDL3_0.0.0 { SDL_GetGamepadStringForType; SDL_GetGamepadTouchpadFinger; SDL_GetGamepadType; + SDL_GetGamepadTypeForID; SDL_GetGamepadTypeFromString; SDL_GetGamepadVendor; + SDL_GetGamepadVendorForID; SDL_GetGamepads; SDL_GetGlobalMouseState; SDL_GetGlobalProperties; SDL_GetGrabbedWindow; SDL_GetHapticEffectStatus; SDL_GetHapticFeatures; - SDL_GetHapticFromInstanceID; - SDL_GetHapticInstanceID; - SDL_GetHapticInstanceName; + SDL_GetHapticFromID; + SDL_GetHapticID; SDL_GetHapticName; + SDL_GetHapticNameForID; SDL_GetHaptics; SDL_GetHint; SDL_GetHintBoolean; @@ -290,54 +358,54 @@ SDL3_0.0.0 { SDL_GetJoystickButton; SDL_GetJoystickConnectionState; SDL_GetJoystickFirmwareVersion; - SDL_GetJoystickFromInstanceID; + SDL_GetJoystickFromID; SDL_GetJoystickFromPlayerIndex; SDL_GetJoystickGUID; - SDL_GetJoystickGUIDFromString; + SDL_GetJoystickGUIDForID; SDL_GetJoystickGUIDInfo; - SDL_GetJoystickGUIDString; SDL_GetJoystickHat; - SDL_GetJoystickInstanceGUID; - SDL_GetJoystickInstanceID; - SDL_GetJoystickInstanceName; - SDL_GetJoystickInstancePath; - SDL_GetJoystickInstancePlayerIndex; - SDL_GetJoystickInstanceProduct; - SDL_GetJoystickInstanceProductVersion; - SDL_GetJoystickInstanceType; - SDL_GetJoystickInstanceVendor; + SDL_GetJoystickID; SDL_GetJoystickName; + SDL_GetJoystickNameForID; SDL_GetJoystickPath; + SDL_GetJoystickPathForID; SDL_GetJoystickPlayerIndex; + SDL_GetJoystickPlayerIndexForID; SDL_GetJoystickPowerInfo; SDL_GetJoystickProduct; + SDL_GetJoystickProductForID; SDL_GetJoystickProductVersion; + SDL_GetJoystickProductVersionForID; SDL_GetJoystickProperties; SDL_GetJoystickSerial; SDL_GetJoystickType; + SDL_GetJoystickTypeForID; SDL_GetJoystickVendor; + SDL_GetJoystickVendorForID; SDL_GetJoysticks; SDL_GetKeyFromName; SDL_GetKeyFromScancode; SDL_GetKeyName; SDL_GetKeyboardFocus; - SDL_GetKeyboardInstanceName; + SDL_GetKeyboardNameForID; SDL_GetKeyboardState; SDL_GetKeyboards; SDL_GetLogOutputFunction; - SDL_GetMasksForPixelFormatEnum; + SDL_GetLogPriority; + SDL_GetMasksForPixelFormat; SDL_GetMaxHapticEffects; SDL_GetMaxHapticEffectsPlaying; SDL_GetMemoryFunctions; SDL_GetMice; SDL_GetModState; SDL_GetMouseFocus; - SDL_GetMouseInstanceName; + SDL_GetMouseNameForID; SDL_GetMouseState; SDL_GetNaturalDisplayOrientation; SDL_GetNumAllocations; SDL_GetNumAudioDrivers; SDL_GetNumCameraDrivers; + SDL_GetNumGPUDrivers; SDL_GetNumGamepadTouchpadFingers; SDL_GetNumGamepadTouchpads; SDL_GetNumHapticAxes; @@ -345,42 +413,32 @@ SDL3_0.0.0 { SDL_GetNumJoystickBalls; SDL_GetNumJoystickButtons; SDL_GetNumJoystickHats; + SDL_GetNumLogicalCPUCores; SDL_GetNumRenderDrivers; - SDL_GetNumTouchFingers; SDL_GetNumVideoDrivers; SDL_GetNumberProperty; SDL_GetOriginalMemoryFunctions; SDL_GetPathInfo; - SDL_GetPenCapabilities; - SDL_GetPenCapabilities; - SDL_GetPenFromGUID; - SDL_GetPenFromGUID; - SDL_GetPenGUID; - SDL_GetPenGUID; - SDL_GetPenName; - SDL_GetPenName; - SDL_GetPenStatus; - SDL_GetPenStatus; - SDL_GetPenType; - SDL_GetPenType; - SDL_GetPens; - SDL_GetPens; SDL_GetPerformanceCounter; SDL_GetPerformanceFrequency; - SDL_GetPixelFormatEnumForMasks; + SDL_GetPixelFormatDetails; + SDL_GetPixelFormatForMasks; SDL_GetPixelFormatName; SDL_GetPlatform; + SDL_GetPointerProperty; SDL_GetPowerInfo; SDL_GetPrefPath; SDL_GetPreferredLocales; SDL_GetPrimaryDisplay; SDL_GetPrimarySelectionText; - SDL_GetProperty; + SDL_GetProcessInput; + SDL_GetProcessOutput; + SDL_GetProcessProperties; SDL_GetPropertyType; SDL_GetRGB; SDL_GetRGBA; - SDL_GetRealGamepadInstanceType; SDL_GetRealGamepadType; + SDL_GetRealGamepadTypeForID; SDL_GetRectAndLineIntersection; SDL_GetRectAndLineIntersectionFloat; SDL_GetRectEnclosingPoints; @@ -389,7 +447,6 @@ SDL3_0.0.0 { SDL_GetRectIntersectionFloat; SDL_GetRectUnion; SDL_GetRectUnionFloat; - SDL_GetRelativeMouseMode; SDL_GetRelativeMouseState; SDL_GetRenderClipRect; SDL_GetRenderColorScale; @@ -398,9 +455,11 @@ SDL3_0.0.0 { SDL_GetRenderDrawColorFloat; SDL_GetRenderDriver; SDL_GetRenderLogicalPresentation; + SDL_GetRenderLogicalPresentationRect; SDL_GetRenderMetalCommandEncoder; SDL_GetRenderMetalLayer; SDL_GetRenderOutputSize; + SDL_GetRenderSafeArea; SDL_GetRenderScale; SDL_GetRenderTarget; SDL_GetRenderVSync; @@ -408,23 +467,24 @@ SDL3_0.0.0 { SDL_GetRenderWindow; SDL_GetRenderer; SDL_GetRendererFromTexture; - SDL_GetRendererInfo; + SDL_GetRendererName; SDL_GetRendererProperties; SDL_GetRevision; + SDL_GetSIMDAlignment; SDL_GetScancodeFromKey; SDL_GetScancodeFromName; SDL_GetScancodeName; SDL_GetSemaphoreValue; SDL_GetSensorData; - SDL_GetSensorFromInstanceID; - SDL_GetSensorInstanceID; - SDL_GetSensorInstanceName; - SDL_GetSensorInstanceNonPortableType; - SDL_GetSensorInstanceType; + SDL_GetSensorFromID; + SDL_GetSensorID; SDL_GetSensorName; + SDL_GetSensorNameForID; SDL_GetSensorNonPortableType; + SDL_GetSensorNonPortableTypeForID; SDL_GetSensorProperties; SDL_GetSensorType; + SDL_GetSensorTypeForID; SDL_GetSensors; SDL_GetSilenceValueForFormat; SDL_GetStorageFileSize; @@ -437,10 +497,13 @@ SDL3_0.0.0 { SDL_GetSurfaceColorKey; SDL_GetSurfaceColorMod; SDL_GetSurfaceColorspace; + SDL_GetSurfaceImages; + SDL_GetSurfacePalette; SDL_GetSurfaceProperties; SDL_GetSystemRAM; SDL_GetSystemTheme; SDL_GetTLS; + SDL_GetTextInputArea; SDL_GetTextureAlphaMod; SDL_GetTextureAlphaModFloat; SDL_GetTextureBlendMode; @@ -448,6 +511,7 @@ SDL3_0.0.0 { SDL_GetTextureColorModFloat; SDL_GetTextureProperties; SDL_GetTextureScaleMode; + SDL_GetTextureSize; SDL_GetThreadID; SDL_GetThreadName; SDL_GetTicks; @@ -455,13 +519,15 @@ SDL3_0.0.0 { SDL_GetTouchDeviceName; SDL_GetTouchDeviceType; SDL_GetTouchDevices; - SDL_GetTouchFinger; + SDL_GetTouchFingers; SDL_GetUserFolder; SDL_GetVersion; SDL_GetVideoDriver; + SDL_GetWindowAspectRatio; SDL_GetWindowBordersSize; SDL_GetWindowDisplayScale; SDL_GetWindowFlags; + SDL_GetWindowFromEvent; SDL_GetWindowFromID; SDL_GetWindowFullscreenMode; SDL_GetWindowICCProfile; @@ -477,10 +543,16 @@ SDL3_0.0.0 { SDL_GetWindowPixelFormat; SDL_GetWindowPosition; SDL_GetWindowProperties; + SDL_GetWindowRelativeMouseMode; + SDL_GetWindowSafeArea; SDL_GetWindowSize; SDL_GetWindowSizeInPixels; SDL_GetWindowSurface; + SDL_GetWindowSurfaceVSync; SDL_GetWindowTitle; + SDL_GetWindows; + SDL_GlobDirectory; + SDL_GlobStorageDirectory; SDL_HapticEffectSupported; SDL_HapticRumbleSupported; SDL_HasARMSIMD; @@ -521,18 +593,18 @@ SDL3_0.0.0 { SDL_Init; SDL_InitHapticRumble; SDL_InitSubSystem; - SDL_IsAndroidTV; + SDL_InsertGPUDebugLabel; SDL_IsChromebook; SDL_IsDeXMode; SDL_IsGamepad; SDL_IsJoystickHaptic; SDL_IsJoystickVirtual; SDL_IsMouseHaptic; + SDL_IsTV; SDL_IsTablet; SDL_JoystickConnected; SDL_JoystickEventsEnabled; - SDL_LinuxSetThreadPriority; - SDL_LinuxSetThreadPriorityAndPolicy; + SDL_KillProcess; SDL_LoadBMP; SDL_LoadBMP_IO; SDL_LoadFile; @@ -555,17 +627,17 @@ SDL3_0.0.0 { SDL_LogCritical; SDL_LogDebug; SDL_LogError; - SDL_LogGetPriority; SDL_LogInfo; SDL_LogMessage; SDL_LogMessageV; - SDL_LogResetPriorities; - SDL_LogSetAllPriority; - SDL_LogSetPriority; + SDL_LogTrace; SDL_LogVerbose; SDL_LogWarn; + SDL_MapGPUTransferBuffer; SDL_MapRGB; SDL_MapRGBA; + SDL_MapSurfaceRGB; + SDL_MapSurfaceRGBA; SDL_MaximizeWindow; SDL_MemoryBarrierAcquireFunction; SDL_MemoryBarrierReleaseFunction; @@ -573,17 +645,17 @@ SDL3_0.0.0 { SDL_Metal_DestroyView; SDL_Metal_GetLayer; SDL_MinimizeWindow; - SDL_MixAudioFormat; - SDL_OnApplicationDidBecomeActive; + SDL_MixAudio; SDL_OnApplicationDidChangeStatusBarOrientation; SDL_OnApplicationDidEnterBackground; + SDL_OnApplicationDidEnterForeground; SDL_OnApplicationDidReceiveMemoryWarning; + SDL_OnApplicationWillEnterBackground; SDL_OnApplicationWillEnterForeground; - SDL_OnApplicationWillResignActive; SDL_OnApplicationWillTerminate; SDL_OpenAudioDevice; SDL_OpenAudioDeviceStream; - SDL_OpenCameraDevice; + SDL_OpenCamera; SDL_OpenFileStorage; SDL_OpenGamepad; SDL_OpenHaptic; @@ -596,31 +668,39 @@ SDL3_0.0.0 { SDL_OpenTitleStorage; SDL_OpenURL; SDL_OpenUserStorage; + SDL_OutOfMemory; SDL_PauseAudioDevice; + SDL_PauseAudioStreamDevice; SDL_PauseHaptic; SDL_PeepEvents; - SDL_PenConnected; - SDL_PenConnected; SDL_PlayHapticRumble; SDL_PollEvent; - SDL_PostSemaphore; + SDL_PopGPUDebugGroup; SDL_PremultiplyAlpha; + SDL_PremultiplySurfaceAlpha; SDL_PumpEvents; SDL_PushEvent; + SDL_PushGPUComputeUniformData; + SDL_PushGPUDebugGroup; + SDL_PushGPUFragmentUniformData; + SDL_PushGPUVertexUniformData; SDL_PutAudioStreamData; - SDL_QueryTexture; + SDL_QueryGPUFence; SDL_Quit; SDL_QuitSubSystem; SDL_RaiseWindow; SDL_ReadIO; + SDL_ReadProcess; SDL_ReadS16BE; SDL_ReadS16LE; SDL_ReadS32BE; SDL_ReadS32LE; SDL_ReadS64BE; SDL_ReadS64LE; + SDL_ReadS8; SDL_ReadStorageFile; SDL_ReadSurfacePixel; + SDL_ReadSurfacePixelFloat; SDL_ReadU16BE; SDL_ReadU16LE; SDL_ReadU32BE; @@ -631,9 +711,21 @@ SDL3_0.0.0 { SDL_RegisterApp; SDL_RegisterEvents; SDL_ReleaseCameraFrame; + SDL_ReleaseGPUBuffer; + SDL_ReleaseGPUComputePipeline; + SDL_ReleaseGPUFence; + SDL_ReleaseGPUGraphicsPipeline; + SDL_ReleaseGPUSampler; + SDL_ReleaseGPUShader; + SDL_ReleaseGPUTexture; + SDL_ReleaseGPUTransferBuffer; + SDL_ReleaseWindowFromGPUDevice; SDL_ReloadGamepadMappings; + SDL_RemoveEventWatch; + SDL_RemoveHintCallback; SDL_RemovePath; SDL_RemoveStoragePath; + SDL_RemoveSurfaceAlternateImages; SDL_RemoveTimer; SDL_RenamePath; SDL_RenameStoragePath; @@ -645,7 +737,6 @@ SDL3_0.0.0 { SDL_RenderFillRects; SDL_RenderGeometry; SDL_RenderGeometryRaw; - SDL_RenderGeometryRawFloat; SDL_RenderLine; SDL_RenderLines; SDL_RenderPoint; @@ -654,16 +745,21 @@ SDL3_0.0.0 { SDL_RenderReadPixels; SDL_RenderRect; SDL_RenderRects; + SDL_RenderTexture9Grid; SDL_RenderTexture; SDL_RenderTextureRotated; + SDL_RenderTextureTiled; SDL_RenderViewportSet; SDL_ReportAssertion; + SDL_RequestAndroidPermission; SDL_ResetAssertionReport; SDL_ResetHint; SDL_ResetHints; SDL_ResetKeyboard; + SDL_ResetLogPriorities; SDL_RestoreWindow; SDL_ResumeAudioDevice; + SDL_ResumeAudioStreamDevice; SDL_ResumeHaptic; SDL_RumbleGamepad; SDL_RumbleGamepadTriggers; @@ -671,29 +767,49 @@ SDL3_0.0.0 { SDL_RumbleJoystickTriggers; SDL_RunApp; SDL_RunHapticEffect; - SDL_SIMDGetAlignment; SDL_SaveBMP; SDL_SaveBMP_IO; + SDL_ScaleSurface; SDL_ScreenKeyboardShown; SDL_ScreenSaverEnabled; SDL_SeekIO; + SDL_SendAndroidBackButton; + SDL_SendAndroidMessage; SDL_SendGamepadEffect; SDL_SendJoystickEffect; + SDL_SendJoystickVirtualSensorData; + SDL_SetAppMetadata; + SDL_SetAppMetadataProperty; SDL_SetAssertionHandler; + SDL_SetAtomicInt; + SDL_SetAtomicPointer; + SDL_SetAtomicU32; + SDL_SetAudioDeviceGain; SDL_SetAudioPostmixCallback; SDL_SetAudioStreamFormat; - SDL_SetAudioStreamFormat; SDL_SetAudioStreamFrequencyRatio; + SDL_SetAudioStreamGain; SDL_SetAudioStreamGetCallback; + SDL_SetAudioStreamInputChannelMap; + SDL_SetAudioStreamOutputChannelMap; SDL_SetAudioStreamPutCallback; SDL_SetBooleanProperty; SDL_SetClipboardData; SDL_SetClipboardText; + SDL_SetCurrentThreadPriority; SDL_SetCursor; + SDL_SetEnvironmentVariable; SDL_SetError; SDL_SetEventEnabled; SDL_SetEventFilter; SDL_SetFloatProperty; + SDL_SetGPUBlendConstants; + SDL_SetGPUBufferName; + SDL_SetGPUScissor; + SDL_SetGPUStencilReference; + SDL_SetGPUSwapchainParameters; + SDL_SetGPUTextureName; + SDL_SetGPUViewport; SDL_SetGamepadEventsEnabled; SDL_SetGamepadLED; SDL_SetGamepadMapping; @@ -703,23 +819,29 @@ SDL3_0.0.0 { SDL_SetHapticGain; SDL_SetHint; SDL_SetHintWithPriority; + SDL_SetInitialized; SDL_SetJoystickEventsEnabled; SDL_SetJoystickLED; SDL_SetJoystickPlayerIndex; SDL_SetJoystickVirtualAxis; + SDL_SetJoystickVirtualBall; SDL_SetJoystickVirtualButton; SDL_SetJoystickVirtualHat; + SDL_SetJoystickVirtualTouchpad; + SDL_SetLinuxThreadPriority; + SDL_SetLinuxThreadPriorityAndPolicy; SDL_SetLogOutputFunction; + SDL_SetLogPriorities; + SDL_SetLogPriority; + SDL_SetLogPriorityPrefix; SDL_SetMainReady; SDL_SetMemoryFunctions; SDL_SetModState; SDL_SetNumberProperty; SDL_SetPaletteColors; - SDL_SetPixelFormatPalette; + SDL_SetPointerProperty; + SDL_SetPointerPropertyWithCleanup; SDL_SetPrimarySelectionText; - SDL_SetProperty; - SDL_SetPropertyWithCleanup; - SDL_SetRelativeMouseMode; SDL_SetRenderClipRect; SDL_SetRenderColorScale; SDL_SetRenderDrawBlendMode; @@ -730,6 +852,7 @@ SDL3_0.0.0 { SDL_SetRenderTarget; SDL_SetRenderVSync; SDL_SetRenderViewport; + SDL_SetScancodeName; SDL_SetStringProperty; SDL_SetSurfaceAlphaMod; SDL_SetSurfaceBlendMode; @@ -740,36 +863,43 @@ SDL3_0.0.0 { SDL_SetSurfacePalette; SDL_SetSurfaceRLE; SDL_SetTLS; - SDL_SetTextInputRect; + SDL_SetTextInputArea; SDL_SetTextureAlphaMod; SDL_SetTextureAlphaModFloat; SDL_SetTextureBlendMode; SDL_SetTextureColorMod; SDL_SetTextureColorModFloat; SDL_SetTextureScaleMode; - SDL_SetThreadPriority; SDL_SetWindowAlwaysOnTop; + SDL_SetWindowAspectRatio; SDL_SetWindowBordered; SDL_SetWindowFocusable; SDL_SetWindowFullscreen; SDL_SetWindowFullscreenMode; SDL_SetWindowHitTest; SDL_SetWindowIcon; - SDL_SetWindowInputFocus; SDL_SetWindowKeyboardGrab; SDL_SetWindowMaximumSize; SDL_SetWindowMinimumSize; - SDL_SetWindowModalFor; + SDL_SetWindowModal; SDL_SetWindowMouseGrab; SDL_SetWindowMouseRect; SDL_SetWindowOpacity; + SDL_SetWindowParent; SDL_SetWindowPosition; + SDL_SetWindowRelativeMouseMode; SDL_SetWindowResizable; SDL_SetWindowShape; SDL_SetWindowSize; + SDL_SetWindowSurfaceVSync; SDL_SetWindowTitle; SDL_SetWindowsMessageHook; SDL_SetX11EventHook; + SDL_SetiOSAnimationCallback; + SDL_SetiOSEventPump; + SDL_ShouldInit; + SDL_ShouldQuit; + SDL_ShowAndroidToast; SDL_ShowCursor; SDL_ShowMessageBox; SDL_ShowOpenFileDialog; @@ -779,13 +909,19 @@ SDL3_0.0.0 { SDL_ShowWindow; SDL_ShowWindowSystemMenu; SDL_SignalCondition; - SDL_SoftStretch; + SDL_SignalSemaphore; SDL_StartTextInput; + SDL_StartTextInputWithProperties; + SDL_StepUTF8; SDL_StopHapticEffect; SDL_StopHapticEffects; SDL_StopHapticRumble; SDL_StopTextInput; SDL_StorageReady; + SDL_StringToGUID; + SDL_SubmitGPUCommandBuffer; + SDL_SubmitGPUCommandBufferAndAcquireFence; + SDL_SurfaceHasAlternateImages; SDL_SurfaceHasColorKey; SDL_SurfaceHasRLE; SDL_SyncWindow; @@ -799,6 +935,7 @@ SDL3_0.0.0 { SDL_TryLockRWLockForWriting; SDL_TryLockSpinlock; SDL_TryWaitSemaphore; + SDL_UCS4ToUTF8; SDL_UnbindAudioStream; SDL_UnbindAudioStreams; SDL_UnloadObject; @@ -810,7 +947,9 @@ SDL3_0.0.0 { SDL_UnlockSpinlock; SDL_UnlockSurface; SDL_UnlockTexture; + SDL_UnmapGPUTransferBuffer; SDL_UnregisterApp; + SDL_UnsetEnvironmentVariable; SDL_UpdateGamepads; SDL_UpdateHapticEffect; SDL_UpdateJoysticks; @@ -820,8 +959,12 @@ SDL3_0.0.0 { SDL_UpdateWindowSurface; SDL_UpdateWindowSurfaceRects; SDL_UpdateYUVTexture; + SDL_UploadToGPUBuffer; + SDL_UploadToGPUTexture; SDL_Vulkan_CreateSurface; + SDL_Vulkan_DestroySurface; SDL_Vulkan_GetInstanceExtensions; + SDL_Vulkan_GetPresentationSupport; SDL_Vulkan_GetVkGetInstanceProcAddr; SDL_Vulkan_LoadLibrary; SDL_Vulkan_UnloadLibrary; @@ -829,16 +972,18 @@ SDL3_0.0.0 { SDL_WaitConditionTimeout; SDL_WaitEvent; SDL_WaitEventTimeout; + SDL_WaitForGPUFences; + SDL_WaitForGPUIdle; + SDL_WaitProcess; SDL_WaitSemaphore; SDL_WaitSemaphoreTimeout; SDL_WaitThread; SDL_WarpMouseGlobal; SDL_WarpMouseInWindow; SDL_WasInit; - SDL_WinRTGetDeviceFamily; - SDL_WinRTGetFSPathUNICODE; - SDL_WinRTGetFSPathUTF8; SDL_WindowHasSurface; + SDL_WindowSupportsGPUPresentMode; + SDL_WindowSupportsGPUSwapchainComposition; SDL_WriteIO; SDL_WriteS16BE; SDL_WriteS16LE; @@ -846,6 +991,10 @@ SDL3_0.0.0 { SDL_WriteS32LE; SDL_WriteS64BE; SDL_WriteS64LE; + SDL_WriteS8; + SDL_WriteStorageFile; + SDL_WriteSurfacePixel; + SDL_WriteSurfacePixelFloat; SDL_WriteU16BE; SDL_WriteU16LE; SDL_WriteU32BE; @@ -888,6 +1037,7 @@ SDL3_0.0.0 { SDL_fmodf; SDL_free; SDL_getenv; + SDL_getenv_unsafe; SDL_hid_ble_scan; SDL_hid_close; SDL_hid_device_change_count; @@ -910,8 +1060,6 @@ SDL3_0.0.0 { SDL_hid_send_feature_report; SDL_hid_set_nonblocking; SDL_hid_write; - SDL_iPhoneSetAnimationCallback; - SDL_iPhoneSetEventPump; SDL_iconv; SDL_iconv_close; SDL_iconv_open; @@ -922,7 +1070,11 @@ SDL3_0.0.0 { SDL_iscntrl; SDL_isdigit; SDL_isgraph; + SDL_isinf; + SDL_isinff; SDL_islower; + SDL_isnan; + SDL_isnanf; SDL_isprint; SDL_ispunct; SDL_isspace; @@ -945,21 +1097,29 @@ SDL3_0.0.0 { SDL_memset; SDL_modf; SDL_modff; + SDL_murmur3_32; SDL_pow; SDL_powf; SDL_qsort; SDL_qsort_r; + SDL_rand; + SDL_rand_bits; + SDL_rand_bits_r; + SDL_rand_r; + SDL_randf; + SDL_randf_r; SDL_realloc; SDL_round; SDL_roundf; SDL_scalbn; SDL_scalbnf; - SDL_setenv; + SDL_setenv_unsafe; SDL_sin; SDL_sinf; SDL_snprintf; SDL_sqrt; SDL_sqrtf; + SDL_srand; SDL_sscanf; SDL_strcasecmp; SDL_strcasestr; @@ -975,6 +1135,7 @@ SDL3_0.0.0 { SDL_strndup; SDL_strnlen; SDL_strnstr; + SDL_strpbrk; SDL_strrchr; SDL_strrev; SDL_strstr; @@ -995,6 +1156,7 @@ SDL3_0.0.0 { SDL_uitoa; SDL_ulltoa; SDL_ultoa; + SDL_unsetenv_unsafe; SDL_utf8strlcpy; SDL_utf8strlen; SDL_utf8strnlen; diff --git a/libs/SDL3/src/dynapi/SDL_dynapi_overrides.h b/libs/SDL3/src/dynapi/SDL_dynapi_overrides.h index b94b0e836..ab9ac5352 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi_overrides.h +++ b/libs/SDL3/src/dynapi/SDL_dynapi_overrides.h @@ -20,55 +20,64 @@ */ -/* DO NOT EDIT THIS FILE BY HAND. It is autogenerated by gendynapi.pl. */ +// DO NOT EDIT THIS FILE BY HAND. It is autogenerated by gendynapi.py. #if !SDL_DYNAMIC_API #error You should not be here. #endif -/* New API symbols are added at the end */ +// New API symbols are added at the end #define SDL_AcquireCameraFrame SDL_AcquireCameraFrame_REAL +#define SDL_AcquireGPUCommandBuffer SDL_AcquireGPUCommandBuffer_REAL +#define SDL_AcquireGPUSwapchainTexture SDL_AcquireGPUSwapchainTexture_REAL +#define SDL_AddAtomicInt SDL_AddAtomicInt_REAL #define SDL_AddEventWatch SDL_AddEventWatch_REAL #define SDL_AddGamepadMapping SDL_AddGamepadMapping_REAL #define SDL_AddGamepadMappingsFromFile SDL_AddGamepadMappingsFromFile_REAL #define SDL_AddGamepadMappingsFromIO SDL_AddGamepadMappingsFromIO_REAL #define SDL_AddHintCallback SDL_AddHintCallback_REAL +#define SDL_AddSurfaceAlternateImage SDL_AddSurfaceAlternateImage_REAL #define SDL_AddTimer SDL_AddTimer_REAL +#define SDL_AddTimerNS SDL_AddTimerNS_REAL #define SDL_AddVulkanRenderSemaphores SDL_AddVulkanRenderSemaphores_REAL -#define SDL_AllocateEventMemory SDL_AllocateEventMemory_REAL -#define SDL_AndroidBackButton SDL_AndroidBackButton_REAL -#define SDL_AndroidGetActivity SDL_AndroidGetActivity_REAL -#define SDL_AndroidGetExternalStoragePath SDL_AndroidGetExternalStoragePath_REAL -#define SDL_AndroidGetExternalStorageState SDL_AndroidGetExternalStorageState_REAL -#define SDL_AndroidGetInternalStoragePath SDL_AndroidGetInternalStoragePath_REAL -#define SDL_AndroidGetJNIEnv SDL_AndroidGetJNIEnv_REAL -#define SDL_AndroidRequestPermission SDL_AndroidRequestPermission_REAL -#define SDL_AndroidSendMessage SDL_AndroidSendMessage_REAL -#define SDL_AndroidShowToast SDL_AndroidShowToast_REAL -#define SDL_AtomicAdd SDL_AtomicAdd_REAL -#define SDL_AtomicCompareAndSwap SDL_AtomicCompareAndSwap_REAL -#define SDL_AtomicCompareAndSwapPointer SDL_AtomicCompareAndSwapPointer_REAL -#define SDL_AtomicGet SDL_AtomicGet_REAL -#define SDL_AtomicGetPtr SDL_AtomicGetPtr_REAL -#define SDL_AtomicSet SDL_AtomicSet_REAL -#define SDL_AtomicSetPtr SDL_AtomicSetPtr_REAL #define SDL_AttachVirtualJoystick SDL_AttachVirtualJoystick_REAL -#define SDL_AttachVirtualJoystickEx SDL_AttachVirtualJoystickEx_REAL #define SDL_AudioDevicePaused SDL_AudioDevicePaused_REAL +#define SDL_BeginGPUComputePass SDL_BeginGPUComputePass_REAL +#define SDL_BeginGPUCopyPass SDL_BeginGPUCopyPass_REAL +#define SDL_BeginGPURenderPass SDL_BeginGPURenderPass_REAL #define SDL_BindAudioStream SDL_BindAudioStream_REAL #define SDL_BindAudioStreams SDL_BindAudioStreams_REAL +#define SDL_BindGPUComputePipeline SDL_BindGPUComputePipeline_REAL +#define SDL_BindGPUComputeSamplers SDL_BindGPUComputeSamplers_REAL +#define SDL_BindGPUComputeStorageBuffers SDL_BindGPUComputeStorageBuffers_REAL +#define SDL_BindGPUComputeStorageTextures SDL_BindGPUComputeStorageTextures_REAL +#define SDL_BindGPUFragmentSamplers SDL_BindGPUFragmentSamplers_REAL +#define SDL_BindGPUFragmentStorageBuffers SDL_BindGPUFragmentStorageBuffers_REAL +#define SDL_BindGPUFragmentStorageTextures SDL_BindGPUFragmentStorageTextures_REAL +#define SDL_BindGPUGraphicsPipeline SDL_BindGPUGraphicsPipeline_REAL +#define SDL_BindGPUIndexBuffer SDL_BindGPUIndexBuffer_REAL +#define SDL_BindGPUVertexBuffers SDL_BindGPUVertexBuffers_REAL +#define SDL_BindGPUVertexSamplers SDL_BindGPUVertexSamplers_REAL +#define SDL_BindGPUVertexStorageBuffers SDL_BindGPUVertexStorageBuffers_REAL +#define SDL_BindGPUVertexStorageTextures SDL_BindGPUVertexStorageTextures_REAL +#define SDL_BlitGPUTexture SDL_BlitGPUTexture_REAL #define SDL_BlitSurface SDL_BlitSurface_REAL +#define SDL_BlitSurface9Grid SDL_BlitSurface9Grid_REAL #define SDL_BlitSurfaceScaled SDL_BlitSurfaceScaled_REAL +#define SDL_BlitSurfaceTiled SDL_BlitSurfaceTiled_REAL +#define SDL_BlitSurfaceTiledWithScale SDL_BlitSurfaceTiledWithScale_REAL #define SDL_BlitSurfaceUnchecked SDL_BlitSurfaceUnchecked_REAL #define SDL_BlitSurfaceUncheckedScaled SDL_BlitSurfaceUncheckedScaled_REAL #define SDL_BroadcastCondition SDL_BroadcastCondition_REAL #define SDL_CaptureMouse SDL_CaptureMouse_REAL +#define SDL_ClaimWindowForGPUDevice SDL_ClaimWindowForGPUDevice_REAL #define SDL_CleanupTLS SDL_CleanupTLS_REAL #define SDL_ClearAudioStream SDL_ClearAudioStream_REAL #define SDL_ClearClipboardData SDL_ClearClipboardData_REAL #define SDL_ClearComposition SDL_ClearComposition_REAL #define SDL_ClearError SDL_ClearError_REAL #define SDL_ClearProperty SDL_ClearProperty_REAL +#define SDL_ClearSurface SDL_ClearSurface_REAL #define SDL_CloseAudioDevice SDL_CloseAudioDevice_REAL #define SDL_CloseCamera SDL_CloseCamera_REAL #define SDL_CloseGamepad SDL_CloseGamepad_REAL @@ -77,25 +86,42 @@ #define SDL_CloseJoystick SDL_CloseJoystick_REAL #define SDL_CloseSensor SDL_CloseSensor_REAL #define SDL_CloseStorage SDL_CloseStorage_REAL +#define SDL_CompareAndSwapAtomicInt SDL_CompareAndSwapAtomicInt_REAL +#define SDL_CompareAndSwapAtomicPointer SDL_CompareAndSwapAtomicPointer_REAL +#define SDL_CompareAndSwapAtomicU32 SDL_CompareAndSwapAtomicU32_REAL #define SDL_ComposeCustomBlendMode SDL_ComposeCustomBlendMode_REAL #define SDL_ConvertAudioSamples SDL_ConvertAudioSamples_REAL #define SDL_ConvertEventToRenderCoordinates SDL_ConvertEventToRenderCoordinates_REAL #define SDL_ConvertPixels SDL_ConvertPixels_REAL #define SDL_ConvertPixelsAndColorspace SDL_ConvertPixelsAndColorspace_REAL #define SDL_ConvertSurface SDL_ConvertSurface_REAL -#define SDL_ConvertSurfaceFormat SDL_ConvertSurfaceFormat_REAL -#define SDL_ConvertSurfaceFormatAndColorspace SDL_ConvertSurfaceFormatAndColorspace_REAL +#define SDL_ConvertSurfaceAndColorspace SDL_ConvertSurfaceAndColorspace_REAL +#define SDL_CopyFile SDL_CopyFile_REAL +#define SDL_CopyGPUBufferToBuffer SDL_CopyGPUBufferToBuffer_REAL +#define SDL_CopyGPUTextureToTexture SDL_CopyGPUTextureToTexture_REAL #define SDL_CopyProperties SDL_CopyProperties_REAL +#define SDL_CopyStorageFile SDL_CopyStorageFile_REAL #define SDL_CreateAudioStream SDL_CreateAudioStream_REAL #define SDL_CreateColorCursor SDL_CreateColorCursor_REAL #define SDL_CreateCondition SDL_CreateCondition_REAL #define SDL_CreateCursor SDL_CreateCursor_REAL #define SDL_CreateDirectory SDL_CreateDirectory_REAL +#define SDL_CreateEnvironment SDL_CreateEnvironment_REAL +#define SDL_CreateGPUBuffer SDL_CreateGPUBuffer_REAL +#define SDL_CreateGPUComputePipeline SDL_CreateGPUComputePipeline_REAL +#define SDL_CreateGPUDevice SDL_CreateGPUDevice_REAL +#define SDL_CreateGPUDeviceWithProperties SDL_CreateGPUDeviceWithProperties_REAL +#define SDL_CreateGPUGraphicsPipeline SDL_CreateGPUGraphicsPipeline_REAL +#define SDL_CreateGPUSampler SDL_CreateGPUSampler_REAL +#define SDL_CreateGPUShader SDL_CreateGPUShader_REAL +#define SDL_CreateGPUTexture SDL_CreateGPUTexture_REAL +#define SDL_CreateGPUTransferBuffer SDL_CreateGPUTransferBuffer_REAL #define SDL_CreateHapticEffect SDL_CreateHapticEffect_REAL #define SDL_CreateMutex SDL_CreateMutex_REAL #define SDL_CreatePalette SDL_CreatePalette_REAL -#define SDL_CreatePixelFormat SDL_CreatePixelFormat_REAL #define SDL_CreatePopupWindow SDL_CreatePopupWindow_REAL +#define SDL_CreateProcess SDL_CreateProcess_REAL +#define SDL_CreateProcessWithProperties SDL_CreateProcessWithProperties_REAL #define SDL_CreateProperties SDL_CreateProperties_REAL #define SDL_CreateRWLock SDL_CreateRWLock_REAL #define SDL_CreateRenderer SDL_CreateRenderer_REAL @@ -105,30 +131,29 @@ #define SDL_CreateStorageDirectory SDL_CreateStorageDirectory_REAL #define SDL_CreateSurface SDL_CreateSurface_REAL #define SDL_CreateSurfaceFrom SDL_CreateSurfaceFrom_REAL +#define SDL_CreateSurfacePalette SDL_CreateSurfacePalette_REAL #define SDL_CreateSystemCursor SDL_CreateSystemCursor_REAL -#define SDL_CreateTLS SDL_CreateTLS_REAL #define SDL_CreateTexture SDL_CreateTexture_REAL #define SDL_CreateTextureFromSurface SDL_CreateTextureFromSurface_REAL #define SDL_CreateTextureWithProperties SDL_CreateTextureWithProperties_REAL -#define SDL_CreateThread SDL_CreateThread_REAL -#define SDL_CreateThreadWithStackSize SDL_CreateThreadWithStackSize_REAL +#define SDL_CreateThreadRuntime SDL_CreateThreadRuntime_REAL +#define SDL_CreateThreadWithPropertiesRuntime SDL_CreateThreadWithPropertiesRuntime_REAL #define SDL_CreateWindow SDL_CreateWindow_REAL #define SDL_CreateWindowAndRenderer SDL_CreateWindowAndRenderer_REAL #define SDL_CreateWindowWithProperties SDL_CreateWindowWithProperties_REAL #define SDL_CursorVisible SDL_CursorVisible_REAL -#define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL #define SDL_DateTimeToTime SDL_DateTimeToTime_REAL -#define SDL_DelEventWatch SDL_DelEventWatch_REAL -#define SDL_DelHintCallback SDL_DelHintCallback_REAL #define SDL_Delay SDL_Delay_REAL #define SDL_DelayNS SDL_DelayNS_REAL #define SDL_DestroyAudioStream SDL_DestroyAudioStream_REAL #define SDL_DestroyCondition SDL_DestroyCondition_REAL #define SDL_DestroyCursor SDL_DestroyCursor_REAL +#define SDL_DestroyEnvironment SDL_DestroyEnvironment_REAL +#define SDL_DestroyGPUDevice SDL_DestroyGPUDevice_REAL #define SDL_DestroyHapticEffect SDL_DestroyHapticEffect_REAL #define SDL_DestroyMutex SDL_DestroyMutex_REAL #define SDL_DestroyPalette SDL_DestroyPalette_REAL -#define SDL_DestroyPixelFormat SDL_DestroyPixelFormat_REAL +#define SDL_DestroyProcess SDL_DestroyProcess_REAL #define SDL_DestroyProperties SDL_DestroyProperties_REAL #define SDL_DestroyRWLock SDL_DestroyRWLock_REAL #define SDL_DestroyRenderer SDL_DestroyRenderer_REAL @@ -139,20 +164,29 @@ #define SDL_DestroyWindowSurface SDL_DestroyWindowSurface_REAL #define SDL_DetachThread SDL_DetachThread_REAL #define SDL_DetachVirtualJoystick SDL_DetachVirtualJoystick_REAL -#define SDL_Direct3D9GetAdapterIndex SDL_Direct3D9GetAdapterIndex_REAL #define SDL_DisableScreenSaver SDL_DisableScreenSaver_REAL +#define SDL_DispatchGPUCompute SDL_DispatchGPUCompute_REAL +#define SDL_DispatchGPUComputeIndirect SDL_DispatchGPUComputeIndirect_REAL +#define SDL_DownloadFromGPUBuffer SDL_DownloadFromGPUBuffer_REAL +#define SDL_DownloadFromGPUTexture SDL_DownloadFromGPUTexture_REAL +#define SDL_DrawGPUIndexedPrimitives SDL_DrawGPUIndexedPrimitives_REAL +#define SDL_DrawGPUIndexedPrimitivesIndirect SDL_DrawGPUIndexedPrimitivesIndirect_REAL +#define SDL_DrawGPUPrimitives SDL_DrawGPUPrimitives_REAL +#define SDL_DrawGPUPrimitivesIndirect SDL_DrawGPUPrimitivesIndirect_REAL #define SDL_DuplicateSurface SDL_DuplicateSurface_REAL -#define SDL_EGL_GetCurrentEGLConfig SDL_EGL_GetCurrentEGLConfig_REAL -#define SDL_EGL_GetCurrentEGLDisplay SDL_EGL_GetCurrentEGLDisplay_REAL +#define SDL_EGL_GetCurrentConfig SDL_EGL_GetCurrentConfig_REAL +#define SDL_EGL_GetCurrentDisplay SDL_EGL_GetCurrentDisplay_REAL #define SDL_EGL_GetProcAddress SDL_EGL_GetProcAddress_REAL -#define SDL_EGL_GetWindowEGLSurface SDL_EGL_GetWindowEGLSurface_REAL -#define SDL_EGL_SetEGLAttributeCallbacks SDL_EGL_SetEGLAttributeCallbacks_REAL +#define SDL_EGL_GetWindowSurface SDL_EGL_GetWindowSurface_REAL +#define SDL_EGL_SetAttributeCallbacks SDL_EGL_SetAttributeCallbacks_REAL #define SDL_EnableScreenSaver SDL_EnableScreenSaver_REAL +#define SDL_EndGPUComputePass SDL_EndGPUComputePass_REAL +#define SDL_EndGPUCopyPass SDL_EndGPUCopyPass_REAL +#define SDL_EndGPURenderPass SDL_EndGPURenderPass_REAL #define SDL_EnterAppMainCallbacks SDL_EnterAppMainCallbacks_REAL #define SDL_EnumerateDirectory SDL_EnumerateDirectory_REAL #define SDL_EnumerateProperties SDL_EnumerateProperties_REAL #define SDL_EnumerateStorageDirectory SDL_EnumerateStorageDirectory_REAL -#define SDL_Error SDL_Error_REAL #define SDL_EventEnabled SDL_EventEnabled_REAL #define SDL_FillSurfaceRect SDL_FillSurfaceRect_REAL #define SDL_FillSurfaceRects SDL_FillSurfaceRects_REAL @@ -162,12 +196,13 @@ #define SDL_FlushAudioStream SDL_FlushAudioStream_REAL #define SDL_FlushEvent SDL_FlushEvent_REAL #define SDL_FlushEvents SDL_FlushEvents_REAL +#define SDL_FlushIO SDL_FlushIO_REAL #define SDL_FlushRenderer SDL_FlushRenderer_REAL -#define SDL_GDKGetDefaultUser SDL_GDKGetDefaultUser_REAL -#define SDL_GDKGetTaskQueue SDL_GDKGetTaskQueue_REAL -#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL +#define SDL_GDKResumeGPU SDL_GDKResumeGPU_REAL +#define SDL_GDKSuspendComplete SDL_GDKSuspendComplete_REAL +#define SDL_GDKSuspendGPU SDL_GDKSuspendGPU_REAL #define SDL_GL_CreateContext SDL_GL_CreateContext_REAL -#define SDL_GL_DeleteContext SDL_GL_DeleteContext_REAL +#define SDL_GL_DestroyContext SDL_GL_DestroyContext_REAL #define SDL_GL_ExtensionSupported SDL_GL_ExtensionSupported_REAL #define SDL_GL_GetAttribute SDL_GL_GetAttribute_REAL #define SDL_GL_GetCurrentContext SDL_GL_GetCurrentContext_REAL @@ -181,7 +216,11 @@ #define SDL_GL_SetSwapInterval SDL_GL_SetSwapInterval_REAL #define SDL_GL_SwapWindow SDL_GL_SwapWindow_REAL #define SDL_GL_UnloadLibrary SDL_GL_UnloadLibrary_REAL -#define SDL_GUIDFromString SDL_GUIDFromString_REAL +#define SDL_GPUSupportsProperties SDL_GPUSupportsProperties_REAL +#define SDL_GPUSupportsShaderFormats SDL_GPUSupportsShaderFormats_REAL +#define SDL_GPUTextureFormatTexelBlockSize SDL_GPUTextureFormatTexelBlockSize_REAL +#define SDL_GPUTextureSupportsFormat SDL_GPUTextureSupportsFormat_REAL +#define SDL_GPUTextureSupportsSampleCount SDL_GPUTextureSupportsSampleCount_REAL #define SDL_GUIDToString SDL_GUIDToString_REAL #define SDL_GamepadConnected SDL_GamepadConnected_REAL #define SDL_GamepadEventsEnabled SDL_GamepadEventsEnabled_REAL @@ -189,35 +228,52 @@ #define SDL_GamepadHasButton SDL_GamepadHasButton_REAL #define SDL_GamepadHasSensor SDL_GamepadHasSensor_REAL #define SDL_GamepadSensorEnabled SDL_GamepadSensorEnabled_REAL -#define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL +#define SDL_GenerateMipmapsForGPUTexture SDL_GenerateMipmapsForGPUTexture_REAL +#define SDL_GetAndroidActivity SDL_GetAndroidActivity_REAL +#define SDL_GetAndroidCachePath SDL_GetAndroidCachePath_REAL +#define SDL_GetAndroidExternalStoragePath SDL_GetAndroidExternalStoragePath_REAL +#define SDL_GetAndroidExternalStorageState SDL_GetAndroidExternalStorageState_REAL +#define SDL_GetAndroidInternalStoragePath SDL_GetAndroidInternalStoragePath_REAL +#define SDL_GetAndroidJNIEnv SDL_GetAndroidJNIEnv_REAL +#define SDL_GetAndroidSDKVersion SDL_GetAndroidSDKVersion_REAL +#define SDL_GetAppMetadataProperty SDL_GetAppMetadataProperty_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_GetAssertionReport SDL_GetAssertionReport_REAL -#define SDL_GetAudioCaptureDevices SDL_GetAudioCaptureDevices_REAL +#define SDL_GetAtomicInt SDL_GetAtomicInt_REAL +#define SDL_GetAtomicPointer SDL_GetAtomicPointer_REAL +#define SDL_GetAtomicU32 SDL_GetAtomicU32_REAL +#define SDL_GetAudioDeviceChannelMap SDL_GetAudioDeviceChannelMap_REAL #define SDL_GetAudioDeviceFormat SDL_GetAudioDeviceFormat_REAL +#define SDL_GetAudioDeviceGain SDL_GetAudioDeviceGain_REAL #define SDL_GetAudioDeviceName SDL_GetAudioDeviceName_REAL #define SDL_GetAudioDriver SDL_GetAudioDriver_REAL -#define SDL_GetAudioOutputDevices SDL_GetAudioOutputDevices_REAL +#define SDL_GetAudioFormatName SDL_GetAudioFormatName_REAL +#define SDL_GetAudioPlaybackDevices SDL_GetAudioPlaybackDevices_REAL +#define SDL_GetAudioRecordingDevices SDL_GetAudioRecordingDevices_REAL #define SDL_GetAudioStreamAvailable SDL_GetAudioStreamAvailable_REAL #define SDL_GetAudioStreamData SDL_GetAudioStreamData_REAL #define SDL_GetAudioStreamDevice SDL_GetAudioStreamDevice_REAL #define SDL_GetAudioStreamFormat SDL_GetAudioStreamFormat_REAL #define SDL_GetAudioStreamFrequencyRatio SDL_GetAudioStreamFrequencyRatio_REAL +#define SDL_GetAudioStreamGain SDL_GetAudioStreamGain_REAL +#define SDL_GetAudioStreamInputChannelMap SDL_GetAudioStreamInputChannelMap_REAL +#define SDL_GetAudioStreamOutputChannelMap SDL_GetAudioStreamOutputChannelMap_REAL #define SDL_GetAudioStreamProperties SDL_GetAudioStreamProperties_REAL #define SDL_GetAudioStreamQueued SDL_GetAudioStreamQueued_REAL #define SDL_GetBasePath SDL_GetBasePath_REAL #define SDL_GetBooleanProperty SDL_GetBooleanProperty_REAL #define SDL_GetCPUCacheLineSize SDL_GetCPUCacheLineSize_REAL -#define SDL_GetCPUCount SDL_GetCPUCount_REAL -#define SDL_GetCameraDeviceName SDL_GetCameraDeviceName_REAL -#define SDL_GetCameraDevicePosition SDL_GetCameraDevicePosition_REAL -#define SDL_GetCameraDeviceSupportedFormats SDL_GetCameraDeviceSupportedFormats_REAL -#define SDL_GetCameraDevices SDL_GetCameraDevices_REAL #define SDL_GetCameraDriver SDL_GetCameraDriver_REAL #define SDL_GetCameraFormat SDL_GetCameraFormat_REAL -#define SDL_GetCameraInstanceID SDL_GetCameraInstanceID_REAL +#define SDL_GetCameraID SDL_GetCameraID_REAL +#define SDL_GetCameraName SDL_GetCameraName_REAL #define SDL_GetCameraPermissionState SDL_GetCameraPermissionState_REAL +#define SDL_GetCameraPosition SDL_GetCameraPosition_REAL #define SDL_GetCameraProperties SDL_GetCameraProperties_REAL +#define SDL_GetCameraSupportedFormats SDL_GetCameraSupportedFormats_REAL +#define SDL_GetCameras SDL_GetCameras_REAL #define SDL_GetClipboardData SDL_GetClipboardData_REAL +#define SDL_GetClipboardMimeTypes SDL_GetClipboardMimeTypes_REAL #define SDL_GetClipboardText SDL_GetClipboardText_REAL #define SDL_GetClosestFullscreenDisplayMode SDL_GetClosestFullscreenDisplayMode_REAL #define SDL_GetCurrentAudioDriver SDL_GetCurrentAudioDriver_REAL @@ -229,12 +285,15 @@ #define SDL_GetCurrentTime SDL_GetCurrentTime_REAL #define SDL_GetCurrentVideoDriver SDL_GetCurrentVideoDriver_REAL #define SDL_GetCursor SDL_GetCursor_REAL +#define SDL_GetDXGIOutputInfo SDL_GetDXGIOutputInfo_REAL +#define SDL_GetDateTimeLocalePreferences SDL_GetDateTimeLocalePreferences_REAL #define SDL_GetDayOfWeek SDL_GetDayOfWeek_REAL #define SDL_GetDayOfYear SDL_GetDayOfYear_REAL #define SDL_GetDaysInMonth SDL_GetDaysInMonth_REAL #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL #define SDL_GetDefaultCursor SDL_GetDefaultCursor_REAL #define SDL_GetDesktopDisplayMode SDL_GetDesktopDisplayMode_REAL +#define SDL_GetDirect3D9AdapterIndex SDL_GetDirect3D9AdapterIndex_REAL #define SDL_GetDisplayBounds SDL_GetDisplayBounds_REAL #define SDL_GetDisplayContentScale SDL_GetDisplayContentScale_REAL #define SDL_GetDisplayForPoint SDL_GetDisplayForPoint_REAL @@ -244,10 +303,19 @@ #define SDL_GetDisplayProperties SDL_GetDisplayProperties_REAL #define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL #define SDL_GetDisplays SDL_GetDisplays_REAL +#define SDL_GetEnvironment SDL_GetEnvironment_REAL +#define SDL_GetEnvironmentVariable SDL_GetEnvironmentVariable_REAL +#define SDL_GetEnvironmentVariables SDL_GetEnvironmentVariables_REAL #define SDL_GetError SDL_GetError_REAL #define SDL_GetEventFilter SDL_GetEventFilter_REAL #define SDL_GetFloatProperty SDL_GetFloatProperty_REAL #define SDL_GetFullscreenDisplayModes SDL_GetFullscreenDisplayModes_REAL +#define SDL_GetGDKDefaultUser SDL_GetGDKDefaultUser_REAL +#define SDL_GetGDKTaskQueue SDL_GetGDKTaskQueue_REAL +#define SDL_GetGPUDeviceDriver SDL_GetGPUDeviceDriver_REAL +#define SDL_GetGPUDriver SDL_GetGPUDriver_REAL +#define SDL_GetGPUShaderFormats SDL_GetGPUShaderFormats_REAL +#define SDL_GetGPUSwapchainTextureFormat SDL_GetGPUSwapchainTextureFormat_REAL #define SDL_GetGamepadAppleSFSymbolsNameForAxis SDL_GetGamepadAppleSFSymbolsNameForAxis_REAL #define SDL_GetGamepadAppleSFSymbolsNameForButton SDL_GetGamepadAppleSFSymbolsNameForButton_REAL #define SDL_GetGamepadAxis SDL_GetGamepadAxis_REAL @@ -259,28 +327,26 @@ #define SDL_GetGamepadButtonLabelForType SDL_GetGamepadButtonLabelForType_REAL #define SDL_GetGamepadConnectionState SDL_GetGamepadConnectionState_REAL #define SDL_GetGamepadFirmwareVersion SDL_GetGamepadFirmwareVersion_REAL -#define SDL_GetGamepadFromInstanceID SDL_GetGamepadFromInstanceID_REAL +#define SDL_GetGamepadFromID SDL_GetGamepadFromID_REAL #define SDL_GetGamepadFromPlayerIndex SDL_GetGamepadFromPlayerIndex_REAL -#define SDL_GetGamepadInstanceGUID SDL_GetGamepadInstanceGUID_REAL -#define SDL_GetGamepadInstanceID SDL_GetGamepadInstanceID_REAL -#define SDL_GetGamepadInstanceMapping SDL_GetGamepadInstanceMapping_REAL -#define SDL_GetGamepadInstanceName SDL_GetGamepadInstanceName_REAL -#define SDL_GetGamepadInstancePath SDL_GetGamepadInstancePath_REAL -#define SDL_GetGamepadInstancePlayerIndex SDL_GetGamepadInstancePlayerIndex_REAL -#define SDL_GetGamepadInstanceProduct SDL_GetGamepadInstanceProduct_REAL -#define SDL_GetGamepadInstanceProductVersion SDL_GetGamepadInstanceProductVersion_REAL -#define SDL_GetGamepadInstanceType SDL_GetGamepadInstanceType_REAL -#define SDL_GetGamepadInstanceVendor SDL_GetGamepadInstanceVendor_REAL +#define SDL_GetGamepadGUIDForID SDL_GetGamepadGUIDForID_REAL +#define SDL_GetGamepadID SDL_GetGamepadID_REAL #define SDL_GetGamepadJoystick SDL_GetGamepadJoystick_REAL #define SDL_GetGamepadMapping SDL_GetGamepadMapping_REAL #define SDL_GetGamepadMappingForGUID SDL_GetGamepadMappingForGUID_REAL +#define SDL_GetGamepadMappingForID SDL_GetGamepadMappingForID_REAL #define SDL_GetGamepadMappings SDL_GetGamepadMappings_REAL #define SDL_GetGamepadName SDL_GetGamepadName_REAL +#define SDL_GetGamepadNameForID SDL_GetGamepadNameForID_REAL #define SDL_GetGamepadPath SDL_GetGamepadPath_REAL +#define SDL_GetGamepadPathForID SDL_GetGamepadPathForID_REAL #define SDL_GetGamepadPlayerIndex SDL_GetGamepadPlayerIndex_REAL +#define SDL_GetGamepadPlayerIndexForID SDL_GetGamepadPlayerIndexForID_REAL #define SDL_GetGamepadPowerInfo SDL_GetGamepadPowerInfo_REAL #define SDL_GetGamepadProduct SDL_GetGamepadProduct_REAL +#define SDL_GetGamepadProductForID SDL_GetGamepadProductForID_REAL #define SDL_GetGamepadProductVersion SDL_GetGamepadProductVersion_REAL +#define SDL_GetGamepadProductVersionForID SDL_GetGamepadProductVersionForID_REAL #define SDL_GetGamepadProperties SDL_GetGamepadProperties_REAL #define SDL_GetGamepadSensorData SDL_GetGamepadSensorData_REAL #define SDL_GetGamepadSensorDataRate SDL_GetGamepadSensorDataRate_REAL @@ -291,18 +357,20 @@ #define SDL_GetGamepadStringForType SDL_GetGamepadStringForType_REAL #define SDL_GetGamepadTouchpadFinger SDL_GetGamepadTouchpadFinger_REAL #define SDL_GetGamepadType SDL_GetGamepadType_REAL +#define SDL_GetGamepadTypeForID SDL_GetGamepadTypeForID_REAL #define SDL_GetGamepadTypeFromString SDL_GetGamepadTypeFromString_REAL #define SDL_GetGamepadVendor SDL_GetGamepadVendor_REAL +#define SDL_GetGamepadVendorForID SDL_GetGamepadVendorForID_REAL #define SDL_GetGamepads SDL_GetGamepads_REAL #define SDL_GetGlobalMouseState SDL_GetGlobalMouseState_REAL #define SDL_GetGlobalProperties SDL_GetGlobalProperties_REAL #define SDL_GetGrabbedWindow SDL_GetGrabbedWindow_REAL #define SDL_GetHapticEffectStatus SDL_GetHapticEffectStatus_REAL #define SDL_GetHapticFeatures SDL_GetHapticFeatures_REAL -#define SDL_GetHapticFromInstanceID SDL_GetHapticFromInstanceID_REAL -#define SDL_GetHapticInstanceID SDL_GetHapticInstanceID_REAL -#define SDL_GetHapticInstanceName SDL_GetHapticInstanceName_REAL +#define SDL_GetHapticFromID SDL_GetHapticFromID_REAL +#define SDL_GetHapticID SDL_GetHapticID_REAL #define SDL_GetHapticName SDL_GetHapticName_REAL +#define SDL_GetHapticNameForID SDL_GetHapticNameForID_REAL #define SDL_GetHaptics SDL_GetHaptics_REAL #define SDL_GetHint SDL_GetHint_REAL #define SDL_GetHintBoolean SDL_GetHintBoolean_REAL @@ -315,54 +383,54 @@ #define SDL_GetJoystickButton SDL_GetJoystickButton_REAL #define SDL_GetJoystickConnectionState SDL_GetJoystickConnectionState_REAL #define SDL_GetJoystickFirmwareVersion SDL_GetJoystickFirmwareVersion_REAL -#define SDL_GetJoystickFromInstanceID SDL_GetJoystickFromInstanceID_REAL +#define SDL_GetJoystickFromID SDL_GetJoystickFromID_REAL #define SDL_GetJoystickFromPlayerIndex SDL_GetJoystickFromPlayerIndex_REAL #define SDL_GetJoystickGUID SDL_GetJoystickGUID_REAL -#define SDL_GetJoystickGUIDFromString SDL_GetJoystickGUIDFromString_REAL +#define SDL_GetJoystickGUIDForID SDL_GetJoystickGUIDForID_REAL #define SDL_GetJoystickGUIDInfo SDL_GetJoystickGUIDInfo_REAL -#define SDL_GetJoystickGUIDString SDL_GetJoystickGUIDString_REAL #define SDL_GetJoystickHat SDL_GetJoystickHat_REAL -#define SDL_GetJoystickInstanceGUID SDL_GetJoystickInstanceGUID_REAL -#define SDL_GetJoystickInstanceID SDL_GetJoystickInstanceID_REAL -#define SDL_GetJoystickInstanceName SDL_GetJoystickInstanceName_REAL -#define SDL_GetJoystickInstancePath SDL_GetJoystickInstancePath_REAL -#define SDL_GetJoystickInstancePlayerIndex SDL_GetJoystickInstancePlayerIndex_REAL -#define SDL_GetJoystickInstanceProduct SDL_GetJoystickInstanceProduct_REAL -#define SDL_GetJoystickInstanceProductVersion SDL_GetJoystickInstanceProductVersion_REAL -#define SDL_GetJoystickInstanceType SDL_GetJoystickInstanceType_REAL -#define SDL_GetJoystickInstanceVendor SDL_GetJoystickInstanceVendor_REAL +#define SDL_GetJoystickID SDL_GetJoystickID_REAL #define SDL_GetJoystickName SDL_GetJoystickName_REAL +#define SDL_GetJoystickNameForID SDL_GetJoystickNameForID_REAL #define SDL_GetJoystickPath SDL_GetJoystickPath_REAL +#define SDL_GetJoystickPathForID SDL_GetJoystickPathForID_REAL #define SDL_GetJoystickPlayerIndex SDL_GetJoystickPlayerIndex_REAL +#define SDL_GetJoystickPlayerIndexForID SDL_GetJoystickPlayerIndexForID_REAL #define SDL_GetJoystickPowerInfo SDL_GetJoystickPowerInfo_REAL #define SDL_GetJoystickProduct SDL_GetJoystickProduct_REAL +#define SDL_GetJoystickProductForID SDL_GetJoystickProductForID_REAL #define SDL_GetJoystickProductVersion SDL_GetJoystickProductVersion_REAL +#define SDL_GetJoystickProductVersionForID SDL_GetJoystickProductVersionForID_REAL #define SDL_GetJoystickProperties SDL_GetJoystickProperties_REAL #define SDL_GetJoystickSerial SDL_GetJoystickSerial_REAL #define SDL_GetJoystickType SDL_GetJoystickType_REAL +#define SDL_GetJoystickTypeForID SDL_GetJoystickTypeForID_REAL #define SDL_GetJoystickVendor SDL_GetJoystickVendor_REAL +#define SDL_GetJoystickVendorForID SDL_GetJoystickVendorForID_REAL #define SDL_GetJoysticks SDL_GetJoysticks_REAL #define SDL_GetKeyFromName SDL_GetKeyFromName_REAL #define SDL_GetKeyFromScancode SDL_GetKeyFromScancode_REAL #define SDL_GetKeyName SDL_GetKeyName_REAL #define SDL_GetKeyboardFocus SDL_GetKeyboardFocus_REAL -#define SDL_GetKeyboardInstanceName SDL_GetKeyboardInstanceName_REAL +#define SDL_GetKeyboardNameForID SDL_GetKeyboardNameForID_REAL #define SDL_GetKeyboardState SDL_GetKeyboardState_REAL #define SDL_GetKeyboards SDL_GetKeyboards_REAL #define SDL_GetLogOutputFunction SDL_GetLogOutputFunction_REAL -#define SDL_GetMasksForPixelFormatEnum SDL_GetMasksForPixelFormatEnum_REAL +#define SDL_GetLogPriority SDL_GetLogPriority_REAL +#define SDL_GetMasksForPixelFormat SDL_GetMasksForPixelFormat_REAL #define SDL_GetMaxHapticEffects SDL_GetMaxHapticEffects_REAL #define SDL_GetMaxHapticEffectsPlaying SDL_GetMaxHapticEffectsPlaying_REAL #define SDL_GetMemoryFunctions SDL_GetMemoryFunctions_REAL #define SDL_GetMice SDL_GetMice_REAL #define SDL_GetModState SDL_GetModState_REAL #define SDL_GetMouseFocus SDL_GetMouseFocus_REAL -#define SDL_GetMouseInstanceName SDL_GetMouseInstanceName_REAL +#define SDL_GetMouseNameForID SDL_GetMouseNameForID_REAL #define SDL_GetMouseState SDL_GetMouseState_REAL #define SDL_GetNaturalDisplayOrientation SDL_GetNaturalDisplayOrientation_REAL #define SDL_GetNumAllocations SDL_GetNumAllocations_REAL #define SDL_GetNumAudioDrivers SDL_GetNumAudioDrivers_REAL #define SDL_GetNumCameraDrivers SDL_GetNumCameraDrivers_REAL +#define SDL_GetNumGPUDrivers SDL_GetNumGPUDrivers_REAL #define SDL_GetNumGamepadTouchpadFingers SDL_GetNumGamepadTouchpadFingers_REAL #define SDL_GetNumGamepadTouchpads SDL_GetNumGamepadTouchpads_REAL #define SDL_GetNumHapticAxes SDL_GetNumHapticAxes_REAL @@ -370,42 +438,32 @@ #define SDL_GetNumJoystickBalls SDL_GetNumJoystickBalls_REAL #define SDL_GetNumJoystickButtons SDL_GetNumJoystickButtons_REAL #define SDL_GetNumJoystickHats SDL_GetNumJoystickHats_REAL +#define SDL_GetNumLogicalCPUCores SDL_GetNumLogicalCPUCores_REAL #define SDL_GetNumRenderDrivers SDL_GetNumRenderDrivers_REAL -#define SDL_GetNumTouchFingers SDL_GetNumTouchFingers_REAL #define SDL_GetNumVideoDrivers SDL_GetNumVideoDrivers_REAL #define SDL_GetNumberProperty SDL_GetNumberProperty_REAL #define SDL_GetOriginalMemoryFunctions SDL_GetOriginalMemoryFunctions_REAL #define SDL_GetPathInfo SDL_GetPathInfo_REAL -#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL -#define SDL_GetPenCapabilities SDL_GetPenCapabilities_REAL -#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL -#define SDL_GetPenFromGUID SDL_GetPenFromGUID_REAL -#define SDL_GetPenGUID SDL_GetPenGUID_REAL -#define SDL_GetPenGUID SDL_GetPenGUID_REAL -#define SDL_GetPenName SDL_GetPenName_REAL -#define SDL_GetPenName SDL_GetPenName_REAL -#define SDL_GetPenStatus SDL_GetPenStatus_REAL -#define SDL_GetPenStatus SDL_GetPenStatus_REAL -#define SDL_GetPenType SDL_GetPenType_REAL -#define SDL_GetPenType SDL_GetPenType_REAL -#define SDL_GetPens SDL_GetPens_REAL -#define SDL_GetPens SDL_GetPens_REAL #define SDL_GetPerformanceCounter SDL_GetPerformanceCounter_REAL #define SDL_GetPerformanceFrequency SDL_GetPerformanceFrequency_REAL -#define SDL_GetPixelFormatEnumForMasks SDL_GetPixelFormatEnumForMasks_REAL +#define SDL_GetPixelFormatDetails SDL_GetPixelFormatDetails_REAL +#define SDL_GetPixelFormatForMasks SDL_GetPixelFormatForMasks_REAL #define SDL_GetPixelFormatName SDL_GetPixelFormatName_REAL #define SDL_GetPlatform SDL_GetPlatform_REAL +#define SDL_GetPointerProperty SDL_GetPointerProperty_REAL #define SDL_GetPowerInfo SDL_GetPowerInfo_REAL #define SDL_GetPrefPath SDL_GetPrefPath_REAL #define SDL_GetPreferredLocales SDL_GetPreferredLocales_REAL #define SDL_GetPrimaryDisplay SDL_GetPrimaryDisplay_REAL #define SDL_GetPrimarySelectionText SDL_GetPrimarySelectionText_REAL -#define SDL_GetProperty SDL_GetProperty_REAL +#define SDL_GetProcessInput SDL_GetProcessInput_REAL +#define SDL_GetProcessOutput SDL_GetProcessOutput_REAL +#define SDL_GetProcessProperties SDL_GetProcessProperties_REAL #define SDL_GetPropertyType SDL_GetPropertyType_REAL #define SDL_GetRGB SDL_GetRGB_REAL #define SDL_GetRGBA SDL_GetRGBA_REAL -#define SDL_GetRealGamepadInstanceType SDL_GetRealGamepadInstanceType_REAL #define SDL_GetRealGamepadType SDL_GetRealGamepadType_REAL +#define SDL_GetRealGamepadTypeForID SDL_GetRealGamepadTypeForID_REAL #define SDL_GetRectAndLineIntersection SDL_GetRectAndLineIntersection_REAL #define SDL_GetRectAndLineIntersectionFloat SDL_GetRectAndLineIntersectionFloat_REAL #define SDL_GetRectEnclosingPoints SDL_GetRectEnclosingPoints_REAL @@ -414,7 +472,6 @@ #define SDL_GetRectIntersectionFloat SDL_GetRectIntersectionFloat_REAL #define SDL_GetRectUnion SDL_GetRectUnion_REAL #define SDL_GetRectUnionFloat SDL_GetRectUnionFloat_REAL -#define SDL_GetRelativeMouseMode SDL_GetRelativeMouseMode_REAL #define SDL_GetRelativeMouseState SDL_GetRelativeMouseState_REAL #define SDL_GetRenderClipRect SDL_GetRenderClipRect_REAL #define SDL_GetRenderColorScale SDL_GetRenderColorScale_REAL @@ -423,9 +480,11 @@ #define SDL_GetRenderDrawColorFloat SDL_GetRenderDrawColorFloat_REAL #define SDL_GetRenderDriver SDL_GetRenderDriver_REAL #define SDL_GetRenderLogicalPresentation SDL_GetRenderLogicalPresentation_REAL +#define SDL_GetRenderLogicalPresentationRect SDL_GetRenderLogicalPresentationRect_REAL #define SDL_GetRenderMetalCommandEncoder SDL_GetRenderMetalCommandEncoder_REAL #define SDL_GetRenderMetalLayer SDL_GetRenderMetalLayer_REAL #define SDL_GetRenderOutputSize SDL_GetRenderOutputSize_REAL +#define SDL_GetRenderSafeArea SDL_GetRenderSafeArea_REAL #define SDL_GetRenderScale SDL_GetRenderScale_REAL #define SDL_GetRenderTarget SDL_GetRenderTarget_REAL #define SDL_GetRenderVSync SDL_GetRenderVSync_REAL @@ -433,23 +492,24 @@ #define SDL_GetRenderWindow SDL_GetRenderWindow_REAL #define SDL_GetRenderer SDL_GetRenderer_REAL #define SDL_GetRendererFromTexture SDL_GetRendererFromTexture_REAL -#define SDL_GetRendererInfo SDL_GetRendererInfo_REAL +#define SDL_GetRendererName SDL_GetRendererName_REAL #define SDL_GetRendererProperties SDL_GetRendererProperties_REAL #define SDL_GetRevision SDL_GetRevision_REAL +#define SDL_GetSIMDAlignment SDL_GetSIMDAlignment_REAL #define SDL_GetScancodeFromKey SDL_GetScancodeFromKey_REAL #define SDL_GetScancodeFromName SDL_GetScancodeFromName_REAL #define SDL_GetScancodeName SDL_GetScancodeName_REAL #define SDL_GetSemaphoreValue SDL_GetSemaphoreValue_REAL #define SDL_GetSensorData SDL_GetSensorData_REAL -#define SDL_GetSensorFromInstanceID SDL_GetSensorFromInstanceID_REAL -#define SDL_GetSensorInstanceID SDL_GetSensorInstanceID_REAL -#define SDL_GetSensorInstanceName SDL_GetSensorInstanceName_REAL -#define SDL_GetSensorInstanceNonPortableType SDL_GetSensorInstanceNonPortableType_REAL -#define SDL_GetSensorInstanceType SDL_GetSensorInstanceType_REAL +#define SDL_GetSensorFromID SDL_GetSensorFromID_REAL +#define SDL_GetSensorID SDL_GetSensorID_REAL #define SDL_GetSensorName SDL_GetSensorName_REAL +#define SDL_GetSensorNameForID SDL_GetSensorNameForID_REAL #define SDL_GetSensorNonPortableType SDL_GetSensorNonPortableType_REAL +#define SDL_GetSensorNonPortableTypeForID SDL_GetSensorNonPortableTypeForID_REAL #define SDL_GetSensorProperties SDL_GetSensorProperties_REAL #define SDL_GetSensorType SDL_GetSensorType_REAL +#define SDL_GetSensorTypeForID SDL_GetSensorTypeForID_REAL #define SDL_GetSensors SDL_GetSensors_REAL #define SDL_GetSilenceValueForFormat SDL_GetSilenceValueForFormat_REAL #define SDL_GetStorageFileSize SDL_GetStorageFileSize_REAL @@ -462,10 +522,13 @@ #define SDL_GetSurfaceColorKey SDL_GetSurfaceColorKey_REAL #define SDL_GetSurfaceColorMod SDL_GetSurfaceColorMod_REAL #define SDL_GetSurfaceColorspace SDL_GetSurfaceColorspace_REAL +#define SDL_GetSurfaceImages SDL_GetSurfaceImages_REAL +#define SDL_GetSurfacePalette SDL_GetSurfacePalette_REAL #define SDL_GetSurfaceProperties SDL_GetSurfaceProperties_REAL #define SDL_GetSystemRAM SDL_GetSystemRAM_REAL #define SDL_GetSystemTheme SDL_GetSystemTheme_REAL #define SDL_GetTLS SDL_GetTLS_REAL +#define SDL_GetTextInputArea SDL_GetTextInputArea_REAL #define SDL_GetTextureAlphaMod SDL_GetTextureAlphaMod_REAL #define SDL_GetTextureAlphaModFloat SDL_GetTextureAlphaModFloat_REAL #define SDL_GetTextureBlendMode SDL_GetTextureBlendMode_REAL @@ -473,6 +536,7 @@ #define SDL_GetTextureColorModFloat SDL_GetTextureColorModFloat_REAL #define SDL_GetTextureProperties SDL_GetTextureProperties_REAL #define SDL_GetTextureScaleMode SDL_GetTextureScaleMode_REAL +#define SDL_GetTextureSize SDL_GetTextureSize_REAL #define SDL_GetThreadID SDL_GetThreadID_REAL #define SDL_GetThreadName SDL_GetThreadName_REAL #define SDL_GetTicks SDL_GetTicks_REAL @@ -480,13 +544,15 @@ #define SDL_GetTouchDeviceName SDL_GetTouchDeviceName_REAL #define SDL_GetTouchDeviceType SDL_GetTouchDeviceType_REAL #define SDL_GetTouchDevices SDL_GetTouchDevices_REAL -#define SDL_GetTouchFinger SDL_GetTouchFinger_REAL +#define SDL_GetTouchFingers SDL_GetTouchFingers_REAL #define SDL_GetUserFolder SDL_GetUserFolder_REAL #define SDL_GetVersion SDL_GetVersion_REAL #define SDL_GetVideoDriver SDL_GetVideoDriver_REAL +#define SDL_GetWindowAspectRatio SDL_GetWindowAspectRatio_REAL #define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL #define SDL_GetWindowDisplayScale SDL_GetWindowDisplayScale_REAL #define SDL_GetWindowFlags SDL_GetWindowFlags_REAL +#define SDL_GetWindowFromEvent SDL_GetWindowFromEvent_REAL #define SDL_GetWindowFromID SDL_GetWindowFromID_REAL #define SDL_GetWindowFullscreenMode SDL_GetWindowFullscreenMode_REAL #define SDL_GetWindowICCProfile SDL_GetWindowICCProfile_REAL @@ -502,10 +568,16 @@ #define SDL_GetWindowPixelFormat SDL_GetWindowPixelFormat_REAL #define SDL_GetWindowPosition SDL_GetWindowPosition_REAL #define SDL_GetWindowProperties SDL_GetWindowProperties_REAL +#define SDL_GetWindowRelativeMouseMode SDL_GetWindowRelativeMouseMode_REAL +#define SDL_GetWindowSafeArea SDL_GetWindowSafeArea_REAL #define SDL_GetWindowSize SDL_GetWindowSize_REAL #define SDL_GetWindowSizeInPixels SDL_GetWindowSizeInPixels_REAL #define SDL_GetWindowSurface SDL_GetWindowSurface_REAL +#define SDL_GetWindowSurfaceVSync SDL_GetWindowSurfaceVSync_REAL #define SDL_GetWindowTitle SDL_GetWindowTitle_REAL +#define SDL_GetWindows SDL_GetWindows_REAL +#define SDL_GlobDirectory SDL_GlobDirectory_REAL +#define SDL_GlobStorageDirectory SDL_GlobStorageDirectory_REAL #define SDL_HapticEffectSupported SDL_HapticEffectSupported_REAL #define SDL_HapticRumbleSupported SDL_HapticRumbleSupported_REAL #define SDL_HasARMSIMD SDL_HasARMSIMD_REAL @@ -546,18 +618,18 @@ #define SDL_Init SDL_Init_REAL #define SDL_InitHapticRumble SDL_InitHapticRumble_REAL #define SDL_InitSubSystem SDL_InitSubSystem_REAL -#define SDL_IsAndroidTV SDL_IsAndroidTV_REAL +#define SDL_InsertGPUDebugLabel SDL_InsertGPUDebugLabel_REAL #define SDL_IsChromebook SDL_IsChromebook_REAL #define SDL_IsDeXMode SDL_IsDeXMode_REAL #define SDL_IsGamepad SDL_IsGamepad_REAL #define SDL_IsJoystickHaptic SDL_IsJoystickHaptic_REAL #define SDL_IsJoystickVirtual SDL_IsJoystickVirtual_REAL #define SDL_IsMouseHaptic SDL_IsMouseHaptic_REAL +#define SDL_IsTV SDL_IsTV_REAL #define SDL_IsTablet SDL_IsTablet_REAL #define SDL_JoystickConnected SDL_JoystickConnected_REAL #define SDL_JoystickEventsEnabled SDL_JoystickEventsEnabled_REAL -#define SDL_LinuxSetThreadPriority SDL_LinuxSetThreadPriority_REAL -#define SDL_LinuxSetThreadPriorityAndPolicy SDL_LinuxSetThreadPriorityAndPolicy_REAL +#define SDL_KillProcess SDL_KillProcess_REAL #define SDL_LoadBMP SDL_LoadBMP_REAL #define SDL_LoadBMP_IO SDL_LoadBMP_IO_REAL #define SDL_LoadFile SDL_LoadFile_REAL @@ -580,17 +652,17 @@ #define SDL_LogCritical SDL_LogCritical_REAL #define SDL_LogDebug SDL_LogDebug_REAL #define SDL_LogError SDL_LogError_REAL -#define SDL_LogGetPriority SDL_LogGetPriority_REAL #define SDL_LogInfo SDL_LogInfo_REAL #define SDL_LogMessage SDL_LogMessage_REAL #define SDL_LogMessageV SDL_LogMessageV_REAL -#define SDL_LogResetPriorities SDL_LogResetPriorities_REAL -#define SDL_LogSetAllPriority SDL_LogSetAllPriority_REAL -#define SDL_LogSetPriority SDL_LogSetPriority_REAL +#define SDL_LogTrace SDL_LogTrace_REAL #define SDL_LogVerbose SDL_LogVerbose_REAL #define SDL_LogWarn SDL_LogWarn_REAL +#define SDL_MapGPUTransferBuffer SDL_MapGPUTransferBuffer_REAL #define SDL_MapRGB SDL_MapRGB_REAL #define SDL_MapRGBA SDL_MapRGBA_REAL +#define SDL_MapSurfaceRGB SDL_MapSurfaceRGB_REAL +#define SDL_MapSurfaceRGBA SDL_MapSurfaceRGBA_REAL #define SDL_MaximizeWindow SDL_MaximizeWindow_REAL #define SDL_MemoryBarrierAcquireFunction SDL_MemoryBarrierAcquireFunction_REAL #define SDL_MemoryBarrierReleaseFunction SDL_MemoryBarrierReleaseFunction_REAL @@ -598,17 +670,17 @@ #define SDL_Metal_DestroyView SDL_Metal_DestroyView_REAL #define SDL_Metal_GetLayer SDL_Metal_GetLayer_REAL #define SDL_MinimizeWindow SDL_MinimizeWindow_REAL -#define SDL_MixAudioFormat SDL_MixAudioFormat_REAL -#define SDL_OnApplicationDidBecomeActive SDL_OnApplicationDidBecomeActive_REAL -#define SDL_OnApplicationDidChangeStatusBarOrientation SDL_OnApplicationDidChangeStatusBarOrientation_REAL +#define SDL_MixAudio SDL_MixAudio_REAL +#define SDL_OnApplicationDidChangeStatusBarOrientation SDL_OnApplicationDidChangeStatusBarOrientation_REAL #define SDL_OnApplicationDidEnterBackground SDL_OnApplicationDidEnterBackground_REAL +#define SDL_OnApplicationDidEnterForeground SDL_OnApplicationDidEnterForeground_REAL #define SDL_OnApplicationDidReceiveMemoryWarning SDL_OnApplicationDidReceiveMemoryWarning_REAL +#define SDL_OnApplicationWillEnterBackground SDL_OnApplicationWillEnterBackground_REAL #define SDL_OnApplicationWillEnterForeground SDL_OnApplicationWillEnterForeground_REAL -#define SDL_OnApplicationWillResignActive SDL_OnApplicationWillResignActive_REAL #define SDL_OnApplicationWillTerminate SDL_OnApplicationWillTerminate_REAL #define SDL_OpenAudioDevice SDL_OpenAudioDevice_REAL #define SDL_OpenAudioDeviceStream SDL_OpenAudioDeviceStream_REAL -#define SDL_OpenCameraDevice SDL_OpenCameraDevice_REAL +#define SDL_OpenCamera SDL_OpenCamera_REAL #define SDL_OpenFileStorage SDL_OpenFileStorage_REAL #define SDL_OpenGamepad SDL_OpenGamepad_REAL #define SDL_OpenHaptic SDL_OpenHaptic_REAL @@ -621,31 +693,39 @@ #define SDL_OpenTitleStorage SDL_OpenTitleStorage_REAL #define SDL_OpenURL SDL_OpenURL_REAL #define SDL_OpenUserStorage SDL_OpenUserStorage_REAL +#define SDL_OutOfMemory SDL_OutOfMemory_REAL #define SDL_PauseAudioDevice SDL_PauseAudioDevice_REAL +#define SDL_PauseAudioStreamDevice SDL_PauseAudioStreamDevice_REAL #define SDL_PauseHaptic SDL_PauseHaptic_REAL #define SDL_PeepEvents SDL_PeepEvents_REAL -#define SDL_PenConnected SDL_PenConnected_REAL -#define SDL_PenConnected SDL_PenConnected_REAL #define SDL_PlayHapticRumble SDL_PlayHapticRumble_REAL #define SDL_PollEvent SDL_PollEvent_REAL -#define SDL_PostSemaphore SDL_PostSemaphore_REAL +#define SDL_PopGPUDebugGroup SDL_PopGPUDebugGroup_REAL #define SDL_PremultiplyAlpha SDL_PremultiplyAlpha_REAL +#define SDL_PremultiplySurfaceAlpha SDL_PremultiplySurfaceAlpha_REAL #define SDL_PumpEvents SDL_PumpEvents_REAL #define SDL_PushEvent SDL_PushEvent_REAL +#define SDL_PushGPUComputeUniformData SDL_PushGPUComputeUniformData_REAL +#define SDL_PushGPUDebugGroup SDL_PushGPUDebugGroup_REAL +#define SDL_PushGPUFragmentUniformData SDL_PushGPUFragmentUniformData_REAL +#define SDL_PushGPUVertexUniformData SDL_PushGPUVertexUniformData_REAL #define SDL_PutAudioStreamData SDL_PutAudioStreamData_REAL -#define SDL_QueryTexture SDL_QueryTexture_REAL +#define SDL_QueryGPUFence SDL_QueryGPUFence_REAL #define SDL_Quit SDL_Quit_REAL #define SDL_QuitSubSystem SDL_QuitSubSystem_REAL #define SDL_RaiseWindow SDL_RaiseWindow_REAL #define SDL_ReadIO SDL_ReadIO_REAL +#define SDL_ReadProcess SDL_ReadProcess_REAL #define SDL_ReadS16BE SDL_ReadS16BE_REAL #define SDL_ReadS16LE SDL_ReadS16LE_REAL #define SDL_ReadS32BE SDL_ReadS32BE_REAL #define SDL_ReadS32LE SDL_ReadS32LE_REAL #define SDL_ReadS64BE SDL_ReadS64BE_REAL #define SDL_ReadS64LE SDL_ReadS64LE_REAL +#define SDL_ReadS8 SDL_ReadS8_REAL #define SDL_ReadStorageFile SDL_ReadStorageFile_REAL #define SDL_ReadSurfacePixel SDL_ReadSurfacePixel_REAL +#define SDL_ReadSurfacePixelFloat SDL_ReadSurfacePixelFloat_REAL #define SDL_ReadU16BE SDL_ReadU16BE_REAL #define SDL_ReadU16LE SDL_ReadU16LE_REAL #define SDL_ReadU32BE SDL_ReadU32BE_REAL @@ -656,9 +736,21 @@ #define SDL_RegisterApp SDL_RegisterApp_REAL #define SDL_RegisterEvents SDL_RegisterEvents_REAL #define SDL_ReleaseCameraFrame SDL_ReleaseCameraFrame_REAL +#define SDL_ReleaseGPUBuffer SDL_ReleaseGPUBuffer_REAL +#define SDL_ReleaseGPUComputePipeline SDL_ReleaseGPUComputePipeline_REAL +#define SDL_ReleaseGPUFence SDL_ReleaseGPUFence_REAL +#define SDL_ReleaseGPUGraphicsPipeline SDL_ReleaseGPUGraphicsPipeline_REAL +#define SDL_ReleaseGPUSampler SDL_ReleaseGPUSampler_REAL +#define SDL_ReleaseGPUShader SDL_ReleaseGPUShader_REAL +#define SDL_ReleaseGPUTexture SDL_ReleaseGPUTexture_REAL +#define SDL_ReleaseGPUTransferBuffer SDL_ReleaseGPUTransferBuffer_REAL +#define SDL_ReleaseWindowFromGPUDevice SDL_ReleaseWindowFromGPUDevice_REAL #define SDL_ReloadGamepadMappings SDL_ReloadGamepadMappings_REAL +#define SDL_RemoveEventWatch SDL_RemoveEventWatch_REAL +#define SDL_RemoveHintCallback SDL_RemoveHintCallback_REAL #define SDL_RemovePath SDL_RemovePath_REAL #define SDL_RemoveStoragePath SDL_RemoveStoragePath_REAL +#define SDL_RemoveSurfaceAlternateImages SDL_RemoveSurfaceAlternateImages_REAL #define SDL_RemoveTimer SDL_RemoveTimer_REAL #define SDL_RenamePath SDL_RenamePath_REAL #define SDL_RenameStoragePath SDL_RenameStoragePath_REAL @@ -670,7 +762,6 @@ #define SDL_RenderFillRects SDL_RenderFillRects_REAL #define SDL_RenderGeometry SDL_RenderGeometry_REAL #define SDL_RenderGeometryRaw SDL_RenderGeometryRaw_REAL -#define SDL_RenderGeometryRawFloat SDL_RenderGeometryRawFloat_REAL #define SDL_RenderLine SDL_RenderLine_REAL #define SDL_RenderLines SDL_RenderLines_REAL #define SDL_RenderPoint SDL_RenderPoint_REAL @@ -680,15 +771,20 @@ #define SDL_RenderRect SDL_RenderRect_REAL #define SDL_RenderRects SDL_RenderRects_REAL #define SDL_RenderTexture SDL_RenderTexture_REAL +#define SDL_RenderTexture9Grid SDL_RenderTexture9Grid_REAL #define SDL_RenderTextureRotated SDL_RenderTextureRotated_REAL +#define SDL_RenderTextureTiled SDL_RenderTextureTiled_REAL #define SDL_RenderViewportSet SDL_RenderViewportSet_REAL #define SDL_ReportAssertion SDL_ReportAssertion_REAL +#define SDL_RequestAndroidPermission SDL_RequestAndroidPermission_REAL #define SDL_ResetAssertionReport SDL_ResetAssertionReport_REAL #define SDL_ResetHint SDL_ResetHint_REAL #define SDL_ResetHints SDL_ResetHints_REAL #define SDL_ResetKeyboard SDL_ResetKeyboard_REAL +#define SDL_ResetLogPriorities SDL_ResetLogPriorities_REAL #define SDL_RestoreWindow SDL_RestoreWindow_REAL #define SDL_ResumeAudioDevice SDL_ResumeAudioDevice_REAL +#define SDL_ResumeAudioStreamDevice SDL_ResumeAudioStreamDevice_REAL #define SDL_ResumeHaptic SDL_ResumeHaptic_REAL #define SDL_RumbleGamepad SDL_RumbleGamepad_REAL #define SDL_RumbleGamepadTriggers SDL_RumbleGamepadTriggers_REAL @@ -696,28 +792,49 @@ #define SDL_RumbleJoystickTriggers SDL_RumbleJoystickTriggers_REAL #define SDL_RunApp SDL_RunApp_REAL #define SDL_RunHapticEffect SDL_RunHapticEffect_REAL -#define SDL_SIMDGetAlignment SDL_SIMDGetAlignment_REAL #define SDL_SaveBMP SDL_SaveBMP_REAL #define SDL_SaveBMP_IO SDL_SaveBMP_IO_REAL +#define SDL_ScaleSurface SDL_ScaleSurface_REAL #define SDL_ScreenKeyboardShown SDL_ScreenKeyboardShown_REAL #define SDL_ScreenSaverEnabled SDL_ScreenSaverEnabled_REAL #define SDL_SeekIO SDL_SeekIO_REAL +#define SDL_SendAndroidBackButton SDL_SendAndroidBackButton_REAL +#define SDL_SendAndroidMessage SDL_SendAndroidMessage_REAL #define SDL_SendGamepadEffect SDL_SendGamepadEffect_REAL #define SDL_SendJoystickEffect SDL_SendJoystickEffect_REAL +#define SDL_SendJoystickVirtualSensorData SDL_SendJoystickVirtualSensorData_REAL +#define SDL_SetAppMetadata SDL_SetAppMetadata_REAL +#define SDL_SetAppMetadataProperty SDL_SetAppMetadataProperty_REAL #define SDL_SetAssertionHandler SDL_SetAssertionHandler_REAL +#define SDL_SetAtomicInt SDL_SetAtomicInt_REAL +#define SDL_SetAtomicPointer SDL_SetAtomicPointer_REAL +#define SDL_SetAtomicU32 SDL_SetAtomicU32_REAL +#define SDL_SetAudioDeviceGain SDL_SetAudioDeviceGain_REAL #define SDL_SetAudioPostmixCallback SDL_SetAudioPostmixCallback_REAL #define SDL_SetAudioStreamFormat SDL_SetAudioStreamFormat_REAL #define SDL_SetAudioStreamFrequencyRatio SDL_SetAudioStreamFrequencyRatio_REAL +#define SDL_SetAudioStreamGain SDL_SetAudioStreamGain_REAL #define SDL_SetAudioStreamGetCallback SDL_SetAudioStreamGetCallback_REAL +#define SDL_SetAudioStreamInputChannelMap SDL_SetAudioStreamInputChannelMap_REAL +#define SDL_SetAudioStreamOutputChannelMap SDL_SetAudioStreamOutputChannelMap_REAL #define SDL_SetAudioStreamPutCallback SDL_SetAudioStreamPutCallback_REAL #define SDL_SetBooleanProperty SDL_SetBooleanProperty_REAL #define SDL_SetClipboardData SDL_SetClipboardData_REAL #define SDL_SetClipboardText SDL_SetClipboardText_REAL +#define SDL_SetCurrentThreadPriority SDL_SetCurrentThreadPriority_REAL #define SDL_SetCursor SDL_SetCursor_REAL +#define SDL_SetEnvironmentVariable SDL_SetEnvironmentVariable_REAL #define SDL_SetError SDL_SetError_REAL #define SDL_SetEventEnabled SDL_SetEventEnabled_REAL #define SDL_SetEventFilter SDL_SetEventFilter_REAL #define SDL_SetFloatProperty SDL_SetFloatProperty_REAL +#define SDL_SetGPUBlendConstants SDL_SetGPUBlendConstants_REAL +#define SDL_SetGPUBufferName SDL_SetGPUBufferName_REAL +#define SDL_SetGPUScissor SDL_SetGPUScissor_REAL +#define SDL_SetGPUStencilReference SDL_SetGPUStencilReference_REAL +#define SDL_SetGPUSwapchainParameters SDL_SetGPUSwapchainParameters_REAL +#define SDL_SetGPUTextureName SDL_SetGPUTextureName_REAL +#define SDL_SetGPUViewport SDL_SetGPUViewport_REAL #define SDL_SetGamepadEventsEnabled SDL_SetGamepadEventsEnabled_REAL #define SDL_SetGamepadLED SDL_SetGamepadLED_REAL #define SDL_SetGamepadMapping SDL_SetGamepadMapping_REAL @@ -727,23 +844,29 @@ #define SDL_SetHapticGain SDL_SetHapticGain_REAL #define SDL_SetHint SDL_SetHint_REAL #define SDL_SetHintWithPriority SDL_SetHintWithPriority_REAL +#define SDL_SetInitialized SDL_SetInitialized_REAL #define SDL_SetJoystickEventsEnabled SDL_SetJoystickEventsEnabled_REAL #define SDL_SetJoystickLED SDL_SetJoystickLED_REAL #define SDL_SetJoystickPlayerIndex SDL_SetJoystickPlayerIndex_REAL #define SDL_SetJoystickVirtualAxis SDL_SetJoystickVirtualAxis_REAL +#define SDL_SetJoystickVirtualBall SDL_SetJoystickVirtualBall_REAL #define SDL_SetJoystickVirtualButton SDL_SetJoystickVirtualButton_REAL #define SDL_SetJoystickVirtualHat SDL_SetJoystickVirtualHat_REAL +#define SDL_SetJoystickVirtualTouchpad SDL_SetJoystickVirtualTouchpad_REAL +#define SDL_SetLinuxThreadPriority SDL_SetLinuxThreadPriority_REAL +#define SDL_SetLinuxThreadPriorityAndPolicy SDL_SetLinuxThreadPriorityAndPolicy_REAL #define SDL_SetLogOutputFunction SDL_SetLogOutputFunction_REAL +#define SDL_SetLogPriorities SDL_SetLogPriorities_REAL +#define SDL_SetLogPriority SDL_SetLogPriority_REAL +#define SDL_SetLogPriorityPrefix SDL_SetLogPriorityPrefix_REAL #define SDL_SetMainReady SDL_SetMainReady_REAL #define SDL_SetMemoryFunctions SDL_SetMemoryFunctions_REAL #define SDL_SetModState SDL_SetModState_REAL #define SDL_SetNumberProperty SDL_SetNumberProperty_REAL #define SDL_SetPaletteColors SDL_SetPaletteColors_REAL -#define SDL_SetPixelFormatPalette SDL_SetPixelFormatPalette_REAL +#define SDL_SetPointerProperty SDL_SetPointerProperty_REAL +#define SDL_SetPointerPropertyWithCleanup SDL_SetPointerPropertyWithCleanup_REAL #define SDL_SetPrimarySelectionText SDL_SetPrimarySelectionText_REAL -#define SDL_SetProperty SDL_SetProperty_REAL -#define SDL_SetPropertyWithCleanup SDL_SetPropertyWithCleanup_REAL -#define SDL_SetRelativeMouseMode SDL_SetRelativeMouseMode_REAL #define SDL_SetRenderClipRect SDL_SetRenderClipRect_REAL #define SDL_SetRenderColorScale SDL_SetRenderColorScale_REAL #define SDL_SetRenderDrawBlendMode SDL_SetRenderDrawBlendMode_REAL @@ -754,6 +877,7 @@ #define SDL_SetRenderTarget SDL_SetRenderTarget_REAL #define SDL_SetRenderVSync SDL_SetRenderVSync_REAL #define SDL_SetRenderViewport SDL_SetRenderViewport_REAL +#define SDL_SetScancodeName SDL_SetScancodeName_REAL #define SDL_SetStringProperty SDL_SetStringProperty_REAL #define SDL_SetSurfaceAlphaMod SDL_SetSurfaceAlphaMod_REAL #define SDL_SetSurfaceBlendMode SDL_SetSurfaceBlendMode_REAL @@ -764,36 +888,43 @@ #define SDL_SetSurfacePalette SDL_SetSurfacePalette_REAL #define SDL_SetSurfaceRLE SDL_SetSurfaceRLE_REAL #define SDL_SetTLS SDL_SetTLS_REAL -#define SDL_SetTextInputRect SDL_SetTextInputRect_REAL +#define SDL_SetTextInputArea SDL_SetTextInputArea_REAL #define SDL_SetTextureAlphaMod SDL_SetTextureAlphaMod_REAL #define SDL_SetTextureAlphaModFloat SDL_SetTextureAlphaModFloat_REAL #define SDL_SetTextureBlendMode SDL_SetTextureBlendMode_REAL #define SDL_SetTextureColorMod SDL_SetTextureColorMod_REAL #define SDL_SetTextureColorModFloat SDL_SetTextureColorModFloat_REAL #define SDL_SetTextureScaleMode SDL_SetTextureScaleMode_REAL -#define SDL_SetThreadPriority SDL_SetThreadPriority_REAL #define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL +#define SDL_SetWindowAspectRatio SDL_SetWindowAspectRatio_REAL #define SDL_SetWindowBordered SDL_SetWindowBordered_REAL #define SDL_SetWindowFocusable SDL_SetWindowFocusable_REAL #define SDL_SetWindowFullscreen SDL_SetWindowFullscreen_REAL #define SDL_SetWindowFullscreenMode SDL_SetWindowFullscreenMode_REAL #define SDL_SetWindowHitTest SDL_SetWindowHitTest_REAL #define SDL_SetWindowIcon SDL_SetWindowIcon_REAL -#define SDL_SetWindowInputFocus SDL_SetWindowInputFocus_REAL #define SDL_SetWindowKeyboardGrab SDL_SetWindowKeyboardGrab_REAL #define SDL_SetWindowMaximumSize SDL_SetWindowMaximumSize_REAL #define SDL_SetWindowMinimumSize SDL_SetWindowMinimumSize_REAL -#define SDL_SetWindowModalFor SDL_SetWindowModalFor_REAL +#define SDL_SetWindowModal SDL_SetWindowModal_REAL #define SDL_SetWindowMouseGrab SDL_SetWindowMouseGrab_REAL #define SDL_SetWindowMouseRect SDL_SetWindowMouseRect_REAL #define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL +#define SDL_SetWindowParent SDL_SetWindowParent_REAL #define SDL_SetWindowPosition SDL_SetWindowPosition_REAL +#define SDL_SetWindowRelativeMouseMode SDL_SetWindowRelativeMouseMode_REAL #define SDL_SetWindowResizable SDL_SetWindowResizable_REAL #define SDL_SetWindowShape SDL_SetWindowShape_REAL #define SDL_SetWindowSize SDL_SetWindowSize_REAL +#define SDL_SetWindowSurfaceVSync SDL_SetWindowSurfaceVSync_REAL #define SDL_SetWindowTitle SDL_SetWindowTitle_REAL -#define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL +#define SDL_SetWindowsMessageHook SDL_SetWindowsMessageHook_REAL #define SDL_SetX11EventHook SDL_SetX11EventHook_REAL +#define SDL_SetiOSAnimationCallback SDL_SetiOSAnimationCallback_REAL +#define SDL_SetiOSEventPump SDL_SetiOSEventPump_REAL +#define SDL_ShouldInit SDL_ShouldInit_REAL +#define SDL_ShouldQuit SDL_ShouldQuit_REAL +#define SDL_ShowAndroidToast SDL_ShowAndroidToast_REAL #define SDL_ShowCursor SDL_ShowCursor_REAL #define SDL_ShowMessageBox SDL_ShowMessageBox_REAL #define SDL_ShowOpenFileDialog SDL_ShowOpenFileDialog_REAL @@ -803,13 +934,19 @@ #define SDL_ShowWindow SDL_ShowWindow_REAL #define SDL_ShowWindowSystemMenu SDL_ShowWindowSystemMenu_REAL #define SDL_SignalCondition SDL_SignalCondition_REAL -#define SDL_SoftStretch SDL_SoftStretch_REAL +#define SDL_SignalSemaphore SDL_SignalSemaphore_REAL #define SDL_StartTextInput SDL_StartTextInput_REAL +#define SDL_StartTextInputWithProperties SDL_StartTextInputWithProperties_REAL +#define SDL_StepUTF8 SDL_StepUTF8_REAL #define SDL_StopHapticEffect SDL_StopHapticEffect_REAL #define SDL_StopHapticEffects SDL_StopHapticEffects_REAL #define SDL_StopHapticRumble SDL_StopHapticRumble_REAL #define SDL_StopTextInput SDL_StopTextInput_REAL #define SDL_StorageReady SDL_StorageReady_REAL +#define SDL_StringToGUID SDL_StringToGUID_REAL +#define SDL_SubmitGPUCommandBuffer SDL_SubmitGPUCommandBuffer_REAL +#define SDL_SubmitGPUCommandBufferAndAcquireFence SDL_SubmitGPUCommandBufferAndAcquireFence_REAL +#define SDL_SurfaceHasAlternateImages SDL_SurfaceHasAlternateImages_REAL #define SDL_SurfaceHasColorKey SDL_SurfaceHasColorKey_REAL #define SDL_SurfaceHasRLE SDL_SurfaceHasRLE_REAL #define SDL_SyncWindow SDL_SyncWindow_REAL @@ -823,6 +960,7 @@ #define SDL_TryLockRWLockForWriting SDL_TryLockRWLockForWriting_REAL #define SDL_TryLockSpinlock SDL_TryLockSpinlock_REAL #define SDL_TryWaitSemaphore SDL_TryWaitSemaphore_REAL +#define SDL_UCS4ToUTF8 SDL_UCS4ToUTF8_REAL #define SDL_UnbindAudioStream SDL_UnbindAudioStream_REAL #define SDL_UnbindAudioStreams SDL_UnbindAudioStreams_REAL #define SDL_UnloadObject SDL_UnloadObject_REAL @@ -834,7 +972,9 @@ #define SDL_UnlockSpinlock SDL_UnlockSpinlock_REAL #define SDL_UnlockSurface SDL_UnlockSurface_REAL #define SDL_UnlockTexture SDL_UnlockTexture_REAL -#define SDL_UnregisterApp SDL_UnregisterApp_REAL +#define SDL_UnmapGPUTransferBuffer SDL_UnmapGPUTransferBuffer_REAL +#define SDL_UnregisterApp SDL_UnregisterApp_REAL +#define SDL_UnsetEnvironmentVariable SDL_UnsetEnvironmentVariable_REAL #define SDL_UpdateGamepads SDL_UpdateGamepads_REAL #define SDL_UpdateHapticEffect SDL_UpdateHapticEffect_REAL #define SDL_UpdateJoysticks SDL_UpdateJoysticks_REAL @@ -844,8 +984,12 @@ #define SDL_UpdateWindowSurface SDL_UpdateWindowSurface_REAL #define SDL_UpdateWindowSurfaceRects SDL_UpdateWindowSurfaceRects_REAL #define SDL_UpdateYUVTexture SDL_UpdateYUVTexture_REAL +#define SDL_UploadToGPUBuffer SDL_UploadToGPUBuffer_REAL +#define SDL_UploadToGPUTexture SDL_UploadToGPUTexture_REAL #define SDL_Vulkan_CreateSurface SDL_Vulkan_CreateSurface_REAL +#define SDL_Vulkan_DestroySurface SDL_Vulkan_DestroySurface_REAL #define SDL_Vulkan_GetInstanceExtensions SDL_Vulkan_GetInstanceExtensions_REAL +#define SDL_Vulkan_GetPresentationSupport SDL_Vulkan_GetPresentationSupport_REAL #define SDL_Vulkan_GetVkGetInstanceProcAddr SDL_Vulkan_GetVkGetInstanceProcAddr_REAL #define SDL_Vulkan_LoadLibrary SDL_Vulkan_LoadLibrary_REAL #define SDL_Vulkan_UnloadLibrary SDL_Vulkan_UnloadLibrary_REAL @@ -853,16 +997,18 @@ #define SDL_WaitConditionTimeout SDL_WaitConditionTimeout_REAL #define SDL_WaitEvent SDL_WaitEvent_REAL #define SDL_WaitEventTimeout SDL_WaitEventTimeout_REAL +#define SDL_WaitForGPUFences SDL_WaitForGPUFences_REAL +#define SDL_WaitForGPUIdle SDL_WaitForGPUIdle_REAL +#define SDL_WaitProcess SDL_WaitProcess_REAL #define SDL_WaitSemaphore SDL_WaitSemaphore_REAL #define SDL_WaitSemaphoreTimeout SDL_WaitSemaphoreTimeout_REAL #define SDL_WaitThread SDL_WaitThread_REAL #define SDL_WarpMouseGlobal SDL_WarpMouseGlobal_REAL #define SDL_WarpMouseInWindow SDL_WarpMouseInWindow_REAL #define SDL_WasInit SDL_WasInit_REAL -#define SDL_WinRTGetDeviceFamily SDL_WinRTGetDeviceFamily_REAL -#define SDL_WinRTGetFSPathUNICODE SDL_WinRTGetFSPathUNICODE_REAL -#define SDL_WinRTGetFSPathUTF8 SDL_WinRTGetFSPathUTF8_REAL #define SDL_WindowHasSurface SDL_WindowHasSurface_REAL +#define SDL_WindowSupportsGPUPresentMode SDL_WindowSupportsGPUPresentMode_REAL +#define SDL_WindowSupportsGPUSwapchainComposition SDL_WindowSupportsGPUSwapchainComposition_REAL #define SDL_WriteIO SDL_WriteIO_REAL #define SDL_WriteS16BE SDL_WriteS16BE_REAL #define SDL_WriteS16LE SDL_WriteS16LE_REAL @@ -870,6 +1016,10 @@ #define SDL_WriteS32LE SDL_WriteS32LE_REAL #define SDL_WriteS64BE SDL_WriteS64BE_REAL #define SDL_WriteS64LE SDL_WriteS64LE_REAL +#define SDL_WriteS8 SDL_WriteS8_REAL +#define SDL_WriteStorageFile SDL_WriteStorageFile_REAL +#define SDL_WriteSurfacePixel SDL_WriteSurfacePixel_REAL +#define SDL_WriteSurfacePixelFloat SDL_WriteSurfacePixelFloat_REAL #define SDL_WriteU16BE SDL_WriteU16BE_REAL #define SDL_WriteU16LE SDL_WriteU16LE_REAL #define SDL_WriteU32BE SDL_WriteU32BE_REAL @@ -884,7 +1034,7 @@ #define SDL_aligned_free SDL_aligned_free_REAL #define SDL_asin SDL_asin_REAL #define SDL_asinf SDL_asinf_REAL -#define SDL_asprintf SDL_asprintf_REAL +#define SDL_asprintf SDL_asprintf_REAL #define SDL_atan SDL_atan_REAL #define SDL_atan2 SDL_atan2_REAL #define SDL_atan2f SDL_atan2f_REAL @@ -912,6 +1062,7 @@ #define SDL_fmodf SDL_fmodf_REAL #define SDL_free SDL_free_REAL #define SDL_getenv SDL_getenv_REAL +#define SDL_getenv_unsafe SDL_getenv_unsafe_REAL #define SDL_hid_ble_scan SDL_hid_ble_scan_REAL #define SDL_hid_close SDL_hid_close_REAL #define SDL_hid_device_change_count SDL_hid_device_change_count_REAL @@ -934,8 +1085,6 @@ #define SDL_hid_send_feature_report SDL_hid_send_feature_report_REAL #define SDL_hid_set_nonblocking SDL_hid_set_nonblocking_REAL #define SDL_hid_write SDL_hid_write_REAL -#define SDL_iPhoneSetAnimationCallback SDL_iPhoneSetAnimationCallback_REAL -#define SDL_iPhoneSetEventPump SDL_iPhoneSetEventPump_REAL #define SDL_iconv SDL_iconv_REAL #define SDL_iconv_close SDL_iconv_close_REAL #define SDL_iconv_open SDL_iconv_open_REAL @@ -946,7 +1095,11 @@ #define SDL_iscntrl SDL_iscntrl_REAL #define SDL_isdigit SDL_isdigit_REAL #define SDL_isgraph SDL_isgraph_REAL +#define SDL_isinf SDL_isinf_REAL +#define SDL_isinff SDL_isinff_REAL #define SDL_islower SDL_islower_REAL +#define SDL_isnan SDL_isnan_REAL +#define SDL_isnanf SDL_isnanf_REAL #define SDL_isprint SDL_isprint_REAL #define SDL_ispunct SDL_ispunct_REAL #define SDL_isspace SDL_isspace_REAL @@ -969,21 +1122,29 @@ #define SDL_memset4 SDL_memset4_REAL #define SDL_modf SDL_modf_REAL #define SDL_modff SDL_modff_REAL +#define SDL_murmur3_32 SDL_murmur3_32_REAL #define SDL_pow SDL_pow_REAL #define SDL_powf SDL_powf_REAL #define SDL_qsort SDL_qsort_REAL #define SDL_qsort_r SDL_qsort_r_REAL +#define SDL_rand SDL_rand_REAL +#define SDL_rand_bits SDL_rand_bits_REAL +#define SDL_rand_bits_r SDL_rand_bits_r_REAL +#define SDL_rand_r SDL_rand_r_REAL +#define SDL_randf SDL_randf_REAL +#define SDL_randf_r SDL_randf_r_REAL #define SDL_realloc SDL_realloc_REAL #define SDL_round SDL_round_REAL #define SDL_roundf SDL_roundf_REAL #define SDL_scalbn SDL_scalbn_REAL #define SDL_scalbnf SDL_scalbnf_REAL -#define SDL_setenv SDL_setenv_REAL +#define SDL_setenv_unsafe SDL_setenv_unsafe_REAL #define SDL_sin SDL_sin_REAL #define SDL_sinf SDL_sinf_REAL #define SDL_snprintf SDL_snprintf_REAL #define SDL_sqrt SDL_sqrt_REAL #define SDL_sqrtf SDL_sqrtf_REAL +#define SDL_srand SDL_srand_REAL #define SDL_sscanf SDL_sscanf_REAL #define SDL_strcasecmp SDL_strcasecmp_REAL #define SDL_strcasestr SDL_strcasestr_REAL @@ -999,6 +1160,7 @@ #define SDL_strndup SDL_strndup_REAL #define SDL_strnlen SDL_strnlen_REAL #define SDL_strnstr SDL_strnstr_REAL +#define SDL_strpbrk SDL_strpbrk_REAL #define SDL_strrchr SDL_strrchr_REAL #define SDL_strrev SDL_strrev_REAL #define SDL_strstr SDL_strstr_REAL @@ -1019,6 +1181,7 @@ #define SDL_uitoa SDL_uitoa_REAL #define SDL_ulltoa SDL_ulltoa_REAL #define SDL_ultoa SDL_ultoa_REAL +#define SDL_unsetenv_unsafe SDL_unsetenv_unsafe_REAL #define SDL_utf8strlcpy SDL_utf8strlcpy_REAL #define SDL_utf8strlen SDL_utf8strlen_REAL #define SDL_utf8strnlen SDL_utf8strnlen_REAL diff --git a/libs/SDL3/src/dynapi/SDL_dynapi_procs.h b/libs/SDL3/src/dynapi/SDL_dynapi_procs.h index 6d7e8825d..2c1ef580c 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi_procs.h +++ b/libs/SDL3/src/dynapi/SDL_dynapi_procs.h @@ -21,14 +21,14 @@ /* - DO NOT EDIT THIS FILE BY HAND. It is autogenerated by gendynapi.pl. + DO NOT EDIT THIS FILE BY HAND. It is autogenerated by gendynapi.py. NEVER REARRANGE THIS FILE, THE ORDER IS ABI LAW. Changing this file means bumping SDL_DYNAPI_VERSION. You can safely add new items to the end of the file, though. Also, this file gets included multiple times, don't add #pragma once, etc. */ -/* direct jump magic can use these, the rest needs special code. */ +// direct jump magic can use these, the rest needs special code. #ifndef SDL_DYNAPI_PROC_NO_VARARGS SDL_DYNAPI_PROC(size_t,SDL_IOprintf,(SDL_IOStream *a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),return) SDL_DYNAPI_PROC(void,SDL_Log,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),) @@ -37,136 +37,144 @@ SDL_DYNAPI_PROC(void,SDL_LogDebug,(int a, SDL_PRINTF_FORMAT_STRING const char *b SDL_DYNAPI_PROC(void,SDL_LogError,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) SDL_DYNAPI_PROC(void,SDL_LogInfo,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) SDL_DYNAPI_PROC(void,SDL_LogMessage,(int a, SDL_LogPriority b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_LogTrace,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) SDL_DYNAPI_PROC(void,SDL_LogVerbose,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) SDL_DYNAPI_PROC(void,SDL_LogWarn,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),) -SDL_DYNAPI_PROC(int,SDL_SetError,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetError,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),return) SDL_DYNAPI_PROC(int,SDL_asprintf,(char **a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),return) SDL_DYNAPI_PROC(int,SDL_snprintf,(SDL_OUT_Z_CAP(b) char *a, size_t b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_sscanf,(const char *a, SDL_SCANF_FORMAT_STRING const char *b, ...),(a,b),return) SDL_DYNAPI_PROC(int,SDL_swprintf,(SDL_OUT_Z_CAP(b) wchar_t *a, size_t b, SDL_PRINTF_FORMAT_STRING const wchar_t *c, ...),(a,b,c),return) #endif -#ifdef SDL_CreateThread -#undef SDL_CreateThread -#endif - -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) -SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char *b, void *c, pfnSDL_CurrentBeginThread d, pfnSDL_CurrentEndThread e),(a,b,c,d,e),return) -#else -SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThread,(SDL_ThreadFunction a, const char *b, void *c),(a,b,c),return) -#endif - -#ifdef SDL_CreateThreadWithStackSize -#undef SDL_CreateThreadWithStackSize -#endif - -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) -SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d, pfnSDL_CurrentBeginThread e, pfnSDL_CurrentEndThread f),(a,b,c,d,e,f),return) -#else -SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithStackSize,(SDL_ThreadFunction a, const char *b, const size_t c, void *d),(a,b,c,d),return) -#endif - -/* New API symbols are added at the end */ +// New API symbols are added at the end SDL_DYNAPI_PROC(SDL_Surface*,SDL_AcquireCameraFrame,(SDL_Camera *a, Uint64 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUCommandBuffer*,SDL_AcquireGPUCommandBuffer,(SDL_GPUDevice *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_AcquireGPUSwapchainTexture,(SDL_GPUCommandBuffer *a, SDL_Window *b, SDL_GPUTexture **c, Uint32 *d, Uint32 *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(int,SDL_AddAtomicInt,(SDL_AtomicInt *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_AddEventWatch,(SDL_EventFilter a, void *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_AddGamepadMapping,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromFile,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromIO,(SDL_IOStream *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_AddGamepadMappingsFromIO,(SDL_IOStream *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_AddHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_AddSurfaceAlternateImage,(SDL_Surface *a, SDL_Surface *b),(a,b),return) SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimer,(Uint32 a, SDL_TimerCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_AddVulkanRenderSemaphores,(SDL_Renderer *a, Uint32 b, Sint64 c, Sint64 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(void*,SDL_AllocateEventMemory,(size_t a),(a),return) -SDL_DYNAPI_PROC(void,SDL_AndroidBackButton,(void),(),) -SDL_DYNAPI_PROC(void*,SDL_AndroidGetActivity,(void),(),return) -SDL_DYNAPI_PROC(const char*,SDL_AndroidGetExternalStoragePath,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_AndroidGetExternalStorageState,(Uint32 *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_AndroidGetInternalStoragePath,(void),(),return) -SDL_DYNAPI_PROC(void*,SDL_AndroidGetJNIEnv,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_AndroidRequestPermission,(const char *a, SDL_AndroidRequestPermissionCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_AndroidSendMessage,(Uint32 a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char *a, int b, int c, int d, int e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_AtomicAdd,(SDL_AtomicInt *a, int b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AtomicCompareAndSwap,(SDL_AtomicInt *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AtomicCompareAndSwapPointer,(void **a, void *b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_AtomicGet,(SDL_AtomicInt *a),(a),return) -SDL_DYNAPI_PROC(void*,SDL_AtomicGetPtr,(void **a),(a),return) -SDL_DYNAPI_PROC(int,SDL_AtomicSet,(SDL_AtomicInt *a, int b),(a,b),return) -SDL_DYNAPI_PROC(void*,SDL_AtomicSetPtr,(void **a, void *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystick,(SDL_JoystickType a, int b, int c, int d),(a,b,c,d),return) -SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystickEx,(const SDL_VirtualJoystickDesc *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_BindAudioStream,(SDL_AudioDeviceID a, SDL_AudioStream *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurface,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUnchecked,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_BroadcastCondition,(SDL_Condition *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return) +SDL_DYNAPI_PROC(SDL_TimerID,SDL_AddTimerNS,(Uint64 a, SDL_NSTimerCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_AddVulkanRenderSemaphores,(SDL_Renderer *a, Uint32 b, Sint64 c, Sint64 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(SDL_JoystickID,SDL_AttachVirtualJoystick,(const SDL_VirtualJoystickDesc *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_AudioDevicePaused,(SDL_AudioDeviceID a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUComputePass*,SDL_BeginGPUComputePass,(SDL_GPUCommandBuffer *a, const SDL_GPUStorageTextureReadWriteBinding *b, Uint32 c, const SDL_GPUStorageBufferReadWriteBinding *d, Uint32 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_GPUCopyPass*,SDL_BeginGPUCopyPass,(SDL_GPUCommandBuffer *a),(a),return) +SDL_DYNAPI_PROC(SDL_GPURenderPass*,SDL_BeginGPURenderPass,(SDL_GPUCommandBuffer *a, const SDL_GPUColorTargetInfo *b, Uint32 c, const SDL_GPUDepthStencilTargetInfo *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_BindAudioStream,(SDL_AudioDeviceID a, SDL_AudioStream *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_BindAudioStreams,(SDL_AudioDeviceID a, SDL_AudioStream **b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_BindGPUComputePipeline,(SDL_GPUComputePass *a, SDL_GPUComputePipeline *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_BindGPUComputeSamplers,(SDL_GPUComputePass *a, Uint32 b, const SDL_GPUTextureSamplerBinding *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUComputeStorageBuffers,(SDL_GPUComputePass *a, Uint32 b, SDL_GPUBuffer *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUComputeStorageTextures,(SDL_GPUComputePass *a, Uint32 b, SDL_GPUTexture *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUFragmentSamplers,(SDL_GPURenderPass *a, Uint32 b, const SDL_GPUTextureSamplerBinding *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUFragmentStorageBuffers,(SDL_GPURenderPass *a, Uint32 b, SDL_GPUBuffer *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUFragmentStorageTextures,(SDL_GPURenderPass *a, Uint32 b, SDL_GPUTexture *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUGraphicsPipeline,(SDL_GPURenderPass *a, SDL_GPUGraphicsPipeline *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_BindGPUIndexBuffer,(SDL_GPURenderPass *a, const SDL_GPUBufferBinding *b, SDL_GPUIndexElementSize c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_BindGPUVertexBuffers,(SDL_GPURenderPass *a, Uint32 b, const SDL_GPUBufferBinding *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUVertexSamplers,(SDL_GPURenderPass *a, Uint32 b, const SDL_GPUTextureSamplerBinding *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUVertexStorageBuffers,(SDL_GPURenderPass *a, Uint32 b, SDL_GPUBuffer *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BindGPUVertexStorageTextures,(SDL_GPURenderPass *a, Uint32 b, SDL_GPUTexture *const *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_BlitGPUTexture,(SDL_GPUCommandBuffer *a, const SDL_GPUBlitInfo *b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_BlitSurface,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurface9Grid,(SDL_Surface *a, const SDL_Rect *b, int c, int d, int e, int f, float g, SDL_ScaleMode h, SDL_Surface *i, const SDL_Rect *j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurfaceScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurfaceTiled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurfaceTiledWithScale,(SDL_Surface *a, const SDL_Rect *b, float c, SDL_ScaleMode d, SDL_Surface *e, const SDL_Rect *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurfaceUnchecked,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_BlitSurfaceUncheckedScaled,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(void,SDL_BroadcastCondition,(SDL_Condition *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_CaptureMouse,(bool a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ClaimWindowForGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) -SDL_DYNAPI_PROC(int,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return) -SDL_DYNAPI_PROC(void,SDL_ClearComposition,(void),(),) -SDL_DYNAPI_PROC(void,SDL_ClearError,(void),(),) -SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ClearClipboardData,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_ClearComposition,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ClearError,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ClearSurface,(SDL_Surface *a, float b, float c, float d, float e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),) SDL_DYNAPI_PROC(void,SDL_CloseCamera,(SDL_Camera *a),(a),) SDL_DYNAPI_PROC(void,SDL_CloseGamepad,(SDL_Gamepad *a),(a),) SDL_DYNAPI_PROC(void,SDL_CloseHaptic,(SDL_Haptic *a),(a),) -SDL_DYNAPI_PROC(int,SDL_CloseIO,(SDL_IOStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_CloseIO,(SDL_IOStream *a),(a),return) SDL_DYNAPI_PROC(void,SDL_CloseJoystick,(SDL_Joystick *a),(a),) SDL_DYNAPI_PROC(void,SDL_CloseSensor,(SDL_Sensor *a),(a),) -SDL_DYNAPI_PROC(int,SDL_CloseStorage,(SDL_Storage *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_CloseStorage,(SDL_Storage *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_CompareAndSwapAtomicInt,(SDL_AtomicInt *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_CompareAndSwapAtomicPointer,(void **a, void *b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_CompareAndSwapAtomicU32,(SDL_AtomicU32 *a, Uint32 b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_BlendMode,SDL_ComposeCustomBlendMode,(SDL_BlendFactor a, SDL_BlendFactor b, SDL_BlendOperation c, SDL_BlendFactor d, SDL_BlendFactor e, SDL_BlendOperation f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(int,SDL_ConvertAudioSamples,(const SDL_AudioSpec *a, const Uint8 *b, int c, const SDL_AudioSpec *d, Uint8 **e, int *f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(int,SDL_ConvertEventToRenderCoordinates,(SDL_Renderer *a, SDL_Event *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_ConvertPixels,(int a, int b, SDL_PixelFormatEnum c, const void *d, int e, SDL_PixelFormatEnum f, void *g, int h),(a,b,c,d,e,f,g,h),return) -SDL_DYNAPI_PROC(int,SDL_ConvertPixelsAndColorspace,(int a, int b, SDL_PixelFormatEnum c, SDL_Colorspace d, SDL_PropertiesID e, const void *f, int g, SDL_PixelFormatEnum h, SDL_Colorspace i, SDL_PropertiesID j, void *k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurface,(SDL_Surface *a, const SDL_PixelFormat *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormat,(SDL_Surface *a, SDL_PixelFormatEnum b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceFormatAndColorspace,(SDL_Surface *a, SDL_PixelFormatEnum b, SDL_Colorspace c, SDL_PropertiesID d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_CopyProperties,(SDL_PropertiesID a, SDL_PropertiesID b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ConvertAudioSamples,(const SDL_AudioSpec *a, const Uint8 *b, int c, const SDL_AudioSpec *d, Uint8 **e, int *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(bool,SDL_ConvertEventToRenderCoordinates,(SDL_Renderer *a, SDL_Event *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ConvertPixels,(int a, int b, SDL_PixelFormat c, const void *d, int e, SDL_PixelFormat f, void *g, int h),(a,b,c,d,e,f,g,h),return) +SDL_DYNAPI_PROC(bool,SDL_ConvertPixelsAndColorspace,(int a, int b, SDL_PixelFormat c, SDL_Colorspace d, SDL_PropertiesID e, const void *f, int g, SDL_PixelFormat h, SDL_Colorspace i, SDL_PropertiesID j, void *k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurface,(SDL_Surface *a, SDL_PixelFormat b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_ConvertSurfaceAndColorspace,(SDL_Surface *a, SDL_PixelFormat b, SDL_Palette *c, SDL_Colorspace d, SDL_PropertiesID e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_CopyFile,(const char *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_CopyGPUBufferToBuffer,(SDL_GPUCopyPass *a, const SDL_GPUBufferLocation *b, const SDL_GPUBufferLocation *c, Uint32 d, bool e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(void,SDL_CopyGPUTextureToTexture,(SDL_GPUCopyPass *a, const SDL_GPUTextureLocation *b, const SDL_GPUTextureLocation *c, Uint32 d, Uint32 e, Uint32 f, bool g),(a,b,c,d,e,f,g),) +SDL_DYNAPI_PROC(bool,SDL_CopyProperties,(SDL_PropertiesID a, SDL_PropertiesID b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_CopyStorageFile,(SDL_Storage *a, const char *b, const char *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_CreateAudioStream,(const SDL_AudioSpec *a, const SDL_AudioSpec *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateColorCursor,(SDL_Surface *a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Condition*,SDL_CreateCondition,(void),(),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateCursor,(const Uint8 *a, const Uint8 *b, int c, int d, int e, int f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(int,SDL_CreateDirectory,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_CreateDirectory,(const char *a),(a),return) +SDL_DYNAPI_PROC(SDL_Environment*,SDL_CreateEnvironment,(bool a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUBuffer*,SDL_CreateGPUBuffer,(SDL_GPUDevice *a, const SDL_GPUBufferCreateInfo* b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUComputePipeline*,SDL_CreateGPUComputePipeline,(SDL_GPUDevice *a, const SDL_GPUComputePipelineCreateInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDevice,(SDL_GPUShaderFormat a, bool b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_GPUDevice*,SDL_CreateGPUDeviceWithProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUGraphicsPipeline*,SDL_CreateGPUGraphicsPipeline,(SDL_GPUDevice *a, const SDL_GPUGraphicsPipelineCreateInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUSampler*,SDL_CreateGPUSampler,(SDL_GPUDevice *a, const SDL_GPUSamplerCreateInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUShader*,SDL_CreateGPUShader,(SDL_GPUDevice *a, const SDL_GPUShaderCreateInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUTexture*,SDL_CreateGPUTexture,(SDL_GPUDevice *a, const SDL_GPUTextureCreateInfo *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GPUTransferBuffer*,SDL_CreateGPUTransferBuffer,(SDL_GPUDevice *a, const SDL_GPUTransferBufferCreateInfo *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_CreateHapticEffect,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Mutex*,SDL_CreateMutex,(void),(),return) SDL_DYNAPI_PROC(SDL_Palette*,SDL_CreatePalette,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_PixelFormat*,SDL_CreatePixelFormat,(SDL_PixelFormatEnum a),(a),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, SDL_WindowFlags f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(SDL_Process*,SDL_CreateProcess,(const char * const *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Process*,SDL_CreateProcessWithProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_CreateProperties,(void),(),return) SDL_DYNAPI_PROC(SDL_RWLock*,SDL_CreateRWLock,(void),(),return) -SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRenderer,(SDL_Window *a, const char *b, Uint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRenderer,(SDL_Window *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateRendererWithProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(SDL_Semaphore*,SDL_CreateSemaphore,(Uint32 a),(a),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateSoftwareRenderer,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_CreateStorageDirectory,(SDL_Storage *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurface,(int a, int b, SDL_PixelFormatEnum c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurfaceFrom,(void *a, int b, int c, int d, SDL_PixelFormatEnum e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_CreateStorageDirectory,(SDL_Storage *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurface,(int a, int b, SDL_PixelFormat c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateSurfaceFrom,(int a, int b, SDL_PixelFormat c, void *d, int e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_Palette*,SDL_CreateSurfacePalette,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_CreateSystemCursor,(SDL_SystemCursor a),(a),return) -SDL_DYNAPI_PROC(SDL_TLSID,SDL_CreateTLS,(void),(),return) -SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTexture,(SDL_Renderer *a, SDL_PixelFormatEnum b, int c, int d, int e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTexture,(SDL_Renderer *a, SDL_PixelFormat b, SDL_TextureAccess c, int d, int e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureFromSurface,(SDL_Renderer *a, SDL_Surface *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Texture*,SDL_CreateTextureWithProperties,(SDL_Renderer *a, SDL_PropertiesID b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindow,(const char *a, int b, int c, Uint32 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_CreateWindowAndRenderer,(int a, int b, Uint32 c, SDL_Window **d, SDL_Renderer **e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadRuntime,(SDL_ThreadFunction a, const char *b, void *c, SDL_FunctionPointer d, SDL_FunctionPointer e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_Thread*,SDL_CreateThreadWithPropertiesRuntime,(SDL_PropertiesID a, SDL_FunctionPointer b, SDL_FunctionPointer c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindow,(const char *a, int b, int c, SDL_WindowFlags d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_CreateWindowAndRenderer,(const char *a, int b, int c, SDL_WindowFlags d, SDL_Window **e, SDL_Renderer **f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowWithProperties,(SDL_PropertiesID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_CursorVisible,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_DXGIGetOutputInfo,(SDL_DisplayID a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_DateTimeToTime,(const SDL_DateTime *a, SDL_Time *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_DelEventWatch,(SDL_EventFilter a, void *b),(a,b),) -SDL_DYNAPI_PROC(void,SDL_DelHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),) +SDL_DYNAPI_PROC(bool,SDL_CursorVisible,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_DateTimeToTime,(const SDL_DateTime *a, SDL_Time *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_Delay,(Uint32 a),(a),) SDL_DYNAPI_PROC(void,SDL_DelayNS,(Uint64 a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyAudioStream,(SDL_AudioStream *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyCondition,(SDL_Condition *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyCursor,(SDL_Cursor *a),(a),) +SDL_DYNAPI_PROC(void,SDL_DestroyEnvironment,(SDL_Environment *a),(a),) +SDL_DYNAPI_PROC(void,SDL_DestroyGPUDevice,(SDL_GPUDevice *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyHapticEffect,(SDL_Haptic *a, int b),(a,b),) SDL_DYNAPI_PROC(void,SDL_DestroyMutex,(SDL_Mutex *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyPalette,(SDL_Palette *a),(a),) -SDL_DYNAPI_PROC(void,SDL_DestroyPixelFormat,(SDL_PixelFormat *a),(a),) +SDL_DYNAPI_PROC(void,SDL_DestroyProcess,(SDL_Process *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyProperties,(SDL_PropertiesID a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyRWLock,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyRenderer,(SDL_Renderer *a),(a),) @@ -174,233 +182,276 @@ SDL_DYNAPI_PROC(void,SDL_DestroySemaphore,(SDL_Semaphore *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroySurface,(SDL_Surface *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyTexture,(SDL_Texture *a),(a),) SDL_DYNAPI_PROC(void,SDL_DestroyWindow,(SDL_Window *a),(a),) -SDL_DYNAPI_PROC(int,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_DestroyWindowSurface,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void,SDL_DetachThread,(SDL_Thread *a),(a),) -SDL_DYNAPI_PROC(int,SDL_DetachVirtualJoystick,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_Direct3D9GetAdapterIndex,(SDL_DisplayID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_DisableScreenSaver,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_DetachVirtualJoystick,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_DisableScreenSaver,(void),(),return) +SDL_DYNAPI_PROC(void,SDL_DispatchGPUCompute,(SDL_GPUComputePass *a, Uint32 b, Uint32 c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_DispatchGPUComputeIndirect,(SDL_GPUComputePass *a, SDL_GPUBuffer *b, Uint32 c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_DownloadFromGPUBuffer,(SDL_GPUCopyPass *a, const SDL_GPUBufferRegion *b, const SDL_GPUTransferBufferLocation *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_DownloadFromGPUTexture,(SDL_GPUCopyPass *a, const SDL_GPUTextureRegion *b, const SDL_GPUTextureTransferInfo *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_DrawGPUIndexedPrimitives,(SDL_GPURenderPass *a, Uint32 b, Uint32 c, Uint32 d, Sint32 e, Uint32 f),(a,b,c,d,e,f),) +SDL_DYNAPI_PROC(void,SDL_DrawGPUIndexedPrimitivesIndirect,(SDL_GPURenderPass *a, SDL_GPUBuffer *b, Uint32 c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_DrawGPUPrimitives,(SDL_GPURenderPass *a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(void,SDL_DrawGPUPrimitivesIndirect,(SDL_GPURenderPass *a, SDL_GPUBuffer *b, Uint32 c, Uint32 d),(a,b,c,d),) SDL_DYNAPI_PROC(SDL_Surface*,SDL_DuplicateSurface,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentEGLConfig,(void),(),return) -SDL_DYNAPI_PROC(SDL_EGLDisplay,SDL_EGL_GetCurrentEGLDisplay,(void),(),return) +SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentConfig,(void),(),return) +SDL_DYNAPI_PROC(SDL_EGLDisplay,SDL_EGL_GetCurrentDisplay,(void),(),return) SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_EGL_GetProcAddress,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_EGLSurface,SDL_EGL_GetWindowEGLSurface,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_EGL_SetEGLAttributeCallbacks,(SDL_EGLAttribArrayCallback a, SDL_EGLIntArrayCallback b, SDL_EGLIntArrayCallback c),(a,b,c),) -SDL_DYNAPI_PROC(int,SDL_EnableScreenSaver,(void),(),return) +SDL_DYNAPI_PROC(SDL_EGLSurface,SDL_EGL_GetWindowSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_EGL_SetAttributeCallbacks,(SDL_EGLAttribArrayCallback a, SDL_EGLIntArrayCallback b, SDL_EGLIntArrayCallback c, void *d),(a,b,c,d),) +SDL_DYNAPI_PROC(bool,SDL_EnableScreenSaver,(void),(),return) +SDL_DYNAPI_PROC(void,SDL_EndGPUComputePass,(SDL_GPUComputePass *a),(a),) +SDL_DYNAPI_PROC(void,SDL_EndGPUCopyPass,(SDL_GPUCopyPass *a),(a),) +SDL_DYNAPI_PROC(void,SDL_EndGPURenderPass,(SDL_GPURenderPass *a),(a),) SDL_DYNAPI_PROC(int,SDL_EnterAppMainCallbacks,(int a, char *b[], SDL_AppInit_func c, SDL_AppIterate_func d, SDL_AppEvent_func e, SDL_AppQuit_func f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(int,SDL_EnumerateDirectory,(const char *a, SDL_EnumerateDirectoryCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_EnumerateStorageDirectory,(SDL_Storage *a, const char *b, SDL_EnumerateDirectoryCallback c, void *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_Error,(SDL_errorcode a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_EventEnabled,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(int,SDL_FillSurfaceRect,(SDL_Surface *a, const SDL_Rect *b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_FillSurfaceRects,(SDL_Surface *a, const SDL_Rect *b, int c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_EnumerateDirectory,(const char *a, SDL_EnumerateDirectoryCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_EnumerateProperties,(SDL_PropertiesID a, SDL_EnumeratePropertiesCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_EnumerateStorageDirectory,(SDL_Storage *a, const char *b, SDL_EnumerateDirectoryCallback c, void *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_EventEnabled,(Uint32 a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_FillSurfaceRect,(SDL_Surface *a, const SDL_Rect *b, Uint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_FillSurfaceRects,(SDL_Surface *a, const SDL_Rect *b, int c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(void,SDL_FilterEvents,(SDL_EventFilter a, void *b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, SDL_FlashOperation b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_FlipSurface,(SDL_Surface *a, SDL_FlipMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_FlushAudioStream,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_FlashWindow,(SDL_Window *a, SDL_FlashOperation b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_FlipSurface,(SDL_Surface *a, SDL_FlipMode b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_FlushAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(void,SDL_FlushEvent,(Uint32 a),(a),) SDL_DYNAPI_PROC(void,SDL_FlushEvents,(Uint32 a, Uint32 b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_FlushRenderer,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GDKGetDefaultUser,(XUserHandle *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GDKGetTaskQueue,(XTaskQueueHandle *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_FlushIO,(SDL_IOStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_FlushRenderer,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_GDKResumeGPU,(SDL_GPUDevice *a),(a),) SDL_DYNAPI_PROC(void,SDL_GDKSuspendComplete,(void),(),) +SDL_DYNAPI_PROC(void,SDL_GDKSuspendGPU,(SDL_GPUDevice *a),(a),) SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_CreateContext,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_DeleteContext,(SDL_GLContext a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GL_ExtensionSupported,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_GetAttribute,(SDL_GLattr a, int *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GL_DestroyContext,(SDL_GLContext a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_ExtensionSupported,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_GetAttribute,(SDL_GLattr a, int *b),(a,b),return) SDL_DYNAPI_PROC(SDL_GLContext,SDL_GL_GetCurrentContext,(void),(),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GL_GetCurrentWindow,(void),(),return) SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_GL_GetProcAddress,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_GetSwapInterval,(int *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_LoadLibrary,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_MakeCurrent,(SDL_Window *a, SDL_GLContext b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GL_GetSwapInterval,(int *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_LoadLibrary,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_MakeCurrent,(SDL_Window *a, SDL_GLContext b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_GL_ResetAttributes,(void),(),) -SDL_DYNAPI_PROC(int,SDL_GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GL_SetSwapInterval,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GL_SwapWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_SetAttribute,(SDL_GLattr a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GL_SetSwapInterval,(int a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GL_SwapWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GL_UnloadLibrary,(void),(),) -SDL_DYNAPI_PROC(SDL_GUID,SDL_GUIDFromString,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GUIDToString,(SDL_GUID a, char *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadConnected,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadEventsEnabled,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadHasAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadHasButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadHasSensor,(SDL_Gamepad *a, SDL_SensorType b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GamepadSensorEnabled,(SDL_Gamepad *a, SDL_SensorType b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GPUSupportsProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GPUSupportsShaderFormats,(SDL_GPUShaderFormat a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(Uint32,SDL_GPUTextureFormatTexelBlockSize,(SDL_GPUTextureFormat a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GPUTextureSupportsFormat,(SDL_GPUDevice *a, SDL_GPUTextureFormat b, SDL_GPUTextureType c, SDL_GPUTextureUsageFlags d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GPUTextureSupportsSampleCount,(SDL_GPUDevice *a, SDL_GPUTextureFormat b, SDL_GPUSampleCount c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_GUIDToString,(SDL_GUID a, char *b, int c),(a,b,c),) +SDL_DYNAPI_PROC(bool,SDL_GamepadConnected,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GamepadEventsEnabled,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_GamepadHasAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GamepadHasButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GamepadHasSensor,(SDL_Gamepad *a, SDL_SensorType b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GamepadSensorEnabled,(SDL_Gamepad *a, SDL_SensorType b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_GenerateMipmapsForGPUTexture,(SDL_GPUCommandBuffer *a, SDL_GPUTexture *b),(a,b),) +SDL_DYNAPI_PROC(void*,SDL_GetAndroidActivity,(void),(),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAndroidCachePath,(void),(),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAndroidExternalStoragePath,(void),(),return) +SDL_DYNAPI_PROC(Uint32,SDL_GetAndroidExternalStorageState,(void),(),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAndroidInternalStoragePath,(void),(),return) +SDL_DYNAPI_PROC(void*,SDL_GetAndroidJNIEnv,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetAndroidSDKVersion,(void),(),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAppMetadataProperty,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetAssertionHandler,(void **a),(a),return) SDL_DYNAPI_PROC(const SDL_AssertData*,SDL_GetAssertionReport,(void),(),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioCaptureDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetAtomicInt,(SDL_AtomicInt *a),(a),return) +SDL_DYNAPI_PROC(void*,SDL_GetAtomicPointer,(void **a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_GetAtomicU32,(SDL_AtomicU32 *a),(a),return) +SDL_DYNAPI_PROC(int*,SDL_GetAudioDeviceChannelMap,(SDL_AudioDeviceID a, int *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetAudioDeviceFormat,(SDL_AudioDeviceID a, SDL_AudioSpec *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(float,SDL_GetAudioDeviceGain,(SDL_AudioDeviceID a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAudioDeviceName,(SDL_AudioDeviceID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetAudioDriver,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioOutputDevices,(int *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetAudioFormatName,(SDL_AudioFormat a),(a),return) +SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioPlaybackDevices,(int *a),(a),return) +SDL_DYNAPI_PROC(SDL_AudioDeviceID*,SDL_GetAudioRecordingDevices,(int *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamAvailable,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamData,(SDL_AudioStream *a, void *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_GetAudioStreamDevice,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioSpec *b, SDL_AudioSpec *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetAudioStreamFormat,(SDL_AudioStream *a, SDL_AudioSpec *b, SDL_AudioSpec *c),(a,b,c),return) SDL_DYNAPI_PROC(float,SDL_GetAudioStreamFrequencyRatio,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(float,SDL_GetAudioStreamGain,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(int*,SDL_GetAudioStreamInputChannelMap,(SDL_AudioStream *a, int *b),(a,b),return) +SDL_DYNAPI_PROC(int*,SDL_GetAudioStreamOutputChannelMap,(SDL_AudioStream *a, int *b),(a,b),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetAudioStreamProperties,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetAudioStreamQueued,(SDL_AudioStream *a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_GetBasePath,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) +SDL_DYNAPI_PROC(const char*,SDL_GetBasePath,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_GetBooleanProperty,(SDL_PropertiesID a, const char *b, bool c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetCPUCacheLineSize,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetCPUCount,(void),(),return) -SDL_DYNAPI_PROC(char*,SDL_GetCameraDeviceName,(SDL_CameraDeviceID a),(a),return) -SDL_DYNAPI_PROC(SDL_CameraPosition,SDL_GetCameraDevicePosition,(SDL_CameraDeviceID a),(a),return) -SDL_DYNAPI_PROC(SDL_CameraSpec*,SDL_GetCameraDeviceSupportedFormats,(SDL_CameraDeviceID a, int *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_CameraDeviceID*,SDL_GetCameraDevices,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetCameraDriver,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetCameraFormat,(SDL_Camera *a, SDL_CameraSpec *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_CameraDeviceID,SDL_GetCameraInstanceID,(SDL_Camera *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetCameraFormat,(SDL_Camera *a, SDL_CameraSpec *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_CameraID,SDL_GetCameraID,(SDL_Camera *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetCameraName,(SDL_CameraID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetCameraPermissionState,(SDL_Camera *a),(a),return) +SDL_DYNAPI_PROC(SDL_CameraPosition,SDL_GetCameraPosition,(SDL_CameraID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetCameraProperties,(SDL_Camera *a),(a),return) +SDL_DYNAPI_PROC(SDL_CameraSpec**,SDL_GetCameraSupportedFormats,(SDL_CameraID a, int *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_CameraID*,SDL_GetCameras,(int *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetClipboardData,(const char *a, size_t *b),(a,b),return) +SDL_DYNAPI_PROC(char **,SDL_GetClipboardMimeTypes,(size_t *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetClipboardText,(void),(),return) -SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetClosestFullscreenDisplayMode,(SDL_DisplayID a, int b, int c, float d, SDL_bool e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetClosestFullscreenDisplayMode,(SDL_DisplayID a, int b, int c, float d, bool e, SDL_DisplayMode *f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(const char*,SDL_GetCurrentAudioDriver,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetCurrentCameraDriver,(void),(),return) SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetCurrentDisplayMode,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetCurrentDisplayOrientation,(SDL_DisplayID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetCurrentRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetCurrentRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_ThreadID,SDL_GetCurrentThreadID,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetCurrentTime,(SDL_Time *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetCurrentTime,(SDL_Time *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetCurrentVideoDriver,(void),(),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_GetCursor,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_GetDXGIOutputInfo,(SDL_DisplayID a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetDateTimeLocalePreferences,(SDL_DateFormat *a, SDL_TimeFormat *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetDayOfWeek,(int a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetDayOfYear,(int a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_GetDaysInMonth,(int a, int b),(a,b),return) SDL_DYNAPI_PROC(SDL_AssertionHandler,SDL_GetDefaultAssertionHandler,(void),(),return) SDL_DYNAPI_PROC(SDL_Cursor*,SDL_GetDefaultCursor,(void),(),return) SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetDesktopDisplayMode,(SDL_DisplayID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetDisplayBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(int,SDL_GetDirect3D9AdapterIndex,(SDL_DisplayID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetDisplayBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_GetDisplayContentScale,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForPoint,(const SDL_Point *a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForRect,(const SDL_Rect *a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetDisplayForWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetDisplayName,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetDisplayProperties,(SDL_DisplayID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetDisplayUsableBounds,(SDL_DisplayID a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_DisplayID*,SDL_GetDisplays,(int *a),(a),return) +SDL_DYNAPI_PROC(SDL_Environment*,SDL_GetEnvironment,(void),(),return) +SDL_DYNAPI_PROC(const char*,SDL_GetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(char**,SDL_GetEnvironmentVariables,(SDL_Environment *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetError,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetEventFilter,(SDL_EventFilter *a, void **b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_GetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) -SDL_DYNAPI_PROC(const SDL_DisplayMode**,SDL_GetFullscreenDisplayModes,(SDL_DisplayID a, int *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_DisplayMode**,SDL_GetFullscreenDisplayModes,(SDL_DisplayID a, int *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetGDKDefaultUser,(XUserHandle *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetGDKTaskQueue,(XTaskQueueHandle *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetGPUDeviceDriver,(SDL_GPUDevice *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetGPUDriver,(int a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUShaderFormat,SDL_GetGPUShaderFormats,(SDL_GPUDevice *a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUTextureFormat,SDL_GetGPUSwapchainTextureFormat,(SDL_GPUDevice *a, SDL_Window *b),(a,b),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadAppleSFSymbolsNameForAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadAppleSFSymbolsNameForButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) SDL_DYNAPI_PROC(Sint16,SDL_GetGamepadAxis,(SDL_Gamepad *a, SDL_GamepadAxis b),(a,b),return) SDL_DYNAPI_PROC(SDL_GamepadAxis,SDL_GetGamepadAxisFromString,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_GamepadBinding **,SDL_GetGamepadBindings,(SDL_Gamepad *a, int *b),(a,b),return) -SDL_DYNAPI_PROC(Uint8,SDL_GetGamepadButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) +SDL_DYNAPI_PROC(SDL_GamepadBinding**,SDL_GetGamepadBindings,(SDL_Gamepad *a, int *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetGamepadButton,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) SDL_DYNAPI_PROC(SDL_GamepadButton,SDL_GetGamepadButtonFromString,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabel,(SDL_Gamepad *a, SDL_GamepadButton b),(a,b),return) SDL_DYNAPI_PROC(SDL_GamepadButtonLabel,SDL_GetGamepadButtonLabelForType,(SDL_GamepadType a, SDL_GamepadButton b),(a,b),return) SDL_DYNAPI_PROC(SDL_JoystickConnectionState,SDL_GetGamepadConnectionState,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadFirmwareVersion,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_GetGamepadFromInstanceID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_GetGamepadFromID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_GetGamepadFromPlayerIndex,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetGamepadInstanceGUID,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetGamepadInstanceID,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_GetGamepadInstanceMapping,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetGamepadInstanceName,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetGamepadInstancePath,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetGamepadInstancePlayerIndex,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceProduct,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceProductVersion,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadInstanceType,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadInstanceVendor,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(SDL_GUID,SDL_GetGamepadGUIDForID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetGamepadID,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetGamepadJoystick,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetGamepadMapping,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForGUID,(SDL_JoystickGUID a),(a),return) -SDL_DYNAPI_PROC(char**,SDL_GetGamepadMappings,(int *a),(a),return) +SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForGUID,(SDL_GUID a),(a),return) +SDL_DYNAPI_PROC(char*,SDL_GetGamepadMappingForID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(char **,SDL_GetGamepadMappings,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadName,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetGamepadNameForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPath,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetGamepadPathForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetGamepadPlayerIndex,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetGamepadPlayerIndexForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_PowerState,SDL_GetGamepadPowerInfo,(SDL_Gamepad *a, int *b),(a,b),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProduct,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProductForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProductVersion,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadProductVersionForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGamepadProperties,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetGamepadSensorData,(SDL_Gamepad *a, SDL_SensorType b, float *c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetGamepadSensorData,(SDL_Gamepad *a, SDL_SensorType b, float *c, int d),(a,b,c,d),return) SDL_DYNAPI_PROC(float,SDL_GetGamepadSensorDataRate,(SDL_Gamepad *a, SDL_SensorType b),(a,b),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadSerial,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetGamepadSteamHandle,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadStringForAxis,(SDL_GamepadAxis a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadStringForButton,(SDL_GamepadButton a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetGamepadStringForType,(SDL_GamepadType a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetGamepadTouchpadFinger,(SDL_Gamepad *a, int b, int c, Uint8 *d, float *e, float *f, float *g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_GetGamepadTouchpadFinger,(SDL_Gamepad *a, int b, int c, bool *d, float *e, float *f, float *g),(a,b,c,d,e,f,g),return) SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadType,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadTypeForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetGamepadTypeFromString,(const char *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadVendor,(SDL_Gamepad *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetGamepadVendorForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_JoystickID*,SDL_GetGamepads,(int *a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetGlobalMouseState,(float *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_MouseButtonFlags,SDL_GetGlobalMouseState,(float *a, float *b),(a,b),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGlobalProperties,(void),(),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetGrabbedWindow,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetHapticEffectStatus,(SDL_Haptic *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetHapticEffectStatus,(SDL_Haptic *a, int b),(a,b),return) SDL_DYNAPI_PROC(Uint32,SDL_GetHapticFeatures,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(SDL_Haptic*,SDL_GetHapticFromInstanceID,(SDL_HapticID a),(a),return) -SDL_DYNAPI_PROC(SDL_HapticID,SDL_GetHapticInstanceID,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetHapticInstanceName,(SDL_HapticID a),(a),return) +SDL_DYNAPI_PROC(SDL_Haptic*,SDL_GetHapticFromID,(SDL_HapticID a),(a),return) +SDL_DYNAPI_PROC(SDL_HapticID,SDL_GetHapticID,(SDL_Haptic *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetHapticName,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetHapticNameForID,(SDL_HapticID a),(a),return) SDL_DYNAPI_PROC(SDL_HapticID*,SDL_GetHaptics,(int *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetHint,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetHintBoolean,(const char *a, SDL_bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetHintBoolean,(const char *a, bool b),(a,b),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetIOProperties,(SDL_IOStream *a),(a),return) SDL_DYNAPI_PROC(Sint64,SDL_GetIOSize,(SDL_IOStream *a),(a),return) SDL_DYNAPI_PROC(SDL_IOStatus,SDL_GetIOStatus,(SDL_IOStream *a),(a),return) SDL_DYNAPI_PROC(Sint16,SDL_GetJoystickAxis,(SDL_Joystick *a, int b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetJoystickAxisInitialState,(SDL_Joystick *a, int b, Sint16 *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetJoystickBall,(SDL_Joystick *a, int b, int *c, int *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(Uint8,SDL_GetJoystickButton,(SDL_Joystick *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetJoystickAxisInitialState,(SDL_Joystick *a, int b, Sint16 *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetJoystickBall,(SDL_Joystick *a, int b, int *c, int *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetJoystickButton,(SDL_Joystick *a, int b),(a,b),return) SDL_DYNAPI_PROC(SDL_JoystickConnectionState,SDL_GetJoystickConnectionState,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickFirmwareVersion,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetJoystickFromInstanceID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetJoystickFromID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_Joystick*,SDL_GetJoystickFromPlayerIndex,(int a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickGUID,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickGUIDFromString,(const char *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_JoystickGUID a, Uint16 *b, Uint16 *c, Uint16 *d, Uint16 *e),(a,b,c,d,e),) -SDL_DYNAPI_PROC(int,SDL_GetJoystickGUIDString,(SDL_JoystickGUID a, char *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_GUID,SDL_GetJoystickGUID,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(SDL_GUID,SDL_GetJoystickGUIDForID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_GUID a, Uint16 *b, Uint16 *c, Uint16 *d, Uint16 *e),(a,b,c,d,e),) SDL_DYNAPI_PROC(Uint8,SDL_GetJoystickHat,(SDL_Joystick *a, int b),(a,b),return) -SDL_DYNAPI_PROC(SDL_JoystickGUID,SDL_GetJoystickInstanceGUID,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetJoystickInstanceID,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetJoystickInstanceName,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetJoystickInstancePath,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetJoystickInstancePlayerIndex,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceProduct,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceProductVersion,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickInstanceType,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickInstanceVendor,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(SDL_JoystickID,SDL_GetJoystickID,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetJoystickName,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetJoystickNameForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetJoystickPath,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetJoystickPathForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetJoystickPlayerIndex,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetJoystickPlayerIndexForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_PowerState,SDL_GetJoystickPowerInfo,(SDL_Joystick *a, int *b),(a,b),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProduct,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProductForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProductVersion,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickProductVersionForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetJoystickProperties,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetJoystickSerial,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickType,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(SDL_JoystickType,SDL_GetJoystickTypeForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickVendor,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(Uint16,SDL_GetJoystickVendorForID,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_JoystickID*,SDL_GetJoysticks,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_Keycode,SDL_GetKeyFromName,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_Keycode,SDL_GetKeyFromScancode,(SDL_Scancode a),(a),return) +SDL_DYNAPI_PROC(SDL_Keycode,SDL_GetKeyFromScancode,(SDL_Scancode a, SDL_Keymod b, bool c),(a,b,c),return) SDL_DYNAPI_PROC(const char*,SDL_GetKeyName,(SDL_Keycode a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetKeyboardFocus,(void),(),return) -SDL_DYNAPI_PROC(const char*,SDL_GetKeyboardInstanceName,(SDL_KeyboardID a),(a),return) -SDL_DYNAPI_PROC(const Uint8*,SDL_GetKeyboardState,(int *a),(a),return) -SDL_DYNAPI_PROC(SDL_MouseID*,SDL_GetKeyboards,(int *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetKeyboardNameForID,(SDL_KeyboardID a),(a),return) +SDL_DYNAPI_PROC(const bool*,SDL_GetKeyboardState,(int *a),(a),return) +SDL_DYNAPI_PROC(SDL_KeyboardID*,SDL_GetKeyboards,(int *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GetLogOutputFunction,(SDL_LogOutputFunction *a, void **b),(a,b),) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetMasksForPixelFormatEnum,(SDL_PixelFormatEnum a, int *b, Uint32 *c, Uint32 *d, Uint32 *e, Uint32 *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(SDL_LogPriority,SDL_GetLogPriority,(int a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetMasksForPixelFormat,(SDL_PixelFormat a, int *b, Uint32 *c, Uint32 *d, Uint32 *e, Uint32 *f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(int,SDL_GetMaxHapticEffects,(SDL_Haptic *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetMaxHapticEffectsPlaying,(SDL_Haptic *a),(a),return) SDL_DYNAPI_PROC(void,SDL_GetMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),) SDL_DYNAPI_PROC(SDL_MouseID*,SDL_GetMice,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_Keymod,SDL_GetModState,(void),(),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetMouseFocus,(void),(),return) -SDL_DYNAPI_PROC(const char*,SDL_GetMouseInstanceName,(SDL_MouseID a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetMouseState,(float *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(const char*,SDL_GetMouseNameForID,(SDL_MouseID a),(a),return) +SDL_DYNAPI_PROC(SDL_MouseButtonFlags,SDL_GetMouseState,(float *a, float *b),(a,b),return) SDL_DYNAPI_PROC(SDL_DisplayOrientation,SDL_GetNaturalDisplayOrientation,(SDL_DisplayID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumAllocations,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumAudioDrivers,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumCameraDrivers,(void),(),return) +SDL_DYNAPI_PROC(int,SDL_GetNumGPUDrivers,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumGamepadTouchpadFingers,(SDL_Gamepad *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_GetNumGamepadTouchpads,(SDL_Gamepad *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumHapticAxes,(SDL_Haptic *a),(a),return) @@ -408,102 +459,105 @@ SDL_DYNAPI_PROC(int,SDL_GetNumJoystickAxes,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickBalls,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickButtons,(SDL_Joystick *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumJoystickHats,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetNumLogicalCPUCores,(void),(),return) SDL_DYNAPI_PROC(int,SDL_GetNumRenderDrivers,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_GetNumTouchFingers,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetNumVideoDrivers,(void),(),return) SDL_DYNAPI_PROC(Sint64,SDL_GetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_GetOriginalMemoryFunctions,(SDL_malloc_func *a, SDL_calloc_func *b, SDL_realloc_func *c, SDL_free_func *d),(a,b,c,d),) -SDL_DYNAPI_PROC(int,SDL_GetPathInfo,(const char *a, SDL_PathInfo *b),(a,b),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetPenCapabilities,(SDL_PenID a, SDL_PenCapabilityInfo *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_PenID,SDL_GetPenFromGUID,(SDL_GUID a),(a),return) -SDL_DYNAPI_PROC(SDL_GUID,SDL_GetPenGUID,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetPenName,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetPenStatus,(SDL_PenID a, float *b, float *c, float *d, size_t e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_PenSubtype,SDL_GetPenType,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(SDL_PenID*,SDL_GetPens,(int *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetPathInfo,(const char *a, SDL_PathInfo *b),(a,b),return) SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceCounter,(void),(),return) SDL_DYNAPI_PROC(Uint64,SDL_GetPerformanceFrequency,(void),(),return) -SDL_DYNAPI_PROC(SDL_PixelFormatEnum,SDL_GetPixelFormatEnumForMasks,(int a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(const char*,SDL_GetPixelFormatName,(SDL_PixelFormatEnum a),(a),return) +SDL_DYNAPI_PROC(const SDL_PixelFormatDetails*,SDL_GetPixelFormatDetails,(SDL_PixelFormat a),(a),return) +SDL_DYNAPI_PROC(SDL_PixelFormat,SDL_GetPixelFormatForMasks,(int a, Uint32 b, Uint32 c, Uint32 d, Uint32 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(const char*,SDL_GetPixelFormatName,(SDL_PixelFormat a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetPlatform,(void),(),return) +SDL_DYNAPI_PROC(void*,SDL_GetPointerProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_PowerState,SDL_GetPowerInfo,(int *a, int *b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_GetPrefPath,(const char *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_Locale*,SDL_GetPreferredLocales,(void),(),return) +SDL_DYNAPI_PROC(SDL_Locale**,SDL_GetPreferredLocales,(int *a),(a),return) SDL_DYNAPI_PROC(SDL_DisplayID,SDL_GetPrimaryDisplay,(void),(),return) SDL_DYNAPI_PROC(char*,SDL_GetPrimarySelectionText,(void),(),return) -SDL_DYNAPI_PROC(void*,SDL_GetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_IOStream*,SDL_GetProcessInput,(SDL_Process *a),(a),return) +SDL_DYNAPI_PROC(SDL_IOStream*,SDL_GetProcessOutput,(SDL_Process *a),(a),return) +SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetProcessProperties,(SDL_Process *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertyType,SDL_GetPropertyType,(SDL_PropertiesID a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_GetRGB,(Uint32 a, const SDL_PixelFormat *b, Uint8 *c, Uint8 *d, Uint8 *e),(a,b,c,d,e),) -SDL_DYNAPI_PROC(void,SDL_GetRGBA,(Uint32 a, const SDL_PixelFormat *b, Uint8 *c, Uint8 *d, Uint8 *e, Uint8 *f),(a,b,c,d,e,f),) -SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadInstanceType,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(void,SDL_GetRGB,(Uint32 a, const SDL_PixelFormatDetails *b, const SDL_Palette *c, Uint8 *d, Uint8 *e, Uint8 *f),(a,b,c,d,e,f),) +SDL_DYNAPI_PROC(void,SDL_GetRGBA,(Uint32 a, const SDL_PixelFormatDetails *b, const SDL_Palette *c, Uint8 *d, Uint8 *e, Uint8 *f, Uint8 *g),(a,b,c,d,e,f,g),) SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadType,(SDL_Gamepad *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectAndLineIntersection,(const SDL_Rect *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectAndLineIntersectionFloat,(const SDL_FRect *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectEnclosingPoints,(const SDL_Point *a, int b, const SDL_Rect *c, SDL_Rect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectEnclosingPointsFloat,(const SDL_FPoint *a, int b, const SDL_FRect *c, SDL_FRect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectIntersection,(const SDL_Rect *a, const SDL_Rect *b, SDL_Rect *c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRectIntersectionFloat,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetRectUnion,(const SDL_Rect *a, const SDL_Rect *b, SDL_Rect *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetRectUnionFloat,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetRelativeMouseMode,(void),(),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetRelativeMouseState,(float *a, float *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderClipRect,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderColorScale,(SDL_Renderer *a, float *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColor,(SDL_Renderer *a, Uint8 *b, Uint8 *c, Uint8 *d, Uint8 *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(SDL_GamepadType,SDL_GetRealGamepadTypeForID,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectAndLineIntersection,(const SDL_Rect *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectAndLineIntersectionFloat,(const SDL_FRect *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectEnclosingPoints,(const SDL_Point *a, int b, const SDL_Rect *c, SDL_Rect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectEnclosingPointsFloat,(const SDL_FPoint *a, int b, const SDL_FRect *c, SDL_FRect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectIntersection,(const SDL_Rect *a, const SDL_Rect *b, SDL_Rect *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectIntersectionFloat,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectUnion,(const SDL_Rect *a, const SDL_Rect *b, SDL_Rect *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetRectUnionFloat,(const SDL_FRect *a, const SDL_FRect *b, SDL_FRect *c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_MouseButtonFlags,SDL_GetRelativeMouseState,(float *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderClipRect,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderColorScale,(SDL_Renderer *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawColor,(SDL_Renderer *a, Uint8 *b, Uint8 *c, Uint8 *d, Uint8 *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderDrawColorFloat,(SDL_Renderer *a, float *b, float *c, float *d, float *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(const char*,SDL_GetRenderDriver,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderLogicalPresentation,(SDL_Renderer *a, int *b, int *c, SDL_RendererLogicalPresentation *d, SDL_ScaleMode *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderLogicalPresentation,(SDL_Renderer *a, int *b, int *c, SDL_RendererLogicalPresentation *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderLogicalPresentationRect,(SDL_Renderer *a, SDL_FRect *b),(a,b),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalCommandEncoder,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetRenderMetalLayer,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderScale,(SDL_Renderer *a, float *b, float *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderOutputSize,(SDL_Renderer *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderSafeArea,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderScale,(SDL_Renderer *a, float *b, float *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Texture*,SDL_GetRenderTarget,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderVSync,(SDL_Renderer *a, int *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetRenderViewport,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderVSync,(SDL_Renderer *a, int *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetRenderViewport,(SDL_Renderer *a, SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetRenderWindow,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetRenderer,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Renderer*,SDL_GetRendererFromTexture,(SDL_Texture *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetRendererInfo,(SDL_Renderer *a, SDL_RendererInfo *b),(a,b),return) +SDL_DYNAPI_PROC(const char *,SDL_GetRendererName,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetRendererProperties,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetRevision,(void),(),return) -SDL_DYNAPI_PROC(SDL_Scancode,SDL_GetScancodeFromKey,(SDL_Keycode a),(a),return) +SDL_DYNAPI_PROC(size_t,SDL_GetSIMDAlignment,(void),(),return) +SDL_DYNAPI_PROC(SDL_Scancode,SDL_GetScancodeFromKey,(SDL_Keycode a, SDL_Keymod *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Scancode,SDL_GetScancodeFromName,(const char *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetScancodeName,(SDL_Scancode a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_GetSemaphoreValue,(SDL_Semaphore *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetSensorData,(SDL_Sensor *a, float *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_Sensor*,SDL_GetSensorFromInstanceID,(SDL_SensorID a),(a),return) -SDL_DYNAPI_PROC(SDL_SensorID,SDL_GetSensorInstanceID,(SDL_Sensor *a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_GetSensorInstanceName,(SDL_SensorID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetSensorInstanceNonPortableType,(SDL_SensorID a),(a),return) -SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorInstanceType,(SDL_SensorID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetSensorData,(SDL_Sensor *a, float *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Sensor*,SDL_GetSensorFromID,(SDL_SensorID a),(a),return) +SDL_DYNAPI_PROC(SDL_SensorID,SDL_GetSensorID,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetSensorName,(SDL_Sensor *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_GetSensorNameForID,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetSensorNonPortableType,(SDL_Sensor *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetSensorNonPortableTypeForID,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSensorProperties,(SDL_Sensor *a),(a),return) SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorType,(SDL_Sensor *a),(a),return) +SDL_DYNAPI_PROC(SDL_SensorType,SDL_GetSensorTypeForID,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(SDL_SensorID*,SDL_GetSensors,(int *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetSilenceValueForFormat,(SDL_AudioFormat a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetStorageFileSize,(SDL_Storage *a, const char *b, Uint64 *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetStoragePathInfo,(SDL_Storage *a, const char *b, SDL_PathInfo *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetStorageFileSize,(SDL_Storage *a, const char *b, Uint64 *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetStoragePathInfo,(SDL_Storage *a, const char *b, SDL_PathInfo *c),(a,b,c),return) SDL_DYNAPI_PROC(Uint64,SDL_GetStorageSpaceRemaining,(SDL_Storage *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceAlphaMod,(SDL_Surface *a, Uint8 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceClipRect,(SDL_Surface *a, SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorKey,(SDL_Surface *a, Uint32 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorMod,(SDL_Surface *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_GetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetSurfaceAlphaMod,(SDL_Surface *a, Uint8 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetSurfaceClipRect,(SDL_Surface *a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetSurfaceColorKey,(SDL_Surface *a, Uint32 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetSurfaceColorMod,(SDL_Surface *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(SDL_Colorspace,SDL_GetSurfaceColorspace,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(SDL_Surface**,SDL_GetSurfaceImages,(SDL_Surface *a, int *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Palette*,SDL_GetSurfacePalette,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(int,SDL_GetSystemRAM,(void),(),return) SDL_DYNAPI_PROC(SDL_SystemTheme,SDL_GetSystemTheme,(void),(),return) -SDL_DYNAPI_PROC(void*,SDL_GetTLS,(SDL_TLSID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaMod,(SDL_Texture *a, Uint8 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureColorMod,(SDL_Texture *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureColorModFloat,(SDL_Texture *a, float *b, float *c, float *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void*,SDL_GetTLS,(SDL_TLSID *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextInputArea,(SDL_Window *a, SDL_Rect *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureAlphaMod,(SDL_Texture *a, Uint8 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureColorMod,(SDL_Texture *a, Uint8 *b, Uint8 *c, Uint8 *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureColorModFloat,(SDL_Texture *a, float *b, float *c, float *d),(a,b,c,d),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetTextureProperties,(SDL_Texture *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetTextureSize,(SDL_Texture *a, float *b, float *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_ThreadID,SDL_GetThreadID,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(const char*,SDL_GetThreadName,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(Uint64,SDL_GetTicks,(void),(),return) @@ -511,126 +565,133 @@ SDL_DYNAPI_PROC(Uint64,SDL_GetTicksNS,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetTouchDeviceName,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(SDL_TouchDeviceType,SDL_GetTouchDeviceType,(SDL_TouchID a),(a),return) SDL_DYNAPI_PROC(SDL_TouchID*,SDL_GetTouchDevices,(int *a),(a),return) -SDL_DYNAPI_PROC(SDL_Finger*,SDL_GetTouchFinger,(SDL_TouchID a, int b),(a,b),return) -SDL_DYNAPI_PROC(char*,SDL_GetUserFolder,(SDL_Folder a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetVersion,(SDL_Version *a),(a),return) +SDL_DYNAPI_PROC(SDL_Finger**,SDL_GetTouchFingers,(SDL_TouchID a, int *b),(a,b),return) +SDL_DYNAPI_PROC(const char*,SDL_GetUserFolder,(SDL_Folder a),(a),return) +SDL_DYNAPI_PROC(int,SDL_GetVersion,(void),(),return) SDL_DYNAPI_PROC(const char*,SDL_GetVideoDriver,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowAspectRatio,(SDL_Window *a, float *b, float *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(float,SDL_GetWindowDisplayScale,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetWindowFlags,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromID,(Uint32 a),(a),return) +SDL_DYNAPI_PROC(SDL_WindowFlags,SDL_GetWindowFlags,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromEvent,(const SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowFromID,(SDL_WindowID a),(a),return) SDL_DYNAPI_PROC(const SDL_DisplayMode*,SDL_GetWindowFullscreenMode,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_GetWindowICCProfile,(SDL_Window *a, size_t *b),(a,b),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetWindowID,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetWindowKeyboardGrab,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowMaximumSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowMinimumSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_GetWindowMouseGrab,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(SDL_WindowID,SDL_GetWindowID,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowKeyboardGrab,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowMaximumSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowMinimumSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowMouseGrab,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(const SDL_Rect*,SDL_GetWindowMouseRect,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowOpacity,(SDL_Window *a, float *b),(a,b),return) +SDL_DYNAPI_PROC(float,SDL_GetWindowOpacity,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowParent,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(float,SDL_GetWindowPixelDensity,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(Uint32,SDL_GetWindowPixelFormat,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowPosition,(SDL_Window *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_PixelFormat,SDL_GetWindowPixelFormat,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowPosition,(SDL_Window *a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetWindowProperties,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowRelativeMouseMode,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowSafeArea,(SDL_Window *a, SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowSize,(SDL_Window *a, int *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_GetWindowSurfaceVSync,(SDL_Window *a, int *b),(a,b),return) SDL_DYNAPI_PROC(const char*,SDL_GetWindowTitle,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HapticEffectSupported,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HapticRumbleSupported,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasARMSIMD,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX2,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasAVX512F,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasAltiVec,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasClipboardData,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasClipboardText,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasEvent,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasEvents,(Uint32 a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasGamepad,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasJoystick,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasKeyboard,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasLASX,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasLSX,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasMMX,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasMouse,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasNEON,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasPrimarySelectionText,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasProperty,(SDL_PropertiesID a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasRectIntersection,(const SDL_Rect *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasRectIntersectionFloat,(const SDL_FRect *a, const SDL_FRect *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE2,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE3,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE41,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasSSE42,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_HasScreenKeyboardSupport,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_HideCursor,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_HideWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(SDL_Window**,SDL_GetWindows,(int *a),(a),return) +SDL_DYNAPI_PROC(char **,SDL_GlobDirectory,(const char *a, const char *b, SDL_GlobFlags c, int *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(char **,SDL_GlobStorageDirectory,(SDL_Storage *a, const char *b, const char *c, SDL_GlobFlags d, int *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_HapticEffectSupported,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_HapticRumbleSupported,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_HasARMSIMD,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasAVX,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasAVX2,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasAVX512F,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasAltiVec,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasClipboardData,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_HasClipboardText,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasEvent,(Uint32 a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_HasEvents,(Uint32 a, Uint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_HasGamepad,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasJoystick,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasKeyboard,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasLASX,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasLSX,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasMMX,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasMouse,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasNEON,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasPrimarySelectionText,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasProperty,(SDL_PropertiesID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_HasRectIntersection,(const SDL_Rect *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_HasRectIntersectionFloat,(const SDL_FRect *a, const SDL_FRect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_HasSSE,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasSSE2,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasSSE3,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasSSE41,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasSSE42,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HasScreenKeyboardSupport,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HideCursor,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_HideWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromConstMem,(const void *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromDynamicMem,(void),(),return) SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromFile,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(SDL_IOStream*,SDL_IOFromMem,(void *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(size_t,SDL_IOvprintf,(SDL_IOStream *a, SDL_PRINTF_FORMAT_STRING const char *b, va_list c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_Init,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(int,SDL_InitHapticRumble,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_InitSubSystem,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsAndroidTV,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsChromebook,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsDeXMode,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsGamepad,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickHaptic,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsJoystickVirtual,(SDL_JoystickID a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsMouseHaptic,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_IsTablet,(void),(),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickConnected,(SDL_Joystick *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_JoystickEventsEnabled,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriority,(Sint64 a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_LinuxSetThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_Init,(SDL_InitFlags a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_InitHapticRumble,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_InitSubSystem,(SDL_InitFlags a),(a),return) +SDL_DYNAPI_PROC(void,SDL_InsertGPUDebugLabel,(SDL_GPUCommandBuffer *a, const char *b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_IsChromebook,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_IsDeXMode,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_IsGamepad,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_IsJoystickHaptic,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_IsJoystickVirtual,(SDL_JoystickID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_IsMouseHaptic,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_IsTV,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_IsTablet,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_JoystickConnected,(SDL_Joystick *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_JoystickEventsEnabled,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_KillProcess,(SDL_Process *a, bool b),(a,b),return) SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP,(const char *a),(a),return) -SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_IO,(SDL_IOStream *a, SDL_bool b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_LoadBMP_IO,(SDL_IOStream *a, bool b),(a,b),return) SDL_DYNAPI_PROC(void*,SDL_LoadFile,(const char *a, size_t *b),(a,b),return) -SDL_DYNAPI_PROC(void*,SDL_LoadFile_IO,(SDL_IOStream *a, size_t *b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(void *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(void*,SDL_LoadObject,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LoadWAV,(const char *a, SDL_AudioSpec *b, Uint8 **c, Uint32 *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_LoadWAV_IO,(SDL_IOStream *a, SDL_bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_LockAudioStream,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(void*,SDL_LoadFile_IO,(SDL_IOStream *a, size_t *b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_LoadFunction,(SDL_SharedObject *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_SharedObject*,SDL_LoadObject,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_LoadWAV,(const char *a, SDL_AudioSpec *b, Uint8 **c, Uint32 *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_LoadWAV_IO,(SDL_IOStream *a, bool b, SDL_AudioSpec *c, Uint8 **d, Uint32 *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_LockAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),) SDL_DYNAPI_PROC(void,SDL_LockMutex,(SDL_Mutex *a),(a),) -SDL_DYNAPI_PROC(int,SDL_LockProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_LockProperties,(SDL_PropertiesID a),(a),return) SDL_DYNAPI_PROC(void,SDL_LockRWLockForReading,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_LockRWLockForWriting,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_LockSpinlock,(SDL_SpinLock *a),(a),) -SDL_DYNAPI_PROC(int,SDL_LockSurface,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_LogPriority,SDL_LogGetPriority,(int a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_LockSurface,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_LockTexture,(SDL_Texture *a, const SDL_Rect *b, void **c, int *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_LockTextureToSurface,(SDL_Texture *a, const SDL_Rect *b, SDL_Surface **c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_LogMessageV,(int a, SDL_LogPriority b, SDL_PRINTF_FORMAT_STRING const char *c, va_list d),(a,b,c,d),) -SDL_DYNAPI_PROC(void,SDL_LogResetPriorities,(void),(),) -SDL_DYNAPI_PROC(void,SDL_LogSetAllPriority,(SDL_LogPriority a),(a),) -SDL_DYNAPI_PROC(void,SDL_LogSetPriority,(int a, SDL_LogPriority b),(a,b),) -SDL_DYNAPI_PROC(Uint32,SDL_MapRGB,(const SDL_PixelFormat *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(Uint32,SDL_MapRGBA,(const SDL_PixelFormat *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_MaximizeWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(void*,SDL_MapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(Uint32,SDL_MapRGB,(const SDL_PixelFormatDetails *a, const SDL_Palette *b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(Uint32,SDL_MapRGBA,(const SDL_PixelFormatDetails *a, const SDL_Palette *b, Uint8 c, Uint8 d, Uint8 e, Uint8 f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(Uint32,SDL_MapSurfaceRGB,(SDL_Surface *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(Uint32,SDL_MapSurfaceRGBA,(SDL_Surface *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_MaximizeWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void,SDL_MemoryBarrierAcquireFunction,(void),(),) SDL_DYNAPI_PROC(void,SDL_MemoryBarrierReleaseFunction,(void),(),) SDL_DYNAPI_PROC(SDL_MetalView,SDL_Metal_CreateView,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(void,SDL_Metal_DestroyView,(SDL_MetalView a),(a),) SDL_DYNAPI_PROC(void*,SDL_Metal_GetLayer,(SDL_MetalView a),(a),return) -SDL_DYNAPI_PROC(int,SDL_MinimizeWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_MixAudioFormat,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, int e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(void,SDL_OnApplicationDidBecomeActive,(void),(),) +SDL_DYNAPI_PROC(bool,SDL_MinimizeWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_MixAudio,(Uint8 *a, const Uint8 *b, SDL_AudioFormat c, Uint32 d, float e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(void,SDL_OnApplicationDidChangeStatusBarOrientation,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationDidEnterBackground,(void),(),) +SDL_DYNAPI_PROC(void,SDL_OnApplicationDidEnterForeground,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationDidReceiveMemoryWarning,(void),(),) +SDL_DYNAPI_PROC(void,SDL_OnApplicationWillEnterBackground,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationWillEnterForeground,(void),(),) -SDL_DYNAPI_PROC(void,SDL_OnApplicationWillResignActive,(void),(),) SDL_DYNAPI_PROC(void,SDL_OnApplicationWillTerminate,(void),(),) SDL_DYNAPI_PROC(SDL_AudioDeviceID,SDL_OpenAudioDevice,(SDL_AudioDeviceID a, const SDL_AudioSpec *b),(a,b),return) SDL_DYNAPI_PROC(SDL_AudioStream*,SDL_OpenAudioDeviceStream,(SDL_AudioDeviceID a, const SDL_AudioSpec *b, SDL_AudioStreamCallback c, void *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(SDL_Camera*,SDL_OpenCameraDevice,(SDL_CameraDeviceID a, const SDL_CameraSpec *b),(a,b),return) +SDL_DYNAPI_PROC(SDL_Camera*,SDL_OpenCamera,(SDL_CameraID a, const SDL_CameraSpec *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenFileStorage,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_Gamepad*,SDL_OpenGamepad,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_Haptic*,SDL_OpenHaptic,(SDL_HapticID a),(a),return) @@ -641,212 +702,279 @@ SDL_DYNAPI_PROC(SDL_Joystick*,SDL_OpenJoystick,(SDL_JoystickID a),(a),return) SDL_DYNAPI_PROC(SDL_Sensor*,SDL_OpenSensor,(SDL_SensorID a),(a),return) SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenStorage,(const SDL_StorageInterface *a, void *b),(a,b),return) SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenTitleStorage,(const char *a, SDL_PropertiesID b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_OpenURL,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_OpenURL,(const char *a),(a),return) SDL_DYNAPI_PROC(SDL_Storage*,SDL_OpenUserStorage,(const char *a, const char *b, SDL_PropertiesID c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_PauseAudioDevice,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PauseHaptic,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PeepEvents,(SDL_Event *a, int b, SDL_eventaction c, Uint32 d, Uint32 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_PenConnected,(SDL_PenID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PlayHapticRumble,(SDL_Haptic *a, float b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_PollEvent,(SDL_Event *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PostSemaphore,(SDL_Semaphore *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PremultiplyAlpha,(int a, int b, SDL_PixelFormatEnum c, const void *d, int e, SDL_PixelFormatEnum f, void *g, int h),(a,b,c,d,e,f,g,h),return) +SDL_DYNAPI_PROC(bool,SDL_OutOfMemory,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_PauseAudioDevice,(SDL_AudioDeviceID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_PauseAudioStreamDevice,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_PauseHaptic,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_PeepEvents,(SDL_Event *a, int b, SDL_EventAction c, Uint32 d, Uint32 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_PlayHapticRumble,(SDL_Haptic *a, float b, Uint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_PollEvent,(SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_PopGPUDebugGroup,(SDL_GPUCommandBuffer *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_PremultiplyAlpha,(int a, int b, SDL_PixelFormat c, const void *d, int e, SDL_PixelFormat f, void *g, int h, bool i),(a,b,c,d,e,f,g,h,i),return) +SDL_DYNAPI_PROC(bool,SDL_PremultiplySurfaceAlpha,(SDL_Surface *a, bool b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_PumpEvents,(void),(),) -SDL_DYNAPI_PROC(int,SDL_PushEvent,(SDL_Event *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_PutAudioStreamData,(SDL_AudioStream *a, const void *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_QueryTexture,(SDL_Texture *a, SDL_PixelFormatEnum *b, int *c, int *d, int *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_PushEvent,(SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_PushGPUComputeUniformData,(SDL_GPUCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_PushGPUDebugGroup,(SDL_GPUCommandBuffer *a, const char *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_PushGPUFragmentUniformData,(SDL_GPUCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_PushGPUVertexUniformData,(SDL_GPUCommandBuffer *a, Uint32 b, const void *c, Uint32 d),(a,b,c,d),) +SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamData,(SDL_AudioStream *a, const void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_QueryGPUFence,(SDL_GPUDevice *a, SDL_GPUFence *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_Quit,(void),(),) -SDL_DYNAPI_PROC(void,SDL_QuitSubSystem,(Uint32 a),(a),) -SDL_DYNAPI_PROC(int,SDL_RaiseWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_QuitSubSystem,(SDL_InitFlags a),(a),) +SDL_DYNAPI_PROC(bool,SDL_RaiseWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_ReadIO,(SDL_IOStream *a, void *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16BE,(SDL_IOStream *a, Sint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS16LE,(SDL_IOStream *a, Sint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32BE,(SDL_IOStream *a, Sint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS32LE,(SDL_IOStream *a, Sint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64BE,(SDL_IOStream *a, Sint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadS64LE,(SDL_IOStream *a, Sint64 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_ReadStorageFile,(SDL_Storage *a, const char *b, void *c, Uint64 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_ReadSurfacePixel,(SDL_Surface *a, int b, int c, Uint8 *d, Uint8 *e, Uint8 *f, Uint8 *g),(a,b,c,d,e,f,g),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16BE,(SDL_IOStream *a, Uint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU16LE,(SDL_IOStream *a, Uint16 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32BE,(SDL_IOStream *a, Uint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU32LE,(SDL_IOStream *a, Uint32 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64BE,(SDL_IOStream *a, Uint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU64LE,(SDL_IOStream *a, Uint64 *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ReadU8,(SDL_IOStream *a, Uint8 *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(void*,SDL_ReadProcess,(SDL_Process *a, size_t *b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS16BE,(SDL_IOStream *a, Sint16 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS16LE,(SDL_IOStream *a, Sint16 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS32BE,(SDL_IOStream *a, Sint32 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS32LE,(SDL_IOStream *a, Sint32 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS64BE,(SDL_IOStream *a, Sint64 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS64LE,(SDL_IOStream *a, Sint64 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadS8,(SDL_IOStream *a, Sint8 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadStorageFile,(SDL_Storage *a, const char *b, void *c, Uint64 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_ReadSurfacePixel,(SDL_Surface *a, int b, int c, Uint8 *d, Uint8 *e, Uint8 *f, Uint8 *g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_ReadSurfacePixelFloat,(SDL_Surface *a, int b, int c, float *d, float *e, float *f, float *g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU16BE,(SDL_IOStream *a, Uint16 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU16LE,(SDL_IOStream *a, Uint16 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU32BE,(SDL_IOStream *a, Uint32 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU32LE,(SDL_IOStream *a, Uint32 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU64BE,(SDL_IOStream *a, Uint64 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU64LE,(SDL_IOStream *a, Uint64 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_ReadU8,(SDL_IOStream *a, Uint8 *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_RegisterApp,(const char *a, Uint32 b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(Uint32,SDL_RegisterEvents,(int a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ReleaseCameraFrame,(SDL_Camera *a, SDL_Surface *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_ReloadGamepadMappings,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_RemovePath,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_RemoveStoragePath,(SDL_Storage *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_RemoveTimer,(SDL_TimerID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_RenamePath,(const char *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RenameStoragePath,(SDL_Storage *a, const char *b, const char *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderClear,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_RenderClipEnabled,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesFromWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_RenderCoordinatesToWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_RenderFillRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RenderFillRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderGeometry,(SDL_Renderer *a, SDL_Texture *b, const SDL_Vertex *c, int d, const int *e, int f),(a,b,c,d,e,f),return) -SDL_DYNAPI_PROC(int,SDL_RenderGeometryRaw,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_Color *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) -SDL_DYNAPI_PROC(int,SDL_RenderGeometryRawFloat,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_FColor *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) -SDL_DYNAPI_PROC(int,SDL_RenderLine,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_RenderLines,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderPoint,(SDL_Renderer *a, float b, float c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderPoints,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderPresent,(SDL_Renderer *a),(a),return) -SDL_DYNAPI_PROC(SDL_Surface *,SDL_RenderReadPixels,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RenderRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_RenderRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_RenderTexture,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_RenderTextureRotated,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d, const double e, const SDL_FPoint *f, const SDL_FlipMode g),(a,b,c,d,e,f,g),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_RenderViewportSet,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_ReleaseCameraFrame,(SDL_Camera *a, SDL_Surface *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUBuffer,(SDL_GPUDevice *a, SDL_GPUBuffer *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUComputePipeline,(SDL_GPUDevice *a, SDL_GPUComputePipeline *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUFence,(SDL_GPUDevice *a, SDL_GPUFence *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUGraphicsPipeline,(SDL_GPUDevice *a, SDL_GPUGraphicsPipeline *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUSampler,(SDL_GPUDevice *a, SDL_GPUSampler *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUShader,(SDL_GPUDevice *a, SDL_GPUShader *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUTexture,(SDL_GPUDevice *a, SDL_GPUTexture *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_ReleaseWindowFromGPUDevice,(SDL_GPUDevice *a, SDL_Window *b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_ReloadGamepadMappings,(void),(),return) +SDL_DYNAPI_PROC(void,SDL_RemoveEventWatch,(SDL_EventFilter a, void *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_RemoveHintCallback,(const char *a, SDL_HintCallback b, void *c),(a,b,c),) +SDL_DYNAPI_PROC(bool,SDL_RemovePath,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_RemoveStoragePath,(SDL_Storage *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_RemoveSurfaceAlternateImages,(SDL_Surface *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_RemoveTimer,(SDL_TimerID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_RenamePath,(const char *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_RenameStoragePath,(SDL_Storage *a, const char *b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderClear,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_RenderClipEnabled,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_RenderCoordinatesFromWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_RenderCoordinatesToWindow,(SDL_Renderer *a, float b, float c, float *d, float *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_RenderFillRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_RenderFillRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderGeometry,(SDL_Renderer *a, SDL_Texture *b, const SDL_Vertex *c, int d, const int *e, int f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(bool,SDL_RenderGeometryRaw,(SDL_Renderer *a, SDL_Texture *b, const float *c, int d, const SDL_FColor *e, int f, const float *g, int h, int i, const void *j, int k, int l),(a,b,c,d,e,f,g,h,i,j,k,l),return) +SDL_DYNAPI_PROC(bool,SDL_RenderLine,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_RenderLines,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderPoint,(SDL_Renderer *a, float b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderPoints,(SDL_Renderer *a, const SDL_FPoint *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderPresent,(SDL_Renderer *a),(a),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_RenderReadPixels,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_RenderRect,(SDL_Renderer *a, const SDL_FRect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_RenderRects,(SDL_Renderer *a, const SDL_FRect *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RenderTexture,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_RenderTexture9Grid,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, float d, float e, float f, float g, float h, const SDL_FRect *i),(a,b,c,d,e,f,g,h,i),return) +SDL_DYNAPI_PROC(bool,SDL_RenderTextureRotated,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, const SDL_FRect *d, double e, const SDL_FPoint *f, SDL_FlipMode g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_RenderTextureTiled,(SDL_Renderer *a, SDL_Texture *b, const SDL_FRect *c, float d, const SDL_FRect *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_RenderViewportSet,(SDL_Renderer *a),(a),return) SDL_DYNAPI_PROC(SDL_AssertState,SDL_ReportAssertion,(SDL_AssertData *a, const char *b, const char *c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_RequestAndroidPermission,(const char *a, SDL_RequestAndroidPermissionCallback b, void *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_ResetAssertionReport,(void),(),) -SDL_DYNAPI_PROC(SDL_bool,SDL_ResetHint,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ResetHint,(const char *a),(a),return) SDL_DYNAPI_PROC(void,SDL_ResetHints,(void),(),) SDL_DYNAPI_PROC(void,SDL_ResetKeyboard,(void),(),) -SDL_DYNAPI_PROC(int,SDL_RestoreWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ResumeAudioDevice,(SDL_AudioDeviceID a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ResumeHaptic,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_RumbleGamepad,(SDL_Gamepad *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_RumbleGamepadTriggers,(SDL_Gamepad *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_RumbleJoystick,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_RumbleJoystickTriggers,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void,SDL_ResetLogPriorities,(void),(),) +SDL_DYNAPI_PROC(bool,SDL_RestoreWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ResumeAudioDevice,(SDL_AudioDeviceID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ResumeAudioStreamDevice,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ResumeHaptic,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_RumbleGamepad,(SDL_Gamepad *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_RumbleGamepadTriggers,(SDL_Gamepad *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_RumbleJoystick,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_RumbleJoystickTriggers,(SDL_Joystick *a, Uint16 b, Uint16 c, Uint32 d),(a,b,c,d),return) SDL_DYNAPI_PROC(int,SDL_RunApp,(int a, char *b[], SDL_main_func c, void *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_RunHapticEffect,(SDL_Haptic *a, int b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(size_t,SDL_SIMDGetAlignment,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_SaveBMP,(SDL_Surface *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SaveBMP_IO,(SDL_Surface *a, SDL_IOStream *b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ScreenKeyboardShown,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_ScreenSaverEnabled,(void),(),return) -SDL_DYNAPI_PROC(Sint64,SDL_SeekIO,(SDL_IOStream *a, Sint64 b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SendGamepadEffect,(SDL_Gamepad *a, const void *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SendJoystickEffect,(SDL_Joystick *a, const void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_RunHapticEffect,(SDL_Haptic *a, int b, Uint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SaveBMP,(SDL_Surface *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SaveBMP_IO,(SDL_Surface *a, SDL_IOStream *b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(SDL_Surface*,SDL_ScaleSurface,(SDL_Surface *a, int b, int c, SDL_ScaleMode d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_ScreenKeyboardShown,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ScreenSaverEnabled,(void),(),return) +SDL_DYNAPI_PROC(Sint64,SDL_SeekIO,(SDL_IOStream *a, Sint64 b, SDL_IOWhence c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_SendAndroidBackButton,(void),(),) +SDL_DYNAPI_PROC(bool,SDL_SendAndroidMessage,(Uint32 a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SendGamepadEffect,(SDL_Gamepad *a, const void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SendJoystickEffect,(SDL_Joystick *a, const void *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SendJoystickVirtualSensorData,(SDL_Joystick *a, SDL_SensorType b, Uint64 c, const float *d, int e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetAppMetadata,(const char *a, const char *b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAppMetadataProperty,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_SetAssertionHandler,(SDL_AssertionHandler a, void *b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFormat,(SDL_AudioStream *a, const SDL_AudioSpec *b, const SDL_AudioSpec *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioStreamGetCallback,(SDL_AudioStream *a, SDL_AudioStreamCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_AudioStreamCallback b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetClipboardText,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetCursor,(SDL_Cursor *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, SDL_bool b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_SetAtomicInt,(SDL_AtomicInt *a, int b),(a,b),return) +SDL_DYNAPI_PROC(void*,SDL_SetAtomicPointer,(void **a, void *b),(a,b),return) +SDL_DYNAPI_PROC(Uint32,SDL_SetAtomicU32,(SDL_AtomicU32 *a, Uint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioDeviceGain,(SDL_AudioDeviceID a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioPostmixCallback,(SDL_AudioDeviceID a, SDL_AudioPostmixCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamFormat,(SDL_AudioStream *a, const SDL_AudioSpec *b, const SDL_AudioSpec *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamFrequencyRatio,(SDL_AudioStream *a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamGain,(SDL_AudioStream *a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamGetCallback,(SDL_AudioStream *a, SDL_AudioStreamCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamInputChannelMap,(SDL_AudioStream *a, const int *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamOutputChannelMap,(SDL_AudioStream *a, const int *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetAudioStreamPutCallback,(SDL_AudioStream *a, SDL_AudioStreamCallback b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetBooleanProperty,(SDL_PropertiesID a, const char *b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetClipboardData,(SDL_ClipboardDataCallback a, SDL_ClipboardCleanupCallback b, void *c, const char **d, size_t e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetClipboardText,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetCurrentThreadPriority,(SDL_ThreadPriority a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetCursor,(SDL_Cursor *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetEnvironmentVariable,(SDL_Environment *a, const char *b, const char *c, bool d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void,SDL_SetEventEnabled,(Uint32 a, bool b),(a,b),) SDL_DYNAPI_PROC(void,SDL_SetEventFilter,(SDL_EventFilter a, void *b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) -SDL_DYNAPI_PROC(void,SDL_SetGamepadEventsEnabled,(SDL_bool a),(a),) -SDL_DYNAPI_PROC(int,SDL_SetGamepadLED,(SDL_Gamepad *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetGamepadMapping,(SDL_JoystickID a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetGamepadPlayerIndex,(SDL_Gamepad *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetGamepadSensorEnabled,(SDL_Gamepad *a, SDL_SensorType b, SDL_bool c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetHapticAutocenter,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetHapticGain,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_SetHint,(const char *a, const char *b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_SetHintWithPriority,(const char *a, const char *b, SDL_HintPriority c),(a,b,c),return) -SDL_DYNAPI_PROC(void,SDL_SetJoystickEventsEnabled,(SDL_bool a),(a),) -SDL_DYNAPI_PROC(int,SDL_SetJoystickLED,(SDL_Joystick *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetJoystickPlayerIndex,(SDL_Joystick *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualAxis,(SDL_Joystick *a, int b, Sint16 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualButton,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetJoystickVirtualHat,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetFloatProperty,(SDL_PropertiesID a, const char *b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_SetGPUBlendConstants,(SDL_GPURenderPass *a, SDL_FColor b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetGPUBufferName,(SDL_GPUDevice *a, SDL_GPUBuffer *b, const char *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_SetGPUScissor,(SDL_GPURenderPass *a, const SDL_Rect *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetGPUStencilReference,(SDL_GPURenderPass *a, Uint8 b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_SetGPUSwapchainParameters,(SDL_GPUDevice *a, SDL_Window *b, SDL_GPUSwapchainComposition c, SDL_GPUPresentMode d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void,SDL_SetGPUTextureName,(SDL_GPUDevice *a, SDL_GPUTexture *b, const char *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_SetGPUViewport,(SDL_GPURenderPass *a, const SDL_GPUViewport *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetGamepadEventsEnabled,(bool a),(a),) +SDL_DYNAPI_PROC(bool,SDL_SetGamepadLED,(SDL_Gamepad *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetGamepadMapping,(SDL_JoystickID a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetGamepadPlayerIndex,(SDL_Gamepad *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetGamepadSensorEnabled,(SDL_Gamepad *a, SDL_SensorType b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetHapticAutocenter,(SDL_Haptic *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetHapticGain,(SDL_Haptic *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetHint,(const char *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetHintWithPriority,(const char *a, const char *b, SDL_HintPriority c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_SetInitialized,(SDL_InitState *a, bool b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetJoystickEventsEnabled,(bool a),(a),) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickLED,(SDL_Joystick *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickPlayerIndex,(SDL_Joystick *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickVirtualAxis,(SDL_Joystick *a, int b, Sint16 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickVirtualBall,(SDL_Joystick *a, int b, Sint16 c, Sint16 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickVirtualButton,(SDL_Joystick *a, int b, bool c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickVirtualHat,(SDL_Joystick *a, int b, Uint8 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetJoystickVirtualTouchpad,(SDL_Joystick *a, int b, int c, bool d, float e, float f, float g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_SetLinuxThreadPriority,(Sint64 a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetLinuxThreadPriorityAndPolicy,(Sint64 a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_SetLogOutputFunction,(SDL_LogOutputFunction a, void *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetLogPriorities,(SDL_LogPriority a),(a),) +SDL_DYNAPI_PROC(void,SDL_SetLogPriority,(int a, SDL_LogPriority b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_SetLogPriorityPrefix,(SDL_LogPriority a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_SetMainReady,(void),(),) -SDL_DYNAPI_PROC(int,SDL_SetMemoryFunctions,(SDL_malloc_func a, SDL_calloc_func b, SDL_realloc_func c, SDL_free_func d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetMemoryFunctions,(SDL_malloc_func a, SDL_calloc_func b, SDL_realloc_func c, SDL_free_func d),(a,b,c,d),return) SDL_DYNAPI_PROC(void,SDL_SetModState,(SDL_Keymod a),(a),) -SDL_DYNAPI_PROC(int,SDL_SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetPaletteColors,(SDL_Palette *a, const SDL_Color *b, int c, int d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetPixelFormatPalette,(SDL_PixelFormat *a, SDL_Palette *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetPrimarySelectionText,(const char *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, void (SDLCALL *d)(void *userdata, void *value), void *e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetRelativeMouseMode,(SDL_bool a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderClipRect,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderColorScale,(SDL_Renderer *a, float b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColor,(SDL_Renderer *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderLogicalPresentation,(SDL_Renderer *a, int b, int c, SDL_RendererLogicalPresentation d, SDL_ScaleMode e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderScale,(SDL_Renderer *a, float b, float c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderTarget,(SDL_Renderer *a, SDL_Texture *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderVSync,(SDL_Renderer *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetRenderViewport,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceAlphaMod,(SDL_Surface *a, Uint8 b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_SetSurfaceClipRect,(SDL_Surface *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorKey,(SDL_Surface *a, int b, Uint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorMod,(SDL_Surface *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfacePalette,(SDL_Surface *a, SDL_Palette *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetSurfaceRLE,(SDL_Surface *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetTLS,(SDL_TLSID a, const void *b, void (SDLCALL *c)(void*)),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetTextInputRect,(const SDL_Rect *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaMod,(SDL_Texture *a, Uint8 b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaModFloat,(SDL_Texture *a, float b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureColorMod,(SDL_Texture *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureColorModFloat,(SDL_Texture *a, float b, float c, float d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_SetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetThreadPriority,(SDL_ThreadPriority a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowBordered,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowFocusable,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowFullscreen,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowFullscreenMode,(SDL_Window *a, const SDL_DisplayMode *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowIcon,(SDL_Window *a, SDL_Surface *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowInputFocus,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowKeyboardGrab,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowMaximumSize,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowMinimumSize,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowModalFor,(SDL_Window *a, SDL_Window *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowMouseGrab,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowPosition,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowShape,(SDL_Window *a, SDL_Surface *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowSize,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetWindowTitle,(SDL_Window *a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetNumberProperty,(SDL_PropertiesID a, const char *b, Sint64 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetPaletteColors,(SDL_Palette *a, const SDL_Color *b, int c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetPointerProperty,(SDL_PropertiesID a, const char *b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetPointerPropertyWithCleanup,(SDL_PropertiesID a, const char *b, void *c, SDL_CleanupPropertyCallback d, void *e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetPrimarySelectionText,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderClipRect,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderColorScale,(SDL_Renderer *a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawBlendMode,(SDL_Renderer *a, SDL_BlendMode b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawColor,(SDL_Renderer *a, Uint8 b, Uint8 c, Uint8 d, Uint8 e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderDrawColorFloat,(SDL_Renderer *a, float b, float c, float d, float e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderLogicalPresentation,(SDL_Renderer *a, int b, int c, SDL_RendererLogicalPresentation d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderScale,(SDL_Renderer *a, float b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderTarget,(SDL_Renderer *a, SDL_Texture *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderVSync,(SDL_Renderer *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetRenderViewport,(SDL_Renderer *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetScancodeName,(SDL_Scancode a, const char *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetStringProperty,(SDL_PropertiesID a, const char *b, const char *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceAlphaMod,(SDL_Surface *a, Uint8 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceBlendMode,(SDL_Surface *a, SDL_BlendMode b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceClipRect,(SDL_Surface *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceColorKey,(SDL_Surface *a, bool b, Uint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceColorMod,(SDL_Surface *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfacePalette,(SDL_Surface *a, SDL_Palette *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetSurfaceRLE,(SDL_Surface *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetTLS,(SDL_TLSID *a, const void *b, SDL_TLSDestructorCallback c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextInputArea,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureAlphaMod,(SDL_Texture *a, Uint8 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureAlphaModFloat,(SDL_Texture *a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureColorMod,(SDL_Texture *a, Uint8 b, Uint8 c, Uint8 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureColorModFloat,(SDL_Texture *a, float b, float c, float d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_SetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowAspectRatio,(SDL_Window *a, float b, float c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowBordered,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowFocusable,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowFullscreen,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowFullscreenMode,(SDL_Window *a, const SDL_DisplayMode *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowHitTest,(SDL_Window *a, SDL_HitTest b, void *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowIcon,(SDL_Window *a, SDL_Surface *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowKeyboardGrab,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowMaximumSize,(SDL_Window *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowMinimumSize,(SDL_Window *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowModal,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowMouseGrab,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowMouseRect,(SDL_Window *a, const SDL_Rect *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowParent,(SDL_Window *a, SDL_Window *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowPosition,(SDL_Window *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowRelativeMouseMode,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowResizable,(SDL_Window *a, bool b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowShape,(SDL_Window *a, SDL_Surface *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowSize,(SDL_Window *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowSurfaceVSync,(SDL_Window *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_SetWindowTitle,(SDL_Window *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_SetWindowsMessageHook,(SDL_WindowsMessageHook a, void *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_SetX11EventHook,(SDL_X11EventHook a, void *b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_ShowCursor,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_ShowMessageBox,(const SDL_MessageBoxData *a, int *b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_ShowOpenFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, const char *e, int f),(a,b,c,d,e,f),) -SDL_DYNAPI_PROC(void,SDL_ShowOpenFolderDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const char *d, int e),(a,b,c,d,e),) -SDL_DYNAPI_PROC(void,SDL_ShowSaveFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, const char *e),(a,b,c,d,e),) -SDL_DYNAPI_PROC(int,SDL_ShowSimpleMessageBox,(Uint32 a, const char *b, const char *c, SDL_Window *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_ShowWindow,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_ShowWindowSystemMenu,(SDL_Window *a, int b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SignalCondition,(SDL_Condition *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SoftStretch,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(void,SDL_StartTextInput,(void),(),) -SDL_DYNAPI_PROC(int,SDL_StopHapticEffect,(SDL_Haptic *a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_StopHapticEffects,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_StopHapticRumble,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_StopTextInput,(void),(),) -SDL_DYNAPI_PROC(SDL_bool,SDL_StorageReady,(SDL_Storage *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasRLE,(SDL_Surface *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetiOSAnimationCallback,(SDL_Window *a, int b, SDL_iOSAnimationCallback c, void *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void,SDL_SetiOSEventPump,(bool a),(a),) +SDL_DYNAPI_PROC(bool,SDL_ShouldInit,(SDL_InitState *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ShouldQuit,(SDL_InitState *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ShowAndroidToast,(const char *a, int b, int c, int d, int e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(bool,SDL_ShowCursor,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_ShowMessageBox,(const SDL_MessageBoxData *a, int *b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_ShowOpenFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, int e, const char *f, bool g),(a,b,c,d,e,f,g),) +SDL_DYNAPI_PROC(void,SDL_ShowOpenFolderDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const char *d, bool e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(void,SDL_ShowSaveFileDialog,(SDL_DialogFileCallback a, void *b, SDL_Window *c, const SDL_DialogFileFilter *d, int e, const char *f),(a,b,c,d,e,f),) +SDL_DYNAPI_PROC(bool,SDL_ShowSimpleMessageBox,(SDL_MessageBoxFlags a, const char *b, const char *c, SDL_Window *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_ShowWindow,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_ShowWindowSystemMenu,(SDL_Window *a, int b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_SignalCondition,(SDL_Condition *a),(a),) +SDL_DYNAPI_PROC(void,SDL_SignalSemaphore,(SDL_Semaphore *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_StartTextInput,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_StartTextInputWithProperties,(SDL_Window *a, SDL_PropertiesID b),(a,b),return) +SDL_DYNAPI_PROC(Uint32,SDL_StepUTF8,(const char **a, size_t *b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_StopHapticEffect,(SDL_Haptic *a, int b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_StopHapticEffects,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_StopHapticRumble,(SDL_Haptic *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_StopTextInput,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_StorageReady,(SDL_Storage *a),(a),return) +SDL_DYNAPI_PROC(SDL_GUID,SDL_StringToGUID,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SubmitGPUCommandBuffer,(SDL_GPUCommandBuffer *a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUFence*,SDL_SubmitGPUCommandBufferAndAcquireFence,(SDL_GPUCommandBuffer *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SurfaceHasAlternateImages,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SurfaceHasRLE,(SDL_Surface *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SyncWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(Sint64,SDL_TellIO,(SDL_IOStream *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_TextInputActive,(void),(),return) +SDL_DYNAPI_PROC(bool,SDL_TextInputActive,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Time,SDL_TimeFromWindows,(Uint32 a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_TimeToDateTime,(SDL_Time a, SDL_DateTime *b, SDL_bool c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_TimeToDateTime,(SDL_Time a, SDL_DateTime *b, bool c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_TimeToWindows,(SDL_Time a, Uint32 *b, Uint32 *c),(a,b,c),) -SDL_DYNAPI_PROC(int,SDL_TryLockMutex,(SDL_Mutex *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForReading,(SDL_RWLock *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_TryLockRWLockForWriting,(SDL_RWLock *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_TryLockSpinlock,(SDL_SpinLock *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_TryLockMutex,(SDL_Mutex *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_TryLockRWLockForReading,(SDL_RWLock *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_TryLockRWLockForWriting,(SDL_RWLock *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_TryLockSpinlock,(SDL_SpinLock *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_TryWaitSemaphore,(SDL_Semaphore *a),(a),return) +SDL_DYNAPI_PROC(char*,SDL_UCS4ToUTF8,(Uint32 a, char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_UnbindAudioStream,(SDL_AudioStream *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnbindAudioStreams,(SDL_AudioStream **a, int b),(a,b),) -SDL_DYNAPI_PROC(void,SDL_UnloadObject,(void *a),(a),) -SDL_DYNAPI_PROC(int,SDL_UnlockAudioStream,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_UnloadObject,(SDL_SharedObject *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_UnlockAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),) SDL_DYNAPI_PROC(void,SDL_UnlockMutex,(SDL_Mutex *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockProperties,(SDL_PropertiesID a),(a),) @@ -854,49 +982,61 @@ SDL_DYNAPI_PROC(void,SDL_UnlockRWLock,(SDL_RWLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockSpinlock,(SDL_SpinLock *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockSurface,(SDL_Surface *a),(a),) SDL_DYNAPI_PROC(void,SDL_UnlockTexture,(SDL_Texture *a),(a),) +SDL_DYNAPI_PROC(void,SDL_UnmapGPUTransferBuffer,(SDL_GPUDevice *a, SDL_GPUTransferBuffer *b),(a,b),) SDL_DYNAPI_PROC(void,SDL_UnregisterApp,(void),(),) +SDL_DYNAPI_PROC(bool,SDL_UnsetEnvironmentVariable,(SDL_Environment *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_UpdateGamepads,(void),(),) -SDL_DYNAPI_PROC(int,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateHapticEffect,(SDL_Haptic *a, int b, const SDL_HapticEffect *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_UpdateJoysticks,(void),(),) -SDL_DYNAPI_PROC(int,SDL_UpdateNVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateNVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(void,SDL_UpdateSensors,(void),(),) -SDL_DYNAPI_PROC(int,SDL_UpdateTexture,(SDL_Texture *a, const SDL_Rect *b, const void *c, int d),(a,b,c,d),return) -SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurface,(SDL_Window *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurfaceRects,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, const struct VkAllocationCallbacks *c, VkSurfaceKHR *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateTexture,(SDL_Texture *a, const SDL_Rect *b, const void *c, int d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateWindowSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateWindowSurfaceRects,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return) +SDL_DYNAPI_PROC(void,SDL_UploadToGPUBuffer,(SDL_GPUCopyPass *a, const SDL_GPUTransferBufferLocation *b, const SDL_GPUBufferRegion *c, bool d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_UploadToGPUTexture,(SDL_GPUCopyPass *a, const SDL_GPUTextureTransferInfo *b, const SDL_GPUTextureRegion *c, bool d),(a,b,c,d),) +SDL_DYNAPI_PROC(bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, const struct VkAllocationCallbacks *c, VkSurfaceKHR *d),(a,b,c,d),return) +SDL_DYNAPI_PROC(void,SDL_Vulkan_DestroySurface,(VkInstance a, VkSurfaceKHR b, const struct VkAllocationCallbacks *c),(a,b,c),) SDL_DYNAPI_PROC(char const* const*,SDL_Vulkan_GetInstanceExtensions,(Uint32 *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_Vulkan_GetPresentationSupport,(VkInstance a, VkPhysicalDevice b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_Vulkan_GetVkGetInstanceProcAddr,(void),(),return) -SDL_DYNAPI_PROC(int,SDL_Vulkan_LoadLibrary,(const char *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_Vulkan_LoadLibrary,(const char *a),(a),return) SDL_DYNAPI_PROC(void,SDL_Vulkan_UnloadLibrary,(void),(),) -SDL_DYNAPI_PROC(int,SDL_WaitCondition,(SDL_Condition *a, SDL_Mutex *b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_WaitConditionTimeout,(SDL_Condition *a, SDL_Mutex *b, Sint32 c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WaitEvent,(SDL_Event *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_WaitSemaphore,(SDL_Semaphore *a),(a),return) -SDL_DYNAPI_PROC(int,SDL_WaitSemaphoreTimeout,(SDL_Semaphore *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(void,SDL_WaitCondition,(SDL_Condition *a, SDL_Mutex *b),(a,b),) +SDL_DYNAPI_PROC(bool,SDL_WaitConditionTimeout,(SDL_Condition *a, SDL_Mutex *b, Sint32 c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_WaitEvent,(SDL_Event *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_WaitEventTimeout,(SDL_Event *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WaitForGPUFences,(SDL_GPUDevice *a, bool b, SDL_GPUFence *const *c, Uint32 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_WaitForGPUIdle,(SDL_GPUDevice *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_WaitProcess,(SDL_Process *a, bool b, int *c),(a,b,c),return) +SDL_DYNAPI_PROC(void,SDL_WaitSemaphore,(SDL_Semaphore *a),(a),) +SDL_DYNAPI_PROC(bool,SDL_WaitSemaphoreTimeout,(SDL_Semaphore *a, Sint32 b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_WaitThread,(SDL_Thread *a, int *b),(a,b),) -SDL_DYNAPI_PROC(int,SDL_WarpMouseGlobal,(float a, float b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WarpMouseGlobal,(float a, float b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_WarpMouseInWindow,(SDL_Window *a, float b, float c),(a,b,c),) -SDL_DYNAPI_PROC(Uint32,SDL_WasInit,(Uint32 a),(a),return) -SDL_DYNAPI_PROC(SDL_WinRT_DeviceFamily,SDL_WinRTGetDeviceFamily,(void),(),return) -SDL_DYNAPI_PROC(const wchar_t*,SDL_WinRTGetFSPathUNICODE,(SDL_WinRT_Path a),(a),return) -SDL_DYNAPI_PROC(const char*,SDL_WinRTGetFSPathUTF8,(SDL_WinRT_Path a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WindowHasSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(SDL_InitFlags,SDL_WasInit,(SDL_InitFlags a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_WindowHasSurface,(SDL_Window *a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_WindowSupportsGPUPresentMode,(SDL_GPUDevice *a, SDL_Window *b, SDL_GPUPresentMode c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_WindowSupportsGPUSwapchainComposition,(SDL_GPUDevice *a, SDL_Window *b, SDL_GPUSwapchainComposition c),(a,b,c),return) SDL_DYNAPI_PROC(size_t,SDL_WriteIO,(SDL_IOStream *a, const void *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16BE,(SDL_IOStream *a, Sint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS16LE,(SDL_IOStream *a, Sint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32BE,(SDL_IOStream *a, Sint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS32LE,(SDL_IOStream *a, Sint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64BE,(SDL_IOStream *a, Sint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteS64LE,(SDL_IOStream *a, Sint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16BE,(SDL_IOStream *a, Uint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU16LE,(SDL_IOStream *a, Uint16 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32BE,(SDL_IOStream *a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU32LE,(SDL_IOStream *a, Uint32 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64BE,(SDL_IOStream *a, Uint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU64LE,(SDL_IOStream *a, Uint64 b),(a,b),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_WriteU8,(SDL_IOStream *a, Uint8 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS16BE,(SDL_IOStream *a, Sint16 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS16LE,(SDL_IOStream *a, Sint16 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS32BE,(SDL_IOStream *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS32LE,(SDL_IOStream *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS64BE,(SDL_IOStream *a, Sint64 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS64LE,(SDL_IOStream *a, Sint64 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteS8,(SDL_IOStream *a, Sint8 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteStorageFile,(SDL_Storage *a, const char *b, const void *c, Uint64 d),(a,b,c,d),return) +SDL_DYNAPI_PROC(bool,SDL_WriteSurfacePixel,(SDL_Surface *a, int b, int c, Uint8 d, Uint8 e, Uint8 f, Uint8 g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_WriteSurfacePixelFloat,(SDL_Surface *a, int b, int c, float d, float e, float f, float g),(a,b,c,d,e,f,g),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU16BE,(SDL_IOStream *a, Uint16 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU16LE,(SDL_IOStream *a, Uint16 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU32BE,(SDL_IOStream *a, Uint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU32LE,(SDL_IOStream *a, Uint32 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU64BE,(SDL_IOStream *a, Uint64 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU64LE,(SDL_IOStream *a, Uint64 b),(a,b),return) +SDL_DYNAPI_PROC(bool,SDL_WriteU8,(SDL_IOStream *a, Uint8 b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_abs,(int a),(a),return) SDL_DYNAPI_PROC(double,SDL_acos,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_acosf,(float a),(a),return) @@ -910,8 +1050,8 @@ SDL_DYNAPI_PROC(float,SDL_atan2f,(float a, float b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_atanf,(float a),(a),return) SDL_DYNAPI_PROC(double,SDL_atof,(const char *a),(a),return) SDL_DYNAPI_PROC(int,SDL_atoi,(const char *a),(a),return) -SDL_DYNAPI_PROC(void*,SDL_bsearch,(const void *a, const void *b, size_t c, size_t d, int (SDLCALL *e)(const void *, const void *)),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(void*,SDL_bsearch_r,(const void *a, const void *b, size_t c, size_t d, int (SDLCALL *e)(void *, const void *, const void *), void *f),(a,b,c,d,e,f),return) +SDL_DYNAPI_PROC(void*,SDL_bsearch,(const void *a, const void *b, size_t c, size_t d, SDL_CompareCallback e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(void*,SDL_bsearch_r,(const void *a, const void *b, size_t c, size_t d, SDL_CompareCallback_r e, void *f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(void*,SDL_calloc,(size_t a, size_t b),(a,b),return) SDL_DYNAPI_PROC(double,SDL_ceil,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_ceilf,(float a),(a),return) @@ -930,8 +1070,9 @@ SDL_DYNAPI_PROC(float,SDL_floorf,(float a),(a),return) SDL_DYNAPI_PROC(double,SDL_fmod,(double a, double b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_fmodf,(float a, float b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_free,(void *a),(a),) -SDL_DYNAPI_PROC(char*,SDL_getenv,(const char *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(SDL_bool a),(a),) +SDL_DYNAPI_PROC(const char*,SDL_getenv,(const char *a),(a),return) +SDL_DYNAPI_PROC(const char*,SDL_getenv_unsafe,(const char *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_hid_ble_scan,(bool a),(a),) SDL_DYNAPI_PROC(int,SDL_hid_close,(SDL_hid_device *a),(a),return) SDL_DYNAPI_PROC(Uint32,SDL_hid_device_change_count,(void),(),return) SDL_DYNAPI_PROC(SDL_hid_device_info*,SDL_hid_enumerate,(unsigned short a, unsigned short b),(a,b),return) @@ -953,8 +1094,6 @@ SDL_DYNAPI_PROC(int,SDL_hid_read_timeout,(SDL_hid_device *a, unsigned char *b, s SDL_DYNAPI_PROC(int,SDL_hid_send_feature_report,(SDL_hid_device *a, const unsigned char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_hid_set_nonblocking,(SDL_hid_device *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_hid_write,(SDL_hid_device *a, const unsigned char *b, size_t c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_iPhoneSetAnimationCallback,(SDL_Window *a, int b, void (SDLCALL *c)(void *), void *d),(a,b,c,d),return) -SDL_DYNAPI_PROC(void,SDL_iPhoneSetEventPump,(SDL_bool a),(a),) SDL_DYNAPI_PROC(size_t,SDL_iconv,(SDL_iconv_t a, const char **b, size_t *c, char **d, size_t *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(int,SDL_iconv_close,(SDL_iconv_t a),(a),return) SDL_DYNAPI_PROC(SDL_iconv_t,SDL_iconv_open,(const char *a, const char *b),(a,b),return) @@ -965,14 +1104,18 @@ SDL_DYNAPI_PROC(int,SDL_isblank,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_iscntrl,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_isdigit,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_isgraph,(int a),(a),return) +SDL_DYNAPI_PROC(int,SDL_isinf,(double a),(a),return) +SDL_DYNAPI_PROC(int,SDL_isinff,(float a),(a),return) SDL_DYNAPI_PROC(int,SDL_islower,(int a),(a),return) +SDL_DYNAPI_PROC(int,SDL_isnan,(double a),(a),return) +SDL_DYNAPI_PROC(int,SDL_isnanf,(float a),(a),return) SDL_DYNAPI_PROC(int,SDL_isprint,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_ispunct,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_isspace,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_isupper,(int a),(a),return) SDL_DYNAPI_PROC(int,SDL_isxdigit,(int a),(a),return) SDL_DYNAPI_PROC(char*,SDL_itoa,(int a, char *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(char*,SDL_lltoa,(Sint64 a, char *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(char*,SDL_lltoa,(long long a, char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(double,SDL_log,(double a),(a),return) SDL_DYNAPI_PROC(double,SDL_log10,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_log10f,(float a),(a),return) @@ -988,20 +1131,28 @@ SDL_DYNAPI_PROC(void*,SDL_memset,(SDL_OUT_BYTECAP(c) void *a, int b, size_t c),( SDL_DYNAPI_PROC(void*,SDL_memset4,(void *a, Uint32 b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(double,SDL_modf,(double a, double *b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_modff,(float a, float *b),(a,b),return) +SDL_DYNAPI_PROC(Uint32,SDL_murmur3_32,(const void *a, size_t b, Uint32 c),(a,b,c),return) SDL_DYNAPI_PROC(double,SDL_pow,(double a, double b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_powf,(float a, float b),(a,b),return) -SDL_DYNAPI_PROC(void,SDL_qsort,(void *a, size_t b, size_t c, int (SDLCALL *d)(const void *, const void *)),(a,b,c,d),) -SDL_DYNAPI_PROC(void,SDL_qsort_r,(void *a, size_t b, size_t c, int (SDLCALL *d)(void *, const void *, const void *), void *e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(void,SDL_qsort,(void *a, size_t b, size_t c, SDL_CompareCallback d),(a,b,c,d),) +SDL_DYNAPI_PROC(void,SDL_qsort_r,(void *a, size_t b, size_t c, SDL_CompareCallback_r d, void *e),(a,b,c,d,e),) +SDL_DYNAPI_PROC(Sint32,SDL_rand,(Sint32 a),(a),return) +SDL_DYNAPI_PROC(Uint32,SDL_rand_bits,(void),(),return) +SDL_DYNAPI_PROC(Uint32,SDL_rand_bits_r,(Uint64 *a),(a),return) +SDL_DYNAPI_PROC(Sint32,SDL_rand_r,(Uint64 *a, Sint32 b),(a,b),return) +SDL_DYNAPI_PROC(float,SDL_randf,(void),(),return) +SDL_DYNAPI_PROC(float,SDL_randf_r,(Uint64 *a),(a),return) SDL_DYNAPI_PROC(void*,SDL_realloc,(void *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(double,SDL_round,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_roundf,(float a),(a),return) SDL_DYNAPI_PROC(double,SDL_scalbn,(double a, int b),(a,b),return) SDL_DYNAPI_PROC(float,SDL_scalbnf,(float a, int b),(a,b),return) -SDL_DYNAPI_PROC(int,SDL_setenv,(const char *a, const char *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_setenv_unsafe,(const char *a, const char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(double,SDL_sin,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_sinf,(float a),(a),return) SDL_DYNAPI_PROC(double,SDL_sqrt,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_sqrtf,(float a),(a),return) +SDL_DYNAPI_PROC(void,SDL_srand,(Uint64 a),(a),) SDL_DYNAPI_PROC(int,SDL_strcasecmp,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strcasestr,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strchr,(const char *a, int b),(a,b),return) @@ -1016,15 +1167,16 @@ SDL_DYNAPI_PROC(int,SDL_strncmp,(const char *a, const char *b, size_t c),(a,b,c) SDL_DYNAPI_PROC(char*,SDL_strndup,(const char *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(size_t,SDL_strnlen,(const char *a, size_t b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strnstr,(const char *a, const char *b, size_t c),(a,b,c),return) +SDL_DYNAPI_PROC(char*,SDL_strpbrk,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strrchr,(const char *a, int b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strrev,(char *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_strstr,(const char *a, const char *b),(a,b),return) SDL_DYNAPI_PROC(double,SDL_strtod,(const char *a, char **b),(a,b),return) SDL_DYNAPI_PROC(char*,SDL_strtok_r,(char *a, const char *b, char **c),(a,b,c),return) SDL_DYNAPI_PROC(long,SDL_strtol,(const char *a, char **b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(Sint64,SDL_strtoll,(const char *a, char **b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(long long,SDL_strtoll,(const char *a, char **b, int c),(a,b,c),return) SDL_DYNAPI_PROC(unsigned long,SDL_strtoul,(const char *a, char **b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(Uint64,SDL_strtoull,(const char *a, char **b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(unsigned long long,SDL_strtoull,(const char *a, char **b, int c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_strupr,(char *a),(a),return) SDL_DYNAPI_PROC(double,SDL_tan,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_tanf,(float a),(a),return) @@ -1033,8 +1185,9 @@ SDL_DYNAPI_PROC(int,SDL_toupper,(int a),(a),return) SDL_DYNAPI_PROC(double,SDL_trunc,(double a),(a),return) SDL_DYNAPI_PROC(float,SDL_truncf,(float a),(a),return) SDL_DYNAPI_PROC(char*,SDL_uitoa,(unsigned int a, char *b, int c),(a,b,c),return) -SDL_DYNAPI_PROC(char*,SDL_ulltoa,(Uint64 a, char *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(char*,SDL_ulltoa,(unsigned long long a, char *b, int c),(a,b,c),return) SDL_DYNAPI_PROC(char*,SDL_ultoa,(unsigned long a, char *b, int c),(a,b,c),return) +SDL_DYNAPI_PROC(int,SDL_unsetenv_unsafe,(const char *a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlcpy,(SDL_OUT_Z_CAP(c) char *a, const char *b, size_t c),(a,b,c),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strlen,(const char *a),(a),return) SDL_DYNAPI_PROC(size_t,SDL_utf8strnlen,(const char *a, size_t b),(a,b),return) diff --git a/libs/SDL3/src/dynapi/SDL_dynapi_unsupported.h b/libs/SDL3/src/dynapi/SDL_dynapi_unsupported.h index af6cd5f3c..780e6d6b6 100644 --- a/libs/SDL3/src/dynapi/SDL_dynapi_unsupported.h +++ b/libs/SDL3/src/dynapi/SDL_dynapi_unsupported.h @@ -23,7 +23,7 @@ #define SDL_dynapi_unsupported_h_ -#if !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) +#if !defined(SDL_PLATFORM_WINDOWS) typedef struct ID3D12Device ID3D12Device; typedef void *SDL_WindowsMessageHook; #endif @@ -37,16 +37,16 @@ typedef struct IDirect3DDevice9 IDirect3DDevice9; typedef struct XTaskQueueHandle XTaskQueueHandle; #endif -#ifndef SDL_PLATFORM_WINRT -typedef int SDL_WinRT_DeviceFamily; -typedef int SDL_WinRT_Path; -#endif #ifndef SDL_PLATFORM_GDK typedef struct XUserHandle XUserHandle; #endif #ifndef SDL_PLATFORM_ANDROID -typedef void *SDL_AndroidRequestPermissionCallback; +typedef void *SDL_RequestAndroidPermissionCallback; +#endif + +#ifndef SDL_PLATFORM_IOS +typedef void *SDL_iOSAnimationCallback; #endif #endif diff --git a/libs/SDL3/src/dynapi/gendynapi.py b/libs/SDL3/src/dynapi/gendynapi.py index 50de69d9c..651174aa0 100644 --- a/libs/SDL3/src/dynapi/gendynapi.py +++ b/libs/SDL3/src/dynapi/gendynapi.py @@ -75,8 +75,21 @@ def main(): parsing_comment = False current_comment = "" + ignore_wiki_documentation = False + for line in input: + # Skip lines if we're in a wiki documentation block. + if ignore_wiki_documentation: + if line.startswith("#endif"): + ignore_wiki_documentation = False + continue + + # Discard wiki documentations blocks. + if line.startswith("#ifdef SDL_WIKI_DOCUMENTATION_SECTION"): + ignore_wiki_documentation = True + continue + # Discard pre-processor directives ^#.* if line.startswith("#"): continue @@ -86,8 +99,8 @@ def main(): if match: continue - # Remove one line comment /* ... */ - # eg: extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */); + # Remove one line comment // ... + # eg: extern SDL_DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */); line = reg_comment_remove_content.sub('', line) # Get the comment block /* ... */ across several lines @@ -154,9 +167,10 @@ def main(): func = func.replace(" SDL_PRINTF_VARARG_FUNCV(2)", ""); func = func.replace(" SDL_PRINTF_VARARG_FUNCV(3)", ""); func = func.replace(" SDL_WPRINTF_VARARG_FUNC(3)", ""); + func = func.replace(" SDL_WPRINTF_VARARG_FUNCV(3)", ""); func = func.replace(" SDL_SCANF_VARARG_FUNC(2)", ""); func = func.replace(" SDL_SCANF_VARARG_FUNCV(2)", ""); - func = func.replace(" __attribute__((analyzer_noreturn))", ""); + func = func.replace(" SDL_ANALYZER_NORETURN", ""); func = func.replace(" SDL_MALLOC", ""); func = func.replace(" SDL_ALLOC_SIZE2(1, 2)", ""); func = func.replace(" SDL_ALLOC_SIZE(2)", ""); @@ -183,7 +197,7 @@ def main(): # func_ret = func_ret.replace('extern', ' ') func_ret = func_ret.replace('SDLCALL', ' ') - func_ret = func_ret.replace('DECLSPEC', ' ') + func_ret = func_ret.replace('SDL_DECLSPEC', ' ') # Remove trailing spaces in front of '*' tmp = "" while func_ret != tmp: @@ -342,7 +356,7 @@ def main(): def full_API_json(): if args.dump: filename = 'sdl.json' - with open(filename, 'w') as f: + with open(filename, 'w', newline='') as f: json.dump(full_API, f, indent=4, sort_keys=True) print("dump API to '%s'" % filename); @@ -469,8 +483,8 @@ def add_dyn_api(proc): # File: SDL_dynapi_procs.h # # Add at last - # SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentEGLConfig,(void),(),return) - f = open(SDL_DYNAPI_PROCS_H, "a") + # SDL_DYNAPI_PROC(SDL_EGLConfig,SDL_EGL_GetCurrentConfig,(void),(),return) + f = open(SDL_DYNAPI_PROCS_H, "a", newline="") dyn_proc = "SDL_DYNAPI_PROC(" + func_ret + "," + func_name + ",(" i = ord('a') @@ -532,7 +546,7 @@ def add_dyn_api(proc): # # Add at last # "#define SDL_DelayNS SDL_DelayNS_REAL - f = open(SDL_DYNAPI_OVERRIDES_H, "a") + f = open(SDL_DYNAPI_OVERRIDES_H, "a", newline="") f.write("#define " + func_name + " " + func_name + "_REAL\n") f.close() @@ -546,7 +560,7 @@ def add_dyn_api(proc): new_input.append(" " + func_name + ";\n") new_input.append(line) input.close() - f = open(SDL_DYNAPI_SYM, 'w') + f = open(SDL_DYNAPI_SYM, 'w', newline='') for line in new_input: f.write(line) f.close() diff --git a/libs/SDL3/src/events/SDL_categories.c b/libs/SDL3/src/events/SDL_categories.c new file mode 100644 index 000000000..57fb8c49c --- /dev/null +++ b/libs/SDL3/src/events/SDL_categories.c @@ -0,0 +1,242 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" + +// SDL event categories + +#include "SDL_events_c.h" +#include "SDL_categories_c.h" + +SDL_EventCategory SDL_GetEventCategory(Uint32 type) +{ + if (type >= SDL_EVENT_USER && type <= SDL_EVENT_LAST) { + return SDL_EVENTCATEGORY_USER; + } + else if (type >= SDL_EVENT_DISPLAY_FIRST && type <= SDL_EVENT_DISPLAY_LAST) { + return SDL_EVENTCATEGORY_DISPLAY; + } + else if (type >= SDL_EVENT_WINDOW_FIRST && type <= SDL_EVENT_WINDOW_LAST) { + return SDL_EVENTCATEGORY_WINDOW; + } + switch (type) { + default: + SDL_SetError("Unknown event type"); + return SDL_EVENTCATEGORY_UNKNOWN; + + case SDL_EVENT_KEYMAP_CHANGED: + case SDL_EVENT_TERMINATING: + case SDL_EVENT_LOW_MEMORY: + case SDL_EVENT_WILL_ENTER_BACKGROUND: + case SDL_EVENT_DID_ENTER_BACKGROUND: + case SDL_EVENT_WILL_ENTER_FOREGROUND: + case SDL_EVENT_DID_ENTER_FOREGROUND: + case SDL_EVENT_LOCALE_CHANGED: + case SDL_EVENT_SYSTEM_THEME_CHANGED: + case SDL_EVENT_RENDER_TARGETS_RESET: + case SDL_EVENT_RENDER_DEVICE_RESET: + return SDL_EVENTCATEGORY_SYSTEM; + + case SDL_EVENT_QUIT: + return SDL_EVENTCATEGORY_QUIT; + + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + return SDL_EVENTCATEGORY_KEY; + + case SDL_EVENT_TEXT_EDITING: + return SDL_EVENTCATEGORY_EDIT; + + case SDL_EVENT_TEXT_INPUT: + return SDL_EVENTCATEGORY_TEXT; + + case SDL_EVENT_KEYBOARD_ADDED: + case SDL_EVENT_KEYBOARD_REMOVED: + return SDL_EVENTCATEGORY_KDEVICE; + + case SDL_EVENT_TEXT_EDITING_CANDIDATES: + return SDL_EVENTCATEGORY_EDIT_CANDIDATES; + + case SDL_EVENT_MOUSE_MOTION: + return SDL_EVENTCATEGORY_MOTION; + + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + return SDL_EVENTCATEGORY_BUTTON; + + case SDL_EVENT_MOUSE_WHEEL: + return SDL_EVENTCATEGORY_WHEEL; + + case SDL_EVENT_MOUSE_ADDED: + case SDL_EVENT_MOUSE_REMOVED: + return SDL_EVENTCATEGORY_MDEVICE; + + case SDL_EVENT_JOYSTICK_AXIS_MOTION: + return SDL_EVENTCATEGORY_JAXIS; + + case SDL_EVENT_JOYSTICK_BALL_MOTION: + return SDL_EVENTCATEGORY_JBALL; + + case SDL_EVENT_JOYSTICK_HAT_MOTION: + return SDL_EVENTCATEGORY_JHAT; + + case SDL_EVENT_JOYSTICK_BUTTON_DOWN: + case SDL_EVENT_JOYSTICK_BUTTON_UP: + return SDL_EVENTCATEGORY_JBUTTON; + + case SDL_EVENT_JOYSTICK_ADDED: + case SDL_EVENT_JOYSTICK_REMOVED: + case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE: + return SDL_EVENTCATEGORY_JDEVICE; + + case SDL_EVENT_JOYSTICK_BATTERY_UPDATED: + return SDL_EVENTCATEGORY_JBATTERY; + + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + return SDL_EVENTCATEGORY_GAXIS; + + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + return SDL_EVENTCATEGORY_GBUTTON; + + case SDL_EVENT_GAMEPAD_ADDED: + case SDL_EVENT_GAMEPAD_REMOVED: + case SDL_EVENT_GAMEPAD_REMAPPED: + case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE: + case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED: + return SDL_EVENTCATEGORY_GDEVICE; + + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: + return SDL_EVENTCATEGORY_GTOUCHPAD; + + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: + return SDL_EVENTCATEGORY_GSENSOR; + + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_MOTION: + return SDL_EVENTCATEGORY_TFINGER; + + case SDL_EVENT_CLIPBOARD_UPDATE: + return SDL_EVENTCATEGORY_CLIPBOARD; + + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + case SDL_EVENT_DROP_BEGIN: + case SDL_EVENT_DROP_COMPLETE: + case SDL_EVENT_DROP_POSITION: + return SDL_EVENTCATEGORY_DROP; + + case SDL_EVENT_AUDIO_DEVICE_ADDED: + case SDL_EVENT_AUDIO_DEVICE_REMOVED: + case SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED: + return SDL_EVENTCATEGORY_ADEVICE; + + case SDL_EVENT_SENSOR_UPDATE: + return SDL_EVENTCATEGORY_SENSOR; + + case SDL_EVENT_PEN_PROXIMITY_IN: + case SDL_EVENT_PEN_PROXIMITY_OUT: + return SDL_EVENTCATEGORY_PPROXIMITY; + + case SDL_EVENT_PEN_DOWN: + case SDL_EVENT_PEN_UP: + return SDL_EVENTCATEGORY_PTOUCH; + + case SDL_EVENT_PEN_BUTTON_DOWN: + case SDL_EVENT_PEN_BUTTON_UP: + return SDL_EVENTCATEGORY_PBUTTON; + + case SDL_EVENT_PEN_MOTION: + return SDL_EVENTCATEGORY_PMOTION; + + case SDL_EVENT_PEN_AXIS: + return SDL_EVENTCATEGORY_PAXIS; + + case SDL_EVENT_CAMERA_DEVICE_ADDED: + case SDL_EVENT_CAMERA_DEVICE_REMOVED: + case SDL_EVENT_CAMERA_DEVICE_APPROVED: + case SDL_EVENT_CAMERA_DEVICE_DENIED: + return SDL_EVENTCATEGORY_CDEVICE; + } +} + +SDL_Window *SDL_GetWindowFromEvent(const SDL_Event *event) +{ + SDL_WindowID windowID; + + switch (SDL_GetEventCategory(event->type)) { + case SDL_EVENTCATEGORY_USER: + windowID = event->user.windowID; + break; + case SDL_EVENTCATEGORY_WINDOW: + windowID = event->window.windowID; + break; + case SDL_EVENTCATEGORY_KEY: + windowID = event->key.windowID; + break; + case SDL_EVENTCATEGORY_EDIT: + windowID = event->edit.windowID; + break; + case SDL_EVENTCATEGORY_TEXT: + windowID = event->text.windowID; + break; + case SDL_EVENTCATEGORY_EDIT_CANDIDATES: + windowID = event->edit_candidates.windowID; + break; + case SDL_EVENTCATEGORY_MOTION: + windowID = event->motion.windowID; + break; + case SDL_EVENTCATEGORY_BUTTON: + windowID = event->button.windowID; + break; + case SDL_EVENTCATEGORY_WHEEL: + windowID = event->wheel.windowID; + break; + case SDL_EVENTCATEGORY_TFINGER: + windowID = event->tfinger.windowID; + break; + case SDL_EVENTCATEGORY_PPROXIMITY: + windowID = event->pproximity.windowID; + break; + case SDL_EVENTCATEGORY_PTOUCH: + windowID = event->ptouch.windowID; + break; + case SDL_EVENTCATEGORY_PBUTTON: + windowID = event->pbutton.windowID; + break; + case SDL_EVENTCATEGORY_PMOTION: + windowID = event->pmotion.windowID; + break; + case SDL_EVENTCATEGORY_PAXIS: + windowID = event->paxis.windowID; + break; + case SDL_EVENTCATEGORY_DROP: + windowID = event->drop.windowID; + break; + default: + // < 0 -> invalid event type (error is set by SDL_GetEventCategory) + // else -> event has no associated window (not an error) + return NULL; + } + return SDL_GetWindowFromID(windowID); +} diff --git a/libs/SDL3/src/events/SDL_categories_c.h b/libs/SDL3/src/events/SDL_categories_c.h new file mode 100644 index 000000000..5f82c00cd --- /dev/null +++ b/libs/SDL3/src/events/SDL_categories_c.h @@ -0,0 +1,69 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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_categories_c_h_ +#define SDL_categories_c_h_ + +typedef enum SDL_EventCategory +{ + SDL_EVENTCATEGORY_UNKNOWN, + SDL_EVENTCATEGORY_SYSTEM, + SDL_EVENTCATEGORY_DISPLAY, + SDL_EVENTCATEGORY_WINDOW, + SDL_EVENTCATEGORY_KDEVICE, + SDL_EVENTCATEGORY_KEY, + SDL_EVENTCATEGORY_EDIT, + SDL_EVENTCATEGORY_EDIT_CANDIDATES, + SDL_EVENTCATEGORY_TEXT, + SDL_EVENTCATEGORY_MDEVICE, + SDL_EVENTCATEGORY_MOTION, + SDL_EVENTCATEGORY_BUTTON, + SDL_EVENTCATEGORY_WHEEL, + SDL_EVENTCATEGORY_JDEVICE, + SDL_EVENTCATEGORY_JAXIS, + SDL_EVENTCATEGORY_JBALL, + SDL_EVENTCATEGORY_JHAT, + SDL_EVENTCATEGORY_JBUTTON, + SDL_EVENTCATEGORY_JBATTERY, + SDL_EVENTCATEGORY_GDEVICE, + SDL_EVENTCATEGORY_GAXIS, + SDL_EVENTCATEGORY_GBUTTON, + SDL_EVENTCATEGORY_GTOUCHPAD, + SDL_EVENTCATEGORY_GSENSOR, + SDL_EVENTCATEGORY_ADEVICE, + SDL_EVENTCATEGORY_CDEVICE, + SDL_EVENTCATEGORY_SENSOR, + SDL_EVENTCATEGORY_QUIT, + SDL_EVENTCATEGORY_USER, + SDL_EVENTCATEGORY_TFINGER, + SDL_EVENTCATEGORY_PPROXIMITY, + SDL_EVENTCATEGORY_PTOUCH, + SDL_EVENTCATEGORY_PMOTION, + SDL_EVENTCATEGORY_PBUTTON, + SDL_EVENTCATEGORY_PAXIS, + SDL_EVENTCATEGORY_DROP, + SDL_EVENTCATEGORY_CLIPBOARD, +} SDL_EventCategory; + +extern SDL_EventCategory SDL_GetEventCategory(Uint32 type); + +#endif // SDL_categories_c_h_ diff --git a/libs/SDL3/src/events/SDL_clipboardevents.c b/libs/SDL3/src/events/SDL_clipboardevents.c index 0c2f20ac5..95245e196 100644 --- a/libs/SDL3/src/events/SDL_clipboardevents.c +++ b/libs/SDL3/src/events/SDL_clipboardevents.c @@ -20,22 +20,22 @@ */ #include "SDL_internal.h" -/* Clipboard event handling code for SDL */ +// Clipboard event handling code for SDL #include "SDL_events_c.h" #include "SDL_clipboardevents_c.h" -int SDL_SendClipboardUpdate(void) +void SDL_SendClipboardUpdate(bool owner, char **mime_types, size_t n_mime_types) { - int posted; - - /* Post the event, if desired */ - posted = 0; if (SDL_EventEnabled(SDL_EVENT_CLIPBOARD_UPDATE)) { SDL_Event event; event.type = SDL_EVENT_CLIPBOARD_UPDATE; - event.clipboard.timestamp = 0; - posted = (SDL_PushEvent(&event) > 0); + + SDL_ClipboardEvent *cevent = &event.clipboard; + cevent->timestamp = 0; + cevent->owner = owner; + cevent->mime_types = (const char **)mime_types; + cevent->n_mime_types = (Uint32)n_mime_types; + SDL_PushEvent(&event); } - return posted; } diff --git a/libs/SDL3/src/events/SDL_clipboardevents_c.h b/libs/SDL3/src/events/SDL_clipboardevents_c.h index 557bd0d1a..140cc4821 100644 --- a/libs/SDL3/src/events/SDL_clipboardevents_c.h +++ b/libs/SDL3/src/events/SDL_clipboardevents_c.h @@ -23,6 +23,6 @@ #ifndef SDL_clipboardevents_c_h_ #define SDL_clipboardevents_c_h_ -extern int SDL_SendClipboardUpdate(void); +extern void SDL_SendClipboardUpdate(bool owner, char **mime_types, size_t n_mime_types); -#endif /* SDL_clipboardevents_c_h_ */ +#endif // SDL_clipboardevents_c_h_ diff --git a/libs/SDL3/src/events/SDL_displayevents.c b/libs/SDL3/src/events/SDL_displayevents.c index 14c29f308..b736fd4a0 100644 --- a/libs/SDL3/src/events/SDL_displayevents.c +++ b/libs/SDL3/src/events/SDL_displayevents.c @@ -20,21 +20,19 @@ */ #include "SDL_internal.h" -/* Display event handling code for SDL */ +// Display event handling code for SDL #include "SDL_events_c.h" -int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1) +void SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2) { - int posted; - if (!display || display->id == 0) { - return 0; + return; } switch (displayevent) { case SDL_EVENT_DISPLAY_ORIENTATION: if (data1 == SDL_ORIENTATION_UNKNOWN || data1 == display->current_orientation) { - return 0; + return; } display->current_orientation = (SDL_DisplayOrientation)data1; break; @@ -42,24 +40,25 @@ int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, break; } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(displayevent)) { SDL_Event event; event.type = displayevent; event.common.timestamp = 0; event.display.displayID = display->id; event.display.data1 = data1; - posted = (SDL_PushEvent(&event) > 0); + event.display.data2 = data2; + SDL_PushEvent(&event); } switch (displayevent) { case SDL_EVENT_DISPLAY_ADDED: SDL_OnDisplayAdded(display); break; + case SDL_EVENT_DISPLAY_MOVED: + SDL_OnDisplayMoved(display); + break; default: break; } - - return posted; } diff --git a/libs/SDL3/src/events/SDL_displayevents_c.h b/libs/SDL3/src/events/SDL_displayevents_c.h index c93d9ffa1..497b50b10 100644 --- a/libs/SDL3/src/events/SDL_displayevents_c.h +++ b/libs/SDL3/src/events/SDL_displayevents_c.h @@ -23,6 +23,6 @@ #ifndef SDL_displayevents_c_h_ #define SDL_displayevents_c_h_ -extern int SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1); +extern void SDL_SendDisplayEvent(SDL_VideoDisplay *display, SDL_EventType displayevent, int data1, int data2); -#endif /* SDL_displayevents_c_h_ */ +#endif // SDL_displayevents_c_h_ diff --git a/libs/SDL3/src/events/SDL_dropevents.c b/libs/SDL3/src/events/SDL_dropevents.c index 610652c25..22388f361 100644 --- a/libs/SDL3/src/events/SDL_dropevents.c +++ b/libs/SDL3/src/events/SDL_dropevents.c @@ -20,23 +20,23 @@ */ #include "SDL_internal.h" -/* Drag and drop event handling code for SDL */ +// Drag and drop event handling code for SDL #include "SDL_events_c.h" #include "SDL_dropevents_c.h" -#include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */ +#include "../video/SDL_sysvideo.h" // for SDL_Window internals. -static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *source, const char *data, float x, float y) +static bool SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *source, const char *data, float x, float y) { - static SDL_bool app_is_dropping = SDL_FALSE; + static bool app_is_dropping = false; static float last_drop_x = 0; static float last_drop_y = 0; - int posted = 0; + bool posted = false; - /* Post the event, if desired */ + // Post the event, if desired if (SDL_EventEnabled(evtype)) { - const SDL_bool need_begin = window ? !window->is_dropping : !app_is_dropping; + const bool need_begin = window ? !window->is_dropping : !app_is_dropping; SDL_Event event; if (need_begin) { @@ -44,14 +44,14 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch event.type = SDL_EVENT_DROP_BEGIN; event.common.timestamp = 0; event.drop.windowID = window ? window->id : 0; - posted = (SDL_PushEvent(&event) > 0); + posted = SDL_PushEvent(&event); if (!posted) { - return 0; + return false; } if (window) { - window->is_dropping = SDL_TRUE; + window->is_dropping = true; } else { - app_is_dropping = SDL_TRUE; + app_is_dropping = true; } } @@ -59,16 +59,16 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch event.type = evtype; event.common.timestamp = 0; if (source) { - event.drop.source = SDL_strdup(source); + event.drop.source = SDL_CreateTemporaryString(source); + if (!event.drop.source) { + return false; + } } if (data) { - size_t size = SDL_strlen(data) + 1; - event.drop.data = (char *)SDL_AllocateEventMemory(size); + event.drop.data = SDL_CreateTemporaryString(data); if (!event.drop.data) { - SDL_free(event.drop.source); - return 0; + return false; } - SDL_memcpy(event.drop.data, data, size); } event.drop.windowID = window ? window->id : 0; @@ -78,13 +78,13 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch } event.drop.x = last_drop_x; event.drop.y = last_drop_y; - posted = (SDL_PushEvent(&event) > 0); + posted = SDL_PushEvent(&event); if (posted && (evtype == SDL_EVENT_DROP_COMPLETE)) { if (window) { - window->is_dropping = SDL_FALSE; + window->is_dropping = false; } else { - app_is_dropping = SDL_FALSE; + app_is_dropping = false; } last_drop_x = 0; @@ -94,22 +94,22 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch return posted; } -int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file) +bool SDL_SendDropFile(SDL_Window *window, const char *source, const char *file) { return SDL_SendDrop(window, SDL_EVENT_DROP_FILE, source, file, 0, 0); } -int SDL_SendDropPosition(SDL_Window *window, float x, float y) +bool SDL_SendDropPosition(SDL_Window *window, float x, float y) { return SDL_SendDrop(window, SDL_EVENT_DROP_POSITION, NULL, NULL, x, y); } -int SDL_SendDropText(SDL_Window *window, const char *text) +bool SDL_SendDropText(SDL_Window *window, const char *text) { return SDL_SendDrop(window, SDL_EVENT_DROP_TEXT, NULL, text, 0, 0); } -int SDL_SendDropComplete(SDL_Window *window) +bool SDL_SendDropComplete(SDL_Window *window) { return SDL_SendDrop(window, SDL_EVENT_DROP_COMPLETE, NULL, NULL, 0, 0); } diff --git a/libs/SDL3/src/events/SDL_dropevents_c.h b/libs/SDL3/src/events/SDL_dropevents_c.h index 4379d68c2..5dbdcf851 100644 --- a/libs/SDL3/src/events/SDL_dropevents_c.h +++ b/libs/SDL3/src/events/SDL_dropevents_c.h @@ -23,9 +23,9 @@ #ifndef SDL_dropevents_c_h_ #define SDL_dropevents_c_h_ -extern int SDL_SendDropFile(SDL_Window *window, const char *source, const char *file); -extern int SDL_SendDropPosition(SDL_Window *window, float x, float y); -extern int SDL_SendDropText(SDL_Window *window, const char *text); -extern int SDL_SendDropComplete(SDL_Window *window); +extern bool SDL_SendDropFile(SDL_Window *window, const char *source, const char *file); +extern bool SDL_SendDropPosition(SDL_Window *window, float x, float y); +extern bool SDL_SendDropText(SDL_Window *window, const char *text); +extern bool SDL_SendDropComplete(SDL_Window *window); -#endif /* SDL_dropevents_c_h_ */ +#endif // SDL_dropevents_c_h_ diff --git a/libs/SDL3/src/events/SDL_events.c b/libs/SDL3/src/events/SDL_events.c index 93af8aa1f..890a78eed 100644 --- a/libs/SDL3/src/events/SDL_events.c +++ b/libs/SDL3/src/events/SDL_events.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* General event handling code for SDL */ +// General event handling code for SDL #include "SDL_events_c.h" #include "../SDL_hints_c.h" @@ -35,38 +35,36 @@ #endif #include "../video/SDL_sysvideo.h" -#undef SDL_PRIs64 -#if (defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) && !defined(SDL_PLATFORM_CYGWIN) -#define SDL_PRIs64 "I64d" -#else -#define SDL_PRIs64 "lld" +#ifdef SDL_PLATFORM_ANDROID +#include "../core/android/SDL_android.h" +#include "../video/android/SDL_androidevents.h" #endif -/* An arbitrary limit so we don't have unbounded growth */ +// An arbitrary limit so we don't have unbounded growth #define SDL_MAX_QUEUED_EVENTS 65535 -/* Determines how often we pump events if joystick or sensor subsystems are active */ +// Determines how often we pump events if joystick or sensor subsystems are active #define ENUMERATION_POLL_INTERVAL_NS (3 * SDL_NS_PER_SECOND) -/* Determines how often to pump events if joysticks or sensors are actively being read */ +// Determines how often to pump events if joysticks or sensors are actively being read #define EVENT_POLL_INTERVAL_NS SDL_MS_TO_NS(1) -/* Make sure the type in the SDL_Event aligns properly across the union */ +// Make sure the type in the SDL_Event aligns properly across the union SDL_COMPILE_TIME_ASSERT(SDL_Event_type, sizeof(Uint32) == sizeof(SDL_EventType)); typedef struct SDL_EventWatcher { SDL_EventFilter callback; void *userdata; - SDL_bool removed; + bool removed; } SDL_EventWatcher; static SDL_Mutex *SDL_event_watchers_lock; static SDL_EventWatcher SDL_EventOK; static SDL_EventWatcher *SDL_event_watchers = NULL; static int SDL_event_watchers_count = 0; -static SDL_bool SDL_event_watchers_dispatching = SDL_FALSE; -static SDL_bool SDL_event_watchers_removed = SDL_FALSE; +static bool SDL_event_watchers_dispatching = false; +static bool SDL_event_watchers_removed = false; static SDL_AtomicInt SDL_sentinel_pending; static Uint32 SDL_last_event_id = 0; @@ -78,10 +76,25 @@ typedef struct static SDL_DisabledEventBlock *SDL_disabled_events[256]; static Uint32 SDL_userevents = SDL_EVENT_USER; -/* Private data -- event queue */ +typedef struct SDL_TemporaryMemory +{ + void *memory; + struct SDL_TemporaryMemory *prev; + struct SDL_TemporaryMemory *next; +} SDL_TemporaryMemory; + +typedef struct SDL_TemporaryMemoryState +{ + SDL_TemporaryMemory *head; + SDL_TemporaryMemory *tail; +} SDL_TemporaryMemoryState; + +static SDL_TLSID SDL_temporary_memory; + typedef struct SDL_EventEntry { SDL_Event event; + SDL_TemporaryMemory *memory; struct SDL_EventEntry *prev; struct SDL_EventEntry *next; } SDL_EventEntry; @@ -89,108 +102,268 @@ typedef struct SDL_EventEntry static struct { SDL_Mutex *lock; - SDL_bool active; + bool active; SDL_AtomicInt count; int max_events_seen; SDL_EventEntry *head; SDL_EventEntry *tail; SDL_EventEntry *free; -} SDL_EventQ = { NULL, SDL_FALSE, { 0 }, 0, NULL, NULL, NULL }; +} SDL_EventQ = { NULL, false, { 0 }, 0, NULL, NULL, NULL }; -typedef struct SDL_EventMemory + +static void SDL_CleanupTemporaryMemory(void *data) { - Uint32 eventID; - void *memory; - struct SDL_EventMemory *next; -} SDL_EventMemory; + SDL_TemporaryMemoryState *state = (SDL_TemporaryMemoryState *)data; -static SDL_Mutex *SDL_event_memory_lock; -static SDL_EventMemory *SDL_event_memory_head; -static SDL_EventMemory *SDL_event_memory_tail; + SDL_FreeTemporaryMemory(); + SDL_free(state); +} -void *SDL_AllocateEventMemory(size_t size) +static SDL_TemporaryMemoryState *SDL_GetTemporaryMemoryState(bool create) { - void *memory = SDL_malloc(size); - if (!memory) { - return NULL; + SDL_TemporaryMemoryState *state; + + state = (SDL_TemporaryMemoryState *)SDL_GetTLS(&SDL_temporary_memory); + if (!state) { + if (!create) { + return NULL; + } + + state = (SDL_TemporaryMemoryState *)SDL_calloc(1, sizeof(*state)); + if (!state) { + return NULL; + } + + if (!SDL_SetTLS(&SDL_temporary_memory, state, SDL_CleanupTemporaryMemory)) { + SDL_free(state); + return NULL; + } } + return state; +} - SDL_LockMutex(SDL_event_memory_lock); - { - SDL_EventMemory *entry = (SDL_EventMemory *)SDL_malloc(sizeof(*entry)); - if (entry) { - entry->eventID = SDL_last_event_id; - entry->memory = memory; - entry->next = NULL; +static SDL_TemporaryMemory *SDL_GetTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, const void *mem) +{ + SDL_TemporaryMemory *entry; - if (SDL_event_memory_tail) { - SDL_event_memory_tail->next = entry; - } else { - SDL_event_memory_head = entry; - } - SDL_event_memory_tail = entry; - } else { - SDL_free(memory); - memory = NULL; + // Start from the end, it's likely to have been recently allocated + for (entry = state->tail; entry; entry = entry->prev) { + if (mem == entry->memory) { + return entry; } } - SDL_UnlockMutex(SDL_event_memory_lock); + return NULL; +} + +static void SDL_LinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry) +{ + entry->prev = state->tail; + entry->next = NULL; + + if (state->tail) { + state->tail->next = entry; + } else { + state->head = entry; + } + state->tail = entry; +} + +static void SDL_UnlinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry) +{ + if (state->head == entry) { + state->head = entry->next; + } + if (state->tail == entry) { + state->tail = entry->prev; + } + + if (entry->prev) { + entry->prev->next = entry->next; + } + if (entry->next) { + entry->next->prev = entry->prev; + } + + entry->prev = NULL; + entry->next = NULL; +} + +static void SDL_FreeTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry, bool free_data) +{ + if (free_data) { + SDL_free(entry->memory); + } + SDL_free(entry); +} + +static void SDL_LinkTemporaryMemoryToEvent(SDL_EventEntry *event, const void *mem) +{ + SDL_TemporaryMemoryState *state; + SDL_TemporaryMemory *entry; + + state = SDL_GetTemporaryMemoryState(false); + if (!state) { + return; + } + + entry = SDL_GetTemporaryMemoryEntry(state, mem); + if (entry) { + SDL_UnlinkTemporaryMemoryEntry(state, entry); + entry->next = event->memory; + event->memory = entry; + } +} + +// Transfer the event memory from the thread-local event memory list to the event +static void SDL_TransferTemporaryMemoryToEvent(SDL_EventEntry *event) +{ + switch (event->event.type) { + case SDL_EVENT_TEXT_EDITING: + SDL_LinkTemporaryMemoryToEvent(event, event->event.edit.text); + break; + case SDL_EVENT_TEXT_EDITING_CANDIDATES: + SDL_LinkTemporaryMemoryToEvent(event, event->event.edit_candidates.candidates); + break; + case SDL_EVENT_TEXT_INPUT: + SDL_LinkTemporaryMemoryToEvent(event, event->event.text.text); + break; + case SDL_EVENT_DROP_BEGIN: + case SDL_EVENT_DROP_FILE: + case SDL_EVENT_DROP_TEXT: + case SDL_EVENT_DROP_COMPLETE: + case SDL_EVENT_DROP_POSITION: + SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.source); + SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.data); + break; + case SDL_EVENT_CLIPBOARD_UPDATE: + SDL_LinkTemporaryMemoryToEvent(event, event->event.clipboard.mime_types); + break; + default: + break; + } +} + +// Transfer the event memory from the event to the thread-local event memory list +static void SDL_TransferTemporaryMemoryFromEvent(SDL_EventEntry *event) +{ + SDL_TemporaryMemoryState *state; + SDL_TemporaryMemory *entry, *next; + + if (!event->memory) { + return; + } + + state = SDL_GetTemporaryMemoryState(true); + if (!state) { + return; // this is now a leak, but you probably have bigger problems if malloc failed. + } + + for (entry = event->memory; entry; entry = next) { + next = entry->next; + SDL_LinkTemporaryMemoryEntry(state, entry); + } + event->memory = NULL; +} + +static void *SDL_FreeLater(void *memory) +{ + SDL_TemporaryMemoryState *state; + + if (memory == NULL) { + return NULL; + } + + // Make sure we're not adding this to the list twice + //SDL_assert(!SDL_ClaimTemporaryMemory(memory)); + + state = SDL_GetTemporaryMemoryState(true); + if (!state) { + return memory; // this is now a leak, but you probably have bigger problems if malloc failed. + } + + SDL_TemporaryMemory *entry = (SDL_TemporaryMemory *)SDL_malloc(sizeof(*entry)); + if (!entry) { + return memory; // this is now a leak, but you probably have bigger problems if malloc failed. We could probably pool up and reuse entries, though. + } + + entry->memory = memory; + + SDL_LinkTemporaryMemoryEntry(state, entry); return memory; } -static void SDL_FlushEventMemory(Uint32 eventID) +void *SDL_AllocateTemporaryMemory(size_t size) { - SDL_LockMutex(SDL_event_memory_lock); - { - if (SDL_event_memory_head) { - while (SDL_event_memory_head) { - SDL_EventMemory *entry = SDL_event_memory_head; + return SDL_FreeLater(SDL_malloc(size)); +} - if (eventID && (Sint32)(eventID - entry->eventID) < 0) { - break; - } +const char *SDL_CreateTemporaryString(const char *string) +{ + if (string) { + return (const char *)SDL_FreeLater(SDL_strdup(string)); + } + return NULL; +} - /* If you crash here, your application has memory corruption - * or freed memory in an event, which is no longer necessary. - */ - SDL_event_memory_head = entry->next; - SDL_free(entry->memory); - SDL_free(entry); - } - if (!SDL_event_memory_head) { - SDL_event_memory_tail = NULL; - } +void *SDL_ClaimTemporaryMemory(const void *mem) +{ + SDL_TemporaryMemoryState *state; + + state = SDL_GetTemporaryMemoryState(false); + if (state && mem) { + SDL_TemporaryMemory *entry = SDL_GetTemporaryMemoryEntry(state, mem); + if (entry) { + SDL_UnlinkTemporaryMemoryEntry(state, entry); + SDL_FreeTemporaryMemoryEntry(state, entry, false); + return (void *)mem; } } - SDL_UnlockMutex(SDL_event_memory_lock); + return NULL; +} + +void SDL_FreeTemporaryMemory(void) +{ + SDL_TemporaryMemoryState *state; + + state = SDL_GetTemporaryMemoryState(false); + if (!state) { + return; + } + + while (state->head) { + SDL_TemporaryMemory *entry = state->head; + + SDL_UnlinkTemporaryMemoryEntry(state, entry); + SDL_FreeTemporaryMemoryEntry(state, entry, true); + } } #ifndef SDL_JOYSTICK_DISABLED -static SDL_bool SDL_update_joysticks = SDL_TRUE; +static bool SDL_update_joysticks = true; static void SDLCALL SDL_AutoUpdateJoysticksChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { - SDL_update_joysticks = SDL_GetStringBoolean(hint, SDL_TRUE); + SDL_update_joysticks = SDL_GetStringBoolean(hint, true); } -#endif /* !SDL_JOYSTICK_DISABLED */ +#endif // !SDL_JOYSTICK_DISABLED #ifndef SDL_SENSOR_DISABLED -static SDL_bool SDL_update_sensors = SDL_TRUE; +static bool SDL_update_sensors = true; static void SDLCALL SDL_AutoUpdateSensorsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { - SDL_update_sensors = SDL_GetStringBoolean(hint, SDL_TRUE); + SDL_update_sensors = SDL_GetStringBoolean(hint, true); } -#endif /* !SDL_SENSOR_DISABLED */ +#endif // !SDL_SENSOR_DISABLED static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { - SDL_SetEventEnabled(SDL_EVENT_POLL_SENTINEL, SDL_GetStringBoolean(hint, SDL_TRUE)); + SDL_SetEventEnabled(SDL_EVENT_POLL_SENTINEL, SDL_GetStringBoolean(hint, true)); } /** @@ -208,13 +381,17 @@ static void SDLCALL SDL_EventLoggingChanged(void *userdata, const char *name, co static void SDL_LogEvent(const SDL_Event *event) { + static const char *pen_axisnames[] = { "PRESSURE", "XTILT", "YTILT", "DISTANCE", "ROTATION", "SLIDER", "TANGENTIAL_PRESSURE" }; + SDL_COMPILE_TIME_ASSERT(pen_axisnames_array_matches, SDL_arraysize(pen_axisnames) == SDL_PEN_AXIS_COUNT); + char name[64]; char details[128]; - /* sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. */ + // sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded. if ((SDL_EventLoggingVerbosity < 2) && ((event->type == SDL_EVENT_MOUSE_MOTION) || (event->type == SDL_EVENT_FINGER_MOTION) || + (event->type == SDL_EVENT_PEN_AXIS) || (event->type == SDL_EVENT_PEN_MOTION) || (event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) || (event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) || @@ -222,13 +399,13 @@ static void SDL_LogEvent(const SDL_Event *event) return; } -/* this is to make (void)SDL_snprintf() calls cleaner. */ +// this is to make (void)SDL_snprintf() calls cleaner. #define uint unsigned int name[0] = '\0'; details[0] = '\0'; - /* !!! FIXME: This code is kinda ugly, sorry. */ + // !!! FIXME: This code is kinda ugly, sorry. if ((event->type >= SDL_EVENT_USER) && (event->type <= SDL_EVENT_LAST)) { char plusstr[16]; @@ -281,15 +458,16 @@ static void SDL_LogEvent(const SDL_Event *event) #define SDL_DISPLAYEVENT_CASE(x) \ case x: \ SDL_strlcpy(name, #x, sizeof(name)); \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d)", \ - (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1); \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d, data2=%d)", \ + (uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1, (int)event->display.data2); \ break SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ORIENTATION); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ADDED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED); + SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED); SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED); - SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_HDR_STATE_CHANGED); #undef SDL_DISPLAYEVENT_CASE #define SDL_WINDOWEVENT_CASE(x) \ @@ -304,17 +482,16 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOVED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_METAL_VIEW_RESIZED); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MINIMIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MAXIMIZED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE); - SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_ENTER); - SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PEN_LEAVE); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED); - SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_TAKE_FOCUS); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HIT_TEST); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ICCPROF_CHANGED); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_CHANGED); @@ -323,6 +500,7 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ENTER_FULLSCREEN); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN); SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED); + SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HDR_STATE_CHANGED); #undef SDL_WINDOWEVENT_CASE #define PRINT_KEYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->kdevice.timestamp, (uint)event->kdevice.which) @@ -334,14 +512,14 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_KEYDEV_EVENT -#define PRINT_KEY_EVENT(event) \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \ - (uint)event->key.timestamp, (uint)event->key.windowID, (uint)event->key.which, \ - event->key.state == SDL_PRESSED ? "pressed" : "released", \ - event->key.repeat ? "true" : "false", \ - (uint)event->key.keysym.scancode, \ - (uint)event->key.keysym.sym, \ - (uint)event->key.keysym.mod) +#define PRINT_KEY_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%s repeat=%s scancode=%u keycode=%u mod=0x%x)", \ + (uint)event->key.timestamp, (uint)event->key.windowID, (uint)event->key.which, \ + event->key.down ? "pressed" : "released", \ + event->key.repeat ? "true" : "false", \ + (uint)event->key.scancode, \ + (uint)event->key.key, \ + (uint)event->key.mod) SDL_EVENT_CASE(SDL_EVENT_KEY_DOWN) PRINT_KEY_EVENT(event); break; @@ -356,6 +534,12 @@ static void SDL_LogEvent(const SDL_Event *event) event->edit.text, (int)event->edit.start, (int)event->edit.length); break; + SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING_CANDIDATES) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u num_candidates=%d selected_candidate=%d)", + (uint)event->edit_candidates.timestamp, (uint)event->edit_candidates.windowID, + (int)event->edit_candidates.num_candidates, (int)event->edit_candidates.selected_candidate); + break; + SDL_EVENT_CASE(SDL_EVENT_TEXT_INPUT) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s')", (uint)event->text.timestamp, (uint)event->text.windowID, event->text.text); break; @@ -381,7 +565,7 @@ static void SDL_LogEvent(const SDL_Event *event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%g y=%g)", \ (uint)event->button.timestamp, (uint)event->button.windowID, \ (uint)event->button.which, (uint)event->button.button, \ - event->button.state == SDL_PRESSED ? "pressed" : "released", \ + event->button.down ? "pressed" : "released", \ (uint)event->button.clicks, event->button.x, event->button.y) SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_DOWN) PRINT_MBUTTON_EVENT(event); @@ -419,7 +603,7 @@ static void SDL_LogEvent(const SDL_Event *event) #define PRINT_JBUTTON_EVENT(event) \ (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \ (uint)event->jbutton.timestamp, (int)event->jbutton.which, \ - (uint)event->jbutton.button, event->jbutton.state == SDL_PRESSED ? "pressed" : "released") + (uint)event->jbutton.button, event->jbutton.down ? "pressed" : "released") SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BUTTON_DOWN) PRINT_JBUTTON_EVENT(event); break; @@ -428,6 +612,12 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_JBUTTON_EVENT + SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BATTERY_UPDATED) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d state=%u percent=%d)", + (uint)event->jbattery.timestamp, (int)event->jbattery.which, + event->jbattery.state, event->jbattery.percent); + break; + #define PRINT_JOYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->jdevice.timestamp, (int)event->jdevice.which) SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_ADDED) PRINT_JOYDEV_EVENT(event); @@ -435,6 +625,9 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_REMOVED) PRINT_JOYDEV_EVENT(event); break; + SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE) + PRINT_JOYDEV_EVENT(event); + break; #undef PRINT_JOYDEV_EVENT SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_AXIS_MOTION) @@ -446,7 +639,7 @@ static void SDL_LogEvent(const SDL_Event *event) #define PRINT_CBUTTON_EVENT(event) \ (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \ (uint)event->gbutton.timestamp, (int)event->gbutton.which, \ - (uint)event->gbutton.button, event->gbutton.state == SDL_PRESSED ? "pressed" : "released") + (uint)event->gbutton.button, event->gbutton.down ? "pressed" : "released") SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_BUTTON_DOWN) PRINT_CBUTTON_EVENT(event); break; @@ -465,6 +658,9 @@ static void SDL_LogEvent(const SDL_Event *event) SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMAPPED) PRINT_GAMEPADDEV_EVENT(event); break; + SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE) + PRINT_GAMEPADDEV_EVENT(event); + break; SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED) PRINT_GAMEPADDEV_EVENT(event); break; @@ -508,45 +704,44 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_FINGER_EVENT -#define PRINT_PTIP_EVENT(event) \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g)", \ - (uint)event->ptip.timestamp, (uint)event->ptip.windowID, \ - (uint)event->ptip.which, (uint)event->ptip.tip, \ - event->ptip.state == SDL_PRESSED ? "down" : "up", \ - event->ptip.x, event->ptip.y) +#define PRINT_PTOUCH_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g eraser=%s state=%s)", \ + (uint)event->ptouch.timestamp, (uint)event->ptouch.windowID, (uint)event->ptouch.which, (uint)event->ptouch.pen_state, event->ptouch.x, event->ptouch.y, \ + event->ptouch.eraser ? "yes" : "no", event->ptouch.down ? "down" : "up"); SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN) - PRINT_PTIP_EVENT(event); + PRINT_PTOUCH_EVENT(event); break; SDL_EVENT_CASE(SDL_EVENT_PEN_UP) - PRINT_PTIP_EVENT(event); + PRINT_PTOUCH_EVENT(event); + break; +#undef PRINT_PTOUCH_EVENT + +#define PRINT_PPROXIMITY_EVENT(event) \ + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u)", \ + (uint)event->pproximity.timestamp, (uint)event->pproximity.windowID, (uint)event->pproximity.which); + SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_IN) + PRINT_PPROXIMITY_EVENT(event); + break; + SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_OUT) + PRINT_PPROXIMITY_EVENT(event); + break; +#undef PRINT_PPROXIMITY_EVENT + + SDL_EVENT_CASE(SDL_EVENT_PEN_AXIS) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g axis=%s value=%g)", + (uint)event->paxis.timestamp, (uint)event->paxis.windowID, (uint)event->paxis.which, (uint)event->paxis.pen_state, event->paxis.x, event->paxis.y, + ((event->paxis.axis >= 0) && (event->paxis.axis < SDL_arraysize(pen_axisnames))) ? pen_axisnames[event->paxis.axis] : "[UNKNOWN]", event->paxis.value); break; -#undef PRINT_PTIP_EVENT SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION) - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%08x x=%g y=%g [%g, %g, %g, %g, %g, %g])", - (uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, - (uint)event->pmotion.which, (uint)event->pmotion.pen_state, - event->pmotion.x, event->pmotion.y, - event->pmotion.axes[SDL_PEN_AXIS_PRESSURE], - event->pmotion.axes[SDL_PEN_AXIS_XTILT], - event->pmotion.axes[SDL_PEN_AXIS_YTILT], - event->pmotion.axes[SDL_PEN_AXIS_DISTANCE], - event->pmotion.axes[SDL_PEN_AXIS_ROTATION], - event->pmotion.axes[SDL_PEN_AXIS_SLIDER]); + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g)", + (uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, (uint)event->pmotion.which, (uint)event->pmotion.pen_state, event->pmotion.x, event->pmotion.y); break; #define PRINT_PBUTTON_EVENT(event) \ - (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u tip=%u state=%s x=%g y=%g axes=[%g, %g, %g, %g, %g, %g])", \ - (uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, \ - (uint)event->pbutton.which, (uint)event->pbutton.button, \ - event->pbutton.state == SDL_PRESSED ? "pressed" : "released", \ - event->pbutton.x, event->pbutton.y, \ - event->pbutton.axes[SDL_PEN_AXIS_PRESSURE], \ - event->pbutton.axes[SDL_PEN_AXIS_XTILT], \ - event->pbutton.axes[SDL_PEN_AXIS_YTILT], \ - event->pbutton.axes[SDL_PEN_AXIS_DISTANCE], \ - event->pbutton.axes[SDL_PEN_AXIS_ROTATION], \ - event->pbutton.axes[SDL_PEN_AXIS_SLIDER]) + (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g button=%u state=%s)", \ + (uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, (uint)event->pbutton.which, (uint)event->pbutton.pen_state, event->pbutton.x, event->pbutton.y, \ + (uint)event->pbutton.button, event->pbutton.down ? "down" : "up"); SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN) PRINT_PBUTTON_EVENT(event); break; @@ -573,7 +768,7 @@ static void SDL_LogEvent(const SDL_Event *event) break; #undef PRINT_DROP_EVENT -#define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u iscapture=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.iscapture ? "true" : "false") +#define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u recording=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.recording ? "true" : "false") SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_ADDED) PRINT_AUDIODEV_EVENT(event); break; @@ -610,13 +805,17 @@ static void SDL_LogEvent(const SDL_Event *event) #undef SDL_EVENT_CASE case SDL_EVENT_POLL_SENTINEL: - /* No logging necessary for this one */ + // No logging necessary for this one break; default: if (!name[0]) { - SDL_strlcpy(name, "UNKNOWN", sizeof(name)); - (void)SDL_snprintf(details, sizeof(details), " #%u! (Bug? FIXME?)", (uint)event->type); + if (event->type >= SDL_EVENT_USER) { + SDL_strlcpy(name, "USER", sizeof(name)); + } else { + SDL_strlcpy(name, "UNKNOWN", sizeof(name)); + } + (void)SDL_snprintf(details, sizeof(details), " 0x%x", (uint)event->type); } break; } @@ -636,16 +835,17 @@ void SDL_StopEventLoop(void) SDL_LockMutex(SDL_EventQ.lock); - SDL_EventQ.active = SDL_FALSE; + SDL_EventQ.active = false; if (report && SDL_atoi(report)) { SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n", SDL_EventQ.max_events_seen); } - /* Clean out EventQ */ + // Clean out EventQ for (entry = SDL_EventQ.head; entry;) { SDL_EventEntry *next = entry->next; + SDL_TransferTemporaryMemoryFromEvent(entry); SDL_free(entry); entry = next; } @@ -655,25 +855,19 @@ void SDL_StopEventLoop(void) entry = next; } - SDL_AtomicSet(&SDL_EventQ.count, 0); + SDL_SetAtomicInt(&SDL_EventQ.count, 0); SDL_EventQ.max_events_seen = 0; SDL_EventQ.head = NULL; SDL_EventQ.tail = NULL; SDL_EventQ.free = NULL; - SDL_AtomicSet(&SDL_sentinel_pending, 0); + SDL_SetAtomicInt(&SDL_sentinel_pending, 0); - SDL_FlushEventMemory(0); - - /* Clear disabled event state */ + // Clear disabled event state for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) { SDL_free(SDL_disabled_events[i]); SDL_disabled_events[i] = NULL; } - if (SDL_event_memory_lock) { - SDL_DestroyMutex(SDL_event_memory_lock); - SDL_event_memory_lock = NULL; - } if (SDL_event_watchers_lock) { SDL_DestroyMutex(SDL_event_watchers_lock); SDL_event_watchers_lock = NULL; @@ -693,8 +887,8 @@ void SDL_StopEventLoop(void) } } -/* This function (and associated calls) may be called more than once */ -int SDL_StartEventLoop(void) +// This function (and associated calls) may be called more than once +bool SDL_StartEventLoop(void) { /* We'll leave the event queue alone, since we might have gotten some important events at launch (like SDL_EVENT_DROP_FILE) @@ -702,12 +896,12 @@ int SDL_StartEventLoop(void) FIXME: Does this introduce any other bugs with events at startup? */ - /* Create the lock and set ourselves active */ + // Create the lock and set ourselves active #ifndef SDL_THREADS_DISABLED if (!SDL_EventQ.lock) { SDL_EventQ.lock = SDL_CreateMutex(); if (SDL_EventQ.lock == NULL) { - return -1; + return false; } } SDL_LockMutex(SDL_EventQ.lock); @@ -716,29 +910,21 @@ int SDL_StartEventLoop(void) SDL_event_watchers_lock = SDL_CreateMutex(); if (SDL_event_watchers_lock == NULL) { SDL_UnlockMutex(SDL_EventQ.lock); - return -1; + return false; } } +#endif // !SDL_THREADS_DISABLED - if (SDL_event_memory_lock == NULL) { - SDL_event_memory_lock = SDL_CreateMutex(); - if (SDL_event_memory_lock == NULL) { - SDL_UnlockMutex(SDL_EventQ.lock); - return -1; - } - } -#endif /* !SDL_THREADS_DISABLED */ - - SDL_EventQ.active = SDL_TRUE; + SDL_EventQ.active = true; SDL_UnlockMutex(SDL_EventQ.lock); - return 0; + return true; } -/* Add an event to the event queue -- called with the queue locked */ +// Add an event to the event queue -- called with the queue locked static int SDL_AddEvent(SDL_Event *event) { SDL_EventEntry *entry; - const int initial_count = SDL_AtomicGet(&SDL_EventQ.count); + const int initial_count = SDL_GetAtomicInt(&SDL_EventQ.count); int final_count; if (initial_count >= SDL_MAX_QUEUED_EVENTS) { @@ -762,8 +948,10 @@ static int SDL_AddEvent(SDL_Event *event) SDL_copyp(&entry->event, event); if (event->type == SDL_EVENT_POLL_SENTINEL) { - SDL_AtomicAdd(&SDL_sentinel_pending, 1); + SDL_AddAtomicInt(&SDL_sentinel_pending, 1); } + entry->memory = NULL; + SDL_TransferTemporaryMemoryToEvent(entry); if (SDL_EventQ.tail) { SDL_EventQ.tail->next = entry; @@ -778,7 +966,7 @@ static int SDL_AddEvent(SDL_Event *event) entry->next = NULL; } - final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1; + final_count = SDL_AddAtomicInt(&SDL_EventQ.count, 1) + 1; if (final_count > SDL_EventQ.max_events_seen) { SDL_EventQ.max_events_seen = final_count; } @@ -788,9 +976,11 @@ static int SDL_AddEvent(SDL_Event *event) return 1; } -/* Remove an event from the queue -- called with the queue locked */ +// Remove an event from the queue -- called with the queue locked static void SDL_CutEvent(SDL_EventEntry *entry) { + SDL_TransferTemporaryMemoryFromEvent(entry); + if (entry->prev) { entry->prev->next = entry->next; } @@ -808,20 +998,23 @@ static void SDL_CutEvent(SDL_EventEntry *entry) } if (entry->event.type == SDL_EVENT_POLL_SENTINEL) { - SDL_AtomicAdd(&SDL_sentinel_pending, -1); + SDL_AddAtomicInt(&SDL_sentinel_pending, -1); } entry->next = SDL_EventQ.free; SDL_EventQ.free = entry; - SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0); - SDL_AtomicAdd(&SDL_EventQ.count, -1); + SDL_assert(SDL_GetAtomicInt(&SDL_EventQ.count) > 0); + SDL_AddAtomicInt(&SDL_EventQ.count, -1); } -static int SDL_SendWakeupEvent(void) +static void SDL_SendWakeupEvent(void) { +#ifdef SDL_PLATFORM_ANDROID + Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_WAKE); +#else SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this == NULL || !_this->SendWakeupEvent) { - return 0; + return; } SDL_LockMutex(_this->wakeup_lock); @@ -829,29 +1022,28 @@ static int SDL_SendWakeupEvent(void) if (_this->wakeup_window) { _this->SendWakeupEvent(_this, _this->wakeup_window); - /* No more wakeup events needed until we enter a new wait */ + // No more wakeup events needed until we enter a new wait _this->wakeup_window = NULL; } } SDL_UnlockMutex(_this->wakeup_lock); - - return 0; +#endif } -/* Lock the event queue, take a peep at it, and unlock it */ -static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventaction action, - Uint32 minType, Uint32 maxType, SDL_bool include_sentinel) +// Lock the event queue, take a peep at it, and unlock it +static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_EventAction action, + Uint32 minType, Uint32 maxType, bool include_sentinel) { int i, used, sentinels_expected = 0; - /* Lock the event queue */ + // Lock the event queue used = 0; SDL_LockMutex(SDL_EventQ.lock); { - /* Don't look after we've quit */ + // Don't look after we've quit if (!SDL_EventQ.active) { - /* We get a few spurious events at shutdown, so don't warn then */ + // We get a few spurious events at shutdown, so don't warn then if (action == SDL_GETEVENT) { SDL_SetError("The event system has been shut down"); } @@ -859,6 +1051,10 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact return -1; } if (action == SDL_ADDEVENT) { + if (!events) { + SDL_UnlockMutex(SDL_EventQ.lock); + return SDL_InvalidParamError("events"); + } for (i = 0; i < numevents; ++i) { used += SDL_AddEvent(&events[i]); } @@ -878,16 +1074,16 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact } } if (type == SDL_EVENT_POLL_SENTINEL) { - /* Special handling for the sentinel event */ + // Special handling for the sentinel event if (!include_sentinel) { - /* Skip it, we don't want to include it */ + // Skip it, we don't want to include it continue; } if (events == NULL || action != SDL_GETEVENT) { ++sentinels_expected; } - if (SDL_AtomicGet(&SDL_sentinel_pending) > sentinels_expected) { - /* Skip it, there's another one pending */ + if (SDL_GetAtomicInt(&SDL_sentinel_pending) > sentinels_expected) { + // Skip it, there's another one pending continue; } } @@ -904,20 +1100,36 @@ static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_eventact return used; } -int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, +int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_EventAction action, Uint32 minType, Uint32 maxType) { - return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, SDL_FALSE); + return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, false); } -SDL_bool SDL_HasEvent(Uint32 type) +bool SDL_HasEvent(Uint32 type) { - return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0; + return SDL_HasEvents(type, type); } -SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType) +bool SDL_HasEvents(Uint32 minType, Uint32 maxType) { - return SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0; + bool found = false; + + SDL_LockMutex(SDL_EventQ.lock); + { + if (SDL_EventQ.active) { + for (SDL_EventEntry *entry = SDL_EventQ.head; entry; entry = entry->next) { + const Uint32 type = entry->event.type; + if (minType <= type && type <= maxType) { + found = true; + break; + } + } + } + } + SDL_UnlockMutex(SDL_EventQ.lock); + + return found; } void SDL_FlushEvent(Uint32 type) @@ -930,7 +1142,7 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) SDL_EventEntry *entry, *next; Uint32 type; - /* Make sure the events are current */ + // Make sure the events are current #if 0 /* Actually, we can't do this since we might be flushing while processing a resize event, and calling this might trigger further resize events. @@ -938,10 +1150,10 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) SDL_PumpEvents(); #endif - /* Lock the event queue */ + // Lock the event queue SDL_LockMutex(SDL_EventQ.lock); { - /* Don't look after we've quit */ + // Don't look after we've quit if (!SDL_EventQ.active) { SDL_UnlockMutex(SDL_EventQ.lock); return; @@ -957,24 +1169,25 @@ void SDL_FlushEvents(Uint32 minType, Uint32 maxType) SDL_UnlockMutex(SDL_EventQ.lock); } -/* Run the system dependent event loops */ -static void SDL_PumpEventsInternal(SDL_bool push_sentinel) +// Run the system dependent event loops +static void SDL_PumpEventsInternal(bool push_sentinel) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - - /* Free old event memory */ - /*SDL_FlushEventMemory(SDL_last_event_id - SDL_MAX_QUEUED_EVENTS);*/ - if (SDL_AtomicGet(&SDL_EventQ.count) == 0) { - SDL_FlushEventMemory(SDL_last_event_id); - } + // Free any temporary memory from old events + SDL_FreeTemporaryMemory(); - /* Release any keys held down from last frame */ + // Release any keys held down from last frame SDL_ReleaseAutoReleaseKeys(); - /* Get events from the video subsystem */ +#ifdef SDL_PLATFORM_ANDROID + // Android event processing is independent of the video subsystem + Android_PumpEvents(0); +#else + // Get events from the video subsystem + SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this) { _this->PumpEvents(_this); } +#endif #ifndef SDL_AUDIO_DISABLED SDL_UpdateAudio(); @@ -985,27 +1198,27 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) #endif #ifndef SDL_SENSOR_DISABLED - /* Check for sensor state change */ + // Check for sensor state change if (SDL_update_sensors) { SDL_UpdateSensors(); } #endif #ifndef SDL_JOYSTICK_DISABLED - /* Check for joystick state change */ + // Check for joystick state change if (SDL_update_joysticks) { SDL_UpdateJoysticks(); } #endif - SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */ + SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc. if (push_sentinel && SDL_EventEnabled(SDL_EVENT_POLL_SENTINEL)) { SDL_Event sentinel; - /* Make sure we don't already have a sentinel in the queue, and add one to the end */ - if (SDL_AtomicGet(&SDL_sentinel_pending) > 0) { - SDL_PeepEventsInternal(&sentinel, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, SDL_TRUE); + // Make sure we don't already have a sentinel in the queue, and add one to the end + if (SDL_GetAtomicInt(&SDL_sentinel_pending) > 0) { + SDL_PeepEventsInternal(&sentinel, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true); } sentinel.type = SDL_EVENT_POLL_SENTINEL; @@ -1016,16 +1229,18 @@ static void SDL_PumpEventsInternal(SDL_bool push_sentinel) void SDL_PumpEvents(void) { - SDL_PumpEventsInternal(SDL_FALSE); + SDL_PumpEventsInternal(false); } -/* Public functions */ +// Public functions -SDL_bool SDL_PollEvent(SDL_Event *event) +bool SDL_PollEvent(SDL_Event *event) { return SDL_WaitEventTimeoutNS(event, 0); } +#ifndef SDL_PLATFORM_ANDROID + static Sint64 SDL_events_get_polling_interval(void) { Sint64 poll_intervalNS = SDL_MAX_SINT64; @@ -1033,10 +1248,10 @@ static Sint64 SDL_events_get_polling_interval(void) #ifndef SDL_JOYSTICK_DISABLED if (SDL_WasInit(SDL_INIT_JOYSTICK) && SDL_update_joysticks) { if (SDL_JoysticksOpened()) { - /* If we have joysticks open, we need to poll rapidly for events */ + // If we have joysticks open, we need to poll rapidly for events poll_intervalNS = SDL_min(poll_intervalNS, EVENT_POLL_INTERVAL_NS); } else { - /* If not, just poll every few seconds to enumerate new joysticks */ + // If not, just poll every few seconds to enumerate new joysticks poll_intervalNS = SDL_min(poll_intervalNS, ENUMERATION_POLL_INTERVAL_NS); } } @@ -1044,7 +1259,7 @@ static Sint64 SDL_events_get_polling_interval(void) #ifndef SDL_SENSOR_DISABLED if (SDL_WasInit(SDL_INIT_SENSOR) && SDL_update_sensors && SDL_SensorsOpened()) { - /* If we have sensors open, we need to poll rapidly for events */ + // If we have sensors open, we need to poll rapidly for events poll_intervalNS = SDL_min(poll_intervalNS, EVENT_POLL_INTERVAL_NS); } #endif @@ -1065,12 +1280,12 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu c) Periodic processing that takes place in some platform PumpEvents() functions happens d) Signals received in WaitEventTimeout() are turned into SDL events */ - SDL_PumpEventsInternal(SDL_TRUE); + SDL_PumpEventsInternal(true); SDL_LockMutex(_this->wakeup_lock); { status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST); - /* If status == 0 we are going to block so wakeup will be needed. */ + // If status == 0 we are going to block so wakeup will be needed. if (status == 0) { _this->wakeup_window = wakeup_window; } else { @@ -1080,24 +1295,24 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu SDL_UnlockMutex(_this->wakeup_lock); if (status < 0) { - /* Got an error: return */ + // Got an error: return break; } if (status > 0) { - /* There is an event, we can return. */ + // There is an event, we can return. return 1; } - /* No events found in the queue, call WaitEventTimeout to wait for an event. */ + // No events found in the queue, call WaitEventTimeout to wait for an event. if (timeoutNS > 0) { Sint64 elapsed = SDL_GetTicksNS() - start; if (elapsed >= timeoutNS) { - /* Set wakeup_window to NULL without holding the lock. */ + // Set wakeup_window to NULL without holding the lock. _this->wakeup_window = NULL; return 0; } loop_timeoutNS = (timeoutNS - elapsed); } - /* Adjust the timeout for any polling requirements we currently have. */ + // Adjust the timeout for any polling requirements we currently have. if (poll_intervalNS != SDL_MAX_SINT64) { if (loop_timeoutNS >= 0) { loop_timeoutNS = SDL_min(loop_timeoutNS, poll_intervalNS); @@ -1106,13 +1321,13 @@ static int SDL_WaitEventTimeout_Device(SDL_VideoDevice *_this, SDL_Window *wakeu } } status = _this->WaitEventTimeout(_this, loop_timeoutNS); - /* Set wakeup_window to NULL without holding the lock. */ + // Set wakeup_window to NULL without holding the lock. _this->wakeup_window = NULL; if (status == 0 && poll_intervalNS != SDL_MAX_SINT64 && loop_timeoutNS == poll_intervalNS) { - /* We may have woken up to poll. Try again */ + // We may have woken up to poll. Try again continue; } else if (status <= 0) { - /* There is either an error or the timeout is elapsed: return */ + // There is either an error or the timeout is elapsed: return return status; } /* An event was found and pumped into the SDL events queue. Continue the loop @@ -1132,12 +1347,14 @@ static SDL_Window *SDL_find_active_window(SDL_VideoDevice *_this) return NULL; } -SDL_bool SDL_WaitEvent(SDL_Event *event) +#endif // !SDL_PLATFORM_ANDROID + +bool SDL_WaitEvent(SDL_Event *event) { return SDL_WaitEventTimeoutNS(event, -1); } -SDL_bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) +bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) { Sint64 timeoutNS; @@ -1149,12 +1366,10 @@ SDL_bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS) return SDL_WaitEventTimeoutNS(event, timeoutNS); } -SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) +bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) { - SDL_VideoDevice *_this = SDL_GetVideoDevice(); - SDL_Window *wakeup_window; Uint64 start, expiration; - SDL_bool include_sentinel = (timeoutNS == 0); + bool include_sentinel = (timeoutNS == 0); int result; if (timeoutNS > 0) { @@ -1165,55 +1380,74 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) expiration = 0; } - /* If there isn't a poll sentinel event pending, pump events and add one */ - if (SDL_AtomicGet(&SDL_sentinel_pending) == 0) { - SDL_PumpEventsInternal(SDL_TRUE); + // If there isn't a poll sentinel event pending, pump events and add one + if (SDL_GetAtomicInt(&SDL_sentinel_pending) == 0) { + SDL_PumpEventsInternal(true); } - /* First check for existing events */ + // First check for existing events result = SDL_PeepEventsInternal(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, include_sentinel); if (result < 0) { - return SDL_FALSE; + return false; } if (include_sentinel) { if (event) { if (event->type == SDL_EVENT_POLL_SENTINEL) { - /* Reached the end of a poll cycle, and not willing to wait */ - return SDL_FALSE; + // Reached the end of a poll cycle, and not willing to wait + return false; } } else { - /* Need to peek the next event to check for sentinel */ + // Need to peek the next event to check for sentinel SDL_Event dummy; - if (SDL_PeepEventsInternal(&dummy, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, SDL_TRUE) && + if (SDL_PeepEventsInternal(&dummy, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, true) && dummy.type == SDL_EVENT_POLL_SENTINEL) { - SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, SDL_TRUE); - /* Reached the end of a poll cycle, and not willing to wait */ - return SDL_FALSE; + SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true); + // Reached the end of a poll cycle, and not willing to wait + return false; } } } if (result == 0) { if (timeoutNS == 0) { - /* No events available, and not willing to wait */ - return SDL_FALSE; + // No events available, and not willing to wait + return false; } } else { - /* Has existing events */ - return SDL_TRUE; + // Has existing events + return true; } - /* We should have completely handled timeoutNS == 0 above */ + // We should have completely handled timeoutNS == 0 above SDL_assert(timeoutNS != 0); +#ifdef SDL_PLATFORM_ANDROID + for (;;) { + if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) { + return true; + } + + Uint64 delay = -1; + if (timeoutNS > 0) { + Uint64 now = SDL_GetTicksNS(); + if (now >= expiration) { + // Timeout expired and no events + return false; + } + delay = (expiration - now); + } + Android_PumpEvents(delay); + } +#else + SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this && _this->WaitEventTimeout && _this->SendWakeupEvent) { - /* Look if a shown window is available to send the wakeup event. */ - wakeup_window = SDL_find_active_window(_this); + // Look if a shown window is available to send the wakeup event. + SDL_Window *wakeup_window = SDL_find_active_window(_this); if (wakeup_window) { result = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, start, timeoutNS); if (result > 0) { - return SDL_TRUE; + return true; } else if (result == 0) { - return SDL_FALSE; + return false; } else { /* There may be implementation-defined conditions where the backend cannot * reliably wait for the next event. If that happens, fall back to polling. @@ -1223,50 +1457,48 @@ SDL_bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS) } for (;;) { - SDL_PumpEventsInternal(SDL_TRUE); + SDL_PumpEventsInternal(true); if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) { - return SDL_TRUE; + return true; } Uint64 delay = EVENT_POLL_INTERVAL_NS; if (timeoutNS > 0) { Uint64 now = SDL_GetTicksNS(); if (now >= expiration) { - /* Timeout expired and no events */ - return SDL_FALSE; + // Timeout expired and no events + return false; } delay = SDL_min((expiration - now), delay); } SDL_DelayNS(delay); } +#endif // SDL_PLATFORM_ANDROID } -int SDL_PushEvent(SDL_Event *event) +static bool SDL_CallEventWatchers(SDL_Event *event) { - if (!event->common.timestamp) { - event->common.timestamp = SDL_GetTicksNS(); - } - - if (SDL_EventOK.callback || SDL_event_watchers_count > 0) { + if ((SDL_EventOK.callback || SDL_event_watchers_count > 0) && + (event->common.type != SDL_EVENT_POLL_SENTINEL)) { SDL_LockMutex(SDL_event_watchers_lock); { if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) { SDL_UnlockMutex(SDL_event_watchers_lock); - return 0; + return false; } if (SDL_event_watchers_count > 0) { - /* Make sure we only dispatch the current watcher list */ + // Make sure we only dispatch the current watcher list int i, event_watchers_count = SDL_event_watchers_count; - SDL_event_watchers_dispatching = SDL_TRUE; + SDL_event_watchers_dispatching = true; for (i = 0; i < event_watchers_count; ++i) { if (!SDL_event_watchers[i].removed) { SDL_event_watchers[i].callback(SDL_event_watchers[i].userdata, event); } } - SDL_event_watchers_dispatching = SDL_FALSE; + SDL_event_watchers_dispatching = false; if (SDL_event_watchers_removed) { for (i = SDL_event_watchers_count; i--;) { @@ -1277,33 +1509,60 @@ int SDL_PushEvent(SDL_Event *event) } } } - SDL_event_watchers_removed = SDL_FALSE; + SDL_event_watchers_removed = false; } } } SDL_UnlockMutex(SDL_event_watchers_lock); } + return true; +} + +bool SDL_PushEvent(SDL_Event *event) +{ + if (!event->common.timestamp) { + event->common.timestamp = SDL_GetTicksNS(); + } + + if (!SDL_CallEventWatchers(event)) { + SDL_ClearError(); + return false; + } + if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) { - return -1; + return false; } - return 1; + return true; } void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata) { + SDL_EventEntry *event, *next; SDL_LockMutex(SDL_event_watchers_lock); { - /* Set filter and discard pending events */ + // Set filter and discard pending events SDL_EventOK.callback = filter; SDL_EventOK.userdata = userdata; - SDL_FlushEvents(SDL_EVENT_FIRST, SDL_EVENT_LAST); + if (filter) { + // Cut all events not accepted by the filter + SDL_LockMutex(SDL_EventQ.lock); + { + for (event = SDL_EventQ.head; event; event = next) { + next = event->next; + if (!filter(userdata, &event->event)) { + SDL_CutEvent(event); + } + } + } + SDL_UnlockMutex(SDL_EventQ.lock); + } } SDL_UnlockMutex(SDL_event_watchers_lock); } -SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) +bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) { SDL_EventWatcher event_ok; @@ -1319,12 +1578,12 @@ SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata) if (userdata) { *userdata = event_ok.userdata; } - return event_ok.callback ? SDL_TRUE : SDL_FALSE; + return event_ok.callback ? true : false; } -int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) +bool SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { - int result = 0; + bool result = true; SDL_LockMutex(SDL_event_watchers_lock); { @@ -1338,10 +1597,10 @@ int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) watcher = &SDL_event_watchers[SDL_event_watchers_count]; watcher->callback = filter; watcher->userdata = userdata; - watcher->removed = SDL_FALSE; + watcher->removed = false; ++SDL_event_watchers_count; } else { - result = -1; + result = false; } } SDL_UnlockMutex(SDL_event_watchers_lock); @@ -1349,7 +1608,7 @@ int SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) return result; } -void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) +void SDL_RemoveEventWatch(SDL_EventFilter filter, void *userdata) { SDL_LockMutex(SDL_event_watchers_lock); { @@ -1358,8 +1617,8 @@ void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) for (i = 0; i < SDL_event_watchers_count; ++i) { if (SDL_event_watchers[i].callback == filter && SDL_event_watchers[i].userdata == userdata) { if (SDL_event_watchers_dispatching) { - SDL_event_watchers[i].removed = SDL_TRUE; - SDL_event_watchers_removed = SDL_TRUE; + SDL_event_watchers[i].removed = true; + SDL_event_watchers_removed = true; } else { --SDL_event_watchers_count; if (i < SDL_event_watchers_count) { @@ -1388,58 +1647,52 @@ void SDL_FilterEvents(SDL_EventFilter filter, void *userdata) SDL_UnlockMutex(SDL_EventQ.lock); } -void SDL_SetEventEnabled(Uint32 type, SDL_bool enabled) +void SDL_SetEventEnabled(Uint32 type, bool enabled) { - SDL_bool current_state; + bool current_state; Uint8 hi = ((type >> 8) & 0xff); Uint8 lo = (type & 0xff); if (SDL_disabled_events[hi] && (SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) { - current_state = SDL_FALSE; + current_state = false; } else { - current_state = SDL_TRUE; + current_state = true; } - if (enabled != current_state) { + if ((enabled != false) != current_state) { if (enabled) { -#ifdef _MSC_VER /* Visual Studio analyzer can't tell that SDL_disabled_events[hi] isn't NULL if enabled is true */ -#pragma warning(push) -#pragma warning(disable : 6011) -#endif + SDL_assert(SDL_disabled_events[hi] != NULL); SDL_disabled_events[hi]->bits[lo / 32] &= ~(1 << (lo & 31)); -#ifdef _MSC_VER -#pragma warning(pop) -#endif - /* Gamepad events depend on joystick events */ + // Gamepad events depend on joystick events switch (type) { case SDL_EVENT_GAMEPAD_ADDED: - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_ADDED, SDL_TRUE); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_ADDED, true); break; case SDL_EVENT_GAMEPAD_REMOVED: - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_REMOVED, SDL_TRUE); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_REMOVED, true); break; case SDL_EVENT_GAMEPAD_AXIS_MOTION: case SDL_EVENT_GAMEPAD_BUTTON_DOWN: case SDL_EVENT_GAMEPAD_BUTTON_UP: - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_DOWN, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_UP, SDL_TRUE); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION, true); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION, true); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_DOWN, true); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_UP, true); break; case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE: - SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, SDL_TRUE); + SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, true); break; default: break; } } else { - /* Disable this event type and discard pending events */ + // Disable this event type and discard pending events if (!SDL_disabled_events[hi]) { SDL_disabled_events[hi] = (SDL_DisabledEventBlock *)SDL_calloc(1, sizeof(SDL_DisabledEventBlock)); } - /* Out of memory, nothing we can do... */ + // Out of memory, nothing we can do... if (SDL_disabled_events[hi]) { SDL_disabled_events[hi]->bits[lo / 32] |= (1 << (lo & 31)); SDL_FlushEvent(type); @@ -1454,16 +1707,16 @@ void SDL_SetEventEnabled(Uint32 type, SDL_bool enabled) } } -SDL_bool SDL_EventEnabled(Uint32 type) +bool SDL_EventEnabled(Uint32 type) { Uint8 hi = ((type >> 8) & 0xff); Uint8 lo = (type & 0xff); if (SDL_disabled_events[hi] && (SDL_disabled_events[hi]->bits[lo / 32] & (1 << (lo & 31)))) { - return SDL_FALSE; + return false; } else { - return SDL_TRUE; + return true; } } @@ -1478,37 +1731,53 @@ Uint32 SDL_RegisterEvents(int numevents) return event_base; } -int SDL_SendAppEvent(SDL_EventType eventType) +void SDL_SendAppEvent(SDL_EventType eventType) { - int posted; - - posted = 0; if (SDL_EventEnabled(eventType)) { SDL_Event event; event.type = eventType; event.common.timestamp = 0; - posted = (SDL_PushEvent(&event) > 0); + + switch (eventType) { + case SDL_EVENT_TERMINATING: + case SDL_EVENT_LOW_MEMORY: + case SDL_EVENT_WILL_ENTER_BACKGROUND: + case SDL_EVENT_DID_ENTER_BACKGROUND: + case SDL_EVENT_WILL_ENTER_FOREGROUND: + case SDL_EVENT_DID_ENTER_FOREGROUND: + // We won't actually queue this event, it needs to be handled in this call stack by an event watcher + if (SDL_EventLoggingVerbosity > 0) { + SDL_LogEvent(&event); + } + SDL_CallEventWatchers(&event); + break; + default: + SDL_PushEvent(&event); + break; + } } - return posted; } -int SDL_SendKeymapChangedEvent(void) +void SDL_SendKeymapChangedEvent(void) { - return SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED); + SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED); } -int SDL_SendLocaleChangedEvent(void) +void SDL_SendLocaleChangedEvent(void) { - return SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED); + SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED); } -int SDL_SendSystemThemeChangedEvent(void) +void SDL_SendSystemThemeChangedEvent(void) { - return SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED); + SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED); } -int SDL_InitEvents(void) +bool SDL_InitEvents(void) { +#ifdef SDL_PLATFORM_ANDROID + Android_InitEvents(); +#endif #ifndef SDL_JOYSTICK_DISABLED SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL); #endif @@ -1517,26 +1786,29 @@ int SDL_InitEvents(void) #endif SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); SDL_AddHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL); - if (SDL_StartEventLoop() < 0) { - SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); - return -1; + if (!SDL_StartEventLoop()) { + SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); + return false; } SDL_InitQuit(); - return 0; + return true; } void SDL_QuitEvents(void) { SDL_QuitQuit(); SDL_StopEventLoop(); - SDL_DelHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL); - SDL_DelHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); + SDL_RemoveHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL); + SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL); #ifndef SDL_JOYSTICK_DISABLED - SDL_DelHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL); + SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL); #endif #ifndef SDL_SENSOR_DISABLED - SDL_DelHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL); + SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL); +#endif +#ifdef SDL_PLATFORM_ANDROID + Android_QuitEvents(); #endif } diff --git a/libs/SDL3/src/events/SDL_events_c.h b/libs/SDL3/src/events/SDL_events_c.h index 181583d71..d8f86eb3c 100644 --- a/libs/SDL3/src/events/SDL_events_c.h +++ b/libs/SDL3/src/events/SDL_events_c.h @@ -24,7 +24,7 @@ #include "SDL_internal.h" -/* Useful functions and variables from SDL_events.c */ +// Useful functions and variables from SDL_events.c #include "../video/SDL_sysvideo.h" #include "SDL_clipboardevents_c.h" @@ -33,26 +33,32 @@ #include "SDL_keyboard_c.h" #include "SDL_mouse_c.h" #include "SDL_touch_c.h" +#include "SDL_pen_c.h" #include "SDL_windowevents_c.h" -/* Start and stop the event processing loop */ -extern int SDL_StartEventLoop(void); +// Start and stop the event processing loop +extern bool SDL_StartEventLoop(void); extern void SDL_StopEventLoop(void); extern void SDL_QuitInterrupt(void); -extern int SDL_SendAppEvent(SDL_EventType eventType); -extern int SDL_SendKeymapChangedEvent(void); -extern int SDL_SendLocaleChangedEvent(void); -extern int SDL_SendSystemThemeChangedEvent(void); +extern void SDL_SendAppEvent(SDL_EventType eventType); +extern void SDL_SendKeymapChangedEvent(void); +extern void SDL_SendLocaleChangedEvent(void); +extern void SDL_SendSystemThemeChangedEvent(void); -extern int SDL_SendQuit(void); +extern void *SDL_AllocateTemporaryMemory(size_t size); +extern const char *SDL_CreateTemporaryString(const char *string); +extern void *SDL_ClaimTemporaryMemory(const void *mem); +extern void SDL_FreeTemporaryMemory(void); -extern int SDL_InitEvents(void); +extern void SDL_SendQuit(void); + +extern bool SDL_InitEvents(void); extern void SDL_QuitEvents(void); extern void SDL_SendPendingSignalEvents(void); -extern int SDL_InitQuit(void); +extern bool SDL_InitQuit(void); extern void SDL_QuitQuit(void); -#endif /* SDL_events_c_h_ */ +#endif // SDL_events_c_h_ diff --git a/libs/SDL3/src/events/SDL_keyboard.c b/libs/SDL3/src/events/SDL_keyboard.c index f1b2cde89..438311ba4 100644 --- a/libs/SDL3/src/events/SDL_keyboard.c +++ b/libs/SDL3/src/events/SDL_keyboard.c @@ -20,26 +20,28 @@ */ #include "SDL_internal.h" -/* General keyboard handling code for SDL */ +// General keyboard handling code for SDL #include "SDL_events_c.h" +#include "SDL_keymap_c.h" #include "../video/SDL_sysvideo.h" -#include "scancodes_ascii.h" -/* #define DEBUG_KEYBOARD */ +// #define DEBUG_KEYBOARD -/* Global keyboard information */ +// Global keyboard information -typedef enum -{ - KEYBOARD_HARDWARE = 0x01, - KEYBOARD_VIRTUAL = 0x02, - KEYBOARD_AUTORELEASE = 0x04, - KEYBOARD_IGNOREMODIFIERS = 0x08 -} SDL_KeyboardFlags; +#define KEYBOARD_HARDWARE 0x01 +#define KEYBOARD_VIRTUAL 0x02 +#define KEYBOARD_AUTORELEASE 0x04 +#define KEYBOARD_IGNOREMODIFIERS 0x08 #define KEYBOARD_SOURCE_MASK (KEYBOARD_HARDWARE | KEYBOARD_AUTORELEASE) +#define KEYCODE_OPTION_HIDE_NUMPAD 0x01 +#define KEYCODE_OPTION_FRENCH_NUMBERS 0x02 +#define KEYCODE_OPTION_LATIN_LETTERS 0x04 +#define DEFAULT_KEYCODE_OPTIONS (KEYCODE_OPTION_FRENCH_NUMBERS | KEYCODE_OPTION_LATIN_LETTERS) + typedef struct SDL_KeyboardInstance { SDL_KeyboardID instance_id; @@ -48,651 +50,64 @@ typedef struct SDL_KeyboardInstance typedef struct SDL_Keyboard { - /* Data common to all keyboards */ + // Data common to all keyboards SDL_Window *focus; - Uint16 modstate; - Uint8 keysource[SDL_NUM_SCANCODES]; - Uint8 keystate[SDL_NUM_SCANCODES]; - SDL_Keycode keymap[SDL_NUM_SCANCODES]; - SDL_bool autorelease_pending; + SDL_Keymod modstate; + Uint8 keysource[SDL_SCANCODE_COUNT]; + bool keystate[SDL_SCANCODE_COUNT]; + SDL_Keymap *keymap; + bool french_numbers; + bool latin_letters; + bool thai_keyboard; + Uint32 keycode_options; + bool autorelease_pending; Uint64 hardware_timestamp; + int next_reserved_scancode; } SDL_Keyboard; static SDL_Keyboard SDL_keyboard; static int SDL_keyboard_count; static SDL_KeyboardInstance *SDL_keyboards; -static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = { - /* 0 */ SDLK_UNKNOWN, - /* 1 */ SDLK_UNKNOWN, - /* 2 */ SDLK_UNKNOWN, - /* 3 */ SDLK_UNKNOWN, - /* 4 */ 'a', - /* 5 */ 'b', - /* 6 */ 'c', - /* 7 */ 'd', - /* 8 */ 'e', - /* 9 */ 'f', - /* 10 */ 'g', - /* 11 */ 'h', - /* 12 */ 'i', - /* 13 */ 'j', - /* 14 */ 'k', - /* 15 */ 'l', - /* 16 */ 'm', - /* 17 */ 'n', - /* 18 */ 'o', - /* 19 */ 'p', - /* 20 */ 'q', - /* 21 */ 'r', - /* 22 */ 's', - /* 23 */ 't', - /* 24 */ 'u', - /* 25 */ 'v', - /* 26 */ 'w', - /* 27 */ 'x', - /* 28 */ 'y', - /* 29 */ 'z', - /* 30 */ '1', - /* 31 */ '2', - /* 32 */ '3', - /* 33 */ '4', - /* 34 */ '5', - /* 35 */ '6', - /* 36 */ '7', - /* 37 */ '8', - /* 38 */ '9', - /* 39 */ '0', - /* 40 */ SDLK_RETURN, - /* 41 */ SDLK_ESCAPE, - /* 42 */ SDLK_BACKSPACE, - /* 43 */ SDLK_TAB, - /* 44 */ SDLK_SPACE, - /* 45 */ '-', - /* 46 */ '=', - /* 47 */ '[', - /* 48 */ ']', - /* 49 */ '\\', - /* 50 */ '#', - /* 51 */ ';', - /* 52 */ '\'', - /* 53 */ '`', - /* 54 */ ',', - /* 55 */ '.', - /* 56 */ '/', - /* 57 */ SDLK_CAPSLOCK, - /* 58 */ SDLK_F1, - /* 59 */ SDLK_F2, - /* 60 */ SDLK_F3, - /* 61 */ SDLK_F4, - /* 62 */ SDLK_F5, - /* 63 */ SDLK_F6, - /* 64 */ SDLK_F7, - /* 65 */ SDLK_F8, - /* 66 */ SDLK_F9, - /* 67 */ SDLK_F10, - /* 68 */ SDLK_F11, - /* 69 */ SDLK_F12, - /* 70 */ SDLK_PRINTSCREEN, - /* 71 */ SDLK_SCROLLLOCK, - /* 72 */ SDLK_PAUSE, - /* 73 */ SDLK_INSERT, - /* 74 */ SDLK_HOME, - /* 75 */ SDLK_PAGEUP, - /* 76 */ SDLK_DELETE, - /* 77 */ SDLK_END, - /* 78 */ SDLK_PAGEDOWN, - /* 79 */ SDLK_RIGHT, - /* 80 */ SDLK_LEFT, - /* 81 */ SDLK_DOWN, - /* 82 */ SDLK_UP, - /* 83 */ SDLK_NUMLOCKCLEAR, - /* 84 */ SDLK_KP_DIVIDE, - /* 85 */ SDLK_KP_MULTIPLY, - /* 86 */ SDLK_KP_MINUS, - /* 87 */ SDLK_KP_PLUS, - /* 88 */ SDLK_KP_ENTER, - /* 89 */ SDLK_KP_1, - /* 90 */ SDLK_KP_2, - /* 91 */ SDLK_KP_3, - /* 92 */ SDLK_KP_4, - /* 93 */ SDLK_KP_5, - /* 94 */ SDLK_KP_6, - /* 95 */ SDLK_KP_7, - /* 96 */ SDLK_KP_8, - /* 97 */ SDLK_KP_9, - /* 98 */ SDLK_KP_0, - /* 99 */ SDLK_KP_PERIOD, - /* 100 */ SDLK_UNKNOWN, - /* 101 */ SDLK_APPLICATION, - /* 102 */ SDLK_POWER, - /* 103 */ SDLK_KP_EQUALS, - /* 104 */ SDLK_F13, - /* 105 */ SDLK_F14, - /* 106 */ SDLK_F15, - /* 107 */ SDLK_F16, - /* 108 */ SDLK_F17, - /* 109 */ SDLK_F18, - /* 110 */ SDLK_F19, - /* 111 */ SDLK_F20, - /* 112 */ SDLK_F21, - /* 113 */ SDLK_F22, - /* 114 */ SDLK_F23, - /* 115 */ SDLK_F24, - /* 116 */ SDLK_EXECUTE, - /* 117 */ SDLK_HELP, - /* 118 */ SDLK_MENU, - /* 119 */ SDLK_SELECT, - /* 120 */ SDLK_STOP, - /* 121 */ SDLK_AGAIN, - /* 122 */ SDLK_UNDO, - /* 123 */ SDLK_CUT, - /* 124 */ SDLK_COPY, - /* 125 */ SDLK_PASTE, - /* 126 */ SDLK_FIND, - /* 127 */ SDLK_MUTE, - /* 128 */ SDLK_VOLUMEUP, - /* 129 */ SDLK_VOLUMEDOWN, - /* 130 */ SDLK_UNKNOWN, - /* 131 */ SDLK_UNKNOWN, - /* 132 */ SDLK_UNKNOWN, - /* 133 */ SDLK_KP_COMMA, - /* 134 */ SDLK_KP_EQUALSAS400, - /* 135 */ SDLK_UNKNOWN, - /* 136 */ SDLK_UNKNOWN, - /* 137 */ SDLK_UNKNOWN, - /* 138 */ SDLK_UNKNOWN, - /* 139 */ SDLK_UNKNOWN, - /* 140 */ SDLK_UNKNOWN, - /* 141 */ SDLK_UNKNOWN, - /* 142 */ SDLK_UNKNOWN, - /* 143 */ SDLK_UNKNOWN, - /* 144 */ SDLK_UNKNOWN, - /* 145 */ SDLK_UNKNOWN, - /* 146 */ SDLK_UNKNOWN, - /* 147 */ SDLK_UNKNOWN, - /* 148 */ SDLK_UNKNOWN, - /* 149 */ SDLK_UNKNOWN, - /* 150 */ SDLK_UNKNOWN, - /* 151 */ SDLK_UNKNOWN, - /* 152 */ SDLK_UNKNOWN, - /* 153 */ SDLK_ALTERASE, - /* 154 */ SDLK_SYSREQ, - /* 155 */ SDLK_CANCEL, - /* 156 */ SDLK_CLEAR, - /* 157 */ SDLK_PRIOR, - /* 158 */ SDLK_RETURN2, - /* 159 */ SDLK_SEPARATOR, - /* 160 */ SDLK_OUT, - /* 161 */ SDLK_OPER, - /* 162 */ SDLK_CLEARAGAIN, - /* 163 */ SDLK_CRSEL, - /* 164 */ SDLK_EXSEL, - /* 165 */ SDLK_UNKNOWN, - /* 166 */ SDLK_UNKNOWN, - /* 167 */ SDLK_UNKNOWN, - /* 168 */ SDLK_UNKNOWN, - /* 169 */ SDLK_UNKNOWN, - /* 170 */ SDLK_UNKNOWN, - /* 171 */ SDLK_UNKNOWN, - /* 172 */ SDLK_UNKNOWN, - /* 173 */ SDLK_UNKNOWN, - /* 174 */ SDLK_UNKNOWN, - /* 175 */ SDLK_UNKNOWN, - /* 176 */ SDLK_KP_00, - /* 177 */ SDLK_KP_000, - /* 178 */ SDLK_THOUSANDSSEPARATOR, - /* 179 */ SDLK_DECIMALSEPARATOR, - /* 180 */ SDLK_CURRENCYUNIT, - /* 181 */ SDLK_CURRENCYSUBUNIT, - /* 182 */ SDLK_KP_LEFTPAREN, - /* 183 */ SDLK_KP_RIGHTPAREN, - /* 184 */ SDLK_KP_LEFTBRACE, - /* 185 */ SDLK_KP_RIGHTBRACE, - /* 186 */ SDLK_KP_TAB, - /* 187 */ SDLK_KP_BACKSPACE, - /* 188 */ SDLK_KP_A, - /* 189 */ SDLK_KP_B, - /* 190 */ SDLK_KP_C, - /* 191 */ SDLK_KP_D, - /* 192 */ SDLK_KP_E, - /* 193 */ SDLK_KP_F, - /* 194 */ SDLK_KP_XOR, - /* 195 */ SDLK_KP_POWER, - /* 196 */ SDLK_KP_PERCENT, - /* 197 */ SDLK_KP_LESS, - /* 198 */ SDLK_KP_GREATER, - /* 199 */ SDLK_KP_AMPERSAND, - /* 200 */ SDLK_KP_DBLAMPERSAND, - /* 201 */ SDLK_KP_VERTICALBAR, - /* 202 */ SDLK_KP_DBLVERTICALBAR, - /* 203 */ SDLK_KP_COLON, - /* 204 */ SDLK_KP_HASH, - /* 205 */ SDLK_KP_SPACE, - /* 206 */ SDLK_KP_AT, - /* 207 */ SDLK_KP_EXCLAM, - /* 208 */ SDLK_KP_MEMSTORE, - /* 209 */ SDLK_KP_MEMRECALL, - /* 210 */ SDLK_KP_MEMCLEAR, - /* 211 */ SDLK_KP_MEMADD, - /* 212 */ SDLK_KP_MEMSUBTRACT, - /* 213 */ SDLK_KP_MEMMULTIPLY, - /* 214 */ SDLK_KP_MEMDIVIDE, - /* 215 */ SDLK_KP_PLUSMINUS, - /* 216 */ SDLK_KP_CLEAR, - /* 217 */ SDLK_KP_CLEARENTRY, - /* 218 */ SDLK_KP_BINARY, - /* 219 */ SDLK_KP_OCTAL, - /* 220 */ SDLK_KP_DECIMAL, - /* 221 */ SDLK_KP_HEXADECIMAL, - /* 222 */ SDLK_UNKNOWN, - /* 223 */ SDLK_UNKNOWN, - /* 224 */ SDLK_LCTRL, - /* 225 */ SDLK_LSHIFT, - /* 226 */ SDLK_LALT, - /* 227 */ SDLK_LGUI, - /* 228 */ SDLK_RCTRL, - /* 229 */ SDLK_RSHIFT, - /* 230 */ SDLK_RALT, - /* 231 */ SDLK_RGUI, - /* 232 */ SDLK_UNKNOWN, - /* 233 */ SDLK_UNKNOWN, - /* 234 */ SDLK_UNKNOWN, - /* 235 */ SDLK_UNKNOWN, - /* 236 */ SDLK_UNKNOWN, - /* 237 */ SDLK_UNKNOWN, - /* 238 */ SDLK_UNKNOWN, - /* 239 */ SDLK_UNKNOWN, - /* 240 */ SDLK_UNKNOWN, - /* 241 */ SDLK_UNKNOWN, - /* 242 */ SDLK_UNKNOWN, - /* 243 */ SDLK_UNKNOWN, - /* 244 */ SDLK_UNKNOWN, - /* 245 */ SDLK_UNKNOWN, - /* 246 */ SDLK_UNKNOWN, - /* 247 */ SDLK_UNKNOWN, - /* 248 */ SDLK_UNKNOWN, - /* 249 */ SDLK_UNKNOWN, - /* 250 */ SDLK_UNKNOWN, - /* 251 */ SDLK_UNKNOWN, - /* 252 */ SDLK_UNKNOWN, - /* 253 */ SDLK_UNKNOWN, - /* 254 */ SDLK_UNKNOWN, - /* 255 */ SDLK_UNKNOWN, - /* 256 */ SDLK_UNKNOWN, - /* 257 */ SDLK_MODE, - /* 258 */ SDLK_AUDIONEXT, - /* 259 */ SDLK_AUDIOPREV, - /* 260 */ SDLK_AUDIOSTOP, - /* 261 */ SDLK_AUDIOPLAY, - /* 262 */ SDLK_AUDIOMUTE, - /* 263 */ SDLK_MEDIASELECT, - /* 264 */ SDLK_WWW, - /* 265 */ SDLK_MAIL, - /* 266 */ SDLK_CALCULATOR, - /* 267 */ SDLK_COMPUTER, - /* 268 */ SDLK_AC_SEARCH, - /* 269 */ SDLK_AC_HOME, - /* 270 */ SDLK_AC_BACK, - /* 271 */ SDLK_AC_FORWARD, - /* 272 */ SDLK_AC_STOP, - /* 273 */ SDLK_AC_REFRESH, - /* 274 */ SDLK_AC_BOOKMARKS, - /* 275 */ SDLK_BRIGHTNESSDOWN, - /* 276 */ SDLK_BRIGHTNESSUP, - /* 277 */ SDLK_DISPLAYSWITCH, - /* 278 */ SDLK_KBDILLUMTOGGLE, - /* 279 */ SDLK_KBDILLUMDOWN, - /* 280 */ SDLK_KBDILLUMUP, - /* 281 */ SDLK_EJECT, - /* 282 */ SDLK_SLEEP, - /* 283 */ SDLK_APP1, - /* 284 */ SDLK_APP2, - /* 285 */ SDLK_AUDIOREWIND, - /* 286 */ SDLK_AUDIOFASTFORWARD, - /* 287 */ SDLK_SOFTLEFT, - /* 288 */ SDLK_SOFTRIGHT, - /* 289 */ SDLK_CALL, - /* 290 */ SDLK_ENDCALL, -}; - -static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = { - /* 0 */ NULL, - /* 1 */ NULL, - /* 2 */ NULL, - /* 3 */ NULL, - /* 4 */ "A", - /* 5 */ "B", - /* 6 */ "C", - /* 7 */ "D", - /* 8 */ "E", - /* 9 */ "F", - /* 10 */ "G", - /* 11 */ "H", - /* 12 */ "I", - /* 13 */ "J", - /* 14 */ "K", - /* 15 */ "L", - /* 16 */ "M", - /* 17 */ "N", - /* 18 */ "O", - /* 19 */ "P", - /* 20 */ "Q", - /* 21 */ "R", - /* 22 */ "S", - /* 23 */ "T", - /* 24 */ "U", - /* 25 */ "V", - /* 26 */ "W", - /* 27 */ "X", - /* 28 */ "Y", - /* 29 */ "Z", - /* 30 */ "1", - /* 31 */ "2", - /* 32 */ "3", - /* 33 */ "4", - /* 34 */ "5", - /* 35 */ "6", - /* 36 */ "7", - /* 37 */ "8", - /* 38 */ "9", - /* 39 */ "0", - /* 40 */ "Return", - /* 41 */ "Escape", - /* 42 */ "Backspace", - /* 43 */ "Tab", - /* 44 */ "Space", - /* 45 */ "-", - /* 46 */ "=", - /* 47 */ "[", - /* 48 */ "]", - /* 49 */ "\\", - /* 50 */ "#", - /* 51 */ ";", - /* 52 */ "'", - /* 53 */ "`", - /* 54 */ ",", - /* 55 */ ".", - /* 56 */ "/", - /* 57 */ "CapsLock", - /* 58 */ "F1", - /* 59 */ "F2", - /* 60 */ "F3", - /* 61 */ "F4", - /* 62 */ "F5", - /* 63 */ "F6", - /* 64 */ "F7", - /* 65 */ "F8", - /* 66 */ "F9", - /* 67 */ "F10", - /* 68 */ "F11", - /* 69 */ "F12", - /* 70 */ "PrintScreen", - /* 71 */ "ScrollLock", - /* 72 */ "Pause", - /* 73 */ "Insert", - /* 74 */ "Home", - /* 75 */ "PageUp", - /* 76 */ "Delete", - /* 77 */ "End", - /* 78 */ "PageDown", - /* 79 */ "Right", - /* 80 */ "Left", - /* 81 */ "Down", - /* 82 */ "Up", - /* 83 */ "Numlock", - /* 84 */ "Keypad /", - /* 85 */ "Keypad *", - /* 86 */ "Keypad -", - /* 87 */ "Keypad +", - /* 88 */ "Keypad Enter", - /* 89 */ "Keypad 1", - /* 90 */ "Keypad 2", - /* 91 */ "Keypad 3", - /* 92 */ "Keypad 4", - /* 93 */ "Keypad 5", - /* 94 */ "Keypad 6", - /* 95 */ "Keypad 7", - /* 96 */ "Keypad 8", - /* 97 */ "Keypad 9", - /* 98 */ "Keypad 0", - /* 99 */ "Keypad .", - /* 100 */ NULL, - /* 101 */ "Application", - /* 102 */ "Power", - /* 103 */ "Keypad =", - /* 104 */ "F13", - /* 105 */ "F14", - /* 106 */ "F15", - /* 107 */ "F16", - /* 108 */ "F17", - /* 109 */ "F18", - /* 110 */ "F19", - /* 111 */ "F20", - /* 112 */ "F21", - /* 113 */ "F22", - /* 114 */ "F23", - /* 115 */ "F24", - /* 116 */ "Execute", - /* 117 */ "Help", - /* 118 */ "Menu", - /* 119 */ "Select", - /* 120 */ "Stop", - /* 121 */ "Again", - /* 122 */ "Undo", - /* 123 */ "Cut", - /* 124 */ "Copy", - /* 125 */ "Paste", - /* 126 */ "Find", - /* 127 */ "Mute", - /* 128 */ "VolumeUp", - /* 129 */ "VolumeDown", - /* 130 */ NULL, - /* 131 */ NULL, - /* 132 */ NULL, - /* 133 */ "Keypad ,", - /* 134 */ "Keypad = (AS400)", - /* 135 */ NULL, - /* 136 */ NULL, - /* 137 */ NULL, - /* 138 */ NULL, - /* 139 */ NULL, - /* 140 */ NULL, - /* 141 */ NULL, - /* 142 */ NULL, - /* 143 */ NULL, - /* 144 */ NULL, - /* 145 */ NULL, - /* 146 */ NULL, - /* 147 */ NULL, - /* 148 */ NULL, - /* 149 */ NULL, - /* 150 */ NULL, - /* 151 */ NULL, - /* 152 */ NULL, - /* 153 */ "AltErase", - /* 154 */ "SysReq", - /* 155 */ "Cancel", - /* 156 */ "Clear", - /* 157 */ "Prior", - /* 158 */ "Return", - /* 159 */ "Separator", - /* 160 */ "Out", - /* 161 */ "Oper", - /* 162 */ "Clear / Again", - /* 163 */ "CrSel", - /* 164 */ "ExSel", - /* 165 */ NULL, - /* 166 */ NULL, - /* 167 */ NULL, - /* 168 */ NULL, - /* 169 */ NULL, - /* 170 */ NULL, - /* 171 */ NULL, - /* 172 */ NULL, - /* 173 */ NULL, - /* 174 */ NULL, - /* 175 */ NULL, - /* 176 */ "Keypad 00", - /* 177 */ "Keypad 000", - /* 178 */ "ThousandsSeparator", - /* 179 */ "DecimalSeparator", - /* 180 */ "CurrencyUnit", - /* 181 */ "CurrencySubUnit", - /* 182 */ "Keypad (", - /* 183 */ "Keypad )", - /* 184 */ "Keypad {", - /* 185 */ "Keypad }", - /* 186 */ "Keypad Tab", - /* 187 */ "Keypad Backspace", - /* 188 */ "Keypad A", - /* 189 */ "Keypad B", - /* 190 */ "Keypad C", - /* 191 */ "Keypad D", - /* 192 */ "Keypad E", - /* 193 */ "Keypad F", - /* 194 */ "Keypad XOR", - /* 195 */ "Keypad ^", - /* 196 */ "Keypad %", - /* 197 */ "Keypad <", - /* 198 */ "Keypad >", - /* 199 */ "Keypad &", - /* 200 */ "Keypad &&", - /* 201 */ "Keypad |", - /* 202 */ "Keypad ||", - /* 203 */ "Keypad :", - /* 204 */ "Keypad #", - /* 205 */ "Keypad Space", - /* 206 */ "Keypad @", - /* 207 */ "Keypad !", - /* 208 */ "Keypad MemStore", - /* 209 */ "Keypad MemRecall", - /* 210 */ "Keypad MemClear", - /* 211 */ "Keypad MemAdd", - /* 212 */ "Keypad MemSubtract", - /* 213 */ "Keypad MemMultiply", - /* 214 */ "Keypad MemDivide", - /* 215 */ "Keypad +/-", - /* 216 */ "Keypad Clear", - /* 217 */ "Keypad ClearEntry", - /* 218 */ "Keypad Binary", - /* 219 */ "Keypad Octal", - /* 220 */ "Keypad Decimal", - /* 221 */ "Keypad Hexadecimal", - /* 222 */ NULL, - /* 223 */ NULL, - /* 224 */ "Left Ctrl", - /* 225 */ "Left Shift", - /* 226 */ "Left Alt", - /* 227 */ "Left GUI", - /* 228 */ "Right Ctrl", - /* 229 */ "Right Shift", - /* 230 */ "Right Alt", - /* 231 */ "Right GUI", - /* 232 */ NULL, - /* 233 */ NULL, - /* 234 */ NULL, - /* 235 */ NULL, - /* 236 */ NULL, - /* 237 */ NULL, - /* 238 */ NULL, - /* 239 */ NULL, - /* 240 */ NULL, - /* 241 */ NULL, - /* 242 */ NULL, - /* 243 */ NULL, - /* 244 */ NULL, - /* 245 */ NULL, - /* 246 */ NULL, - /* 247 */ NULL, - /* 248 */ NULL, - /* 249 */ NULL, - /* 250 */ NULL, - /* 251 */ NULL, - /* 252 */ NULL, - /* 253 */ NULL, - /* 254 */ NULL, - /* 255 */ NULL, - /* 256 */ NULL, - /* 257 */ "ModeSwitch", - /* 258 */ "AudioNext", - /* 259 */ "AudioPrev", - /* 260 */ "AudioStop", - /* 261 */ "AudioPlay", - /* 262 */ "AudioMute", - /* 263 */ "MediaSelect", - /* 264 */ "WWW", - /* 265 */ "Mail", - /* 266 */ "Calculator", - /* 267 */ "Computer", - /* 268 */ "AC Search", - /* 269 */ "AC Home", - /* 270 */ "AC Back", - /* 271 */ "AC Forward", - /* 272 */ "AC Stop", - /* 273 */ "AC Refresh", - /* 274 */ "AC Bookmarks", - /* 275 */ "BrightnessDown", - /* 276 */ "BrightnessUp", - /* 277 */ "DisplaySwitch", - /* 278 */ "KBDIllumToggle", - /* 279 */ "KBDIllumDown", - /* 280 */ "KBDIllumUp", - /* 281 */ "Eject", - /* 282 */ "Sleep", - /* 283 */ "App1", - /* 284 */ "App2", - /* 285 */ "AudioRewind", - /* 286 */ "AudioFastForward", - /* 287 */ "SoftLeft", - /* 288 */ "SoftRight", - /* 289 */ "Call", - /* 290 */ "EndCall", -}; - -/* Taken from SDL_iconv() */ -char *SDL_UCS4ToUTF8(Uint32 ch, char *dst) +static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { - Uint8 *p = (Uint8 *)dst; - if (ch <= 0x7F) { - *p = (Uint8)ch; - ++dst; - } else if (ch <= 0x7FF) { - p[0] = 0xC0 | (Uint8)((ch >> 6) & 0x1F); - p[1] = 0x80 | (Uint8)(ch & 0x3F); - dst += 2; - } else if (ch <= 0xFFFF) { - p[0] = 0xE0 | (Uint8)((ch >> 12) & 0x0F); - p[1] = 0x80 | (Uint8)((ch >> 6) & 0x3F); - p[2] = 0x80 | (Uint8)(ch & 0x3F); - dst += 3; + SDL_Keyboard *keyboard = (SDL_Keyboard *)userdata; + + if (hint && *hint) { + keyboard->keycode_options = 0; + if (!SDL_strstr(hint, "none")) { + if (SDL_strstr(hint, "hide_numpad")) { + keyboard->keycode_options |= KEYCODE_OPTION_HIDE_NUMPAD; + } + if (SDL_strstr(hint, "french_numbers")) { + keyboard->keycode_options |= KEYCODE_OPTION_FRENCH_NUMBERS; + } + if (SDL_strstr(hint, "latin_letters")) { + keyboard->keycode_options |= KEYCODE_OPTION_LATIN_LETTERS; + } + } } else { - p[0] = 0xF0 | (Uint8)((ch >> 18) & 0x07); - p[1] = 0x80 | (Uint8)((ch >> 12) & 0x3F); - p[2] = 0x80 | (Uint8)((ch >> 6) & 0x3F); - p[3] = 0x80 | (Uint8)(ch & 0x3F); - dst += 4; + keyboard->keycode_options = DEFAULT_KEYCODE_OPTIONS; } - return dst; } -/* Public functions */ -int SDL_InitKeyboard(void) +// Public functions +bool SDL_InitKeyboard(void) { - /* Set the default keymap */ - SDL_SetKeymap(0, SDL_default_keymap, SDL_NUM_SCANCODES, SDL_FALSE); - return 0; + SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS, + SDL_KeycodeOptionsChanged, &SDL_keyboard); + return true; } -SDL_bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys) +bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys) { const int REAL_KEYBOARD_KEY_COUNT = 50; if (num_keys > 0 && num_keys < REAL_KEYBOARD_KEY_COUNT) { - return SDL_FALSE; + return false; } - /* Eventually we'll have a blacklist of devices that enumerate as keyboards but aren't really */ - return SDL_TRUE; + // Eventually we'll have a blacklist of devices that enumerate as keyboards but aren't really + return true; } static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID) @@ -705,11 +120,11 @@ static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID) return -1; } -void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, SDL_bool send_event) +void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, bool send_event) { int keyboard_index = SDL_GetKeyboardIndex(keyboardID); if (keyboard_index >= 0) { - /* We already know about this keyboard */ + // We already know about this keyboard return; } @@ -734,11 +149,11 @@ void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, SDL_bool send_ } } -void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID) +void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, bool send_event) { int keyboard_index = SDL_GetKeyboardIndex(keyboardID); if (keyboard_index < 0) { - /* We don't know about this keyboard */ + // We don't know about this keyboard return; } @@ -749,14 +164,16 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID) } --SDL_keyboard_count; - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_KEYBOARD_REMOVED; - event.kdevice.which = keyboardID; - SDL_PushEvent(&event); + if (send_event) { + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_KEYBOARD_REMOVED; + event.kdevice.which = keyboardID; + SDL_PushEvent(&event); + } } -SDL_bool SDL_HasKeyboard(void) +bool SDL_HasKeyboard(void) { return (SDL_keyboard_count > 0); } @@ -785,95 +202,113 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count) return keyboards; } -const char *SDL_GetKeyboardInstanceName(SDL_KeyboardID instance_id) +const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id) { int keyboard_index = SDL_GetKeyboardIndex(instance_id); if (keyboard_index < 0) { return NULL; } - return SDL_keyboards[keyboard_index].name; + return SDL_GetPersistentString(SDL_keyboards[keyboard_index].name); } void SDL_ResetKeyboard(void) { SDL_Keyboard *keyboard = &SDL_keyboard; - SDL_Scancode scancode; + int scancode; #ifdef DEBUG_KEYBOARD printf("Resetting keyboard\n"); #endif - for (scancode = (SDL_Scancode)0; scancode < SDL_NUM_SCANCODES; ++scancode) { - if (keyboard->keystate[scancode] == SDL_PRESSED) { - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scancode); + for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) { + if (keyboard->keystate[scancode]) { + SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false); } } } -void SDL_GetDefaultKeymap(SDL_Keycode *keymap) -{ - SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap)); -} - -void SDL_SetKeymap(int start, const SDL_Keycode *keys, int length, SDL_bool send_event) +SDL_Keymap *SDL_GetCurrentKeymap(void) { SDL_Keyboard *keyboard = &SDL_keyboard; - SDL_Scancode scancode; - SDL_Keycode normalized_keymap[SDL_NUM_SCANCODES]; - SDL_bool is_azerty = SDL_FALSE; - if (start < 0 || start + length > SDL_NUM_SCANCODES) { - return; + if (keyboard->thai_keyboard) { + // Thai keyboards are QWERTY plus Thai characters, use the default QWERTY keymap + return NULL; } - if (start > 0) { - SDL_memcpy(&normalized_keymap[0], &keyboard->keymap[0], sizeof(*keys) * start); + if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) && + !keyboard->latin_letters) { + // We'll use the default QWERTY keymap + return NULL; } - SDL_memcpy(&normalized_keymap[start], keys, sizeof(*keys) * length); + return keyboard->keymap; +} + +void SDL_SetKeymap(SDL_Keymap *keymap, bool send_event) +{ + SDL_Keyboard *keyboard = &SDL_keyboard; - if (start + length < SDL_NUM_SCANCODES) { - int offset = start + length; - SDL_memcpy(&normalized_keymap[offset], &keyboard->keymap[offset], sizeof(*keys) * (SDL_NUM_SCANCODES - offset)); + if (keyboard->keymap) { + SDL_DestroyKeymap(keyboard->keymap); } - /* On AZERTY layouts the number keys are technically symbols, but users (and games) - * always think of them and view them in UI as number keys, so remap them here. - */ - if (normalized_keymap[SDL_SCANCODE_0] < SDLK_0 || normalized_keymap[SDL_SCANCODE_0] > SDLK_9) { - is_azerty = SDL_TRUE; - for (scancode = SDL_SCANCODE_1; scancode <= SDL_SCANCODE_9; ++scancode) { - if (normalized_keymap[scancode] >= SDLK_0 && normalized_keymap[scancode] <= SDLK_9) { - /* There's a number on this row, it's not AZERTY */ - is_azerty = SDL_FALSE; - break; - } + keyboard->keymap = keymap; + + // Detect French number row (all symbols) + keyboard->french_numbers = true; + for (int i = SDL_SCANCODE_1; i <= SDL_SCANCODE_0; ++i) { + if (SDL_isdigit(SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE)) || + !SDL_isdigit(SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_SHIFT))) { + keyboard->french_numbers = false; + break; } } - if (is_azerty) { - normalized_keymap[SDL_SCANCODE_0] = SDLK_0; - for (scancode = SDL_SCANCODE_1; scancode <= SDL_SCANCODE_9; ++scancode) { - normalized_keymap[scancode] = SDLK_1 + (scancode - SDL_SCANCODE_1); + + // Detect non-Latin keymap + keyboard->thai_keyboard = false; + keyboard->latin_letters = false; + for (int i = SDL_SCANCODE_A; i <= SDL_SCANCODE_D; ++i) { + SDL_Keycode key = SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE); + if (key <= 0xFF) { + keyboard->latin_letters = true; + break; } - } - /* If the mapping didn't really change, we're done here */ - if (!SDL_memcmp(&keyboard->keymap[start], &normalized_keymap[start], sizeof(*keys) * length)) { - return; + if (key >= 0x0E00 && key <= 0x0E7F) { + keyboard->thai_keyboard = true; + break; + } } - SDL_memcpy(&keyboard->keymap[start], &normalized_keymap[start], sizeof(*keys) * length); - if (send_event) { SDL_SendKeymapChangedEvent(); } } -void SDL_SetScancodeName(SDL_Scancode scancode, const char *name) +static SDL_Scancode GetNextReservedScancode(void) { - if (scancode >= SDL_NUM_SCANCODES) { - return; + SDL_Keyboard *keyboard = &SDL_keyboard; + SDL_Scancode scancode; + + if (keyboard->next_reserved_scancode && keyboard->next_reserved_scancode < SDL_SCANCODE_RESERVED + 100) { + scancode = (SDL_Scancode)keyboard->next_reserved_scancode; + } else { + scancode = SDL_SCANCODE_RESERVED; } - SDL_scancode_names[scancode] = name; + keyboard->next_reserved_scancode = (int)scancode + 1; + + return scancode; +} + +static void SetKeymapEntry(SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode) +{ + SDL_Keyboard *keyboard = &SDL_keyboard; + + if (!keyboard->keymap) { + keyboard->keymap = SDL_CreateKeymap(); + } + + SDL_SetKeymapEntry(keyboard->keymap, scancode, modstate, keycode); } SDL_Window *SDL_GetKeyboardFocus(void) @@ -883,41 +318,30 @@ SDL_Window *SDL_GetKeyboardFocus(void) return keyboard->focus; } -int SDL_SetKeyboardFocus(SDL_Window *window) +bool SDL_SetKeyboardFocus(SDL_Window *window) { SDL_VideoDevice *video = SDL_GetVideoDevice(); SDL_Keyboard *keyboard = &SDL_keyboard; if (window) { - if (!video || window->magic != &video->window_magic || window->is_destroying) { + if (!SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW) || window->is_destroying) { return SDL_SetError("Invalid window"); } } if (keyboard->focus && !window) { - /* We won't get anymore keyboard messages, so reset keyboard state */ + // We won't get anymore keyboard messages, so reset keyboard state SDL_ResetKeyboard(); } - /* See if the current window has lost focus */ + // See if the current window has lost focus if (keyboard->focus && keyboard->focus != window) { - - /* new window shouldn't think it has mouse captured. */ - SDL_assert(window == NULL || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)); - - /* old window must lose an existing mouse capture. */ - if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) { - SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */ - SDL_UpdateMouseCapture(SDL_TRUE); - SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE)); - } - SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0); - /* Ensures IME compositions are committed */ - if (SDL_TextInputActive()) { + // Ensures IME compositions are committed + if (SDL_TextInputActive(keyboard->focus)) { if (video && video->StopTextInput) { - video->StopTextInput(video); + video->StopTextInput(video, keyboard->focus); } } } @@ -927,78 +351,203 @@ int SDL_SetKeyboardFocus(SDL_Window *window) if (keyboard->focus) { SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0); - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(keyboard->focus)) { if (video && video->StartTextInput) { - video->StartTextInput(video); + video->StartTextInput(video, keyboard->focus, keyboard->focus->text_input_props); } } } - return 0; + + SDL_UpdateRelativeMouseMode(); + + return true; +} + +static SDL_Keycode SDL_ConvertNumpadKeycode(SDL_Keycode keycode, bool numlock) +{ + switch (keycode) { + case SDLK_KP_DIVIDE: + return SDLK_SLASH; + case SDLK_KP_MULTIPLY: + return SDLK_ASTERISK; + case SDLK_KP_MINUS: + return SDLK_MINUS; + case SDLK_KP_PLUS: + return SDLK_PLUS; + case SDLK_KP_ENTER: + return SDLK_RETURN; + case SDLK_KP_1: + return numlock ? SDLK_1 : SDLK_END; + case SDLK_KP_2: + return numlock ? SDLK_2 : SDLK_DOWN; + case SDLK_KP_3: + return numlock ? SDLK_3 : SDLK_PAGEDOWN; + case SDLK_KP_4: + return numlock ? SDLK_4 : SDLK_LEFT; + case SDLK_KP_5: + return numlock ? SDLK_5 : SDLK_CLEAR; + case SDLK_KP_6: + return numlock ? SDLK_6 : SDLK_RIGHT; + case SDLK_KP_7: + return numlock ? SDLK_7 : SDLK_HOME; + case SDLK_KP_8: + return numlock ? SDLK_8 : SDLK_UP; + case SDLK_KP_9: + return numlock ? SDLK_9 : SDLK_PAGEUP; + case SDLK_KP_0: + return numlock ? SDLK_0 : SDLK_INSERT; + case SDLK_KP_PERIOD: + return numlock ? SDLK_PERIOD : SDLK_DELETE; + case SDLK_KP_EQUALS: + return SDLK_EQUALS; + case SDLK_KP_COMMA: + return SDLK_COMMA; + case SDLK_KP_EQUALSAS400: + return SDLK_EQUALS; + case SDLK_KP_LEFTPAREN: + return SDLK_LEFTPAREN; + case SDLK_KP_RIGHTPAREN: + return SDLK_RIGHTPAREN; + case SDLK_KP_LEFTBRACE: + return SDLK_LEFTBRACE; + case SDLK_KP_RIGHTBRACE: + return SDLK_RIGHTBRACE; + case SDLK_KP_TAB: + return SDLK_TAB; + case SDLK_KP_BACKSPACE: + return SDLK_BACKSPACE; + case SDLK_KP_A: + return SDLK_A; + case SDLK_KP_B: + return SDLK_B; + case SDLK_KP_C: + return SDLK_C; + case SDLK_KP_D: + return SDLK_D; + case SDLK_KP_E: + return SDLK_E; + case SDLK_KP_F: + return SDLK_F; + case SDLK_KP_PERCENT: + return SDLK_PERCENT; + case SDLK_KP_LESS: + return SDLK_LESS; + case SDLK_KP_GREATER: + return SDLK_GREATER; + case SDLK_KP_AMPERSAND: + return SDLK_AMPERSAND; + case SDLK_KP_COLON: + return SDLK_COLON; + case SDLK_KP_HASH: + return SDLK_HASH; + case SDLK_KP_SPACE: + return SDLK_SPACE; + case SDLK_KP_AT: + return SDLK_AT; + case SDLK_KP_EXCLAM: + return SDLK_EXCLAIM; + case SDLK_KP_PLUSMINUS: + return SDLK_PLUSMINUS; + default: + return keycode; + } } -static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) +SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate, bool key_event) { SDL_Keyboard *keyboard = &SDL_keyboard; - int posted; - SDL_Keymod modifier; - Uint32 type; - Uint8 repeat = SDL_FALSE; - const Uint8 source = flags & KEYBOARD_SOURCE_MASK; - if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { - return 0; + if (key_event) { + SDL_Keymap *keymap = SDL_GetCurrentKeymap(); + bool numlock = (modstate & SDL_KMOD_NUM) != 0; + SDL_Keycode keycode; + + // We won't be applying any modifiers by default + modstate = SDL_KMOD_NONE; + + if ((keyboard->keycode_options & KEYCODE_OPTION_FRENCH_NUMBERS) && + keyboard->french_numbers && + (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0)) { + // Add the shift state to generate a numeric keycode + modstate |= SDL_KMOD_SHIFT; + } + + keycode = SDL_GetKeymapKeycode(keymap, scancode, modstate); + + if (keyboard->keycode_options & KEYCODE_OPTION_HIDE_NUMPAD) { + keycode = SDL_ConvertNumpadKeycode(keycode, numlock); + } + return keycode; } + return SDL_GetKeymapKeycode(keyboard->keymap, scancode, modstate); +} + +SDL_Scancode SDL_GetScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate) +{ + SDL_Keyboard *keyboard = &SDL_keyboard; + + return SDL_GetKeymapScancode(keyboard->keymap, key, modstate); +} + +static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down) +{ + SDL_Keyboard *keyboard = &SDL_keyboard; + bool posted = false; + SDL_Keycode keycode = SDLK_UNKNOWN; + Uint32 type; + bool repeat = false; + const Uint8 source = flags & KEYBOARD_SOURCE_MASK; + #ifdef DEBUG_KEYBOARD - printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode), - state == SDL_PRESSED ? "pressed" : "released"); + printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode), down ? "pressed" : "released"); #endif - /* Figure out what type of event this is */ - switch (state) { - case SDL_PRESSED: + // Figure out what type of event this is + if (down) { type = SDL_EVENT_KEY_DOWN; - break; - case SDL_RELEASED: + } else { type = SDL_EVENT_KEY_UP; - break; - default: - /* Invalid state -- bail */ - return 0; } - /* Drop events that don't change state */ - if (state) { - if (keyboard->keystate[scancode]) { - if (!(keyboard->keysource[scancode] & source)) { - keyboard->keysource[scancode] |= source; - return 0; + if (scancode > SDL_SCANCODE_UNKNOWN && scancode < SDL_SCANCODE_COUNT) { + // Drop events that don't change state + if (down) { + if (keyboard->keystate[scancode]) { + if (!(keyboard->keysource[scancode] & source)) { + keyboard->keysource[scancode] |= source; + return false; + } + repeat = true; } - repeat = SDL_TRUE; - } - keyboard->keysource[scancode] |= source; - } else { - if (!keyboard->keystate[scancode]) { - return 0; + keyboard->keysource[scancode] |= source; + } else { + if (!keyboard->keystate[scancode]) { + return false; + } + keyboard->keysource[scancode] = 0; } - keyboard->keysource[scancode] = 0; - } - /* Update internal keyboard state */ - keyboard->keystate[scancode] = state; + // Update internal keyboard state + keyboard->keystate[scancode] = down; + + keycode = SDL_GetKeyFromScancode(scancode, keyboard->modstate, true); - if (keycode == SDLK_UNKNOWN) { - keycode = keyboard->keymap[scancode]; + } else if (rawcode == 0) { + // Nothing to do! + return false; } if (source == KEYBOARD_HARDWARE) { keyboard->hardware_timestamp = SDL_GetTicks(); } else if (source == KEYBOARD_AUTORELEASE) { - keyboard->autorelease_pending = SDL_TRUE; + keyboard->autorelease_pending = true; } - /* Update modifiers state if applicable */ - if (!(flags & KEYBOARD_IGNOREMODIFIERS)) { + // Update modifiers state if applicable + if (!(flags & KEYBOARD_IGNOREMODIFIERS) && !repeat) { + SDL_Keymod modifier; + switch (keycode) { case SDLK_LCTRL: modifier = SDL_KMOD_LCTRL; @@ -1051,32 +600,31 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keybo } } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(type)) { SDL_Event event; event.type = type; event.common.timestamp = timestamp; - event.key.state = state; + event.key.scancode = scancode; + event.key.key = keycode; + event.key.mod = keyboard->modstate; + event.key.raw = (Uint16)rawcode; + event.key.down = down; event.key.repeat = repeat; - event.key.keysym.scancode = scancode; - event.key.keysym.sym = keycode; - event.key.keysym.mod = keyboard->modstate; event.key.windowID = keyboard->focus ? keyboard->focus->id : 0; event.key.which = keyboardID; - posted = (SDL_PushEvent(&event) > 0); + posted = SDL_PushEvent(&event); } /* If the keyboard is grabbed and the grabbed window is in full-screen, minimize the window when we receive Alt+Tab, unless the application has explicitly opted out of this behavior. */ - if (keycode == SDLK_TAB && - state == SDL_PRESSED && + if (keycode == SDLK_TAB && down && (keyboard->modstate & SDL_KMOD_ALT) && keyboard->focus && (keyboard->focus->flags & SDL_WINDOW_KEYBOARD_GRABBED) && (keyboard->focus->flags & SDL_WINDOW_FULLSCREEN) && - SDL_GetHintBoolean(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, SDL_TRUE)) { + SDL_GetHintBoolean(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, true)) { /* We will temporarily forfeit our grab by minimizing our window, allowing the user to escape the application */ SDL_MinimizeWindow(keyboard->focus); @@ -1085,146 +633,138 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keybo return posted; } -int SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch) +void SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch) { - SDL_Scancode code = SDL_SCANCODE_UNKNOWN; - uint16_t mod = 0; + SDL_Keyboard *keyboard = &SDL_keyboard; + SDL_Keymod modstate = SDL_KMOD_NONE; + SDL_Scancode scancode = SDL_GetKeymapScancode(keyboard->keymap, ch, &modstate); - if (ch < SDL_arraysize(SDL_ASCIIKeyInfoTable)) { - code = SDL_ASCIIKeyInfoTable[ch].code; - mod = SDL_ASCIIKeyInfoTable[ch].mod; + // Make sure we have this keycode in our keymap + if (scancode == SDL_SCANCODE_UNKNOWN && ch < SDLK_SCANCODE_MASK) { + scancode = GetNextReservedScancode(); + SetKeymapEntry(scancode, modstate, ch); } - if (mod & SDL_KMOD_SHIFT) { - /* If the character uses shift, press shift down */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); + if (modstate & SDL_KMOD_SHIFT) { + // If the character uses shift, press shift down + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_LSHIFT, true); } - /* Send a keydown and keyup for the character */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, code, SDLK_UNKNOWN); - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, code, SDLK_UNKNOWN); + // Send a keydown and keyup for the character + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true); + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false); - if (mod & SDL_KMOD_SHIFT) { - /* If the character uses shift, release shift */ - SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN); + if (modstate & SDL_KMOD_SHIFT) { + // If the character uses shift, release shift + SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, 0, SDL_SCANCODE_LSHIFT, false); } - return 0; } -int SDL_SendVirtualKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode) +bool SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_GLOBAL_KEYBOARD_ID, state, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, rawcode, scancode, down); } -int SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode) +bool SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, SDL_Keycode keycode, bool down) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, SDLK_UNKNOWN); -} + if (down) { + // Make sure we have this keycode in our keymap + SetKeymapEntry(scancode, SDL_GetModState(), keycode); + } -int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode) -{ - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, keycode); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, rawcode, scancode, down); } -int SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode) +bool SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, keyboardID, rawcode, scancode, down); } -int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode) +bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode) { - return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, keyboardID, state, scancode, SDLK_UNKNOWN); + return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false); } void SDL_ReleaseAutoReleaseKeys(void) { SDL_Keyboard *keyboard = &SDL_keyboard; - SDL_Scancode scancode; + int scancode; if (keyboard->autorelease_pending) { - for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) { + for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) { if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) { - SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scancode, SDLK_UNKNOWN); + SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false); } } - keyboard->autorelease_pending = SDL_FALSE; + keyboard->autorelease_pending = false; } if (keyboard->hardware_timestamp) { - /* Keep hardware keyboard "active" for 250 ms */ + // Keep hardware keyboard "active" for 250 ms if (SDL_GetTicks() >= keyboard->hardware_timestamp + 250) { keyboard->hardware_timestamp = 0; } } } -SDL_bool SDL_HardwareKeyboardKeyPressed(void) +bool SDL_HardwareKeyboardKeyPressed(void) { SDL_Keyboard *keyboard = &SDL_keyboard; - SDL_Scancode scancode; + int scancode; - for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) { + for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_SCANCODE_COUNT; ++scancode) { if (keyboard->keysource[scancode] & KEYBOARD_HARDWARE) { - return SDL_TRUE; + return true; } } - return keyboard->hardware_timestamp ? SDL_TRUE : SDL_FALSE; + return keyboard->hardware_timestamp ? true : false; } -int SDL_SendKeyboardText(const char *text) +void SDL_SendKeyboardText(const char *text) { SDL_Keyboard *keyboard = &SDL_keyboard; - int posted; - if (!SDL_TextInputActive()) { - return 0; + if (!SDL_TextInputActive(keyboard->focus)) { + return; } if (!text || !*text) { - return 0; + return; } - /* Don't post text events for unprintable characters */ + // Don't post text events for unprintable characters if (SDL_iscntrl((unsigned char)*text)) { - return 0; + return; } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { SDL_Event event; event.type = SDL_EVENT_TEXT_INPUT; event.common.timestamp = 0; event.text.windowID = keyboard->focus ? keyboard->focus->id : 0; - - size_t size = SDL_strlen(text) + 1; - event.text.text = (char *)SDL_AllocateEventMemory(size); + event.text.text = SDL_CreateTemporaryString(text); if (!event.text.text) { - return 0; + return; } - SDL_memcpy(event.text.text, text, size); - - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } - return posted; } -int SDL_SendEditingText(const char *text, int start, int length) +void SDL_SendEditingText(const char *text, int start, int length) { SDL_Keyboard *keyboard = &SDL_keyboard; - int posted; - if (!SDL_TextInputActive()) { - return 0; + if (!SDL_TextInputActive(keyboard->focus)) { + return; } if (!text) { - return 0; + return; } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) { SDL_Event event; @@ -1233,219 +773,128 @@ int SDL_SendEditingText(const char *text, int start, int length) event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; event.edit.start = start; event.edit.length = length; - - size_t size = SDL_strlen(text) + 1; - event.edit.text = (char *)SDL_AllocateEventMemory(size); + event.edit.text = SDL_CreateTemporaryString(text); if (!event.edit.text) { - return 0; + return; } - SDL_memcpy(event.edit.text, text, size); - - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } - return posted; } -void SDL_QuitKeyboard(void) +static const char * const *CreateCandidatesForEvent(char **candidates, int num_candidates) { - SDL_keyboard_count = 0; - SDL_free(SDL_keyboards); - SDL_keyboards = NULL; -} + const char **event_candidates; + int i; + char *ptr; + size_t total_length = (num_candidates + 1) * sizeof(*event_candidates); -const Uint8 *SDL_GetKeyboardState(int *numkeys) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; + for (i = 0; i < num_candidates; ++i) { + size_t length = SDL_strlen(candidates[i]) + 1; - if (numkeys != (int *)0) { - *numkeys = SDL_NUM_SCANCODES; + total_length += length; } - return keyboard->keystate; -} - -SDL_Keymod SDL_GetModState(void) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; - - return (SDL_Keymod)keyboard->modstate; -} - -void SDL_SetModState(SDL_Keymod modstate) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; - - keyboard->modstate = modstate; -} -/* Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. */ -void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; - if (toggle) { - keyboard->modstate |= modstate; - } else { - keyboard->modstate &= ~modstate; + event_candidates = (const char **)SDL_AllocateTemporaryMemory(total_length); + if (!event_candidates) { + return NULL; } -} + ptr = (char *)(event_candidates + (num_candidates + 1)); -SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; + for (i = 0; i < num_candidates; ++i) { + size_t length = SDL_strlen(candidates[i]) + 1; - if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { - SDL_InvalidParamError("scancode"); - return 0; + event_candidates[i] = ptr; + SDL_memcpy(ptr, candidates[i], length); + ptr += length; } + event_candidates[i] = NULL; - return keyboard->keymap[scancode]; + return event_candidates; } -SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode) +void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int selected_candidate, bool horizontal) { - if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { - SDL_InvalidParamError("scancode"); - return 0; - } + SDL_Keyboard *keyboard = &SDL_keyboard; - return SDL_default_keymap[scancode]; -} + if (!SDL_TextInputActive(keyboard->focus)) { + return; + } -SDL_Scancode SDL_GetScancodeFromKey(SDL_Keycode key) -{ - SDL_Keyboard *keyboard = &SDL_keyboard; - SDL_Scancode scancode; + // Post the event, if desired + if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING_CANDIDATES)) { + SDL_Event event; - for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; - ++scancode) { - if (keyboard->keymap[scancode] == key) { - return scancode; + event.type = SDL_EVENT_TEXT_EDITING_CANDIDATES; + event.common.timestamp = 0; + event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0; + if (num_candidates > 0) { + const char * const *event_candidates = CreateCandidatesForEvent(candidates, num_candidates); + if (!event_candidates) { + return; + } + event.edit_candidates.candidates = event_candidates; + event.edit_candidates.num_candidates = num_candidates; + event.edit_candidates.selected_candidate = selected_candidate; + event.edit_candidates.horizontal = horizontal; + } else { + event.edit_candidates.candidates = NULL; + event.edit_candidates.num_candidates = 0; + event.edit_candidates.selected_candidate = -1; + event.edit_candidates.horizontal = false; } + SDL_PushEvent(&event); } - return SDL_SCANCODE_UNKNOWN; } -const char *SDL_GetScancodeName(SDL_Scancode scancode) +void SDL_QuitKeyboard(void) { - const char *name; - if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) { - SDL_InvalidParamError("scancode"); - return ""; + for (int i = SDL_keyboard_count; i--;) { + SDL_RemoveKeyboard(SDL_keyboards[i].instance_id, false); } + SDL_free(SDL_keyboards); + SDL_keyboards = NULL; - name = SDL_scancode_names[scancode]; - if (name) { - return name; + if (SDL_keyboard.keymap) { + SDL_DestroyKeymap(SDL_keyboard.keymap); + SDL_keyboard.keymap = NULL; } - return ""; + SDL_RemoveHintCallback(SDL_HINT_KEYCODE_OPTIONS, + SDL_KeycodeOptionsChanged, &SDL_keyboard); } -SDL_Scancode SDL_GetScancodeFromName(const char *name) +const bool *SDL_GetKeyboardState(int *numkeys) { - int i; - - if (!name || !*name) { - SDL_InvalidParamError("name"); - return SDL_SCANCODE_UNKNOWN; - } + SDL_Keyboard *keyboard = &SDL_keyboard; - for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) { - if (!SDL_scancode_names[i]) { - continue; - } - if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) { - return (SDL_Scancode)i; - } + if (numkeys != (int *)0) { + *numkeys = SDL_SCANCODE_COUNT; } - - SDL_InvalidParamError("name"); - return SDL_SCANCODE_UNKNOWN; + return keyboard->keystate; } -const char *SDL_GetKeyName(SDL_Keycode key) +SDL_Keymod SDL_GetModState(void) { - static char name[8]; - char *end; - - if (key & SDLK_SCANCODE_MASK) { - return SDL_GetScancodeName((SDL_Scancode)(key & ~SDLK_SCANCODE_MASK)); - } - - switch (key) { - case SDLK_RETURN: - return SDL_GetScancodeName(SDL_SCANCODE_RETURN); - case SDLK_ESCAPE: - return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE); - case SDLK_BACKSPACE: - return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE); - case SDLK_TAB: - return SDL_GetScancodeName(SDL_SCANCODE_TAB); - case SDLK_SPACE: - return SDL_GetScancodeName(SDL_SCANCODE_SPACE); - case SDLK_DELETE: - return SDL_GetScancodeName(SDL_SCANCODE_DELETE); - default: - /* Unaccented letter keys on latin keyboards are normally - labeled in upper case (and probably on others like Greek or - Cyrillic too, so if you happen to know for sure, please - adapt this). */ - if (key >= 'a' && key <= 'z') { - key -= 32; - } + SDL_Keyboard *keyboard = &SDL_keyboard; - end = SDL_UCS4ToUTF8((Uint32)key, name); - *end = '\0'; - return name; - } + return keyboard->modstate; } -SDL_Keycode SDL_GetKeyFromName(const char *name) +void SDL_SetModState(SDL_Keymod modstate) { - SDL_Keycode key; + SDL_Keyboard *keyboard = &SDL_keyboard; - /* Check input */ - if (!name) { - return SDLK_UNKNOWN; - } + keyboard->modstate = modstate; +} - /* If it's a single UTF-8 character, then that's the keycode itself */ - key = *(const unsigned char *)name; - if (key >= 0xF0) { - if (SDL_strlen(name) == 4) { - int i = 0; - key = (Uint16)(name[i] & 0x07) << 18; - key |= (Uint16)(name[++i] & 0x3F) << 12; - key |= (Uint16)(name[++i] & 0x3F) << 6; - key |= (Uint16)(name[++i] & 0x3F); - return key; - } - return SDLK_UNKNOWN; - } else if (key >= 0xE0) { - if (SDL_strlen(name) == 3) { - int i = 0; - key = (Uint16)(name[i] & 0x0F) << 12; - key |= (Uint16)(name[++i] & 0x3F) << 6; - key |= (Uint16)(name[++i] & 0x3F); - return key; - } - return SDLK_UNKNOWN; - } else if (key >= 0xC0) { - if (SDL_strlen(name) == 2) { - int i = 0; - key = (Uint16)(name[i] & 0x1F) << 6; - key |= (Uint16)(name[++i] & 0x3F); - return key; - } - return SDLK_UNKNOWN; +// Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. +void SDL_ToggleModState(SDL_Keymod modstate, bool toggle) +{ + SDL_Keyboard *keyboard = &SDL_keyboard; + if (toggle) { + keyboard->modstate |= modstate; } else { - if (SDL_strlen(name) == 1) { - if (key >= 'A' && key <= 'Z') { - key += 32; - } - return key; - } - - /* Get the scancode for this name, and the associated keycode */ - return SDL_default_keymap[SDL_GetScancodeFromName(name)]; + keyboard->modstate &= ~modstate; } } + diff --git a/libs/SDL3/src/events/SDL_keyboard_c.h b/libs/SDL3/src/events/SDL_keyboard_c.h index 323b139d1..4023822fa 100644 --- a/libs/SDL3/src/events/SDL_keyboard_c.h +++ b/libs/SDL3/src/events/SDL_keyboard_c.h @@ -23,78 +23,65 @@ #ifndef SDL_keyboard_c_h_ #define SDL_keyboard_c_h_ -/* Keyboard events not associated with a specific input device */ +#include "SDL_keymap_c.h" + +// Keyboard events not associated with a specific input device #define SDL_GLOBAL_KEYBOARD_ID 0 -/* The default keyboard input device, for platforms that don't have multiple keyboards */ +// The default keyboard input device, for platforms that don't have multiple keyboards #define SDL_DEFAULT_KEYBOARD_ID 1 -/* Initialize the keyboard subsystem */ -extern int SDL_InitKeyboard(void); - -/* Return whether a device is actually a keyboard */ -extern SDL_bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys); - -/* A keyboard has been added to the system */ -extern void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, SDL_bool send_event); - -/* A keyboard has been removed from the system */ -extern void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID); +// Initialize the keyboard subsystem +extern bool SDL_InitKeyboard(void); -/* Get the default keymap */ -extern void SDL_GetDefaultKeymap(SDL_Keycode *keymap); +// Return whether a device is actually a keyboard +extern bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys); -/* Get the default key code for a scancode */ -extern SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode); +// A keyboard has been added to the system +extern void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name, bool send_event); -/* Set the mapping of scancode to key codes */ -extern void SDL_SetKeymap(int start, const SDL_Keycode *keys, int length, SDL_bool send_event); +// A keyboard has been removed from the system +extern void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, bool send_event); -/* Set a platform-dependent key name, overriding the default platform-agnostic - name. Encoded as UTF-8. The string is not copied, thus the pointer given to - this function must stay valid forever (or at least until the call to - VideoQuit()). */ -extern void SDL_SetScancodeName(SDL_Scancode scancode, const char *name); +// Set the mapping of scancode to key codes +extern void SDL_SetKeymap(SDL_Keymap *keymap, bool send_event); -/* Set the keyboard focus window */ -extern int SDL_SetKeyboardFocus(SDL_Window *window); +// Set the keyboard focus window +extern bool SDL_SetKeyboardFocus(SDL_Window *window); /* Send a character from an on-screen keyboard as scancode and modifier key events, currently assuming ASCII characters on a US keyboard layout */ -extern int SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch); +extern void SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch); -/* Send a key from a virtual key source, like an on-screen keyboard */ -extern int SDL_SendVirtualKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode); - -/* Send a keyboard key event */ -extern int SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode); -extern int SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode); -extern int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode); +// Send a keyboard key event +extern bool SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down); +extern bool SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, bool down); +extern bool SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode); /* This is for platforms that don't know the keymap but can report scancode and keycode directly. Most platforms should prefer to optionally call SDL_SetKeymap and then use SDL_SendKeyboardKey. */ -extern int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode); +extern bool SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, int rawcode, SDL_Scancode scancode, SDL_Keycode keycode, bool down); -/* Release all the autorelease keys */ +// Release all the autorelease keys extern void SDL_ReleaseAutoReleaseKeys(void); -/* Return true if any hardware key is pressed */ -extern SDL_bool SDL_HardwareKeyboardKeyPressed(void); +// Return true if any hardware key is pressed +extern bool SDL_HardwareKeyboardKeyPressed(void); -/* Send keyboard text input */ -extern int SDL_SendKeyboardText(const char *text); +// Send keyboard text input +extern void SDL_SendKeyboardText(const char *text); -/* Send editing text for selected range from start to end */ -extern int SDL_SendEditingText(const char *text, int start, int length); +// Send editing text for selected range from start to end +extern void SDL_SendEditingText(const char *text, int start, int length); -/* Shutdown the keyboard subsystem */ -extern void SDL_QuitKeyboard(void); +// Send editing text candidates, which will be copied into the event +extern void SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int selected_candidate, bool horizontal); -/* Convert to UTF-8 */ -extern char *SDL_UCS4ToUTF8(Uint32 ch, char *dst); +// Shutdown the keyboard subsystem +extern void SDL_QuitKeyboard(void); -/* Toggle on or off pieces of the keyboard mod state. */ -extern void SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle); +// Toggle on or off pieces of the keyboard mod state. +extern void SDL_ToggleModState(SDL_Keymod modstate, bool toggle); -#endif /* SDL_keyboard_c_h_ */ +#endif // SDL_keyboard_c_h_ diff --git a/libs/SDL3/src/events/SDL_keymap.c b/libs/SDL3/src/events/SDL_keymap.c new file mode 100644 index 000000000..6bd69c50c --- /dev/null +++ b/libs/SDL3/src/events/SDL_keymap.c @@ -0,0 +1,1091 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" + +#include "SDL_keymap_c.h" +#include "SDL_keyboard_c.h" + +struct SDL_Keymap +{ + SDL_HashTable *scancode_to_keycode; + SDL_HashTable *keycode_to_scancode; +}; + +static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate); +static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate); + +SDL_Keymap *SDL_CreateKeymap(void) +{ + SDL_Keymap *keymap = (SDL_Keymap *)SDL_malloc(sizeof(*keymap)); + if (!keymap) { + return NULL; + } + + keymap->scancode_to_keycode = SDL_CreateHashTable(NULL, 64, SDL_HashID, SDL_KeyMatchID, NULL, false); + keymap->keycode_to_scancode = SDL_CreateHashTable(NULL, 64, SDL_HashID, SDL_KeyMatchID, NULL, false); + if (!keymap->scancode_to_keycode || !keymap->keycode_to_scancode) { + SDL_DestroyKeymap(keymap); + return NULL; + } + return keymap; +} + +static SDL_Keymod NormalizeModifierStateForKeymap(SDL_Keymod modstate) +{ + // The modifiers that affect the keymap are: SHIFT, CAPS, ALT, and MODE + modstate &= (SDL_KMOD_SHIFT | SDL_KMOD_CAPS | SDL_KMOD_ALT | SDL_KMOD_MODE); + + // If either right or left Shift are set, set both in the output + if (modstate & SDL_KMOD_SHIFT) { + modstate |= SDL_KMOD_SHIFT; + } + + // If either right or left Alt are set, set both in the output + if (modstate & SDL_KMOD_ALT) { + modstate |= SDL_KMOD_ALT; + } + + return modstate; +} + +void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode) +{ + if (!keymap) { + return; + } + + if (keycode == SDL_GetKeymapKeycode(keymap, scancode, modstate)) { + return; + } + + Uint32 key = ((Uint32)NormalizeModifierStateForKeymap(modstate) << 16) | scancode; + const void *value; + if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + // Changing the mapping, need to remove the existing entry from the keymap + SDL_RemoveFromHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key); + SDL_RemoveFromHashTable(keymap->keycode_to_scancode, value); + } + + SDL_InsertIntoHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, (void *)(uintptr_t)keycode); + SDL_InsertIntoHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, (void *)(uintptr_t)key); +} + +SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate) +{ + SDL_Keycode keycode; + + Uint32 key = ((Uint32)NormalizeModifierStateForKeymap(modstate) << 16) | scancode; + const void *value; + if (keymap && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + keycode = (SDL_Keycode)(uintptr_t)value; + } else { + keycode = SDL_GetDefaultKeyFromScancode(scancode, modstate); + } + return keycode; +} + +SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate) +{ + SDL_Scancode scancode; + + const void *value; + if (keymap && SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) { + scancode = (SDL_Scancode)((uintptr_t)value & 0xFFFF); + if (modstate) { + *modstate = (SDL_Keymod)((uintptr_t)value >> 16); + } + } else { + scancode = SDL_GetDefaultScancodeFromKey(keycode, modstate); + } + return scancode; +} + +void SDL_DestroyKeymap(SDL_Keymap *keymap) +{ + if (!keymap) { + return; + } + + SDL_DestroyHashTable(keymap->scancode_to_keycode); + SDL_DestroyHashTable(keymap->keycode_to_scancode); + SDL_free(keymap); +} + +static const SDL_Keycode normal_default_symbols[] = { + SDLK_1, + SDLK_2, + SDLK_3, + SDLK_4, + SDLK_5, + SDLK_6, + SDLK_7, + SDLK_8, + SDLK_9, + SDLK_0, + SDLK_RETURN, + SDLK_ESCAPE, + SDLK_BACKSPACE, + SDLK_TAB, + SDLK_SPACE, + SDLK_MINUS, + SDLK_EQUALS, + SDLK_LEFTBRACKET, + SDLK_RIGHTBRACKET, + SDLK_BACKSLASH, + SDLK_HASH, + SDLK_SEMICOLON, + SDLK_APOSTROPHE, + SDLK_GRAVE, + SDLK_COMMA, + SDLK_PERIOD, + SDLK_SLASH, +}; + +static const SDL_Keycode shifted_default_symbols[] = { + SDLK_EXCLAIM, + SDLK_AT, + SDLK_HASH, + SDLK_DOLLAR, + SDLK_PERCENT, + SDLK_CARET, + SDLK_AMPERSAND, + SDLK_ASTERISK, + SDLK_LEFTPAREN, + SDLK_RIGHTPAREN, + SDLK_RETURN, + SDLK_ESCAPE, + SDLK_BACKSPACE, + SDLK_TAB, + SDLK_SPACE, + SDLK_UNDERSCORE, + SDLK_PLUS, + SDLK_LEFTBRACE, + SDLK_RIGHTBRACE, + SDLK_PIPE, + SDLK_HASH, + SDLK_COLON, + SDLK_DBLAPOSTROPHE, + SDLK_TILDE, + SDLK_LESS, + SDLK_GREATER, + SDLK_QUESTION +}; + +static SDL_Keycode SDL_GetDefaultKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate) +{ + if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { + SDL_InvalidParamError("scancode"); + return SDLK_UNKNOWN; + } + + if (scancode < SDL_SCANCODE_A) { + return SDLK_UNKNOWN; + } + + if (scancode < SDL_SCANCODE_1) { + bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false; +#ifdef SDL_PLATFORM_APPLE + // Apple maps to upper case for either shift or capslock inclusive + if (modstate & SDL_KMOD_CAPS) { + shifted = true; + } +#else + if (modstate & SDL_KMOD_CAPS) { + shifted = !shifted; + } +#endif + if (modstate & SDL_KMOD_MODE) { + return SDLK_UNKNOWN; + } + if (!shifted) { + return (SDL_Keycode)('a' + scancode - SDL_SCANCODE_A); + } else { + return (SDL_Keycode)('A' + scancode - SDL_SCANCODE_A); + } + } + + if (scancode < SDL_SCANCODE_CAPSLOCK) { + bool shifted = (modstate & SDL_KMOD_SHIFT) ? true : false; + + if (modstate & SDL_KMOD_MODE) { + return SDLK_UNKNOWN; + } + if (!shifted) { + return normal_default_symbols[scancode - SDL_SCANCODE_1]; + } else { + return shifted_default_symbols[scancode - SDL_SCANCODE_1]; + } + } + + // These scancodes are not mapped to printable keycodes + switch (scancode) { + case SDL_SCANCODE_DELETE: + return SDLK_DELETE; + case SDL_SCANCODE_CAPSLOCK: + return SDLK_CAPSLOCK; + case SDL_SCANCODE_F1: + return SDLK_F1; + case SDL_SCANCODE_F2: + return SDLK_F2; + case SDL_SCANCODE_F3: + return SDLK_F3; + case SDL_SCANCODE_F4: + return SDLK_F4; + case SDL_SCANCODE_F5: + return SDLK_F5; + case SDL_SCANCODE_F6: + return SDLK_F6; + case SDL_SCANCODE_F7: + return SDLK_F7; + case SDL_SCANCODE_F8: + return SDLK_F8; + case SDL_SCANCODE_F9: + return SDLK_F9; + case SDL_SCANCODE_F10: + return SDLK_F10; + case SDL_SCANCODE_F11: + return SDLK_F11; + case SDL_SCANCODE_F12: + return SDLK_F12; + case SDL_SCANCODE_PRINTSCREEN: + return SDLK_PRINTSCREEN; + case SDL_SCANCODE_SCROLLLOCK: + return SDLK_SCROLLLOCK; + case SDL_SCANCODE_PAUSE: + return SDLK_PAUSE; + case SDL_SCANCODE_INSERT: + return SDLK_INSERT; + case SDL_SCANCODE_HOME: + return SDLK_HOME; + case SDL_SCANCODE_PAGEUP: + return SDLK_PAGEUP; + case SDL_SCANCODE_END: + return SDLK_END; + case SDL_SCANCODE_PAGEDOWN: + return SDLK_PAGEDOWN; + case SDL_SCANCODE_RIGHT: + return SDLK_RIGHT; + case SDL_SCANCODE_LEFT: + return SDLK_LEFT; + case SDL_SCANCODE_DOWN: + return SDLK_DOWN; + case SDL_SCANCODE_UP: + return SDLK_UP; + case SDL_SCANCODE_NUMLOCKCLEAR: + return SDLK_NUMLOCKCLEAR; + case SDL_SCANCODE_KP_DIVIDE: + return SDLK_KP_DIVIDE; + case SDL_SCANCODE_KP_MULTIPLY: + return SDLK_KP_MULTIPLY; + case SDL_SCANCODE_KP_MINUS: + return SDLK_KP_MINUS; + case SDL_SCANCODE_KP_PLUS: + return SDLK_KP_PLUS; + case SDL_SCANCODE_KP_ENTER: + return SDLK_KP_ENTER; + case SDL_SCANCODE_KP_1: + return SDLK_KP_1; + case SDL_SCANCODE_KP_2: + return SDLK_KP_2; + case SDL_SCANCODE_KP_3: + return SDLK_KP_3; + case SDL_SCANCODE_KP_4: + return SDLK_KP_4; + case SDL_SCANCODE_KP_5: + return SDLK_KP_5; + case SDL_SCANCODE_KP_6: + return SDLK_KP_6; + case SDL_SCANCODE_KP_7: + return SDLK_KP_7; + case SDL_SCANCODE_KP_8: + return SDLK_KP_8; + case SDL_SCANCODE_KP_9: + return SDLK_KP_9; + case SDL_SCANCODE_KP_0: + return SDLK_KP_0; + case SDL_SCANCODE_KP_PERIOD: + return SDLK_KP_PERIOD; + case SDL_SCANCODE_APPLICATION: + return SDLK_APPLICATION; + case SDL_SCANCODE_POWER: + return SDLK_POWER; + case SDL_SCANCODE_KP_EQUALS: + return SDLK_KP_EQUALS; + case SDL_SCANCODE_F13: + return SDLK_F13; + case SDL_SCANCODE_F14: + return SDLK_F14; + case SDL_SCANCODE_F15: + return SDLK_F15; + case SDL_SCANCODE_F16: + return SDLK_F16; + case SDL_SCANCODE_F17: + return SDLK_F17; + case SDL_SCANCODE_F18: + return SDLK_F18; + case SDL_SCANCODE_F19: + return SDLK_F19; + case SDL_SCANCODE_F20: + return SDLK_F20; + case SDL_SCANCODE_F21: + return SDLK_F21; + case SDL_SCANCODE_F22: + return SDLK_F22; + case SDL_SCANCODE_F23: + return SDLK_F23; + case SDL_SCANCODE_F24: + return SDLK_F24; + case SDL_SCANCODE_EXECUTE: + return SDLK_EXECUTE; + case SDL_SCANCODE_HELP: + return SDLK_HELP; + case SDL_SCANCODE_MENU: + return SDLK_MENU; + case SDL_SCANCODE_SELECT: + return SDLK_SELECT; + case SDL_SCANCODE_STOP: + return SDLK_STOP; + case SDL_SCANCODE_AGAIN: + return SDLK_AGAIN; + case SDL_SCANCODE_UNDO: + return SDLK_UNDO; + case SDL_SCANCODE_CUT: + return SDLK_CUT; + case SDL_SCANCODE_COPY: + return SDLK_COPY; + case SDL_SCANCODE_PASTE: + return SDLK_PASTE; + case SDL_SCANCODE_FIND: + return SDLK_FIND; + case SDL_SCANCODE_MUTE: + return SDLK_MUTE; + case SDL_SCANCODE_VOLUMEUP: + return SDLK_VOLUMEUP; + case SDL_SCANCODE_VOLUMEDOWN: + return SDLK_VOLUMEDOWN; + case SDL_SCANCODE_KP_COMMA: + return SDLK_KP_COMMA; + case SDL_SCANCODE_KP_EQUALSAS400: + return SDLK_KP_EQUALSAS400; + case SDL_SCANCODE_ALTERASE: + return SDLK_ALTERASE; + case SDL_SCANCODE_SYSREQ: + return SDLK_SYSREQ; + case SDL_SCANCODE_CANCEL: + return SDLK_CANCEL; + case SDL_SCANCODE_CLEAR: + return SDLK_CLEAR; + case SDL_SCANCODE_PRIOR: + return SDLK_PRIOR; + case SDL_SCANCODE_RETURN2: + return SDLK_RETURN2; + case SDL_SCANCODE_SEPARATOR: + return SDLK_SEPARATOR; + case SDL_SCANCODE_OUT: + return SDLK_OUT; + case SDL_SCANCODE_OPER: + return SDLK_OPER; + case SDL_SCANCODE_CLEARAGAIN: + return SDLK_CLEARAGAIN; + case SDL_SCANCODE_CRSEL: + return SDLK_CRSEL; + case SDL_SCANCODE_EXSEL: + return SDLK_EXSEL; + case SDL_SCANCODE_KP_00: + return SDLK_KP_00; + case SDL_SCANCODE_KP_000: + return SDLK_KP_000; + case SDL_SCANCODE_THOUSANDSSEPARATOR: + return SDLK_THOUSANDSSEPARATOR; + case SDL_SCANCODE_DECIMALSEPARATOR: + return SDLK_DECIMALSEPARATOR; + case SDL_SCANCODE_CURRENCYUNIT: + return SDLK_CURRENCYUNIT; + case SDL_SCANCODE_CURRENCYSUBUNIT: + return SDLK_CURRENCYSUBUNIT; + case SDL_SCANCODE_KP_LEFTPAREN: + return SDLK_KP_LEFTPAREN; + case SDL_SCANCODE_KP_RIGHTPAREN: + return SDLK_KP_RIGHTPAREN; + case SDL_SCANCODE_KP_LEFTBRACE: + return SDLK_KP_LEFTBRACE; + case SDL_SCANCODE_KP_RIGHTBRACE: + return SDLK_KP_RIGHTBRACE; + case SDL_SCANCODE_KP_TAB: + return SDLK_KP_TAB; + case SDL_SCANCODE_KP_BACKSPACE: + return SDLK_KP_BACKSPACE; + case SDL_SCANCODE_KP_A: + return SDLK_KP_A; + case SDL_SCANCODE_KP_B: + return SDLK_KP_B; + case SDL_SCANCODE_KP_C: + return SDLK_KP_C; + case SDL_SCANCODE_KP_D: + return SDLK_KP_D; + case SDL_SCANCODE_KP_E: + return SDLK_KP_E; + case SDL_SCANCODE_KP_F: + return SDLK_KP_F; + case SDL_SCANCODE_KP_XOR: + return SDLK_KP_XOR; + case SDL_SCANCODE_KP_POWER: + return SDLK_KP_POWER; + case SDL_SCANCODE_KP_PERCENT: + return SDLK_KP_PERCENT; + case SDL_SCANCODE_KP_LESS: + return SDLK_KP_LESS; + case SDL_SCANCODE_KP_GREATER: + return SDLK_KP_GREATER; + case SDL_SCANCODE_KP_AMPERSAND: + return SDLK_KP_AMPERSAND; + case SDL_SCANCODE_KP_DBLAMPERSAND: + return SDLK_KP_DBLAMPERSAND; + case SDL_SCANCODE_KP_VERTICALBAR: + return SDLK_KP_VERTICALBAR; + case SDL_SCANCODE_KP_DBLVERTICALBAR: + return SDLK_KP_DBLVERTICALBAR; + case SDL_SCANCODE_KP_COLON: + return SDLK_KP_COLON; + case SDL_SCANCODE_KP_HASH: + return SDLK_KP_HASH; + case SDL_SCANCODE_KP_SPACE: + return SDLK_KP_SPACE; + case SDL_SCANCODE_KP_AT: + return SDLK_KP_AT; + case SDL_SCANCODE_KP_EXCLAM: + return SDLK_KP_EXCLAM; + case SDL_SCANCODE_KP_MEMSTORE: + return SDLK_KP_MEMSTORE; + case SDL_SCANCODE_KP_MEMRECALL: + return SDLK_KP_MEMRECALL; + case SDL_SCANCODE_KP_MEMCLEAR: + return SDLK_KP_MEMCLEAR; + case SDL_SCANCODE_KP_MEMADD: + return SDLK_KP_MEMADD; + case SDL_SCANCODE_KP_MEMSUBTRACT: + return SDLK_KP_MEMSUBTRACT; + case SDL_SCANCODE_KP_MEMMULTIPLY: + return SDLK_KP_MEMMULTIPLY; + case SDL_SCANCODE_KP_MEMDIVIDE: + return SDLK_KP_MEMDIVIDE; + case SDL_SCANCODE_KP_PLUSMINUS: + return SDLK_KP_PLUSMINUS; + case SDL_SCANCODE_KP_CLEAR: + return SDLK_KP_CLEAR; + case SDL_SCANCODE_KP_CLEARENTRY: + return SDLK_KP_CLEARENTRY; + case SDL_SCANCODE_KP_BINARY: + return SDLK_KP_BINARY; + case SDL_SCANCODE_KP_OCTAL: + return SDLK_KP_OCTAL; + case SDL_SCANCODE_KP_DECIMAL: + return SDLK_KP_DECIMAL; + case SDL_SCANCODE_KP_HEXADECIMAL: + return SDLK_KP_HEXADECIMAL; + case SDL_SCANCODE_LCTRL: + return SDLK_LCTRL; + case SDL_SCANCODE_LSHIFT: + return SDLK_LSHIFT; + case SDL_SCANCODE_LALT: + return SDLK_LALT; + case SDL_SCANCODE_LGUI: + return SDLK_LGUI; + case SDL_SCANCODE_RCTRL: + return SDLK_RCTRL; + case SDL_SCANCODE_RSHIFT: + return SDLK_RSHIFT; + case SDL_SCANCODE_RALT: + return SDLK_RALT; + case SDL_SCANCODE_RGUI: + return SDLK_RGUI; + case SDL_SCANCODE_MODE: + return SDLK_MODE; + case SDL_SCANCODE_SLEEP: + return SDLK_SLEEP; + case SDL_SCANCODE_WAKE: + return SDLK_WAKE; + case SDL_SCANCODE_CHANNEL_INCREMENT: + return SDLK_CHANNEL_INCREMENT; + case SDL_SCANCODE_CHANNEL_DECREMENT: + return SDLK_CHANNEL_DECREMENT; + case SDL_SCANCODE_MEDIA_PLAY: + return SDLK_MEDIA_PLAY; + case SDL_SCANCODE_MEDIA_PAUSE: + return SDLK_MEDIA_PAUSE; + case SDL_SCANCODE_MEDIA_RECORD: + return SDLK_MEDIA_RECORD; + case SDL_SCANCODE_MEDIA_FAST_FORWARD: + return SDLK_MEDIA_FAST_FORWARD; + case SDL_SCANCODE_MEDIA_REWIND: + return SDLK_MEDIA_REWIND; + case SDL_SCANCODE_MEDIA_NEXT_TRACK: + return SDLK_MEDIA_NEXT_TRACK; + case SDL_SCANCODE_MEDIA_PREVIOUS_TRACK: + return SDLK_MEDIA_PREVIOUS_TRACK; + case SDL_SCANCODE_MEDIA_STOP: + return SDLK_MEDIA_STOP; + case SDL_SCANCODE_MEDIA_EJECT: + return SDLK_MEDIA_EJECT; + case SDL_SCANCODE_MEDIA_PLAY_PAUSE: + return SDLK_MEDIA_PLAY_PAUSE; + case SDL_SCANCODE_MEDIA_SELECT: + return SDLK_MEDIA_SELECT; + case SDL_SCANCODE_AC_NEW: + return SDLK_AC_NEW; + case SDL_SCANCODE_AC_OPEN: + return SDLK_AC_OPEN; + case SDL_SCANCODE_AC_CLOSE: + return SDLK_AC_CLOSE; + case SDL_SCANCODE_AC_EXIT: + return SDLK_AC_EXIT; + case SDL_SCANCODE_AC_SAVE: + return SDLK_AC_SAVE; + case SDL_SCANCODE_AC_PRINT: + return SDLK_AC_PRINT; + case SDL_SCANCODE_AC_PROPERTIES: + return SDLK_AC_PROPERTIES; + case SDL_SCANCODE_AC_SEARCH: + return SDLK_AC_SEARCH; + case SDL_SCANCODE_AC_HOME: + return SDLK_AC_HOME; + case SDL_SCANCODE_AC_BACK: + return SDLK_AC_BACK; + case SDL_SCANCODE_AC_FORWARD: + return SDLK_AC_FORWARD; + case SDL_SCANCODE_AC_STOP: + return SDLK_AC_STOP; + case SDL_SCANCODE_AC_REFRESH: + return SDLK_AC_REFRESH; + case SDL_SCANCODE_AC_BOOKMARKS: + return SDLK_AC_BOOKMARKS; + case SDL_SCANCODE_SOFTLEFT: + return SDLK_SOFTLEFT; + case SDL_SCANCODE_SOFTRIGHT: + return SDLK_SOFTRIGHT; + case SDL_SCANCODE_CALL: + return SDLK_CALL; + case SDL_SCANCODE_ENDCALL: + return SDLK_ENDCALL; + default: + return SDLK_UNKNOWN; + } +} + +static SDL_Scancode SDL_GetDefaultScancodeFromKey(SDL_Keycode key, SDL_Keymod *modstate) +{ + if (modstate) { + *modstate = SDL_KMOD_NONE; + } + + if (key == SDLK_UNKNOWN) { + return SDL_SCANCODE_UNKNOWN; + } + + if (key & SDLK_SCANCODE_MASK) { + return (SDL_Scancode)(key & ~SDLK_SCANCODE_MASK); + } + + if (key >= SDLK_A && key <= SDLK_Z) { + return (SDL_Scancode)(SDL_SCANCODE_A + key - SDLK_A); + } + + if (key >= 'A' && key <= 'Z') { + if (modstate) { + *modstate = SDL_KMOD_SHIFT; + } + return (SDL_Scancode)(SDL_SCANCODE_A + key - 'A'); + } + + for (int i = 0; i < SDL_arraysize(normal_default_symbols); ++i) { + if (key == normal_default_symbols[i]) { + return(SDL_Scancode)(SDL_SCANCODE_1 + i); + } + } + + for (int i = 0; i < SDL_arraysize(shifted_default_symbols); ++i) { + if (key == shifted_default_symbols[i]) { + if (modstate) { + *modstate = SDL_KMOD_SHIFT; + } + return(SDL_Scancode)(SDL_SCANCODE_1 + i); + } + } + + if (key == SDLK_DELETE) { + return SDL_SCANCODE_DELETE; + } + + return SDL_SCANCODE_UNKNOWN; +} + +static const char *SDL_scancode_names[SDL_SCANCODE_COUNT] = +{ + /* 0 */ NULL, + /* 1 */ NULL, + /* 2 */ NULL, + /* 3 */ NULL, + /* 4 */ "A", + /* 5 */ "B", + /* 6 */ "C", + /* 7 */ "D", + /* 8 */ "E", + /* 9 */ "F", + /* 10 */ "G", + /* 11 */ "H", + /* 12 */ "I", + /* 13 */ "J", + /* 14 */ "K", + /* 15 */ "L", + /* 16 */ "M", + /* 17 */ "N", + /* 18 */ "O", + /* 19 */ "P", + /* 20 */ "Q", + /* 21 */ "R", + /* 22 */ "S", + /* 23 */ "T", + /* 24 */ "U", + /* 25 */ "V", + /* 26 */ "W", + /* 27 */ "X", + /* 28 */ "Y", + /* 29 */ "Z", + /* 30 */ "1", + /* 31 */ "2", + /* 32 */ "3", + /* 33 */ "4", + /* 34 */ "5", + /* 35 */ "6", + /* 36 */ "7", + /* 37 */ "8", + /* 38 */ "9", + /* 39 */ "0", + /* 40 */ "Return", + /* 41 */ "Escape", + /* 42 */ "Backspace", + /* 43 */ "Tab", + /* 44 */ "Space", + /* 45 */ "-", + /* 46 */ "=", + /* 47 */ "[", + /* 48 */ "]", + /* 49 */ "\\", + /* 50 */ "#", + /* 51 */ ";", + /* 52 */ "'", + /* 53 */ "`", + /* 54 */ ",", + /* 55 */ ".", + /* 56 */ "/", + /* 57 */ "CapsLock", + /* 58 */ "F1", + /* 59 */ "F2", + /* 60 */ "F3", + /* 61 */ "F4", + /* 62 */ "F5", + /* 63 */ "F6", + /* 64 */ "F7", + /* 65 */ "F8", + /* 66 */ "F9", + /* 67 */ "F10", + /* 68 */ "F11", + /* 69 */ "F12", + /* 70 */ "PrintScreen", + /* 71 */ "ScrollLock", + /* 72 */ "Pause", + /* 73 */ "Insert", + /* 74 */ "Home", + /* 75 */ "PageUp", + /* 76 */ "Delete", + /* 77 */ "End", + /* 78 */ "PageDown", + /* 79 */ "Right", + /* 80 */ "Left", + /* 81 */ "Down", + /* 82 */ "Up", + /* 83 */ "Numlock", + /* 84 */ "Keypad /", + /* 85 */ "Keypad *", + /* 86 */ "Keypad -", + /* 87 */ "Keypad +", + /* 88 */ "Keypad Enter", + /* 89 */ "Keypad 1", + /* 90 */ "Keypad 2", + /* 91 */ "Keypad 3", + /* 92 */ "Keypad 4", + /* 93 */ "Keypad 5", + /* 94 */ "Keypad 6", + /* 95 */ "Keypad 7", + /* 96 */ "Keypad 8", + /* 97 */ "Keypad 9", + /* 98 */ "Keypad 0", + /* 99 */ "Keypad .", + /* 100 */ NULL, + /* 101 */ "Application", + /* 102 */ "Power", + /* 103 */ "Keypad =", + /* 104 */ "F13", + /* 105 */ "F14", + /* 106 */ "F15", + /* 107 */ "F16", + /* 108 */ "F17", + /* 109 */ "F18", + /* 110 */ "F19", + /* 111 */ "F20", + /* 112 */ "F21", + /* 113 */ "F22", + /* 114 */ "F23", + /* 115 */ "F24", + /* 116 */ "Execute", + /* 117 */ "Help", + /* 118 */ "Menu", + /* 119 */ "Select", + /* 120 */ "Stop", + /* 121 */ "Again", + /* 122 */ "Undo", + /* 123 */ "Cut", + /* 124 */ "Copy", + /* 125 */ "Paste", + /* 126 */ "Find", + /* 127 */ "Mute", + /* 128 */ "VolumeUp", + /* 129 */ "VolumeDown", + /* 130 */ NULL, + /* 131 */ NULL, + /* 132 */ NULL, + /* 133 */ "Keypad ,", + /* 134 */ "Keypad = (AS400)", + /* 135 */ NULL, + /* 136 */ NULL, + /* 137 */ NULL, + /* 138 */ NULL, + /* 139 */ NULL, + /* 140 */ NULL, + /* 141 */ NULL, + /* 142 */ NULL, + /* 143 */ NULL, + /* 144 */ NULL, + /* 145 */ NULL, + /* 146 */ NULL, + /* 147 */ NULL, + /* 148 */ NULL, + /* 149 */ NULL, + /* 150 */ NULL, + /* 151 */ NULL, + /* 152 */ NULL, + /* 153 */ "AltErase", + /* 154 */ "SysReq", + /* 155 */ "Cancel", + /* 156 */ "Clear", + /* 157 */ "Prior", + /* 158 */ "Return", + /* 159 */ "Separator", + /* 160 */ "Out", + /* 161 */ "Oper", + /* 162 */ "Clear / Again", + /* 163 */ "CrSel", + /* 164 */ "ExSel", + /* 165 */ NULL, + /* 166 */ NULL, + /* 167 */ NULL, + /* 168 */ NULL, + /* 169 */ NULL, + /* 170 */ NULL, + /* 171 */ NULL, + /* 172 */ NULL, + /* 173 */ NULL, + /* 174 */ NULL, + /* 175 */ NULL, + /* 176 */ "Keypad 00", + /* 177 */ "Keypad 000", + /* 178 */ "ThousandsSeparator", + /* 179 */ "DecimalSeparator", + /* 180 */ "CurrencyUnit", + /* 181 */ "CurrencySubUnit", + /* 182 */ "Keypad (", + /* 183 */ "Keypad )", + /* 184 */ "Keypad {", + /* 185 */ "Keypad }", + /* 186 */ "Keypad Tab", + /* 187 */ "Keypad Backspace", + /* 188 */ "Keypad A", + /* 189 */ "Keypad B", + /* 190 */ "Keypad C", + /* 191 */ "Keypad D", + /* 192 */ "Keypad E", + /* 193 */ "Keypad F", + /* 194 */ "Keypad XOR", + /* 195 */ "Keypad ^", + /* 196 */ "Keypad %", + /* 197 */ "Keypad <", + /* 198 */ "Keypad >", + /* 199 */ "Keypad &", + /* 200 */ "Keypad &&", + /* 201 */ "Keypad |", + /* 202 */ "Keypad ||", + /* 203 */ "Keypad :", + /* 204 */ "Keypad #", + /* 205 */ "Keypad Space", + /* 206 */ "Keypad @", + /* 207 */ "Keypad !", + /* 208 */ "Keypad MemStore", + /* 209 */ "Keypad MemRecall", + /* 210 */ "Keypad MemClear", + /* 211 */ "Keypad MemAdd", + /* 212 */ "Keypad MemSubtract", + /* 213 */ "Keypad MemMultiply", + /* 214 */ "Keypad MemDivide", + /* 215 */ "Keypad +/-", + /* 216 */ "Keypad Clear", + /* 217 */ "Keypad ClearEntry", + /* 218 */ "Keypad Binary", + /* 219 */ "Keypad Octal", + /* 220 */ "Keypad Decimal", + /* 221 */ "Keypad Hexadecimal", + /* 222 */ NULL, + /* 223 */ NULL, + /* 224 */ "Left Ctrl", + /* 225 */ "Left Shift", + /* 226 */ "Left Alt", + /* 227 */ "Left GUI", + /* 228 */ "Right Ctrl", + /* 229 */ "Right Shift", + /* 230 */ "Right Alt", + /* 231 */ "Right GUI", + /* 232 */ NULL, + /* 233 */ NULL, + /* 234 */ NULL, + /* 235 */ NULL, + /* 236 */ NULL, + /* 237 */ NULL, + /* 238 */ NULL, + /* 239 */ NULL, + /* 240 */ NULL, + /* 241 */ NULL, + /* 242 */ NULL, + /* 243 */ NULL, + /* 244 */ NULL, + /* 245 */ NULL, + /* 246 */ NULL, + /* 247 */ NULL, + /* 248 */ NULL, + /* 249 */ NULL, + /* 250 */ NULL, + /* 251 */ NULL, + /* 252 */ NULL, + /* 253 */ NULL, + /* 254 */ NULL, + /* 255 */ NULL, + /* 256 */ NULL, + /* 257 */ "ModeSwitch", + /* 258 */ "Sleep", + /* 259 */ "Wake", + /* 260 */ "ChannelUp", + /* 261 */ "ChannelDown", + /* 262 */ "MediaPlay", + /* 263 */ "MediaPause", + /* 264 */ "MediaRecord", + /* 265 */ "MediaFastForward", + /* 266 */ "MediaRewind", + /* 267 */ "MediaTrackNext", + /* 268 */ "MediaTrackPrevious", + /* 269 */ "MediaStop", + /* 270 */ "Eject", + /* 271 */ "MediaPlayPause", + /* 272 */ "MediaSelect", + /* 273 */ "AC New", + /* 274 */ "AC Open", + /* 275 */ "AC Close", + /* 276 */ "AC Exit", + /* 277 */ "AC Save", + /* 278 */ "AC Print", + /* 279 */ "AC Properties", + /* 280 */ "AC Search", + /* 281 */ "AC Home", + /* 282 */ "AC Back", + /* 283 */ "AC Forward", + /* 284 */ "AC Stop", + /* 285 */ "AC Refresh", + /* 286 */ "AC Bookmarks", + /* 287 */ "SoftLeft", + /* 288 */ "SoftRight", + /* 289 */ "Call", + /* 290 */ "EndCall", +}; + +bool SDL_SetScancodeName(SDL_Scancode scancode, const char *name) +{ + if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { + return SDL_InvalidParamError("scancode"); + } + + SDL_scancode_names[scancode] = name; + return true; +} + +const char *SDL_GetScancodeName(SDL_Scancode scancode) +{ + const char *name; + if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_SCANCODE_COUNT) { + SDL_InvalidParamError("scancode"); + return ""; + } + + name = SDL_scancode_names[scancode]; + if (!name) { + name = ""; + } + // This is pointing to static memory or application managed memory + return name; +} + +SDL_Scancode SDL_GetScancodeFromName(const char *name) +{ + int i; + + if (!name || !*name) { + SDL_InvalidParamError("name"); + return SDL_SCANCODE_UNKNOWN; + } + + for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) { + if (!SDL_scancode_names[i]) { + continue; + } + if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) { + return (SDL_Scancode)i; + } + } + + SDL_InvalidParamError("name"); + return SDL_SCANCODE_UNKNOWN; +} + +const char *SDL_GetKeyName(SDL_Keycode key) +{ + const bool uppercase = true; + char name[8]; + char *end; + + if (key & SDLK_SCANCODE_MASK) { + return SDL_GetScancodeName((SDL_Scancode)(key & ~SDLK_SCANCODE_MASK)); + } + + switch (key) { + case SDLK_RETURN: + return SDL_GetScancodeName(SDL_SCANCODE_RETURN); + case SDLK_ESCAPE: + return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE); + case SDLK_BACKSPACE: + return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE); + case SDLK_TAB: + return SDL_GetScancodeName(SDL_SCANCODE_TAB); + case SDLK_SPACE: + return SDL_GetScancodeName(SDL_SCANCODE_SPACE); + case SDLK_DELETE: + return SDL_GetScancodeName(SDL_SCANCODE_DELETE); + default: + if (uppercase) { + // SDL_Keycode is defined as the unshifted key on the keyboard, + // but the key name is defined as the letter printed on that key, + // which is usually the shifted capital letter. + if (key > 0x7F || (key >= 'a' && key <= 'z')) { + SDL_Keymap *keymap = SDL_GetCurrentKeymap(); + SDL_Keymod modstate; + SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate); + if (scancode != SDL_SCANCODE_UNKNOWN && !(modstate & SDL_KMOD_SHIFT)) { + SDL_Keycode capital = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_SHIFT); + if (capital > 0x7F || (capital >= 'A' && capital <= 'Z')) { + key = capital; + } + } + } + } + + end = SDL_UCS4ToUTF8(key, name); + *end = '\0'; + return SDL_GetPersistentString(name); + } +} + +SDL_Keycode SDL_GetKeyFromName(const char *name) +{ + const bool uppercase = true; + SDL_Keycode key; + + // Check input + if (!name) { + return SDLK_UNKNOWN; + } + + // If it's a single UTF-8 character, then that's the keycode itself + key = *(const unsigned char *)name; + if (key >= 0xF0) { + if (SDL_strlen(name) == 4) { + int i = 0; + key = (Uint16)(name[i] & 0x07) << 18; + key |= (Uint16)(name[++i] & 0x3F) << 12; + key |= (Uint16)(name[++i] & 0x3F) << 6; + key |= (Uint16)(name[++i] & 0x3F); + } else { + key = SDLK_UNKNOWN; + } + } else if (key >= 0xE0) { + if (SDL_strlen(name) == 3) { + int i = 0; + key = (Uint16)(name[i] & 0x0F) << 12; + key |= (Uint16)(name[++i] & 0x3F) << 6; + key |= (Uint16)(name[++i] & 0x3F); + } else { + key = SDLK_UNKNOWN; + } + } else if (key >= 0xC0) { + if (SDL_strlen(name) == 2) { + int i = 0; + key = (Uint16)(name[i] & 0x1F) << 6; + key |= (Uint16)(name[++i] & 0x3F); + } else { + key = SDLK_UNKNOWN; + } + } else { + if (SDL_strlen(name) != 1) { + key = SDLK_UNKNOWN; + } + } + + if (key != SDLK_UNKNOWN) { + if (uppercase) { + // SDL_Keycode is defined as the unshifted key on the keyboard, + // but the key name is defined as the letter printed on that key, + // which is usually the shifted capital letter. + SDL_Keymap *keymap = SDL_GetCurrentKeymap(); + SDL_Keymod modstate; + SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate); + if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & SDL_KMOD_SHIFT)) { + key = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_NONE); + } + } + return key; + } + + return SDL_GetKeyFromScancode(SDL_GetScancodeFromName(name), SDL_KMOD_NONE, false); +} diff --git a/libs/SDL3/src/events/SDL_keymap_c.h b/libs/SDL3/src/events/SDL_keymap_c.h new file mode 100644 index 000000000..1f8cff464 --- /dev/null +++ b/libs/SDL3/src/events/SDL_keymap_c.h @@ -0,0 +1,35 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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_keymap_c_h_ +#define SDL_keymap_c_h_ + +typedef struct SDL_Keymap SDL_Keymap; + +SDL_Keymap *SDL_GetCurrentKeymap(void); +SDL_Keymap *SDL_CreateKeymap(void); +void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode); +SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate); +SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate); +void SDL_DestroyKeymap(SDL_Keymap *keymap); + +#endif // SDL_keymap_c_h_ diff --git a/libs/SDL3/src/events/SDL_keysym_to_scancode.c b/libs/SDL3/src/events/SDL_keysym_to_scancode.c index 08e980942..e80b6f6d7 100644 --- a/libs/SDL3/src/events/SDL_keysym_to_scancode.c +++ b/libs/SDL3/src/events/SDL_keysym_to_scancode.c @@ -26,290 +26,290 @@ #include "SDL_scancode_tables_c.h" #include "SDL_keysym_to_scancode_c.h" -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static const struct { Uint32 keysym; SDL_Scancode scancode; } KeySymToSDLScancode[] = { - { 0xFF9C, SDL_SCANCODE_KP_1 }, /* XK_KP_End */ - { 0xFF99, SDL_SCANCODE_KP_2 }, /* XK_KP_Down */ - { 0xFF9B, SDL_SCANCODE_KP_3 }, /* XK_KP_Next */ - { 0xFF96, SDL_SCANCODE_KP_4 }, /* XK_KP_Left */ - { 0xFF9D, SDL_SCANCODE_KP_5 }, /* XK_KP_Begin */ - { 0xFF98, SDL_SCANCODE_KP_6 }, /* XK_KP_Right */ - { 0xFF95, SDL_SCANCODE_KP_7 }, /* XK_KP_Home */ - { 0xFF97, SDL_SCANCODE_KP_8 }, /* XK_KP_Up */ - { 0xFF9A, SDL_SCANCODE_KP_9 }, /* XK_KP_Prior */ - { 0xFF9E, SDL_SCANCODE_KP_0 }, /* XK_KP_Insert */ - { 0xFF9F, SDL_SCANCODE_KP_PERIOD }, /* XK_KP_Delete */ - { 0xFF62, SDL_SCANCODE_EXECUTE }, /* XK_Execute */ - { 0xFFEE, SDL_SCANCODE_APPLICATION }, /* XK_Hyper_R */ - { 0xFE03, SDL_SCANCODE_RALT }, /* XK_ISO_Level3_Shift */ - { 0xFFEB, SDL_SCANCODE_LGUI }, /* XK_Super_L */ - { 0xFFEC, SDL_SCANCODE_RGUI }, /* XK_Super_R */ - { 0xFF7E, SDL_SCANCODE_MODE }, /* XK_Mode_switch */ - { 0x1008FF65, SDL_SCANCODE_MENU }, /* XF86MenuKB */ - { 0x1008FF81, SDL_SCANCODE_F13 }, /* XF86Tools */ - { 0x1008FF45, SDL_SCANCODE_F14 }, /* XF86Launch5 */ - { 0x1008FF46, SDL_SCANCODE_F15 }, /* XF86Launch6 */ - { 0x1008FF47, SDL_SCANCODE_F16 }, /* XF86Launch7 */ - { 0x1008FF48, SDL_SCANCODE_F17 }, /* XF86Launch8 */ - { 0x1008FF49, SDL_SCANCODE_F18 }, /* XF86Launch9 */ + { 0xFF9C, SDL_SCANCODE_KP_1 }, // XK_KP_End + { 0xFF99, SDL_SCANCODE_KP_2 }, // XK_KP_Down + { 0xFF9B, SDL_SCANCODE_KP_3 }, // XK_KP_Next + { 0xFF96, SDL_SCANCODE_KP_4 }, // XK_KP_Left + { 0xFF9D, SDL_SCANCODE_KP_5 }, // XK_KP_Begin + { 0xFF98, SDL_SCANCODE_KP_6 }, // XK_KP_Right + { 0xFF95, SDL_SCANCODE_KP_7 }, // XK_KP_Home + { 0xFF97, SDL_SCANCODE_KP_8 }, // XK_KP_Up + { 0xFF9A, SDL_SCANCODE_KP_9 }, // XK_KP_Prior + { 0xFF9E, SDL_SCANCODE_KP_0 }, // XK_KP_Insert + { 0xFF9F, SDL_SCANCODE_KP_PERIOD }, // XK_KP_Delete + { 0xFF62, SDL_SCANCODE_EXECUTE }, // XK_Execute + { 0xFFEE, SDL_SCANCODE_APPLICATION }, // XK_Hyper_R + { 0xFE03, SDL_SCANCODE_RALT }, // XK_ISO_Level3_Shift + { 0xFFEB, SDL_SCANCODE_LGUI }, // XK_Super_L + { 0xFFEC, SDL_SCANCODE_RGUI }, // XK_Super_R + { 0xFF7E, SDL_SCANCODE_MODE }, // XK_Mode_switch + { 0x1008FF65, SDL_SCANCODE_MENU }, // XF86MenuKB + { 0x1008FF81, SDL_SCANCODE_F13 }, // XF86Tools + { 0x1008FF45, SDL_SCANCODE_F14 }, // XF86Launch5 + { 0x1008FF46, SDL_SCANCODE_F15 }, // XF86Launch6 + { 0x1008FF47, SDL_SCANCODE_F16 }, // XF86Launch7 + { 0x1008FF48, SDL_SCANCODE_F17 }, // XF86Launch8 + { 0x1008FF49, SDL_SCANCODE_F18 }, // XF86Launch9 }; -/* This is a mapping from X keysym to Linux keycode */ +// This is a mapping from X keysym to Linux keycode static const Uint32 LinuxKeycodeKeysyms[] = { - /* 0, 0x000 */ 0x0, /* NoSymbol */ - /* 1, 0x001 */ 0xFF1B, /* Escape */ - /* 2, 0x002 */ 0x31, /* 1 */ - /* 3, 0x003 */ 0x32, /* 2 */ - /* 4, 0x004 */ 0x33, /* 3 */ - /* 5, 0x005 */ 0x34, /* 4 */ - /* 6, 0x006 */ 0x35, /* 5 */ - /* 7, 0x007 */ 0x36, /* 6 */ - /* 8, 0x008 */ 0x37, /* 7 */ - /* 9, 0x009 */ 0x38, /* 8 */ - /* 10, 0x00a */ 0x39, /* 9 */ - /* 11, 0x00b */ 0x30, /* 0 */ - /* 12, 0x00c */ 0x2D, /* minus */ - /* 13, 0x00d */ 0x3D, /* equal */ - /* 14, 0x00e */ 0xFF08, /* BackSpace */ - /* 15, 0x00f */ 0xFF09, /* Tab */ - /* 16, 0x010 */ 0x71, /* q */ - /* 17, 0x011 */ 0x77, /* w */ - /* 18, 0x012 */ 0x65, /* e */ - /* 19, 0x013 */ 0x72, /* r */ - /* 20, 0x014 */ 0x74, /* t */ - /* 21, 0x015 */ 0x79, /* y */ - /* 22, 0x016 */ 0x75, /* u */ - /* 23, 0x017 */ 0x69, /* i */ - /* 24, 0x018 */ 0x6F, /* o */ - /* 25, 0x019 */ 0x70, /* p */ - /* 26, 0x01a */ 0x5B, /* bracketleft */ - /* 27, 0x01b */ 0x5D, /* bracketright */ - /* 28, 0x01c */ 0xFF0D, /* Return */ - /* 29, 0x01d */ 0xFFE3, /* Control_L */ - /* 30, 0x01e */ 0x61, /* a */ - /* 31, 0x01f */ 0x73, /* s */ - /* 32, 0x020 */ 0x64, /* d */ - /* 33, 0x021 */ 0x66, /* f */ - /* 34, 0x022 */ 0x67, /* g */ - /* 35, 0x023 */ 0x68, /* h */ - /* 36, 0x024 */ 0x6A, /* j */ - /* 37, 0x025 */ 0x6B, /* k */ - /* 38, 0x026 */ 0x6C, /* l */ - /* 39, 0x027 */ 0x3B, /* semicolon */ - /* 40, 0x028 */ 0x27, /* apostrophe */ - /* 41, 0x029 */ 0x60, /* grave */ - /* 42, 0x02a */ 0xFFE1, /* Shift_L */ - /* 43, 0x02b */ 0x5C, /* backslash */ - /* 44, 0x02c */ 0x7A, /* z */ - /* 45, 0x02d */ 0x78, /* x */ - /* 46, 0x02e */ 0x63, /* c */ - /* 47, 0x02f */ 0x76, /* v */ - /* 48, 0x030 */ 0x62, /* b */ - /* 49, 0x031 */ 0x6E, /* n */ - /* 50, 0x032 */ 0x6D, /* m */ - /* 51, 0x033 */ 0x2C, /* comma */ - /* 52, 0x034 */ 0x2E, /* period */ - /* 53, 0x035 */ 0x2F, /* slash */ - /* 54, 0x036 */ 0xFFE2, /* Shift_R */ - /* 55, 0x037 */ 0xFFAA, /* KP_Multiply */ - /* 56, 0x038 */ 0xFFE9, /* Alt_L */ - /* 57, 0x039 */ 0x20, /* space */ - /* 58, 0x03a */ 0xFFE5, /* Caps_Lock */ - /* 59, 0x03b */ 0xFFBE, /* F1 */ - /* 60, 0x03c */ 0xFFBF, /* F2 */ - /* 61, 0x03d */ 0xFFC0, /* F3 */ - /* 62, 0x03e */ 0xFFC1, /* F4 */ - /* 63, 0x03f */ 0xFFC2, /* F5 */ - /* 64, 0x040 */ 0xFFC3, /* F6 */ - /* 65, 0x041 */ 0xFFC4, /* F7 */ - /* 66, 0x042 */ 0xFFC5, /* F8 */ - /* 67, 0x043 */ 0xFFC6, /* F9 */ - /* 68, 0x044 */ 0xFFC7, /* F10 */ - /* 69, 0x045 */ 0xFF7F, /* Num_Lock */ - /* 70, 0x046 */ 0xFF14, /* Scroll_Lock */ - /* 71, 0x047 */ 0xFFB7, /* KP_7 */ - /* 72, 0x048 */ 0XFFB8, /* KP_8 */ - /* 73, 0x049 */ 0XFFB9, /* KP_9 */ - /* 74, 0x04a */ 0xFFAD, /* KP_Subtract */ - /* 75, 0x04b */ 0xFFB4, /* KP_4 */ - /* 76, 0x04c */ 0xFFB5, /* KP_5 */ - /* 77, 0x04d */ 0xFFB6, /* KP_6 */ - /* 78, 0x04e */ 0xFFAB, /* KP_Add */ - /* 79, 0x04f */ 0xFFB1, /* KP_1 */ - /* 80, 0x050 */ 0xFFB2, /* KP_2 */ - /* 81, 0x051 */ 0xFFB3, /* KP_3 */ - /* 82, 0x052 */ 0xFFB0, /* KP_0 */ - /* 83, 0x053 */ 0xFFAE, /* KP_Decimal */ - /* 84, 0x054 */ 0x0, /* NoSymbol */ - /* 85, 0x055 */ 0x0, /* NoSymbol */ - /* 86, 0x056 */ 0x3C, /* less */ - /* 87, 0x057 */ 0xFFC8, /* F11 */ - /* 88, 0x058 */ 0xFFC9, /* F12 */ - /* 89, 0x059 */ 0x0, /* NoSymbol */ - /* 90, 0x05a */ 0xFF26, /* Katakana */ - /* 91, 0x05b */ 0xFF25, /* Hiragana */ - /* 92, 0x05c */ 0xFF23, /* Henkan_Mode */ - /* 93, 0x05d */ 0xFF27, /* Hiragana_Katakana */ - /* 94, 0x05e */ 0xFF22, /* Muhenkan */ - /* 95, 0x05f */ 0x0, /* NoSymbol */ - /* 96, 0x060 */ 0xFF8D, /* KP_Enter */ - /* 97, 0x061 */ 0xFFE4, /* Control_R */ - /* 98, 0x062 */ 0xFFAF, /* KP_Divide */ - /* 99, 0x063 */ 0xFF15, /* Sys_Req */ - /* 100, 0x064 */ 0xFFEA, /* Alt_R */ - /* 101, 0x065 */ 0xFF0A, /* Linefeed */ - /* 102, 0x066 */ 0xFF50, /* Home */ - /* 103, 0x067 */ 0xFF52, /* Up */ - /* 104, 0x068 */ 0xFF55, /* Prior */ - /* 105, 0x069 */ 0xFF51, /* Left */ - /* 106, 0x06a */ 0xFF53, /* Right */ - /* 107, 0x06b */ 0xFF57, /* End */ - /* 108, 0x06c */ 0xFF54, /* Down */ - /* 109, 0x06d */ 0xFF56, /* Next */ - /* 110, 0x06e */ 0xFF63, /* Insert */ - /* 111, 0x06f */ 0xFFFF, /* Delete */ - /* 112, 0x070 */ 0x0, /* NoSymbol */ - /* 113, 0x071 */ 0x1008FF12, /* XF86AudioMute */ - /* 114, 0x072 */ 0x1008FF11, /* XF86AudioLowerVolume */ - /* 115, 0x073 */ 0x1008FF13, /* XF86AudioRaiseVolume */ - /* 116, 0x074 */ 0x1008FF2A, /* XF86PowerOff */ - /* 117, 0x075 */ 0xFFBD, /* KP_Equal */ - /* 118, 0x076 */ 0xB1, /* plusminus */ - /* 119, 0x077 */ 0xFF13, /* Pause */ - /* 120, 0x078 */ 0x1008FF4A, /* XF86LaunchA */ - /* 121, 0x079 */ 0xFFAC, /* KP_Separator */ - /* 122, 0x07a */ 0xFF31, /* Hangul */ - /* 123, 0x07b */ 0xFF34, /* Hangul_Hanja */ - /* 124, 0x07c */ 0x0, /* NoSymbol */ - /* 125, 0x07d */ 0xFFE7, /* Meta_L */ - /* 126, 0x07e */ 0xFFE8, /* Meta_R */ - /* 127, 0x07f */ 0xFF67, /* Menu */ - /* 128, 0x080 */ 0x00, /* NoSymbol */ - /* 129, 0x081 */ 0xFF66, /* Redo */ - /* 130, 0x082 */ 0x1005FF70, /* SunProps */ - /* 131, 0x083 */ 0xFF65, /* Undo */ - /* 132, 0x084 */ 0x1005FF71, /* SunFront */ - /* 133, 0x085 */ 0x1008FF57, /* XF86Copy */ - /* 134, 0x086 */ 0x1008FF6B, /* XF86Open */ - /* 135, 0x087 */ 0x1008FF6D, /* XF86Paste */ - /* 136, 0x088 */ 0xFF68, /* Find */ - /* 137, 0x089 */ 0x1008FF58, /* XF86Cut */ - /* 138, 0x08a */ 0xFF6A, /* Help */ - /* 139, 0x08b */ 0xFF67, /* Menu */ - /* 140, 0x08c */ 0x1008FF1D, /* XF86Calculator */ - /* 141, 0x08d */ 0x0, /* NoSymbol */ - /* 142, 0x08e */ 0x1008FF2F, /* XF86Sleep */ - /* 143, 0x08f */ 0x1008FF2B, /* XF86WakeUp */ - /* 144, 0x090 */ 0x1008FF5D, /* XF86Explorer */ - /* 145, 0x091 */ 0x1008FF7B, /* XF86Send */ - /* 146, 0x092 */ 0x0, /* NoSymbol */ - /* 147, 0x093 */ 0x1008FF8A, /* XF86Xfer */ - /* 148, 0x094 */ 0x1008FF41, /* XF86Launch1 */ - /* 149, 0x095 */ 0x1008FF42, /* XF86Launch2 */ - /* 150, 0x096 */ 0x1008FF2E, /* XF86WWW */ - /* 151, 0x097 */ 0x1008FF5A, /* XF86DOS */ - /* 152, 0x098 */ 0x1008FF2D, /* XF86ScreenSaver */ - /* 153, 0x099 */ 0x1008FF74, /* XF86RotateWindows */ - /* 154, 0x09a */ 0x1008FF7F, /* XF86TaskPane */ - /* 155, 0x09b */ 0x1008FF19, /* XF86Mail */ - /* 156, 0x09c */ 0x1008FF30, /* XF86Favorites */ - /* 157, 0x09d */ 0x1008FF33, /* XF86MyComputer */ - /* 158, 0x09e */ 0x1008FF26, /* XF86Back */ - /* 159, 0x09f */ 0x1008FF27, /* XF86Forward */ - /* 160, 0x0a0 */ 0x0, /* NoSymbol */ - /* 161, 0x0a1 */ 0x1008FF2C, /* XF86Eject */ - /* 162, 0x0a2 */ 0x1008FF2C, /* XF86Eject */ - /* 163, 0x0a3 */ 0x1008FF17, /* XF86AudioNext */ - /* 164, 0x0a4 */ 0x1008FF14, /* XF86AudioPlay */ - /* 165, 0x0a5 */ 0x1008FF16, /* XF86AudioPrev */ - /* 166, 0x0a6 */ 0x1008FF15, /* XF86AudioStop */ - /* 167, 0x0a7 */ 0x1008FF1C, /* XF86AudioRecord */ - /* 168, 0x0a8 */ 0x1008FF3E, /* XF86AudioRewind */ - /* 169, 0x0a9 */ 0x1008FF6E, /* XF86Phone */ - /* 170, 0x0aa */ 0x0, /* NoSymbol */ - /* 171, 0x0ab */ 0x1008FF81, /* XF86Tools */ - /* 172, 0x0ac */ 0x1008FF18, /* XF86HomePage */ - /* 173, 0x0ad */ 0x1008FF73, /* XF86Reload */ - /* 174, 0x0ae */ 0x1008FF56, /* XF86Close */ - /* 175, 0x0af */ 0x0, /* NoSymbol */ - /* 176, 0x0b0 */ 0x0, /* NoSymbol */ - /* 177, 0x0b1 */ 0x1008FF78, /* XF86ScrollUp */ - /* 178, 0x0b2 */ 0x1008FF79, /* XF86ScrollDown */ - /* 179, 0x0b3 */ 0x0, /* NoSymbol */ - /* 180, 0x0b4 */ 0x0, /* NoSymbol */ - /* 181, 0x0b5 */ 0x1008FF68, /* XF86New */ - /* 182, 0x0b6 */ 0xFF66, /* Redo */ - /* 183, 0x0b7 */ 0xFFCA, /* F13 */ - /* 184, 0x0b8 */ 0xFFCB, /* F14 */ - /* 185, 0x0b9 */ 0xFFCC, /* F15 */ - /* 186, 0x0ba */ 0xFFCD, /* F16 */ - /* 187, 0x0bb */ 0xFFCE, /* F17 */ - /* 188, 0x0bc */ 0xFFCF, /* F18 */ - /* 189, 0x0bd */ 0xFFD0, /* F19 */ - /* 190, 0x0be */ 0xFFD1, /* F20 */ - /* 191, 0x0bf */ 0xFFD2, /* F21 */ - /* 192, 0x0c0 */ 0xFFD3, /* F22 */ - /* 193, 0x0c1 */ 0xFFD4, /* F23 */ - /* 194, 0x0c2 */ 0xFFD5, /* F24 */ - /* 195, 0x0c3 */ 0x0, /* NoSymbol */ - /* 196, 0x0c4 */ 0x0, /* NoSymbol */ - /* 197, 0x0c5 */ 0x0, /* NoSymbol */ - /* 198, 0x0c6 */ 0x0, /* NoSymbol */ - /* 199, 0x0c7 */ 0x0, /* NoSymbol */ - /* 200, 0x0c8 */ 0x1008FF14, /* XF86AudioPlay */ - /* 201, 0x0c9 */ 0x1008FF31, /* XF86AudioPause */ - /* 202, 0x0ca */ 0x1008FF43, /* XF86Launch3 */ - /* 203, 0x0cb */ 0x1008FF44, /* XF86Launch4 */ - /* 204, 0x0cc */ 0x1008FF4B, /* XF86LaunchB */ - /* 205, 0x0cd */ 0x1008FFA7, /* XF86Suspend */ - /* 206, 0x0ce */ 0x1008FF56, /* XF86Close */ - /* 207, 0x0cf */ 0x1008FF14, /* XF86AudioPlay */ - /* 208, 0x0d0 */ 0x1008FF97, /* XF86AudioForward */ - /* 209, 0x0d1 */ 0x0, /* NoSymbol */ - /* 210, 0x0d2 */ 0xFF61, /* Print */ - /* 211, 0x0d3 */ 0x0, /* NoSymbol */ - /* 212, 0x0d4 */ 0x1008FF8F, /* XF86WebCam */ - /* 213, 0x0d5 */ 0x1008FFB6, /* XF86AudioPreset */ - /* 214, 0x0d6 */ 0x0, /* NoSymbol */ - /* 215, 0x0d7 */ 0x1008FF19, /* XF86Mail */ - /* 216, 0x0d8 */ 0x1008FF8E, /* XF86Messenger */ - /* 217, 0x0d9 */ 0x1008FF1B, /* XF86Search */ - /* 218, 0x0da */ 0x1008FF5F, /* XF86Go */ - /* 219, 0x0db */ 0x1008FF3C, /* XF86Finance */ - /* 220, 0x0dc */ 0x1008FF5E, /* XF86Game */ - /* 221, 0x0dd */ 0x1008FF36, /* XF86Shop */ - /* 222, 0x0de */ 0x0, /* NoSymbol */ - /* 223, 0x0df */ 0xFF69, /* Cancel */ - /* 224, 0x0e0 */ 0x1008FF03, /* XF86MonBrightnessDown */ - /* 225, 0x0e1 */ 0x1008FF02, /* XF86MonBrightnessUp */ - /* 226, 0x0e2 */ 0x1008FF32, /* XF86AudioMedia */ - /* 227, 0x0e3 */ 0x1008FF59, /* XF86Display */ - /* 228, 0x0e4 */ 0x1008FF04, /* XF86KbdLightOnOff */ - /* 229, 0x0e5 */ 0x1008FF06, /* XF86KbdBrightnessDown */ - /* 230, 0x0e6 */ 0x1008FF05, /* XF86KbdBrightnessUp */ - /* 231, 0x0e7 */ 0x1008FF7B, /* XF86Send */ - /* 232, 0x0e8 */ 0x1008FF72, /* XF86Reply */ - /* 233, 0x0e9 */ 0x1008FF90, /* XF86MailForward */ - /* 234, 0x0ea */ 0x1008FF77, /* XF86Save */ - /* 235, 0x0eb */ 0x1008FF5B, /* XF86Documents */ - /* 236, 0x0ec */ 0x1008FF93, /* XF86Battery */ - /* 237, 0x0ed */ 0x1008FF94, /* XF86Bluetooth */ - /* 238, 0x0ee */ 0x1008FF95, /* XF86WLAN */ - /* 239, 0x0ef */ 0x1008FF96, /* XF86UWB */ - /* 240, 0x0f0 */ 0x0, /* NoSymbol */ - /* 241, 0x0f1 */ 0x1008FE22, /* XF86Next_VMode */ - /* 242, 0x0f2 */ 0x1008FE23, /* XF86Prev_VMode */ - /* 243, 0x0f3 */ 0x1008FF07, /* XF86MonBrightnessCycle */ - /* 244, 0x0f4 */ 0x100810F4, /* XF86BrightnessAuto */ - /* 245, 0x0f5 */ 0x100810F5, /* XF86DisplayOff */ - /* 246, 0x0f6 */ 0x1008FFB4, /* XF86WWAN */ - /* 247, 0x0f7 */ 0x1008FFB5, /* XF86RFKill */ + /* 0, 0x000 */ 0x0, // NoSymbol + /* 1, 0x001 */ 0xFF1B, // Escape + /* 2, 0x002 */ 0x31, // 1 + /* 3, 0x003 */ 0x32, // 2 + /* 4, 0x004 */ 0x33, // 3 + /* 5, 0x005 */ 0x34, // 4 + /* 6, 0x006 */ 0x35, // 5 + /* 7, 0x007 */ 0x36, // 6 + /* 8, 0x008 */ 0x37, // 7 + /* 9, 0x009 */ 0x38, // 8 + /* 10, 0x00a */ 0x39, // 9 + /* 11, 0x00b */ 0x30, // 0 + /* 12, 0x00c */ 0x2D, // minus + /* 13, 0x00d */ 0x3D, // equal + /* 14, 0x00e */ 0xFF08, // BackSpace + /* 15, 0x00f */ 0xFF09, // Tab + /* 16, 0x010 */ 0x71, // q + /* 17, 0x011 */ 0x77, // w + /* 18, 0x012 */ 0x65, // e + /* 19, 0x013 */ 0x72, // r + /* 20, 0x014 */ 0x74, // t + /* 21, 0x015 */ 0x79, // y + /* 22, 0x016 */ 0x75, // u + /* 23, 0x017 */ 0x69, // i + /* 24, 0x018 */ 0x6F, // o + /* 25, 0x019 */ 0x70, // p + /* 26, 0x01a */ 0x5B, // bracketleft + /* 27, 0x01b */ 0x5D, // bracketright + /* 28, 0x01c */ 0xFF0D, // Return + /* 29, 0x01d */ 0xFFE3, // Control_L + /* 30, 0x01e */ 0x61, // a + /* 31, 0x01f */ 0x73, // s + /* 32, 0x020 */ 0x64, // d + /* 33, 0x021 */ 0x66, // f + /* 34, 0x022 */ 0x67, // g + /* 35, 0x023 */ 0x68, // h + /* 36, 0x024 */ 0x6A, // j + /* 37, 0x025 */ 0x6B, // k + /* 38, 0x026 */ 0x6C, // l + /* 39, 0x027 */ 0x3B, // semicolon + /* 40, 0x028 */ 0x27, // apostrophe + /* 41, 0x029 */ 0x60, // grave + /* 42, 0x02a */ 0xFFE1, // Shift_L + /* 43, 0x02b */ 0x5C, // backslash + /* 44, 0x02c */ 0x7A, // z + /* 45, 0x02d */ 0x78, // x + /* 46, 0x02e */ 0x63, // c + /* 47, 0x02f */ 0x76, // v + /* 48, 0x030 */ 0x62, // b + /* 49, 0x031 */ 0x6E, // n + /* 50, 0x032 */ 0x6D, // m + /* 51, 0x033 */ 0x2C, // comma + /* 52, 0x034 */ 0x2E, // period + /* 53, 0x035 */ 0x2F, // slash + /* 54, 0x036 */ 0xFFE2, // Shift_R + /* 55, 0x037 */ 0xFFAA, // KP_Multiply + /* 56, 0x038 */ 0xFFE9, // Alt_L + /* 57, 0x039 */ 0x20, // space + /* 58, 0x03a */ 0xFFE5, // Caps_Lock + /* 59, 0x03b */ 0xFFBE, // F1 + /* 60, 0x03c */ 0xFFBF, // F2 + /* 61, 0x03d */ 0xFFC0, // F3 + /* 62, 0x03e */ 0xFFC1, // F4 + /* 63, 0x03f */ 0xFFC2, // F5 + /* 64, 0x040 */ 0xFFC3, // F6 + /* 65, 0x041 */ 0xFFC4, // F7 + /* 66, 0x042 */ 0xFFC5, // F8 + /* 67, 0x043 */ 0xFFC6, // F9 + /* 68, 0x044 */ 0xFFC7, // F10 + /* 69, 0x045 */ 0xFF7F, // Num_Lock + /* 70, 0x046 */ 0xFF14, // Scroll_Lock + /* 71, 0x047 */ 0xFFB7, // KP_7 + /* 72, 0x048 */ 0XFFB8, // KP_8 + /* 73, 0x049 */ 0XFFB9, // KP_9 + /* 74, 0x04a */ 0xFFAD, // KP_Subtract + /* 75, 0x04b */ 0xFFB4, // KP_4 + /* 76, 0x04c */ 0xFFB5, // KP_5 + /* 77, 0x04d */ 0xFFB6, // KP_6 + /* 78, 0x04e */ 0xFFAB, // KP_Add + /* 79, 0x04f */ 0xFFB1, // KP_1 + /* 80, 0x050 */ 0xFFB2, // KP_2 + /* 81, 0x051 */ 0xFFB3, // KP_3 + /* 82, 0x052 */ 0xFFB0, // KP_0 + /* 83, 0x053 */ 0xFFAE, // KP_Decimal + /* 84, 0x054 */ 0x0, // NoSymbol + /* 85, 0x055 */ 0x0, // NoSymbol + /* 86, 0x056 */ 0x3C, // less + /* 87, 0x057 */ 0xFFC8, // F11 + /* 88, 0x058 */ 0xFFC9, // F12 + /* 89, 0x059 */ 0x0, // NoSymbol + /* 90, 0x05a */ 0xFF26, // Katakana + /* 91, 0x05b */ 0xFF25, // Hiragana + /* 92, 0x05c */ 0xFF23, // Henkan_Mode + /* 93, 0x05d */ 0xFF27, // Hiragana_Katakana + /* 94, 0x05e */ 0xFF22, // Muhenkan + /* 95, 0x05f */ 0x0, // NoSymbol + /* 96, 0x060 */ 0xFF8D, // KP_Enter + /* 97, 0x061 */ 0xFFE4, // Control_R + /* 98, 0x062 */ 0xFFAF, // KP_Divide + /* 99, 0x063 */ 0xFF15, // Sys_Req + /* 100, 0x064 */ 0xFFEA, // Alt_R + /* 101, 0x065 */ 0xFF0A, // Linefeed + /* 102, 0x066 */ 0xFF50, // Home + /* 103, 0x067 */ 0xFF52, // Up + /* 104, 0x068 */ 0xFF55, // Prior + /* 105, 0x069 */ 0xFF51, // Left + /* 106, 0x06a */ 0xFF53, // Right + /* 107, 0x06b */ 0xFF57, // End + /* 108, 0x06c */ 0xFF54, // Down + /* 109, 0x06d */ 0xFF56, // Next + /* 110, 0x06e */ 0xFF63, // Insert + /* 111, 0x06f */ 0xFFFF, // Delete + /* 112, 0x070 */ 0x0, // NoSymbol + /* 113, 0x071 */ 0x1008FF12, // XF86AudioMute + /* 114, 0x072 */ 0x1008FF11, // XF86AudioLowerVolume + /* 115, 0x073 */ 0x1008FF13, // XF86AudioRaiseVolume + /* 116, 0x074 */ 0x1008FF2A, // XF86PowerOff + /* 117, 0x075 */ 0xFFBD, // KP_Equal + /* 118, 0x076 */ 0xB1, // plusminus + /* 119, 0x077 */ 0xFF13, // Pause + /* 120, 0x078 */ 0x1008FF4A, // XF86LaunchA + /* 121, 0x079 */ 0xFFAC, // KP_Separator + /* 122, 0x07a */ 0xFF31, // Hangul + /* 123, 0x07b */ 0xFF34, // Hangul_Hanja + /* 124, 0x07c */ 0x0, // NoSymbol + /* 125, 0x07d */ 0xFFE7, // Meta_L + /* 126, 0x07e */ 0xFFE8, // Meta_R + /* 127, 0x07f */ 0xFF67, // Menu + /* 128, 0x080 */ 0x00, // NoSymbol + /* 129, 0x081 */ 0xFF66, // Redo + /* 130, 0x082 */ 0x1005FF70, // SunProps + /* 131, 0x083 */ 0xFF65, // Undo + /* 132, 0x084 */ 0x1005FF71, // SunFront + /* 133, 0x085 */ 0x1008FF57, // XF86Copy + /* 134, 0x086 */ 0x1008FF6B, // XF86Open + /* 135, 0x087 */ 0x1008FF6D, // XF86Paste + /* 136, 0x088 */ 0xFF68, // Find + /* 137, 0x089 */ 0x1008FF58, // XF86Cut + /* 138, 0x08a */ 0xFF6A, // Help + /* 139, 0x08b */ 0xFF67, // Menu + /* 140, 0x08c */ 0x1008FF1D, // XF86Calculator + /* 141, 0x08d */ 0x0, // NoSymbol + /* 142, 0x08e */ 0x1008FF2F, // XF86Sleep + /* 143, 0x08f */ 0x1008FF2B, // XF86WakeUp + /* 144, 0x090 */ 0x1008FF5D, // XF86Explorer + /* 145, 0x091 */ 0x1008FF7B, // XF86Send + /* 146, 0x092 */ 0x0, // NoSymbol + /* 147, 0x093 */ 0x1008FF8A, // XF86Xfer + /* 148, 0x094 */ 0x1008FF41, // XF86Launch1 + /* 149, 0x095 */ 0x1008FF42, // XF86Launch2 + /* 150, 0x096 */ 0x1008FF2E, // XF86WWW + /* 151, 0x097 */ 0x1008FF5A, // XF86DOS + /* 152, 0x098 */ 0x1008FF2D, // XF86ScreenSaver + /* 153, 0x099 */ 0x1008FF74, // XF86RotateWindows + /* 154, 0x09a */ 0x1008FF7F, // XF86TaskPane + /* 155, 0x09b */ 0x1008FF19, // XF86Mail + /* 156, 0x09c */ 0x1008FF30, // XF86Favorites + /* 157, 0x09d */ 0x1008FF33, // XF86MyComputer + /* 158, 0x09e */ 0x1008FF26, // XF86Back + /* 159, 0x09f */ 0x1008FF27, // XF86Forward + /* 160, 0x0a0 */ 0x0, // NoSymbol + /* 161, 0x0a1 */ 0x1008FF2C, // XF86Eject + /* 162, 0x0a2 */ 0x1008FF2C, // XF86Eject + /* 163, 0x0a3 */ 0x1008FF17, // XF86AudioNext + /* 164, 0x0a4 */ 0x1008FF14, // XF86AudioPlay + /* 165, 0x0a5 */ 0x1008FF16, // XF86AudioPrev + /* 166, 0x0a6 */ 0x1008FF15, // XF86AudioStop + /* 167, 0x0a7 */ 0x1008FF1C, // XF86AudioRecord + /* 168, 0x0a8 */ 0x1008FF3E, // XF86AudioRewind + /* 169, 0x0a9 */ 0x1008FF6E, // XF86Phone + /* 170, 0x0aa */ 0x0, // NoSymbol + /* 171, 0x0ab */ 0x1008FF81, // XF86Tools + /* 172, 0x0ac */ 0x1008FF18, // XF86HomePage + /* 173, 0x0ad */ 0x1008FF73, // XF86Reload + /* 174, 0x0ae */ 0x1008FF56, // XF86Close + /* 175, 0x0af */ 0x0, // NoSymbol + /* 176, 0x0b0 */ 0x0, // NoSymbol + /* 177, 0x0b1 */ 0x1008FF78, // XF86ScrollUp + /* 178, 0x0b2 */ 0x1008FF79, // XF86ScrollDown + /* 179, 0x0b3 */ 0x0, // NoSymbol + /* 180, 0x0b4 */ 0x0, // NoSymbol + /* 181, 0x0b5 */ 0x1008FF68, // XF86New + /* 182, 0x0b6 */ 0xFF66, // Redo + /* 183, 0x0b7 */ 0xFFCA, // F13 + /* 184, 0x0b8 */ 0xFFCB, // F14 + /* 185, 0x0b9 */ 0xFFCC, // F15 + /* 186, 0x0ba */ 0xFFCD, // F16 + /* 187, 0x0bb */ 0xFFCE, // F17 + /* 188, 0x0bc */ 0xFFCF, // F18 + /* 189, 0x0bd */ 0xFFD0, // F19 + /* 190, 0x0be */ 0xFFD1, // F20 + /* 191, 0x0bf */ 0xFFD2, // F21 + /* 192, 0x0c0 */ 0xFFD3, // F22 + /* 193, 0x0c1 */ 0xFFD4, // F23 + /* 194, 0x0c2 */ 0xFFD5, // F24 + /* 195, 0x0c3 */ 0x0, // NoSymbol + /* 196, 0x0c4 */ 0x0, // NoSymbol + /* 197, 0x0c5 */ 0x0, // NoSymbol + /* 198, 0x0c6 */ 0x0, // NoSymbol + /* 199, 0x0c7 */ 0x0, // NoSymbol + /* 200, 0x0c8 */ 0x1008FF14, // XF86AudioPlay + /* 201, 0x0c9 */ 0x1008FF31, // XF86AudioPause + /* 202, 0x0ca */ 0x1008FF43, // XF86Launch3 + /* 203, 0x0cb */ 0x1008FF44, // XF86Launch4 + /* 204, 0x0cc */ 0x1008FF4B, // XF86LaunchB + /* 205, 0x0cd */ 0x1008FFA7, // XF86Suspend + /* 206, 0x0ce */ 0x1008FF56, // XF86Close + /* 207, 0x0cf */ 0x1008FF14, // XF86AudioPlay + /* 208, 0x0d0 */ 0x1008FF97, // XF86AudioForward + /* 209, 0x0d1 */ 0x0, // NoSymbol + /* 210, 0x0d2 */ 0xFF61, // Print + /* 211, 0x0d3 */ 0x0, // NoSymbol + /* 212, 0x0d4 */ 0x1008FF8F, // XF86WebCam + /* 213, 0x0d5 */ 0x1008FFB6, // XF86AudioPreset + /* 214, 0x0d6 */ 0x0, // NoSymbol + /* 215, 0x0d7 */ 0x1008FF19, // XF86Mail + /* 216, 0x0d8 */ 0x1008FF8E, // XF86Messenger + /* 217, 0x0d9 */ 0x1008FF1B, // XF86Search + /* 218, 0x0da */ 0x1008FF5F, // XF86Go + /* 219, 0x0db */ 0x1008FF3C, // XF86Finance + /* 220, 0x0dc */ 0x1008FF5E, // XF86Game + /* 221, 0x0dd */ 0x1008FF36, // XF86Shop + /* 222, 0x0de */ 0x0, // NoSymbol + /* 223, 0x0df */ 0xFF69, // Cancel + /* 224, 0x0e0 */ 0x1008FF03, // XF86MonBrightnessDown + /* 225, 0x0e1 */ 0x1008FF02, // XF86MonBrightnessUp + /* 226, 0x0e2 */ 0x1008FF32, // XF86AudioMedia + /* 227, 0x0e3 */ 0x1008FF59, // XF86Display + /* 228, 0x0e4 */ 0x1008FF04, // XF86KbdLightOnOff + /* 229, 0x0e5 */ 0x1008FF06, // XF86KbdBrightnessDown + /* 230, 0x0e6 */ 0x1008FF05, // XF86KbdBrightnessUp + /* 231, 0x0e7 */ 0x1008FF7B, // XF86Send + /* 232, 0x0e8 */ 0x1008FF72, // XF86Reply + /* 233, 0x0e9 */ 0x1008FF90, // XF86MailForward + /* 234, 0x0ea */ 0x1008FF77, // XF86Save + /* 235, 0x0eb */ 0x1008FF5B, // XF86Documents + /* 236, 0x0ec */ 0x1008FF93, // XF86Battery + /* 237, 0x0ed */ 0x1008FF94, // XF86Bluetooth + /* 238, 0x0ee */ 0x1008FF95, // XF86WLAN + /* 239, 0x0ef */ 0x1008FF96, // XF86UWB + /* 240, 0x0f0 */ 0x0, // NoSymbol + /* 241, 0x0f1 */ 0x1008FE22, // XF86Next_VMode + /* 242, 0x0f2 */ 0x1008FE23, // XF86Prev_VMode + /* 243, 0x0f3 */ 0x1008FF07, // XF86MonBrightnessCycle + /* 244, 0x0f4 */ 0x100810F4, // XF86BrightnessAuto + /* 245, 0x0f5 */ 0x100810F5, // XF86DisplayOff + /* 246, 0x0f6 */ 0x1008FFB4, // XF86WWAN + /* 247, 0x0f7 */ 0x1008FFB5, // XF86RFKill }; -#if 0 /* Here is a script to generate the ExtendedLinuxKeycodeKeysyms table */ +#if 0 // Here is a script to generate the ExtendedLinuxKeycodeKeysyms table #!/bin/bash function process_line @@ -329,70 +329,70 @@ static const struct { Uint32 keysym; int linux_keycode; } ExtendedLinuxKeycodeKeysyms[] = { - { 0x1008FF2C, 0x0a2 }, /* XF86XK_Eject */ - { 0x1008FF68, 0x0b5 }, /* XF86XK_New */ - { 0x0000FF66, 0x0b6 }, /* XK_Redo */ - { 0x1008FF4B, 0x0cc }, /* XF86XK_LaunchB */ - { 0x1008FF59, 0x0e3 }, /* XF86XK_Display */ - { 0x1008FF04, 0x0e4 }, /* XF86XK_KbdLightOnOff */ - { 0x1008FF06, 0x0e5 }, /* XF86XK_KbdBrightnessDown */ - { 0x1008FF05, 0x0e6 }, /* XF86XK_KbdBrightnessUp */ - { 0x1008FF7B, 0x0e7 }, /* XF86XK_Send */ - { 0x1008FF72, 0x0e8 }, /* XF86XK_Reply */ - { 0x1008FF90, 0x0e9 }, /* XF86XK_MailForward */ - { 0x1008FF77, 0x0ea }, /* XF86XK_Save */ - { 0x1008FF5B, 0x0eb }, /* XF86XK_Documents */ - { 0x1008FF93, 0x0ec }, /* XF86XK_Battery */ - { 0x1008FF94, 0x0ed }, /* XF86XK_Bluetooth */ - { 0x1008FF95, 0x0ee }, /* XF86XK_WLAN */ - { 0x1008FF96, 0x0ef }, /* XF86XK_UWB */ - { 0x1008FE22, 0x0f1 }, /* XF86XK_Next_VMode */ - { 0x1008FE23, 0x0f2 }, /* XF86XK_Prev_VMode */ - { 0x1008FF07, 0x0f3 }, /* XF86XK_MonBrightnessCycle */ - { 0x1008FFB4, 0x0f6 }, /* XF86XK_WWAN */ - { 0x1008FFB5, 0x0f7 }, /* XF86XK_RFKill */ - { 0x1008FFB2, 0x0f8 }, /* XF86XK_AudioMicMute */ - { 0x1008FF9C, 0x173 }, /* XF86XK_CycleAngle */ - { 0x1008FFB8, 0x174 }, /* XF86XK_FullScreen */ - { 0x1008FF87, 0x189 }, /* XF86XK_Video */ - { 0x1008FF20, 0x18d }, /* XF86XK_Calendar */ - { 0x1008FF99, 0x19a }, /* XF86XK_AudioRandomPlay */ - { 0x1008FF5E, 0x1a1 }, /* XF86XK_Game */ - { 0x1008FF8B, 0x1a2 }, /* XF86XK_ZoomIn */ - { 0x1008FF8C, 0x1a3 }, /* XF86XK_ZoomOut */ - { 0x1008FF89, 0x1a5 }, /* XF86XK_Word */ - { 0x1008FF5C, 0x1a7 }, /* XF86XK_Excel */ - { 0x1008FF69, 0x1ab }, /* XF86XK_News */ - { 0x1008FF8E, 0x1ae }, /* XF86XK_Messenger */ - { 0x1008FF61, 0x1b1 }, /* XF86XK_LogOff */ - { 0x00000024, 0x1b2 }, /* XK_dollar */ - { 0x000020AC, 0x1b3 }, /* XK_EuroSign */ - { 0x1008FF9D, 0x1b4 }, /* XF86XK_FrameBack */ - { 0x1008FF9E, 0x1b5 }, /* XF86XK_FrameForward */ - { 0x0000FFF1, 0x1f1 }, /* XK_braille_dot_1 */ - { 0x0000FFF2, 0x1f2 }, /* XK_braille_dot_2 */ - { 0x0000FFF3, 0x1f3 }, /* XK_braille_dot_3 */ - { 0x0000FFF4, 0x1f4 }, /* XK_braille_dot_4 */ - { 0x0000FFF5, 0x1f5 }, /* XK_braille_dot_5 */ - { 0x0000FFF6, 0x1f6 }, /* XK_braille_dot_6 */ - { 0x0000FFF7, 0x1f7 }, /* XK_braille_dot_7 */ - { 0x0000FFF8, 0x1f8 }, /* XK_braille_dot_8 */ - { 0x0000FFF9, 0x1f9 }, /* XK_braille_dot_9 */ - { 0x0000FFF1, 0x1fa }, /* XK_braille_dot_1 */ - { 0x1008FFA9, 0x212 }, /* XF86XK_TouchpadToggle */ - { 0x1008FFB0, 0x213 }, /* XF86XK_TouchpadOn */ - { 0x1008FFB1, 0x214 }, /* XF86XK_TouchpadOff */ - { 0x1008FFB7, 0x231 }, /* XF86XK_RotationLockToggle */ - { 0x0000FE08, 0x248 }, /* XK_ISO_Next_Group */ + { 0x1008FF2C, 0x0a2 }, // XF86XK_Eject + { 0x1008FF68, 0x0b5 }, // XF86XK_New + { 0x0000FF66, 0x0b6 }, // XK_Redo + { 0x1008FF4B, 0x0cc }, // XF86XK_LaunchB + { 0x1008FF59, 0x0e3 }, // XF86XK_Display + { 0x1008FF04, 0x0e4 }, // XF86XK_KbdLightOnOff + { 0x1008FF06, 0x0e5 }, // XF86XK_KbdBrightnessDown + { 0x1008FF05, 0x0e6 }, // XF86XK_KbdBrightnessUp + { 0x1008FF7B, 0x0e7 }, // XF86XK_Send + { 0x1008FF72, 0x0e8 }, // XF86XK_Reply + { 0x1008FF90, 0x0e9 }, // XF86XK_MailForward + { 0x1008FF77, 0x0ea }, // XF86XK_Save + { 0x1008FF5B, 0x0eb }, // XF86XK_Documents + { 0x1008FF93, 0x0ec }, // XF86XK_Battery + { 0x1008FF94, 0x0ed }, // XF86XK_Bluetooth + { 0x1008FF95, 0x0ee }, // XF86XK_WLAN + { 0x1008FF96, 0x0ef }, // XF86XK_UWB + { 0x1008FE22, 0x0f1 }, // XF86XK_Next_VMode + { 0x1008FE23, 0x0f2 }, // XF86XK_Prev_VMode + { 0x1008FF07, 0x0f3 }, // XF86XK_MonBrightnessCycle + { 0x1008FFB4, 0x0f6 }, // XF86XK_WWAN + { 0x1008FFB5, 0x0f7 }, // XF86XK_RFKill + { 0x1008FFB2, 0x0f8 }, // XF86XK_AudioMicMute + { 0x1008FF9C, 0x173 }, // XF86XK_CycleAngle + { 0x1008FFB8, 0x174 }, // XF86XK_FullScreen + { 0x1008FF87, 0x189 }, // XF86XK_Video + { 0x1008FF20, 0x18d }, // XF86XK_Calendar + { 0x1008FF99, 0x19a }, // XF86XK_AudioRandomPlay + { 0x1008FF5E, 0x1a1 }, // XF86XK_Game + { 0x1008FF8B, 0x1a2 }, // XF86XK_ZoomIn + { 0x1008FF8C, 0x1a3 }, // XF86XK_ZoomOut + { 0x1008FF89, 0x1a5 }, // XF86XK_Word + { 0x1008FF5C, 0x1a7 }, // XF86XK_Excel + { 0x1008FF69, 0x1ab }, // XF86XK_News + { 0x1008FF8E, 0x1ae }, // XF86XK_Messenger + { 0x1008FF61, 0x1b1 }, // XF86XK_LogOff + { 0x00000024, 0x1b2 }, // XK_dollar + { 0x000020AC, 0x1b3 }, // XK_EuroSign + { 0x1008FF9D, 0x1b4 }, // XF86XK_FrameBack + { 0x1008FF9E, 0x1b5 }, // XF86XK_FrameForward + { 0x0000FFF1, 0x1f1 }, // XK_braille_dot_1 + { 0x0000FFF2, 0x1f2 }, // XK_braille_dot_2 + { 0x0000FFF3, 0x1f3 }, // XK_braille_dot_3 + { 0x0000FFF4, 0x1f4 }, // XK_braille_dot_4 + { 0x0000FFF5, 0x1f5 }, // XK_braille_dot_5 + { 0x0000FFF6, 0x1f6 }, // XK_braille_dot_6 + { 0x0000FFF7, 0x1f7 }, // XK_braille_dot_7 + { 0x0000FFF8, 0x1f8 }, // XK_braille_dot_8 + { 0x0000FFF9, 0x1f9 }, // XK_braille_dot_9 + { 0x0000FFF1, 0x1fa }, // XK_braille_dot_1 + { 0x1008FFA9, 0x212 }, // XF86XK_TouchpadToggle + { 0x1008FFB0, 0x213 }, // XF86XK_TouchpadOn + { 0x1008FFB1, 0x214 }, // XF86XK_TouchpadOff + { 0x1008FFB7, 0x231 }, // XF86XK_RotationLockToggle + { 0x0000FE08, 0x248 }, // XK_ISO_Next_Group }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode) { int i; Uint32 linux_keycode = 0; - /* First check our custom list */ + // First check our custom list for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) { if (keysym == KeySymToSDLScancode[i].keysym) { return KeySymToSDLScancode[i].scancode; @@ -400,7 +400,7 @@ SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode) } if (keysym >= 0x41 && keysym <= 0x5a) { - /* Normalize alphabetic keysyms to the lowercase form */ + // Normalize alphabetic keysyms to the lowercase form keysym += 0x20; } else if (keysym >= 0x10081000 && keysym <= 0x10081FFF) { /* The rest of the keysyms map to Linux keycodes, so use that mapping @@ -409,12 +409,12 @@ SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode) linux_keycode = (keysym - 0x10081000); } if (!linux_keycode) { - /* See if this keysym is an exact match in our table */ + // See if this keysym is an exact match in our table i = (keycode - 8); if (i >= 0 && i < SDL_arraysize(LinuxKeycodeKeysyms) && keysym == LinuxKeycodeKeysyms[i]) { linux_keycode = i; } else { - /* Scan the table for this keysym */ + // Scan the table for this keysym for (i = 0; i < SDL_arraysize(LinuxKeycodeKeysyms); ++i) { if (keysym == LinuxKeycodeKeysyms[i]) { linux_keycode = i; @@ -424,7 +424,7 @@ SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode) } } if (!linux_keycode) { - /* Scan the extended table for this keysym */ + // Scan the extended table for this keysym for (i = 0; i < SDL_arraysize(ExtendedLinuxKeycodeKeysyms); ++i) { if (keysym == ExtendedLinuxKeycodeKeysyms[i].keysym) { linux_keycode = ExtendedLinuxKeycodeKeysyms[i].linux_keycode; @@ -435,4 +435,4 @@ SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode) return SDL_GetScancodeFromTable(SDL_SCANCODE_TABLE_LINUX, linux_keycode); } -#endif /* SDL_VIDEO_DRIVER_WAYLAND */ +#endif // SDL_VIDEO_DRIVER_WAYLAND diff --git a/libs/SDL3/src/events/SDL_keysym_to_scancode_c.h b/libs/SDL3/src/events/SDL_keysym_to_scancode_c.h index 91611a5d1..2d504145e 100644 --- a/libs/SDL3/src/events/SDL_keysym_to_scancode_c.h +++ b/libs/SDL3/src/events/SDL_keysym_to_scancode_c.h @@ -22,7 +22,7 @@ #ifndef SDL_keysym_to_scancode_c_h_ #define SDL_keysym_to_scancode_c_h_ -/* This function only correctly maps letters and numbers for keyboards in US QWERTY layout */ +// This function only correctly maps letters and numbers for keyboards in US QWERTY layout extern SDL_Scancode SDL_GetScancodeFromKeySym(Uint32 keysym, Uint32 keycode); -#endif /* SDL_keysym_to_scancode_c_h_ */ +#endif // SDL_keysym_to_scancode_c_h_ diff --git a/libs/SDL3/src/events/SDL_mouse.c b/libs/SDL3/src/events/SDL_mouse.c index 885179c90..6e30e9d75 100644 --- a/libs/SDL3/src/events/SDL_mouse.c +++ b/libs/SDL3/src/events/SDL_mouse.c @@ -20,18 +20,19 @@ */ #include "SDL_internal.h" -/* General mouse handling code for SDL */ +// General mouse handling code for SDL #include "../SDL_hints_c.h" #include "../video/SDL_sysvideo.h" #include "SDL_events_c.h" #include "SDL_mouse_c.h" -#include "SDL_pen_c.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) +#if defined(SDL_PLATFORM_WINDOWS) #include "../core/windows/SDL_windows.h" // For GetDoubleClickTime() #endif -/* #define DEBUG_MOUSE */ +// #define DEBUG_MOUSE + +#define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30) typedef struct SDL_MouseInstance { @@ -39,15 +40,15 @@ typedef struct SDL_MouseInstance char *name; } SDL_MouseInstance; -/* The mouse state */ +// The mouse state static SDL_Mouse SDL_mouse; static int SDL_mouse_count; static SDL_MouseInstance *SDL_mice; -/* for mapping mouse events to touch */ -static SDL_bool track_mouse_down = SDL_FALSE; +// for mapping mouse events to touch +static bool track_mouse_down = false; -static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y); +static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y); static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { @@ -64,6 +65,17 @@ static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char * } } +static void SDLCALL SDL_MouseRelativeClipIntervalChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + if (hint && *hint) { + mouse->relative_mode_clip_interval = SDL_atoi(hint); + } else { + mouse->relative_mode_clip_interval = 3000; + } +} + static void SDLCALL SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; @@ -71,7 +83,7 @@ static void SDLCALL SDL_MouseDoubleClickRadiusChanged(void *userdata, const char if (hint && *hint) { mouse->double_click_radius = SDL_atoi(hint); } else { - mouse->double_click_radius = 32; /* 32 pixels seems about right for touch interfaces */ + mouse->double_click_radius = 32; // 32 pixels seems about right for touch interfaces } } @@ -80,10 +92,10 @@ static void SDLCALL SDL_MouseNormalSpeedScaleChanged(void *userdata, const char SDL_Mouse *mouse = (SDL_Mouse *)userdata; if (hint && *hint) { - mouse->enable_normal_speed_scale = SDL_TRUE; + mouse->enable_normal_speed_scale = true; mouse->normal_speed_scale = (float)SDL_atof(hint); } else { - mouse->enable_normal_speed_scale = SDL_FALSE; + mouse->enable_normal_speed_scale = false; mouse->normal_speed_scale = 1.0f; } } @@ -93,10 +105,10 @@ static void SDLCALL SDL_MouseRelativeSpeedScaleChanged(void *userdata, const cha SDL_Mouse *mouse = (SDL_Mouse *)userdata; if (hint && *hint) { - mouse->enable_relative_speed_scale = SDL_TRUE; + mouse->enable_relative_speed_scale = true; mouse->relative_speed_scale = (float)SDL_atof(hint); } else { - mouse->enable_relative_speed_scale = SDL_FALSE; + mouse->enable_relative_speed_scale = false; mouse->relative_speed_scale = 1.0f; } } @@ -105,14 +117,26 @@ static void SDLCALL SDL_MouseRelativeSystemScaleChanged(void *userdata, const ch { SDL_Mouse *mouse = (SDL_Mouse *)userdata; - mouse->enable_relative_system_scale = SDL_GetStringBoolean(hint, SDL_FALSE); + mouse->enable_relative_system_scale = SDL_GetStringBoolean(hint, false); +} + +static void SDLCALL SDL_MouseWarpEmulationChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->warp_emulation_hint = SDL_GetStringBoolean(hint, true); + + if (!mouse->warp_emulation_hint && mouse->warp_emulation_active) { + SDL_SetRelativeMouseMode(false); + mouse->warp_emulation_active = false; + } } static void SDLCALL SDL_TouchMouseEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; - mouse->touch_mouse_events = SDL_GetStringBoolean(hint, SDL_TRUE); + mouse->touch_mouse_events = SDL_GetStringBoolean(hint, true); } #ifdef SDL_PLATFORM_VITA @@ -139,12 +163,12 @@ static void SDLCALL SDL_VitaTouchMouseDeviceChanged(void *userdata, const char * static void SDLCALL SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; - SDL_bool default_value; + bool default_value; #if defined(SDL_PLATFORM_ANDROID) || (defined(SDL_PLATFORM_IOS) && !defined(SDL_PLATFORM_TVOS)) - default_value = SDL_TRUE; + default_value = true; #else - default_value = SDL_FALSE; + default_value = false; #endif mouse->mouse_touch_events = SDL_GetStringBoolean(hint, default_value); @@ -156,11 +180,11 @@ static void SDLCALL SDL_MouseTouchEventsChanged(void *userdata, const char *name static void SDLCALL SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; - SDL_bool auto_capture = SDL_GetStringBoolean(hint, SDL_TRUE); + bool auto_capture = SDL_GetStringBoolean(hint, true); if (auto_capture != mouse->auto_capture) { mouse->auto_capture = auto_capture; - SDL_UpdateMouseCapture(SDL_FALSE); + SDL_UpdateMouseCapture(false); } } @@ -168,11 +192,18 @@ static void SDLCALL SDL_MouseRelativeWarpMotionChanged(void *userdata, const cha { SDL_Mouse *mouse = (SDL_Mouse *)userdata; - mouse->relative_mode_warp_motion = SDL_GetStringBoolean(hint, SDL_FALSE); + mouse->relative_mode_warp_motion = SDL_GetStringBoolean(hint, false); +} + +static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->relative_mode_cursor_visible = SDL_GetStringBoolean(hint, false); } -/* Public functions */ -int SDL_PreInitMouse(void) +// Public functions +bool SDL_PreInitMouse(void) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -193,6 +224,9 @@ int SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, SDL_MouseRelativeSystemScaleChanged, mouse); + SDL_AddHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE, + SDL_MouseWarpEmulationChanged, mouse); + SDL_AddHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS, SDL_TouchMouseEventsChanged, mouse); @@ -210,10 +244,17 @@ int SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, SDL_MouseRelativeWarpMotionChanged, mouse); - mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */ + SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, + SDL_MouseRelativeCursorVisibleChanged, mouse); + + SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL, + SDL_MouseRelativeClipIntervalChanged, mouse); + + mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending - mouse->cursor_shown = SDL_TRUE; - return 0; + mouse->cursor_shown = true; + + return true; } void SDL_PostInitMouse(void) @@ -231,14 +272,12 @@ void SDL_PostInitMouse(void) SDL_DestroySurface(surface); } } - - SDL_PenInit(); } -SDL_bool SDL_IsMouse(Uint16 vendor, Uint16 product) +bool SDL_IsMouse(Uint16 vendor, Uint16 product) { - /* Eventually we'll have a blacklist of devices that enumerate as mice but aren't really */ - return SDL_TRUE; + // Eventually we'll have a blacklist of devices that enumerate as mice but aren't really + return true; } static int SDL_GetMouseIndex(SDL_MouseID mouseID) @@ -251,11 +290,11 @@ static int SDL_GetMouseIndex(SDL_MouseID mouseID) return -1; } -void SDL_AddMouse(SDL_MouseID mouseID, const char *name, SDL_bool send_event) +void SDL_AddMouse(SDL_MouseID mouseID, const char *name, bool send_event) { int mouse_index = SDL_GetMouseIndex(mouseID); if (mouse_index >= 0) { - /* We already know about this mouse */ + // We already know about this mouse return; } @@ -280,11 +319,11 @@ void SDL_AddMouse(SDL_MouseID mouseID, const char *name, SDL_bool send_event) } } -void SDL_RemoveMouse(SDL_MouseID mouseID) +void SDL_RemoveMouse(SDL_MouseID mouseID, bool send_event) { int mouse_index = SDL_GetMouseIndex(mouseID); if (mouse_index < 0) { - /* We don't know about this mouse */ + // We don't know about this mouse return; } @@ -295,7 +334,7 @@ void SDL_RemoveMouse(SDL_MouseID mouseID) } --SDL_mouse_count; - /* Remove any mouse input sources for this mouseID */ + // Remove any mouse input sources for this mouseID SDL_Mouse *mouse = SDL_GetMouse(); for (int i = 0; i < mouse->num_sources; ++i) { SDL_MouseInputSource *source = &mouse->sources[i]; @@ -308,14 +347,16 @@ void SDL_RemoveMouse(SDL_MouseID mouseID) } } - SDL_Event event; - SDL_zero(event); - event.type = SDL_EVENT_MOUSE_REMOVED; - event.mdevice.which = mouseID; - SDL_PushEvent(&event); + if (send_event) { + SDL_Event event; + SDL_zero(event); + event.type = SDL_EVENT_MOUSE_REMOVED; + event.mdevice.which = mouseID; + SDL_PushEvent(&event); + } } -SDL_bool SDL_HasMouse(void) +bool SDL_HasMouse(void) { return (SDL_mouse_count > 0); } @@ -344,13 +385,13 @@ SDL_MouseID *SDL_GetMice(int *count) return mice; } -const char *SDL_GetMouseInstanceName(SDL_MouseID instance_id) +const char *SDL_GetMouseNameForID(SDL_MouseID instance_id) { int mouse_index = SDL_GetMouseIndex(instance_id); if (mouse_index < 0) { return NULL; } - return SDL_mice[mouse_index].name; + return SDL_GetPersistentString(SDL_mice[mouse_index].name); } void SDL_SetDefaultCursor(SDL_Cursor *cursor) @@ -383,7 +424,7 @@ void SDL_SetDefaultCursor(SDL_Cursor *cursor) } } - if (mouse->FreeCursor && default_cursor->driverdata) { + if (mouse->FreeCursor && default_cursor->internal) { mouse->FreeCursor(default_cursor); } else { SDL_free(default_cursor); @@ -402,10 +443,10 @@ SDL_Mouse *SDL_GetMouse(void) return &SDL_mouse; } -Uint32 SDL_GetMouseButtonState(SDL_Mouse *mouse, SDL_MouseID mouseID, SDL_bool include_touch) +static SDL_MouseButtonFlags SDL_GetMouseButtonState(SDL_Mouse *mouse, SDL_MouseID mouseID, bool include_touch) { int i; - Uint32 buttonstate = 0; + SDL_MouseButtonFlags buttonstate = 0; for (i = 0; i < mouse->num_sources; ++i) { if (mouseID == SDL_GLOBAL_MOUSE_ID || mouseID == SDL_TOUCH_MOUSEID) { @@ -440,17 +481,17 @@ SDL_Window *SDL_GetMouseFocus(void) void SDL_ResetMouse(void) { SDL_Mouse *mouse = SDL_GetMouse(); - Uint32 buttonState = SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE); + Uint32 buttonState = SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false); int i; for (i = 1; i <= sizeof(buttonState)*8; ++i) { - if (buttonState & SDL_BUTTON(i)) { - SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, SDL_RELEASED, i); + if (buttonState & SDL_BUTTON_MASK(i)) { + SDL_SendMouseButton(0, mouse->focus, mouse->mouseID, i, false); } } - SDL_assert(SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE) == 0); + SDL_assert(SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false) == 0); } -#endif /* 0 */ +#endif // 0 void SDL_SetMouseFocus(SDL_Window *window) { @@ -467,46 +508,46 @@ void SDL_SetMouseFocus(SDL_Window *window) */ #if 0 if (mouse->focus && !window) { - /* We won't get anymore mouse messages, so reset mouse state */ + // We won't get anymore mouse messages, so reset mouse state SDL_ResetMouse(); } #endif - /* See if the current window has lost focus */ + // See if the current window has lost focus if (mouse->focus) { SDL_SendWindowEvent(mouse->focus, SDL_EVENT_WINDOW_MOUSE_LEAVE, 0, 0); } mouse->focus = window; - mouse->has_position = SDL_FALSE; + mouse->has_position = false; if (mouse->focus) { SDL_SendWindowEvent(mouse->focus, SDL_EVENT_WINDOW_MOUSE_ENTER, 0, 0); } - /* Update cursor visibility */ + // Update cursor visibility SDL_SetCursor(NULL); } -SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y) +bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y) { if (!window) { - return SDL_FALSE; + return false; } if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) { if (x < 0.0f || y < 0.0f || x >= (float)window->w || y >= (float)window->h) { - return SDL_FALSE; + return false; } } - return SDL_TRUE; + return true; } -/* Check to see if we need to synthesize focus events */ -static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, SDL_bool send_mouse_motion) +// Check to see if we need to synthesize focus events +static bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint32 buttonstate, bool send_mouse_motion) { SDL_Mouse *mouse = SDL_GetMouse(); - SDL_bool inWindow = SDL_MousePositionInWindow(window, x, y); + bool inWindow = SDL_MousePositionInWindow(window, x, y); if (!inWindow) { if (window == mouse->focus) { @@ -514,11 +555,11 @@ static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint3 SDL_Log("Mouse left window, synthesizing move & focus lost event\n"); #endif if (send_mouse_motion) { - SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y); } SDL_SetMouseFocus(NULL); } - return SDL_FALSE; + return false; } if (window != mouse->focus) { @@ -527,22 +568,22 @@ static SDL_bool SDL_UpdateMouseFocus(SDL_Window *window, float x, float y, Uint3 #endif SDL_SetMouseFocus(window); if (send_mouse_motion) { - SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y); } } - return SDL_TRUE; + return true; } -int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y) +void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y) { if (window && !relative) { SDL_Mouse *mouse = SDL_GetMouse(); - if (!SDL_UpdateMouseFocus(window, x, y, SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE), (mouseID != SDL_TOUCH_MOUSEID))) { - return 0; + if (!SDL_UpdateMouseFocus(window, x, y, SDL_GetMouseButtonState(mouse, mouseID, true), (mouseID != SDL_TOUCH_MOUSEID))) { + return; } } - return SDL_PrivateSendMouseMotion(timestamp, window, mouseID, relative, x, y); + SDL_PrivateSendMouseMotion(timestamp, window, mouseID, relative, x, y); } static float CalculateSystemScale(SDL_Mouse *mouse, SDL_Window *window, const float *x, const float *y) @@ -552,7 +593,7 @@ static float CalculateSystemScale(SDL_Mouse *mouse, SDL_Window *window, const fl float *v = mouse->system_scale_values; float speed, coef, scale; - /* If we're using a single scale value, return that */ + // If we're using a single scale value, return that if (n == 1) { scale = v[0]; } else { @@ -573,7 +614,7 @@ static float CalculateSystemScale(SDL_Mouse *mouse, SDL_Window *window, const fl } #ifdef SDL_PLATFORM_WIN32 { - /* On Windows the mouse speed is affected by the content scale */ + // On Windows the mouse speed is affected by the content scale SDL_VideoDisplay *display; if (window) { @@ -589,16 +630,16 @@ static float CalculateSystemScale(SDL_Mouse *mouse, SDL_Window *window, const fl return scale; } -/* You can set either a single scale, or a set of {speed, scale} values in ascending order */ -int SDL_SetMouseSystemScale(int num_values, const float *values) +// You can set either a single scale, or a set of {speed, scale} values in ascending order +bool SDL_SetMouseSystemScale(int num_values, const float *values) { SDL_Mouse *mouse = SDL_GetMouse(); float *v; if (num_values == mouse->num_system_scale_values && SDL_memcmp(values, mouse->system_scale_values, num_values * sizeof(*values)) == 0) { - /* Nothing has changed */ - return 0; + // Nothing has changed + return true; } if (num_values < 1) { @@ -606,7 +647,7 @@ int SDL_SetMouseSystemScale(int num_values, const float *values) } if (num_values > 1) { - /* Validate the values */ + // Validate the values int i; if (num_values < 4 || (num_values % 2) != 0) { @@ -622,13 +663,13 @@ int SDL_SetMouseSystemScale(int num_values, const float *values) v = (float *)SDL_realloc(mouse->system_scale_values, num_values * sizeof(*values)); if (!v) { - return -1; + return false; } SDL_memcpy(v, values, num_values * sizeof(*values)); mouse->num_system_scale_values = num_values; mouse->system_scale_values = v; - return 0; + return true; } static void GetScaledMouseDeltas(SDL_Mouse *mouse, SDL_Window *window, float *x, float *y) @@ -691,19 +732,18 @@ static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float * } } -static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y) +static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y) { SDL_Mouse *mouse = SDL_GetMouse(); - int posted; float xrel = 0.0f; float yrel = 0.0f; - if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) { - /* We're not in relative mode, so all mouse events are global mouse events */ + if ((!mouse->relative_mode || mouse->warp_emulation_active) && mouseID != SDL_TOUCH_MOUSEID) { + // We're not in relative mode, so all mouse events are global mouse events mouseID = SDL_GLOBAL_MOUSE_ID; } - /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ + // SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events if (mouse->mouse_touch_events) { if (mouseID != SDL_TOUCH_MOUSEID && !relative && track_mouse_down) { if (window) { @@ -714,9 +754,9 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ } } - /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */ + // SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer if (!mouse->touch_mouse_events && mouseID == SDL_TOUCH_MOUSEID) { - return 0; + return; } if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) { @@ -730,14 +770,14 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ mouse->last_x = center_x; mouse->last_y = center_y; if (!mouse->relative_mode_warp_motion) { - return 0; + return; } } else { if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS)) { if (mouse->WarpMouse) { mouse->WarpMouse(window, center_x, center_y); } else { - SDL_PrivateSendMouseMotion(timestamp, window, mouseID, SDL_FALSE, center_x, center_y); + SDL_PrivateSendMouseMotion(timestamp, window, mouseID, false, center_x, center_y); } } } @@ -759,21 +799,21 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ } } - if (mouse->has_position && xrel == 0.0f && yrel == 0.0f) { /* Drop events that don't change state */ + if (mouse->has_position && xrel == 0.0f && yrel == 0.0f) { // Drop events that don't change state #ifdef DEBUG_MOUSE SDL_Log("Mouse event didn't change state - dropped!\n"); #endif - return 0; + return; } - /* Ignore relative motion positioning the first touch */ - if (mouseID == SDL_TOUCH_MOUSEID && !SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE)) { + // Ignore relative motion positioning the first touch + if (mouseID == SDL_TOUCH_MOUSEID && !SDL_GetMouseButtonState(mouse, mouseID, true)) { xrel = 0.0f; yrel = 0.0f; } if (mouse->has_position) { - /* Update internal mouse coordinates */ + // Update internal mouse coordinates if (!mouse->relative_mode) { mouse->x = x; mouse->y = y; @@ -785,47 +825,45 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_ } else { mouse->x = x; mouse->y = y; - mouse->has_position = SDL_TRUE; + mouse->has_position = true; } mouse->xdelta += xrel; mouse->ydelta += yrel; - /* Move the mouse cursor, if needed */ + // Move the mouse cursor, if needed if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { mouse->MoveCursor(mouse->cur_cursor); } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) { SDL_Event event; event.type = SDL_EVENT_MOUSE_MOTION; event.common.timestamp = timestamp; event.motion.windowID = mouse->focus ? mouse->focus->id : 0; event.motion.which = mouseID; - /* Set us pending (or clear during a normal mouse movement event) as having triggered */ + // Set us pending (or clear during a normal mouse movement event) as having triggered mouse->was_touch_mouse_events = (mouseID == SDL_TOUCH_MOUSEID); - event.motion.state = SDL_GetMouseButtonState(mouse, mouseID, SDL_TRUE); + event.motion.state = SDL_GetMouseButtonState(mouse, mouseID, true); event.motion.x = mouse->x; event.motion.y = mouse->y; event.motion.xrel = xrel; event.motion.yrel = yrel; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } if (relative) { mouse->last_x = mouse->x; mouse->last_y = mouse->y; } else { - /* Use unclamped values if we're getting events outside the window */ + // Use unclamped values if we're getting events outside the window mouse->last_x = x; mouse->last_y = y; } - return posted; } -static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID, Uint8 state, Uint8 button) +static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID, bool down, Uint8 button) { SDL_MouseInputSource *source, *match = NULL, *sources; int i; @@ -838,13 +876,13 @@ static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID m } } - if (!state && (!match || !(match->buttonstate & SDL_BUTTON(button)))) { + if (!down && (!match || !(match->buttonstate & SDL_BUTTON_MASK(button)))) { /* This might be a button release from a transition between mouse messages and raw input. * See if there's another mouse source that already has that button down and use that. */ for (i = 0; i < mouse->num_sources; ++i) { source = &mouse->sources[i]; - if ((source->buttonstate & SDL_BUTTON(button))) { + if ((source->buttonstate & SDL_BUTTON_MASK(button))) { match = source; break; } @@ -884,32 +922,31 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button) return &mouse->clickstate[button]; } -static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks) +static void SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks) { SDL_Mouse *mouse = SDL_GetMouse(); - int posted; Uint32 type; Uint32 buttonstate; SDL_MouseInputSource *source; - if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID && mouseID != SDL_PEN_MOUSEID) { - /* We're not in relative mode, so all mouse events are global mouse events */ + if (!mouse->relative_mode && mouseID != SDL_TOUCH_MOUSEID) { + // We're not in relative mode, so all mouse events are global mouse events mouseID = SDL_GLOBAL_MOUSE_ID; } - source = GetMouseInputSource(mouse, mouseID, state, button); + source = GetMouseInputSource(mouse, mouseID, down, button); if (!source) { - return 0; + return; } buttonstate = source->buttonstate; - /* SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events */ + // SDL_HINT_MOUSE_TOUCH_EVENTS: controlling whether mouse events should generate synthetic touch events if (mouse->mouse_touch_events) { if (mouseID != SDL_TOUCH_MOUSEID && button == SDL_BUTTON_LEFT) { - if (state == SDL_PRESSED) { - track_mouse_down = SDL_TRUE; + if (down) { + track_mouse_down = true; } else { - track_mouse_down = SDL_FALSE; + track_mouse_down = false; } if (window) { float normalized_x = mouse->x / (float)window->w; @@ -919,43 +956,37 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ } } - /* SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer */ + // SDL_HINT_TOUCH_MOUSE_EVENTS: if not set, discard synthetic mouse events coming from platform layer if (mouse->touch_mouse_events == 0) { if (mouseID == SDL_TOUCH_MOUSEID) { - return 0; + return; } } - /* Figure out which event to perform */ - switch (state) { - case SDL_PRESSED: + // Figure out which event to perform + if (down) { type = SDL_EVENT_MOUSE_BUTTON_DOWN; - buttonstate |= SDL_BUTTON(button); - break; - case SDL_RELEASED: + buttonstate |= SDL_BUTTON_MASK(button); + } else { type = SDL_EVENT_MOUSE_BUTTON_UP; - buttonstate &= ~SDL_BUTTON(button); - break; - default: - /* Invalid state -- bail */ - return 0; + buttonstate &= ~SDL_BUTTON_MASK(button); } - /* We do this after calculating buttonstate so button presses gain focus */ - if (window && state == SDL_PRESSED) { - SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE); + // We do this after calculating buttonstate so button presses gain focus + if (window && down) { + SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, true); } if (buttonstate == source->buttonstate) { - /* Ignore this event, no state change */ - return 0; + // Ignore this event, no state change + return; } source->buttonstate = buttonstate; if (clicks < 0) { SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button); if (clickstate) { - if (state == SDL_PRESSED) { + if (down) { Uint64 now = SDL_GetTicks(); if (now >= (clickstate->last_timestamp + mouse->double_click_time) || @@ -976,61 +1007,56 @@ static int SDL_PrivateSendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_ } } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(type)) { SDL_Event event; event.type = type; event.common.timestamp = timestamp; event.button.windowID = mouse->focus ? mouse->focus->id : 0; event.button.which = source->mouseID; - event.button.state = state; + event.button.down = down; event.button.button = button; event.button.clicks = (Uint8)SDL_min(clicks, 255); event.button.x = mouse->x; event.button.y = mouse->y; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } - /* We do this after dispatching event so button releases can lose focus */ - if (window && state == SDL_RELEASED) { - SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE); + // We do this after dispatching event so button releases can lose focus + if (window && !down) { + SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, true); } - /* Automatically capture the mouse while buttons are pressed */ + // Automatically capture the mouse while buttons are pressed if (mouse->auto_capture) { - SDL_UpdateMouseCapture(SDL_FALSE); + SDL_UpdateMouseCapture(false); } - - return posted; } -int SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks) +void SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks) { clicks = SDL_max(clicks, 0); - return SDL_PrivateSendMouseButton(timestamp, window, mouseID, state, button, clicks); + SDL_PrivateSendMouseButton(timestamp, window, mouseID, button, down, clicks); } -int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button) +void SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down) { - return SDL_PrivateSendMouseButton(timestamp, window, mouseID, state, button, -1); + SDL_PrivateSendMouseButton(timestamp, window, mouseID, button, down, -1); } -int SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction) +void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction) { SDL_Mouse *mouse = SDL_GetMouse(); - int posted; if (window) { SDL_SetMouseFocus(window); } if (x == 0.0f && y == 0.0f) { - return 0; + return; } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_MOUSE_WHEEL)) { SDL_Event event; event.type = SDL_EVENT_MOUSE_WHEEL; @@ -1042,9 +1068,8 @@ int SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID event.wheel.direction = direction; event.wheel.mouse_x = mouse->x; event.wheel.mouse_y = mouse->y; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } - return posted; } void SDL_QuitMouse(void) @@ -1053,12 +1078,11 @@ void SDL_QuitMouse(void) SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->CaptureMouse) { - SDL_CaptureMouse(SDL_FALSE); - SDL_UpdateMouseCapture(SDL_TRUE); + SDL_CaptureMouse(false); + SDL_UpdateMouseCapture(true); } - SDL_SetRelativeMouseMode(SDL_FALSE); + SDL_SetRelativeMouseMode(false); SDL_ShowCursor(); - SDL_PenQuit(); if (mouse->def_cursor) { SDL_SetDefaultCursor(NULL); @@ -1091,39 +1115,50 @@ void SDL_QuitMouse(void) } mouse->num_system_scale_values = 0; - SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME, SDL_MouseDoubleClickTimeChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, SDL_MouseDoubleClickRadiusChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, SDL_MouseNormalSpeedScaleChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, SDL_MouseRelativeSpeedScaleChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, SDL_MouseRelativeSystemScaleChanged, mouse); - SDL_DelHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE, + SDL_MouseWarpEmulationChanged, mouse); + + SDL_RemoveHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS, SDL_TouchMouseEventsChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS, SDL_MouseTouchEventsChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, SDL_MouseAutoCaptureChanged, mouse); - SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, + SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, SDL_MouseRelativeWarpMotionChanged, mouse); - SDL_mouse_count = 0; + SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, + SDL_MouseRelativeCursorVisibleChanged, mouse); + + SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL, + SDL_MouseRelativeClipIntervalChanged, mouse); + + for (int i = SDL_mouse_count; i--; ) { + SDL_RemoveMouse(SDL_mice[i].instance_id, false); + } SDL_free(SDL_mice); SDL_mice = NULL; } -Uint32 SDL_GetMouseState(float *x, float *y) +SDL_MouseButtonFlags SDL_GetMouseState(float *x, float *y) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1133,10 +1168,10 @@ Uint32 SDL_GetMouseState(float *x, float *y) if (y) { *y = mouse->y; } - return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_TRUE); + return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, true); } -Uint32 SDL_GetRelativeMouseState(float *x, float *y) +SDL_MouseButtonFlags SDL_GetRelativeMouseState(float *x, float *y) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1148,17 +1183,17 @@ Uint32 SDL_GetRelativeMouseState(float *x, float *y) } mouse->xdelta = 0.0f; mouse->ydelta = 0.0f; - return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_TRUE); + return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, true); } -Uint32 SDL_GetGlobalMouseState(float *x, float *y) +SDL_MouseButtonFlags SDL_GetGlobalMouseState(float *x, float *y) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->GetGlobalMouseState) { float tmpx, tmpy; - /* make sure these are never NULL for the backend implementations... */ + // make sure these are never NULL for the backend implementations... if (!x) { x = &tmpx; } @@ -1174,7 +1209,7 @@ Uint32 SDL_GetGlobalMouseState(float *x, float *y) } } -void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool ignore_relative_mode) +void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ignore_relative_mode) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1190,10 +1225,10 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool return; } - /* Ignore the previous position when we warp */ + // Ignore the previous position when we warp mouse->last_x = x; mouse->last_y = y; - mouse->has_position = SDL_FALSE; + mouse->has_position = false; if (mouse->relative_mode && !ignore_relative_mode) { /* 2.0.22 made warping in relative mode actually functional, which @@ -1206,7 +1241,7 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool if (!mouse->relative_mode_warp_motion) { mouse->x = x; mouse->y = y; - mouse->has_position = SDL_TRUE; + mouse->has_position = true; return; } } @@ -1215,16 +1250,62 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool (!mouse->relative_mode || mouse->relative_mode_warp)) { mouse->WarpMouse(window, x, y); } else { - SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, SDL_FALSE, x, y); + SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y); + } +} + +void SDL_DisableMouseWarpEmulation(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse->warp_emulation_active) { + SDL_SetRelativeMouseMode(false); + } + + mouse->warp_emulation_prohibited = true; +} + +static void SDL_MaybeEnableWarpEmulation(SDL_Window *window, float x, float y) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + + if (!mouse->warp_emulation_prohibited && mouse->warp_emulation_hint && !mouse->cursor_shown && !mouse->warp_emulation_active) { + if (!window) { + window = mouse->focus; + } + + if (window) { + const float cx = window->w / 2.f; + const float cy = window->h / 2.f; + if (x >= SDL_floorf(cx) && x <= SDL_ceilf(cx) && + y >= SDL_floorf(cy) && y <= SDL_ceilf(cy)) { + + // Require two consecutive warps to the center within a certain timespan to enter warp emulation mode. + const Uint64 now = SDL_GetTicksNS(); + if (now - mouse->last_center_warp_time_ns < WARP_EMULATION_THRESHOLD_NS) { + if (SDL_SetRelativeMouseMode(true)) { + mouse->warp_emulation_active = true; + } + } + + mouse->last_center_warp_time_ns = now; + return; + } + } + + mouse->last_center_warp_time_ns = 0; } } void SDL_WarpMouseInWindow(SDL_Window *window, float x, float y) { - SDL_PerformWarpMouseInWindow(window, x, y, SDL_FALSE); + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_MaybeEnableWarpEmulation(window, x, y); + + SDL_PerformWarpMouseInWindow(window, x, y, mouse->warp_emulation_active); } -int SDL_WarpMouseGlobal(float x, float y) +bool SDL_WarpMouseGlobal(float x, float y) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1235,43 +1316,48 @@ int SDL_WarpMouseGlobal(float x, float y) return SDL_Unsupported(); } -static SDL_bool SDL_ShouldUseRelativeModeWarp(SDL_Mouse *mouse) +static bool SDL_ShouldUseRelativeModeWarp(SDL_Mouse *mouse) { if (!mouse->WarpMouse) { - /* Need this functionality for relative mode warp implementation */ - return SDL_FALSE; + // Need this functionality for relative mode warp implementation + return false; } - return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE); + return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, false); } -int SDL_SetRelativeMouseMode(SDL_bool enabled) +bool SDL_SetRelativeMouseMode(bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *focusWindow = SDL_GetKeyboardFocus(); + if (!enabled) { + // If warps were being emulated, reset the flag. + mouse->warp_emulation_active = false; + } + if (enabled == mouse->relative_mode) { - return 0; + return true; } - /* Set the relative mode */ + // Set the relative mode if (!enabled && mouse->relative_mode_warp) { - mouse->relative_mode_warp = SDL_FALSE; + mouse->relative_mode_warp = false; } else if (enabled && SDL_ShouldUseRelativeModeWarp(mouse)) { - mouse->relative_mode_warp = SDL_TRUE; - } else if (!mouse->SetRelativeMouseMode || mouse->SetRelativeMouseMode(enabled) < 0) { + mouse->relative_mode_warp = true; + } else if (!mouse->SetRelativeMouseMode || !mouse->SetRelativeMouseMode(enabled)) { if (enabled) { - /* Fall back to warp mode if native relative mode failed */ + // Fall back to warp mode if native relative mode failed if (!mouse->WarpMouse) { return SDL_SetError("No relative mode implementation available"); } - mouse->relative_mode_warp = SDL_TRUE; + mouse->relative_mode_warp = true; } } mouse->relative_mode = enabled; if (enabled) { - /* Update cursor visibility before we potentially warp the mouse */ + // Update cursor visibility before we potentially warp the mouse SDL_SetCursor(NULL); } @@ -1281,51 +1367,62 @@ int SDL_SetRelativeMouseMode(SDL_bool enabled) if (mouse->relative_mode_warp) { float center_x = (float)focusWindow->w / 2.0f; float center_y = (float)focusWindow->h / 2.0f; - SDL_PerformWarpMouseInWindow(focusWindow, center_x, center_y, SDL_TRUE); + SDL_PerformWarpMouseInWindow(focusWindow, center_x, center_y, true); } } if (focusWindow) { SDL_UpdateWindowGrab(focusWindow); - /* Put the cursor back to where the application expects it */ + // Put the cursor back to where the application expects it if (!enabled) { - SDL_PerformWarpMouseInWindow(focusWindow, mouse->x, mouse->y, SDL_TRUE); + SDL_PerformWarpMouseInWindow(focusWindow, mouse->x, mouse->y, true); } - SDL_UpdateMouseCapture(SDL_FALSE); + SDL_UpdateMouseCapture(false); } if (!enabled) { - /* Update cursor visibility after we restore the mouse position */ + // Update cursor visibility after we restore the mouse position SDL_SetCursor(NULL); } - /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */ + // Flush pending mouse motion - ideally we would pump events, but that's not always safe SDL_FlushEvent(SDL_EVENT_MOUSE_MOTION); - return 0; + return true; } -SDL_bool SDL_GetRelativeMouseMode(void) +bool SDL_GetRelativeMouseMode(void) { SDL_Mouse *mouse = SDL_GetMouse(); return mouse->relative_mode; } -int SDL_UpdateMouseCapture(SDL_bool force_release) +void SDL_UpdateRelativeMouseMode(void) +{ + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_Window *focus = SDL_GetKeyboardFocus(); + bool relative_mode = (focus && (focus->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE)); + + if (relative_mode != mouse->relative_mode) { + SDL_SetRelativeMouseMode(relative_mode); + } +} + +bool SDL_UpdateMouseCapture(bool force_release) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *capture_window = NULL; if (!mouse->CaptureMouse) { - return 0; + return true; } if (!force_release) { if (SDL_GetMessageBoxCount() == 0 && - (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, SDL_FALSE) != 0))) { + (mouse->capture_desired || (mouse->auto_capture && SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, false) != 0))) { if (!mouse->relative_mode) { capture_window = mouse->focus; } @@ -1349,8 +1446,8 @@ int SDL_UpdateMouseCapture(SDL_bool force_release) mouse->capture_window = capture_window; - if (mouse->CaptureMouse(capture_window) < 0) { - /* CaptureMouse() will have set an error, just restore the state */ + if (!mouse->CaptureMouse(capture_window)) { + // CaptureMouse() will have set an error, just restore the state if (previous_capture) { previous_capture->flags |= SDL_WINDOW_MOUSE_CAPTURE; } @@ -1359,13 +1456,13 @@ int SDL_UpdateMouseCapture(SDL_bool force_release) } mouse->capture_window = previous_capture; - return -1; + return false; } } - return 0; + return true; } -int SDL_CaptureMouse(SDL_bool enabled) +bool SDL_CaptureMouse(bool enabled) { SDL_Mouse *mouse = SDL_GetMouse(); @@ -1382,14 +1479,14 @@ int SDL_CaptureMouse(SDL_bool enabled) if (!SDL_OnVideoThread()) { return SDL_SetError("SDL_CaptureMouse() must be called on the main thread"); } -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) */ +#endif // defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_WINGDK) if (enabled && SDL_GetKeyboardFocus() == NULL) { return SDL_SetError("No window has focus"); } mouse->capture_desired = enabled; - return SDL_UpdateMouseCapture(SDL_FALSE); + return SDL_UpdateMouseCapture(false); } SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, int hot_x, int hot_y) @@ -1403,16 +1500,16 @@ SDL_Cursor *SDL_CreateCursor(const Uint8 *data, const Uint8 *mask, int w, int h, const Uint32 white = 0xFFFFFFFF; const Uint32 transparent = 0x00000000; #if defined(SDL_PLATFORM_WIN32) - /* Only Windows backend supports inverted pixels in mono cursors. */ + // Only Windows backend supports inverted pixels in mono cursors. const Uint32 inverted = 0x00FFFFFF; #else const Uint32 inverted = 0xFF000000; -#endif /* defined(SDL_PLATFORM_WIN32) */ +#endif // defined(SDL_PLATFORM_WIN32) - /* Make sure the width is a multiple of 8 */ + // Make sure the width is a multiple of 8 w = ((w + 7) & ~7); - /* Create the surface from a bitmap */ + // Create the surface from a bitmap surface = SDL_CreateSurface(w, h, SDL_PIXELFORMAT_ARGB8888); if (!surface) { return NULL; @@ -1452,15 +1549,15 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y) return NULL; } - /* Sanity check the hot spot */ + // Sanity check the hot spot if ((hot_x < 0) || (hot_y < 0) || (hot_x >= surface->w) || (hot_y >= surface->h)) { SDL_SetError("Cursor hot spot doesn't lie within cursor"); return NULL; } - if (surface->format->format != SDL_PIXELFORMAT_ARGB8888) { - temp = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_ARGB8888); + if (surface->format != SDL_PIXELFORMAT_ARGB8888) { + temp = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ARGB8888); if (!temp) { return NULL; } @@ -1505,18 +1602,18 @@ SDL_Cursor *SDL_CreateSystemCursor(SDL_SystemCursor id) if this is desired for any reason. This is used when setting the video mode and when the SDL window gains the mouse focus. */ -int SDL_SetCursor(SDL_Cursor *cursor) +bool SDL_SetCursor(SDL_Cursor *cursor) { SDL_Mouse *mouse = SDL_GetMouse(); - /* Return immediately if setting the cursor to the currently set one (fixes #7151) */ + // Return immediately if setting the cursor to the currently set one (fixes #7151) if (cursor == mouse->cur_cursor) { - return 0; + return true; } - /* Set the new cursor */ + // Set the new cursor if (cursor) { - /* Make sure the cursor is still valid for this mouse */ + // Make sure the cursor is still valid for this mouse if (cursor != mouse->def_cursor) { SDL_Cursor *found; for (found = mouse->cursors; found; found = found->next) { @@ -1537,7 +1634,7 @@ int SDL_SetCursor(SDL_Cursor *cursor) } } - if (cursor && mouse->cursor_shown && !mouse->relative_mode) { + if (cursor && (!mouse->focus || (mouse->cursor_shown && (!mouse->relative_mode || mouse->relative_mode_cursor_visible)))) { if (mouse->ShowCursor) { mouse->ShowCursor(cursor); } @@ -1546,7 +1643,7 @@ int SDL_SetCursor(SDL_Cursor *cursor) mouse->ShowCursor(NULL); } } - return 0; + return true; } SDL_Cursor *SDL_GetCursor(void) @@ -1594,7 +1691,7 @@ void SDL_DestroyCursor(SDL_Cursor *cursor) mouse->cursors = curr->next; } - if (mouse->FreeCursor && curr->driverdata) { + if (mouse->FreeCursor && curr->internal) { mouse->FreeCursor(curr); } else { SDL_free(curr); @@ -1604,29 +1701,34 @@ void SDL_DestroyCursor(SDL_Cursor *cursor) } } -int SDL_ShowCursor(void) +bool SDL_ShowCursor(void) { SDL_Mouse *mouse = SDL_GetMouse(); + if (mouse->warp_emulation_active) { + SDL_SetRelativeMouseMode(false); + mouse->warp_emulation_active = false; + } + if (!mouse->cursor_shown) { - mouse->cursor_shown = SDL_TRUE; + mouse->cursor_shown = true; SDL_SetCursor(NULL); } - return 0; + return true; } -int SDL_HideCursor(void) +bool SDL_HideCursor(void) { SDL_Mouse *mouse = SDL_GetMouse(); if (mouse->cursor_shown) { - mouse->cursor_shown = SDL_FALSE; + mouse->cursor_shown = false; SDL_SetCursor(NULL); } - return 0; + return true; } -SDL_bool SDL_CursorVisible(void) +bool SDL_CursorVisible(void) { SDL_Mouse *mouse = SDL_GetMouse(); diff --git a/libs/SDL3/src/events/SDL_mouse_c.h b/libs/SDL3/src/events/SDL_mouse_c.h index 4dc0c1119..993e2ae16 100644 --- a/libs/SDL3/src/events/SDL_mouse_c.h +++ b/libs/SDL3/src/events/SDL_mouse_c.h @@ -23,16 +23,18 @@ #ifndef SDL_mouse_c_h_ #define SDL_mouse_c_h_ -/* Mouse events not associated with a specific input device */ +// Mouse events not associated with a specific input device #define SDL_GLOBAL_MOUSE_ID 0 -/* The default mouse input device, for platforms that don't have multiple mice */ +// The default mouse input device, for platforms that don't have multiple mice #define SDL_DEFAULT_MOUSE_ID 1 +typedef struct SDL_CursorData SDL_CursorData; + struct SDL_Cursor { struct SDL_Cursor *next; - void *driverdata; + SDL_CursorData *internal; }; typedef struct @@ -50,140 +52,149 @@ typedef struct typedef struct { - /* Create a cursor from a surface */ + // Create a cursor from a surface SDL_Cursor *(*CreateCursor)(SDL_Surface *surface, int hot_x, int hot_y); - /* Create a system cursor */ + // Create a system cursor SDL_Cursor *(*CreateSystemCursor)(SDL_SystemCursor id); - /* Show the specified cursor, or hide if cursor is NULL */ - int (*ShowCursor)(SDL_Cursor *cursor); + // Show the specified cursor, or hide if cursor is NULL + bool (*ShowCursor)(SDL_Cursor *cursor); - /* This is called when a mouse motion event occurs */ - int (*MoveCursor)(SDL_Cursor *cursor); + // This is called when a mouse motion event occurs + bool (*MoveCursor)(SDL_Cursor *cursor); - /* Free a window manager cursor */ + // Free a window manager cursor void (*FreeCursor)(SDL_Cursor *cursor); - /* Warp the mouse to (x,y) within a window */ - int (*WarpMouse)(SDL_Window *window, float x, float y); + // Warp the mouse to (x,y) within a window + bool (*WarpMouse)(SDL_Window *window, float x, float y); - /* Warp the mouse to (x,y) in screen space */ - int (*WarpMouseGlobal)(float x, float y); + // Warp the mouse to (x,y) in screen space + bool (*WarpMouseGlobal)(float x, float y); - /* Set relative mode */ - int (*SetRelativeMouseMode)(SDL_bool enabled); + // Set relative mode + bool (*SetRelativeMouseMode)(bool enabled); - /* Set mouse capture */ - int (*CaptureMouse)(SDL_Window *window); + // Set mouse capture + bool (*CaptureMouse)(SDL_Window *window); - /* Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call. */ - Uint32 (*GetGlobalMouseState)(float *x, float *y); + // Get absolute mouse coordinates. (x) and (y) are never NULL and set to zero before call. + SDL_MouseButtonFlags (*GetGlobalMouseState)(float *x, float *y); - /* Data common to all mice */ + // Data common to all mice SDL_Window *focus; float x; float y; float xdelta; float ydelta; - float last_x, last_y; /* the last reported x and y coordinates */ - SDL_bool has_position; - SDL_bool relative_mode; - SDL_bool relative_mode_warp; - SDL_bool relative_mode_warp_motion; - SDL_bool enable_normal_speed_scale; + float last_x, last_y; // the last reported x and y coordinates + bool has_position; + bool relative_mode; + bool relative_mode_warp; + bool relative_mode_warp_motion; + bool relative_mode_cursor_visible; + bool warp_emulation_hint; + bool warp_emulation_active; + bool warp_emulation_prohibited; + Uint64 last_center_warp_time_ns; + int relative_mode_clip_interval; + bool enable_normal_speed_scale; float normal_speed_scale; - SDL_bool enable_relative_speed_scale; + bool enable_relative_speed_scale; float relative_speed_scale; - SDL_bool enable_relative_system_scale; + bool enable_relative_system_scale; int num_system_scale_values; float *system_scale_values; Uint32 double_click_time; int double_click_radius; - SDL_bool touch_mouse_events; - SDL_bool mouse_touch_events; - SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */ + bool touch_mouse_events; + bool mouse_touch_events; + bool was_touch_mouse_events; // Was a touch-mouse event pending? #ifdef SDL_PLATFORM_VITA Uint8 vita_touch_mouse_device; #endif - SDL_bool auto_capture; - SDL_bool capture_desired; + bool auto_capture; + bool capture_desired; SDL_Window *capture_window; - /* Data for input source state */ + // Data for input source state int num_sources; SDL_MouseInputSource *sources; - /* Data for double-click tracking */ + // Data for double-click tracking int num_clickstates; SDL_MouseClickState *clickstate; SDL_Cursor *cursors; SDL_Cursor *def_cursor; SDL_Cursor *cur_cursor; - SDL_bool cursor_shown; + bool cursor_shown; - /* Driver-dependent data. */ - void *driverdata; + // Driver-dependent data. + void *internal; } SDL_Mouse; -/* Initialize the mouse subsystem, called before the main video driver is initialized */ -extern int SDL_PreInitMouse(void); +// Initialize the mouse subsystem, called before the main video driver is initialized +extern bool SDL_PreInitMouse(void); -/* Finish initializing the mouse subsystem, called after the main video driver was initialized */ +// Finish initializing the mouse subsystem, called after the main video driver was initialized extern void SDL_PostInitMouse(void); -/* Return whether a device is actually a mouse */ -extern SDL_bool SDL_IsMouse(Uint16 vendor, Uint16 product); +// Return whether a device is actually a mouse +extern bool SDL_IsMouse(Uint16 vendor, Uint16 product); -/* A mouse has been added to the system */ -extern void SDL_AddMouse(SDL_MouseID mouseID, const char *name, SDL_bool send_event); +// A mouse has been added to the system +extern void SDL_AddMouse(SDL_MouseID mouseID, const char *name, bool send_event); -/* A mouse has been removed from the system */ -extern void SDL_RemoveMouse(SDL_MouseID mouseID); +// A mouse has been removed from the system +extern void SDL_RemoveMouse(SDL_MouseID mouseID, bool send_event); -/* Get the mouse state structure */ +// Get the mouse state structure extern SDL_Mouse *SDL_GetMouse(void); -/* Set the default mouse cursor */ +// Set the default mouse cursor extern void SDL_SetDefaultCursor(SDL_Cursor *cursor); -/* Set the mouse focus window */ +// Set the mouse focus window extern void SDL_SetMouseFocus(SDL_Window *window); -/* Update the mouse capture window */ -extern int SDL_UpdateMouseCapture(SDL_bool force_release); +// Update the mouse capture window +extern bool SDL_UpdateMouseCapture(bool force_release); -/* Get the current mouse button state for a mouse */ -Uint32 SDL_GetMouseButtonState(SDL_Mouse *mouse, SDL_MouseID mouseID, SDL_bool include_touch); +// You can set either a single scale, or a set of {speed, scale} values in sorted order +extern bool SDL_SetMouseSystemScale(int num_values, const float *values); -/* You can set either a single scale, or a set of {speed, scale} values in sorted order */ -extern int SDL_SetMouseSystemScale(int num_values, const float *values); +// Send a mouse motion event +extern void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, bool relative, float x, float y); -/* Send a mouse motion event */ -extern int SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, SDL_bool relative, float x, float y); +// Send a mouse button event +extern void SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down); -/* Send a mouse button event */ -extern int SDL_SendMouseButton(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button); +// Send a mouse button event with a click count +extern void SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 button, bool down, int clicks); -/* Send a mouse button event with a click count */ -extern int SDL_SendMouseButtonClicks(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks); +// Send a mouse wheel event +extern void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction); -/* Send a mouse wheel event */ -extern int SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float x, float y, SDL_MouseWheelDirection direction); +// Warp the mouse within the window, potentially overriding relative mode +extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ignore_relative_mode); -/* Warp the mouse within the window, potentially overriding relative mode */ -extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool ignore_relative_mode); +// Relative mouse mode +extern bool SDL_SetRelativeMouseMode(bool enabled); +extern bool SDL_GetRelativeMouseMode(void); +extern void SDL_UpdateRelativeMouseMode(void); +extern void SDL_DisableMouseWarpEmulation(void); -/* TODO RECONNECT: Set mouse state to "zero" */ +// TODO RECONNECT: Set mouse state to "zero" #if 0 extern void SDL_ResetMouse(void); -#endif /* 0 */ +#endif // 0 -/* Check if mouse position is within window or captured by window */ -extern SDL_bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y); +// Check if mouse position is within window or captured by window +extern bool SDL_MousePositionInWindow(SDL_Window *window, float x, float y); -/* Shutdown the mouse subsystem */ +// Shutdown the mouse subsystem extern void SDL_QuitMouse(void); -#endif /* SDL_mouse_c_h_ */ +#endif // SDL_mouse_c_h_ diff --git a/libs/SDL3/src/events/SDL_pen.c b/libs/SDL3/src/events/SDL_pen.c index e1d69115b..65f772085 100644 --- a/libs/SDL3/src/events/SDL_pen.c +++ b/libs/SDL3/src/events/SDL_pen.c @@ -20,1089 +20,479 @@ */ #include "SDL_internal.h" -/* Pressure-sensitive pen handling code for SDL */ +// Pressure-sensitive pen handling code for SDL #include "../SDL_hints_c.h" #include "SDL_events_c.h" #include "SDL_pen_c.h" -#define PEN_MOUSE_EMULATE 0 /* pen behaves like mouse */ -#define PEN_MOUSE_STATELESS 1 /* pen does not update mouse state */ -#define PEN_MOUSE_DISABLED 2 /* pen does not send mouse events */ - -/* flags that are not SDL_PEN_FLAG_ */ -#define PEN_FLAGS_CAPABILITIES (~(SDL_PEN_FLAG_NEW | SDL_PEN_FLAG_DETACHED | SDL_PEN_FLAG_STALE)) - -#define PEN_GET_PUBLIC_STATUS_MASK(pen) (((pen)->header.flags & (SDL_PEN_ERASER_MASK | SDL_PEN_DOWN_MASK))) - -static int pen_mouse_emulation_mode = PEN_MOUSE_EMULATE; /* SDL_HINT_PEN_NOT_MOUSE */ - -static int pen_delay_mouse_button_mode = 1; /* SDL_HINT_PEN_DELAY_MOUSE_BUTTON */ - -#ifndef SDL_THREADS_DISABLED -static SDL_Mutex *SDL_pen_access_lock; -# define SDL_LOCK_PENS() SDL_LockMutex(SDL_pen_access_lock) -# define SDL_UNLOCK_PENS() SDL_UnlockMutex(SDL_pen_access_lock) -#else -# define SDL_LOCK_PENS() -# define SDL_UNLOCK_PENS() -#endif - -static struct -{ - SDL_Pen *pens; /* if "sorted" is SDL_TRUE: - sorted by: (is-attached, id): - - first all attached pens, in ascending ID order - - then all detached pens, in ascending ID order */ - size_t pens_allocated; /* # entries allocated to "pens" */ - size_t pens_known; /* <= pens_allocated; this includes detached pens */ - size_t pens_attached; /* <= pens_known; all attached pens are at the beginning of "pens" */ - SDL_bool sorted; /* This is SDL_FALSE in the period between SDL_PenGCMark() and SDL_PenGCSWeep() */ -} pen_handler; - -static SDL_PenID pen_invalid = { SDL_PEN_INVALID }; - -static SDL_GUID pen_guid_zero = { { 0 } }; - -#define SDL_LOAD_LOCK_PEN(penvar, instance_id, err_return) \ - SDL_Pen *penvar; \ - if (instance_id == SDL_PEN_INVALID) { \ - SDL_SetError("Invalid SDL_PenID"); \ - return (err_return); \ - } \ - SDL_LOCK_PENS();\ - penvar = SDL_GetPenPtr(instance_id); \ - if (!(penvar)) { \ - SDL_SetError("Stale SDL_PenID"); \ - SDL_UNLOCK_PENS(); \ - return (err_return); \ +typedef struct SDL_Pen +{ + SDL_PenID instance_id; + char *name; + SDL_PenInfo info; + float axes[SDL_PEN_AXIS_COUNT]; + float x; + float y; + SDL_PenInputFlags input_state; + void *driverdata; +} SDL_Pen; + +// we assume there's usually 0-1 pens in most cases and this list doesn't +// usually change after startup, so a simple array with a RWlock is fine for now. +static SDL_RWLock *pen_device_rwlock = NULL; +static SDL_Pen *pen_devices SDL_GUARDED_BY(pen_device_rwlock) = NULL; +static int pen_device_count SDL_GUARDED_BY(pen_device_rwlock) = 0; + +// You must hold pen_device_rwlock before calling this, and result is only safe while lock is held! +// If SDL isn't initialized, grabbing the NULL lock is a no-op and there will be zero devices, so +// locking and calling this in that case will do the right thing. +static SDL_Pen *FindPenByInstanceId(SDL_PenID instance_id) SDL_REQUIRES_SHARED(pen_device_rwlock) +{ + if (instance_id) { + for (int i = 0; i < pen_device_count; i++) { + if (pen_devices[i].instance_id == instance_id) { + return &pen_devices[i]; + } + } } - -static int SDL_GUIDCompare(SDL_GUID lhs, SDL_GUID rhs) -{ - return SDL_memcmp(lhs.data, rhs.data, sizeof(lhs.data)); + SDL_SetError("Invalid pen instance ID"); + return NULL; } -static int SDLCALL pen_compare(const void *lhs, const void *rhs) +SDL_PenID SDL_FindPenByHandle(void *handle) { - int left_inactive = (((const SDL_Pen *)lhs)->header.flags & SDL_PEN_FLAG_DETACHED); - int right_inactive = (((const SDL_Pen *)rhs)->header.flags & SDL_PEN_FLAG_DETACHED); - if (left_inactive && !right_inactive) { - return 1; - } - if (!left_inactive && right_inactive) { - return -1; + SDL_PenID result = 0; + SDL_LockRWLockForReading(pen_device_rwlock); + for (int i = 0; i < pen_device_count; i++) { + if (pen_devices[i].driverdata == handle) { + result = pen_devices[i].instance_id; + break; + } } - return ((const SDL_Pen *)lhs)->header.id - ((const SDL_Pen *)rhs)->header.id; + SDL_UnlockRWLock(pen_device_rwlock); + return result; } -static int SDLCALL pen_header_compare(const void *lhs, const void *rhs) +SDL_PenID SDL_FindPenByCallback(bool (*callback)(void *handle, void *userdata), void *userdata) { - const SDL_PenHeader *l = (const SDL_PenHeader *)lhs; - const SDL_PenHeader *r = (const SDL_PenHeader *)rhs; - int l_detached = l->flags & SDL_PEN_FLAG_DETACHED; - int r_detached = r->flags & SDL_PEN_FLAG_DETACHED; - - if (l_detached != r_detached) { - if (l_detached) { - return -1; + SDL_PenID result = 0; + SDL_LockRWLockForReading(pen_device_rwlock); + for (int i = 0; i < pen_device_count; i++) { + if (callback(pen_devices[i].driverdata, userdata)) { + result = pen_devices[i].instance_id; + break; } - return 1; } - - return l->id - r->id; + SDL_UnlockRWLock(pen_device_rwlock); + return result; } -SDL_Pen *SDL_GetPenPtr(Uint32 instance_id) -{ - unsigned int i; - if (!pen_handler.pens) { - return NULL; - } - if (pen_handler.sorted) { - SDL_PenHeader key; - SDL_Pen *pen; +// public API ... - SDL_zero(key); - key.id = instance_id; - - pen = (SDL_Pen *)SDL_bsearch(&key, pen_handler.pens, pen_handler.pens_known, sizeof(SDL_Pen), pen_header_compare); - if (pen) { - return pen; - } - /* If the pen is not active, fall through */ - } - - /* fall back to linear search */ - for (i = 0; i < pen_handler.pens_known; ++i) { - if (pen_handler.pens[i].header.id == instance_id) { - return &pen_handler.pens[i]; - } - } - return NULL; -} - -SDL_PenID *SDL_GetPens(int *count) +bool SDL_InitPen(void) { - int i; - int pens_nr = (int)pen_handler.pens_attached; - SDL_PenID *pens = (SDL_PenID *)SDL_calloc(pens_nr + 1, sizeof(SDL_PenID)); - if (!pens) { /* OOM */ - return pens; + SDL_assert(pen_device_rwlock == NULL); + SDL_assert(pen_devices == NULL); + SDL_assert(pen_device_count == 0); + pen_device_rwlock = SDL_CreateRWLock(); + if (!pen_device_rwlock) { + return false; } - - for (i = 0; i < pens_nr; ++i) { - pens[i] = pen_handler.pens[i].header.id; - } - - if (count) { - *count = pens_nr; - } - return pens; + return true; } -SDL_PenID SDL_GetPenFromGUID(SDL_GUID guid) +void SDL_QuitPen(void) { - unsigned int i; - /* Must do linear search */ - SDL_LOCK_PENS(); - for (i = 0; i < pen_handler.pens_known; ++i) { - SDL_Pen *pen = &pen_handler.pens[i]; - - if (0 == SDL_GUIDCompare(guid, pen->guid)) { - SDL_UNLOCK_PENS(); - return pen->header.id; - } - } - SDL_UNLOCK_PENS(); - return pen_invalid; + SDL_DestroyRWLock(pen_device_rwlock); + pen_device_rwlock = 0; + SDL_free(pen_devices); + pen_devices = NULL; + pen_device_count = 0; } -SDL_bool SDL_PenConnected(SDL_PenID instance_id) +#if 0 // not a public API at the moment. +SDL_PenID *SDL_GetPens(int *count) { - SDL_Pen *pen; - SDL_bool result; - - if (instance_id == SDL_PEN_INVALID) { - return SDL_FALSE; + SDL_LockRWLockForReading(pen_device_rwlock); + const int num_devices = pen_device_count; + SDL_PenID *result = (SDL_PenID *) SDL_malloc((num_devices + 1) * sizeof (SDL_PenID)); + if (result) { + for (int i = 0; i < num_devices; i++) { + result[i] = pen_devices[i].instance_id; + } + result[num_devices] = 0; // null-terminated. } + SDL_UnlockRWLock(pen_device_rwlock); - SDL_LOCK_PENS(); - pen = SDL_GetPenPtr(instance_id); - if (!pen) { - SDL_UNLOCK_PENS(); - return SDL_FALSE; + if (count) { + *count = result ? num_devices : 0; } - result = (pen->header.flags & SDL_PEN_FLAG_DETACHED) ? SDL_FALSE : SDL_TRUE; - SDL_UNLOCK_PENS(); - return result; -} - -SDL_GUID SDL_GetPenGUID(SDL_PenID instance_id) -{ - SDL_GUID result; - SDL_LOAD_LOCK_PEN(pen, instance_id, pen_guid_zero); - result = pen->guid; - SDL_UNLOCK_PENS(); return result; } const char *SDL_GetPenName(SDL_PenID instance_id) { - const char *result; - SDL_LOAD_LOCK_PEN(pen, instance_id, NULL); - result = pen->name; /* Allocated separately from the pen table, so it is safe to hand to client code */ - SDL_UNLOCK_PENS(); - return result; -} - -SDL_PenSubtype SDL_GetPenType(SDL_PenID instance_id) -{ - SDL_PenSubtype result; - SDL_LOAD_LOCK_PEN(pen, instance_id, SDL_PEN_TYPE_UNKNOWN); - result = pen->type; - SDL_UNLOCK_PENS(); + SDL_LockRWLockForReading(pen_device_rwlock); + const SDL_Pen *pen = FindPenByInstanceId(instance_id); + const char *result = pen ? SDL_GetPersistentString(pen->name) : NULL; + SDL_UnlockRWLock(pen_device_rwlock); return result; } -Uint32 SDL_GetPenCapabilities(SDL_PenID instance_id, SDL_PenCapabilityInfo *info) +bool SDL_GetPenInfo(SDL_PenID instance_id, SDL_PenInfo *info) { - Uint32 result; - SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); + SDL_LockRWLockForReading(pen_device_rwlock); + const SDL_Pen *pen = FindPenByInstanceId(instance_id); + const bool result = pen ? true : false; if (info) { - *info = pen->info; - } - result = pen->header.flags & PEN_FLAGS_CAPABILITIES; - SDL_UNLOCK_PENS(); - return result; -} - -Uint32 SDL_GetPenStatus(SDL_PenID instance_id, float *x, float *y, float *axes, size_t num_axes) -{ - Uint32 result; - SDL_LOAD_LOCK_PEN(pen, instance_id, 0u); - - if (x) { - *x = pen->last.x; - } - if (y) { - *y = pen->last.y; - } - if (axes && num_axes) { - size_t axes_to_copy = SDL_min(num_axes, SDL_PEN_NUM_AXES); - SDL_memcpy(axes, pen->last.axes, sizeof(float) * axes_to_copy); + if (result) { + SDL_copyp(info, &pen->info); + } else { + SDL_zerop(info); + } } - result = pen->last.buttons | (pen->header.flags & (SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_DOWN_MASK)); - SDL_UNLOCK_PENS(); + SDL_UnlockRWLock(pen_device_rwlock); return result; } -/* Backend functionality */ - -/* Sort all pens. Only safe during SDL_LOCK_PENS. */ -static void pen_sort(void) +SDL_PenInputFlags SDL_GetPenStatus(SDL_PenID instance_id, float *axes, int num_axes) { - SDL_qsort(pen_handler.pens, - pen_handler.pens_known, - sizeof(SDL_Pen), - pen_compare); - pen_handler.sorted = SDL_TRUE; -} - -SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) -{ - SDL_PenID id = { 0 }; - const size_t alloc_growth_constant = 1; /* Expect few pens */ - SDL_Pen *pen; - - id = instance_id; - - if (id == SDL_PEN_INVALID) { - SDL_SetError("Invalid SDL_PenID"); - return NULL; + if (num_axes < 0) { + num_axes = 0; } - SDL_LOCK_PENS(); - pen = SDL_GetPenPtr(id); - - if (!pen) { - if (!pen_handler.pens || pen_handler.pens_known == pen_handler.pens_allocated) { - size_t pens_to_allocate = pen_handler.pens_allocated + alloc_growth_constant; - SDL_Pen *pens; - if (pen_handler.pens) { - pens = (SDL_Pen *)SDL_realloc(pen_handler.pens, sizeof(SDL_Pen) * pens_to_allocate); - SDL_memset(pens + pen_handler.pens_known, 0, - sizeof(SDL_Pen) * (pens_to_allocate - pen_handler.pens_allocated)); - } else { - pens = (SDL_Pen *)SDL_calloc(sizeof(SDL_Pen), pens_to_allocate); + SDL_LockRWLockForReading(pen_device_rwlock); + const SDL_Pen *pen = FindPenByInstanceId(instance_id); + SDL_PenInputFlags result = 0; + if (pen) { + result = pen->input_state; + if (axes && num_axes) { + SDL_memcpy(axes, pen->axes, SDL_min(num_axes, SDL_PEN_AXIS_COUNT) * sizeof (*axes)); + // zero out axes we don't know about, in case the caller built with newer SDL headers that support more of them. + if (num_axes > SDL_PEN_AXIS_COUNT) { + SDL_memset(&axes[SDL_PEN_AXIS_COUNT], '\0', (num_axes - SDL_PEN_AXIS_COUNT) * sizeof (*axes)); } - pen_handler.pens = pens; - pen_handler.pens_allocated = pens_to_allocate; } - pen = &pen_handler.pens[pen_handler.pens_known]; - pen_handler.pens_known += 1; - - /* Default pen initialization */ - pen->header.id = id; - pen->header.flags = SDL_PEN_FLAG_NEW; - pen->info.num_buttons = SDL_PEN_INFO_UNKNOWN; - pen->info.max_tilt = SDL_PEN_INFO_UNKNOWN; - pen->type = SDL_PEN_TYPE_PEN; - pen->name = (char *)SDL_calloc(1, SDL_PEN_MAX_NAME); /* Never deallocated */ } - return pen; + SDL_UnlockRWLock(pen_device_rwlock); + return result; } -void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities) +bool SDL_PenConnected(SDL_PenID instance_id) { - if (capabilities & SDL_PEN_ERASER_MASK) { - pen->header.flags &= ~SDL_PEN_INK_MASK; - } else if (capabilities & SDL_PEN_INK_MASK) { - pen->header.flags &= ~SDL_PEN_ERASER_MASK; - } - pen->header.flags |= (capabilities & PEN_FLAGS_CAPABILITIES); + SDL_LockRWLockForReading(pen_device_rwlock); + const SDL_Pen *pen = FindPenByInstanceId(instance_id); + const bool result = (pen != NULL); + SDL_UnlockRWLock(pen_device_rwlock); + return result; } +#endif -static void pen_hotplug_attach(SDL_Pen *pen) +SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis) { - if (!pen->header.window) { - /* Attach to default window */ - const SDL_Mouse *mouse = SDL_GetMouse(); - SDL_SendPenWindowEvent(0, pen->header.id, mouse->focus); + // the initial capability bits happen to match up, but as + // more features show up later, the bits may no longer be contiguous! + if ((axis >= SDL_PEN_AXIS_PRESSURE) && (axis <= SDL_PEN_AXIS_SLIDER)) { + return ((SDL_PenCapabilityFlags) 1u) << ((SDL_PenCapabilityFlags) axis); } + return 0; // oh well. } -static void pen_hotplug_detach(SDL_Pen *pen) +SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, const SDL_PenInfo *info, void *handle) { - SDL_SendPenWindowEvent(0, pen->header.id, NULL); -} - -void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach) -{ - SDL_bool is_new = pen->header.flags & SDL_PEN_FLAG_NEW; - SDL_bool was_attached = !(pen->header.flags & (SDL_PEN_FLAG_DETACHED | SDL_PEN_FLAG_NEW)); - SDL_bool broke_sort_order = SDL_FALSE; - - if (pen->type == SDL_PEN_TYPE_NONE) { - /* remove pen */ - if (!is_new) { - if (!(pen->header.flags & SDL_PEN_FLAG_ERROR)) { - SDL_Log("Error: attempt to remove known pen %lu", (unsigned long) pen->header.id); - pen->header.flags |= SDL_PEN_FLAG_ERROR; - } + SDL_assert(handle != NULL); // just allocate a Uint8 so you have a unique pointer if not needed! + SDL_assert(SDL_FindPenByHandle(handle) == 0); // Backends shouldn't double-add pens! + SDL_assert(pen_device_rwlock != NULL); // subsystem should be initialized by now! - /* Treat as detached pen of unknown type instead */ - pen->type = SDL_PEN_TYPE_PEN; - attach = SDL_FALSE; - } else { - pen_handler.pens_known -= 1; - SDL_free(pen->name); - SDL_memset(pen, 0, sizeof(SDL_Pen)); - SDL_UNLOCK_PENS(); - return; - } + char *namecpy = SDL_strdup(name ? name : "Unnamed pen"); + if (!namecpy) { + return 0; } - pen->header.flags &= ~(SDL_PEN_FLAG_NEW | SDL_PEN_FLAG_STALE | SDL_PEN_FLAG_DETACHED); - if (attach == SDL_FALSE) { - pen->header.flags |= SDL_PEN_FLAG_DETACHED; - if (was_attached) { - broke_sort_order = SDL_TRUE; - if (!is_new) { - pen_handler.pens_attached -= 1; - } - pen_hotplug_detach(pen); - } - } else if (!was_attached || is_new) { - broke_sort_order = SDL_TRUE; - pen_handler.pens_attached += 1; - pen_hotplug_attach(pen); - } + SDL_PenID result = 0; - if (is_new) { - /* default: name */ - if (!pen->name[0]) { - SDL_snprintf(pen->name, SDL_PEN_MAX_NAME, - "%s %lu", - pen->type == SDL_PEN_TYPE_ERASER ? "Eraser" : "Pen", - (unsigned long) pen->header.id); - } + SDL_LockRWLockForWriting(pen_device_rwlock); - /* default: enabled axes */ - if (!(pen->header.flags & (SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK))) { - pen->info.max_tilt = 0; /* no tilt => no max_tilt */ - } + SDL_Pen *pen = NULL; + void *ptr = SDL_realloc(pen_devices, (pen_device_count + 1) * sizeof (*pen)); + if (ptr) { + result = (SDL_PenID) SDL_GetNextObjectID(); + pen_devices = (SDL_Pen *) ptr; + pen = &pen_devices[pen_device_count]; + pen_device_count++; - /* sanity-check GUID */ - if (0 == SDL_GUIDCompare(pen->guid, pen_guid_zero)) { - SDL_Log("Error: pen %lu: has GUID 0", (unsigned long) pen->header.id); + SDL_zerop(pen); + pen->instance_id = result; + pen->name = namecpy; + if (info) { + SDL_copyp(&pen->info, info); } - - /* pen or eraser? */ - if (pen->type == SDL_PEN_TYPE_ERASER || pen->header.flags & SDL_PEN_ERASER_MASK) { - pen->header.flags = (pen->header.flags & ~SDL_PEN_INK_MASK) | SDL_PEN_ERASER_MASK; - pen->type = SDL_PEN_TYPE_ERASER; - } else { - pen->header.flags = (pen->header.flags & ~SDL_PEN_ERASER_MASK) | SDL_PEN_INK_MASK; - } - - broke_sort_order = SDL_TRUE; - } - if (broke_sort_order && pen_handler.sorted) { - /* Maintain sortedness invariant */ - pen_sort(); + pen->driverdata = handle; + // axes and input state defaults to zero. } - SDL_UNLOCK_PENS(); -} + SDL_UnlockRWLock(pen_device_rwlock); -void SDL_PenGCMark(void) -{ - unsigned int i; - SDL_LOCK_PENS(); - for (i = 0; i < pen_handler.pens_known; ++i) { - SDL_Pen *pen = &pen_handler.pens[i]; - pen->header.flags |= SDL_PEN_FLAG_STALE; - } - pen_handler.sorted = SDL_FALSE; - SDL_UNLOCK_PENS(); -} - -void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32, void *, void *)) -{ - unsigned int i; - pen_handler.pens_attached = 0; - - SDL_LOCK_PENS(); - /* We don't actually free the SDL_Pen entries, so that we can still answer queries about - formerly active SDL_PenIDs later. */ - for (i = 0; i < pen_handler.pens_known; ++i) { - SDL_Pen *pen = &pen_handler.pens[i]; - - if (pen->header.flags & SDL_PEN_FLAG_STALE) { - pen->header.flags |= SDL_PEN_FLAG_DETACHED; - pen_hotplug_detach(pen); - if (pen->deviceinfo) { - free_deviceinfo(pen->header.id, pen->deviceinfo, context); - pen->deviceinfo = NULL; - } - } else { - pen_handler.pens_attached += 1; - } - - pen->header.flags &= ~SDL_PEN_FLAG_STALE; + if (!pen) { + SDL_free(namecpy); } - pen_sort(); - /* We could test for changes in the above and send a hotplugging event here */ - SDL_UNLOCK_PENS(); -} - -static void pen_relative_coordinates(SDL_Window *window, SDL_bool window_relative, float *x, float *y) -{ - int win_x, win_y; - if (window_relative) { - return; + if (result && SDL_EventEnabled(SDL_EVENT_PEN_PROXIMITY_IN)) { + SDL_Event event; + SDL_zero(event); + event.pproximity.type = SDL_EVENT_PEN_PROXIMITY_IN; + event.pproximity.timestamp = timestamp; + event.pproximity.which = result; + SDL_PushEvent(&event); } - SDL_GetWindowPosition(window, &win_x, &win_y); - *x -= win_x; - *y -= win_y; -} - -/* Initialises timestamp, windowID, which, pen_state, x, y, and axes */ -static void event_setup(const SDL_Pen *pen, const SDL_Window *window, Uint64 timestamp, const SDL_PenStatusInfo *status, SDL_Event *event) -{ - Uint16 last_buttons = pen->last.buttons; - if (timestamp == 0) { - /* Generate timestamp ourselves, if needed, so that we report the same timestamp - for the pen event and for any emulated mouse event */ - timestamp = SDL_GetTicksNS(); - } - - /* This code assumes that all of the SDL_Pen*Event structures have the same layout for these fields. - * This is checked by testautomation_pen.c, pen_memoryLayout(). */ - event->pmotion.timestamp = timestamp; - event->pmotion.windowID = window ? window->id : 0; - event->pmotion.which = pen->header.id; - event->pmotion.pen_state = last_buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); - event->pmotion.x = status->x; - event->pmotion.y = status->y; - SDL_memcpy(event->pmotion.axes, status->axes, SDL_PEN_NUM_AXES * sizeof(float)); + return result; } - -int SDL_SendPenMotion(Uint64 timestamp, - SDL_PenID instance_id, - SDL_bool window_relative, - const SDL_PenStatusInfo *status) +void SDL_RemovePenDevice(Uint64 timestamp, SDL_PenID instance_id) { - int i; - SDL_Pen *pen = SDL_GetPenPtr(instance_id); - SDL_Event event; - SDL_bool posted = SDL_FALSE; - float x = status->x; - float y = status->y; - float last_x = pen->last.x; - float last_y = pen->last.y; - /* Suppress mouse updates for axis changes or sub-pixel movement: */ - SDL_bool send_mouse_update; - SDL_bool axes_changed = SDL_FALSE; - SDL_Window *window; - - if (!pen) { - return SDL_FALSE; - } - window = pen->header.window; - if (!window) { - return SDL_FALSE; - } - - pen_relative_coordinates(window, window_relative, &x, &y); - - /* Check if the event actually modifies any cached axis or location, update as neeed */ - if (x != last_x || y != last_y) { - axes_changed = SDL_TRUE; - pen->last.x = status->x; - pen->last.y = status->y; - } - for (i = 0; i < SDL_PEN_NUM_AXES; ++i) { - if ((pen->header.flags & SDL_PEN_AXIS_CAPABILITY(i)) && (status->axes[i] != pen->last.axes[i])) { - axes_changed = SDL_TRUE; - pen->last.axes[i] = status->axes[i]; - } - } - if (!axes_changed) { - /* No-op event */ - return SDL_FALSE; - } - - send_mouse_update = (x != last_x) || (y != last_y); - - if (!(SDL_MousePositionInWindow(window, x, y))) { - return SDL_FALSE; + if (!instance_id) { + return; } - if (SDL_EventEnabled(SDL_EVENT_PEN_MOTION)) { - event_setup(pen, window, timestamp, status, &event); - event.pmotion.type = SDL_EVENT_PEN_MOTION; - - posted = SDL_PushEvent(&event) > 0; - - if (!posted) { - return SDL_FALSE; + SDL_LockRWLockForWriting(pen_device_rwlock); + SDL_Pen *pen = FindPenByInstanceId(instance_id); + if (pen) { + SDL_free(pen->name); + // we don't free `pen`, it's just part of simple array. Shuffle it out. + const int idx = ((int) (pen - pen_devices)); + SDL_assert((idx >= 0) && (idx < pen_device_count)); + if ( idx < (pen_device_count - 1) ) { + SDL_memmove(&pen_devices[idx], &pen_devices[idx + 1], sizeof (*pen) * ((pen_device_count - idx) - 1)); } - } - if (send_mouse_update) { - switch (pen_mouse_emulation_mode) { - case PEN_MOUSE_EMULATE: - return (SDL_SendMouseMotion(0, window, SDL_PEN_MOUSEID, SDL_FALSE, x, y)) || posted; + SDL_assert(pen_device_count > 0); + pen_device_count--; - case PEN_MOUSE_STATELESS: - /* Report mouse event but don't update mouse state */ - if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) { - event.motion.windowID = window->id; - event.motion.timestamp = timestamp; - event.motion.which = SDL_PEN_MOUSEID; - event.motion.type = SDL_EVENT_MOUSE_MOTION; - event.motion.state = pen->last.buttons | PEN_GET_PUBLIC_STATUS_MASK(pen); - event.motion.x = x; - event.motion.y = y; - event.motion.xrel = last_x - x; - event.motion.yrel = last_y - y; - return (SDL_PushEvent(&event) > 0) || posted; + if (pen_device_count) { + void *ptr = SDL_realloc(pen_devices, sizeof (*pen) * pen_device_count); // shrink it down. + if (ptr) { + pen_devices = (SDL_Pen *) ptr; } - break; - - default: - break; - } - } - return posted; -} - -int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state) -{ - SDL_Pen *pen = SDL_GetPenPtr(instance_id); - SDL_Event event; - SDL_bool posted = SDL_FALSE; - SDL_PenStatusInfo *last = &pen->last; - Uint8 mouse_button = SDL_BUTTON_LEFT; - SDL_Window *window; - - if (!pen) { - return SDL_FALSE; - } - window = pen->header.window; - - if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) { - return SDL_FALSE; - } - - if (state == SDL_PRESSED) { - event.pbutton.type = SDL_EVENT_PEN_DOWN; - pen->header.flags |= SDL_PEN_DOWN_MASK; - } else { - event.pbutton.type = SDL_EVENT_PEN_UP; - pen->header.flags &= ~SDL_PEN_DOWN_MASK; - } - - if (SDL_EventEnabled(event.ptip.type)) { - event_setup(pen, window, timestamp, &pen->last, &event); - - /* Used as eraser? Report eraser event, otherwise ink event */ - event.ptip.tip = (pen->header.flags & SDL_PEN_ERASER_MASK) ? SDL_PEN_TIP_ERASER : SDL_PEN_TIP_INK; - event.ptip.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; - - posted = SDL_PushEvent(&event) > 0; - - if (!posted) { - return SDL_FALSE; - } - } - - /* Mouse emulation */ - if (pen_delay_mouse_button_mode) { - /* Send button events when pen touches / leaves surface */ - mouse_button = pen->last_mouse_button; - if (mouse_button == 0) { - mouse_button = SDL_BUTTON_LEFT; /* No current button? Instead report left mouse button */ + } else { + SDL_free(pen_devices); + pen_devices = NULL; } } + SDL_UnlockRWLock(pen_device_rwlock); - switch (pen_mouse_emulation_mode) { - case PEN_MOUSE_EMULATE: - return (SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, state, mouse_button)) || posted; - - case PEN_MOUSE_STATELESS: - /* Report mouse event without updating mouse state */ - event.button.type = state == SDL_PRESSED ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; - if (SDL_EventEnabled(event.button.type)) { - event.button.windowID = window ? window->id : 0; - event.button.timestamp = timestamp; - event.button.which = SDL_PEN_MOUSEID; - - event.button.state = state; - event.button.button = mouse_button; - event.button.clicks = 1; - event.button.x = last->x; - event.button.y = last->y; - return (SDL_PushEvent(&event) > 0) || posted; - } - break; - - default: - break; + if (pen && SDL_EventEnabled(SDL_EVENT_PEN_PROXIMITY_OUT)) { + SDL_Event event; + SDL_zero(event); + event.pproximity.type = SDL_EVENT_PEN_PROXIMITY_OUT; + event.pproximity.timestamp = timestamp; + event.pproximity.which = instance_id; + SDL_PushEvent(&event); } - return posted; } -int SDL_SendPenButton(Uint64 timestamp, - SDL_PenID instance_id, - Uint8 state, Uint8 button) +// This presumably is happening during video quit, so we don't send PROXIMITY_OUT events here. +void SDL_RemoveAllPenDevices(void (*callback)(SDL_PenID instance_id, void *handle, void *userdata), void *userdata) { - SDL_Pen *pen = SDL_GetPenPtr(instance_id); - SDL_Event event; - SDL_bool posted = SDL_FALSE; - SDL_PenStatusInfo *last = &pen->last; - Uint8 mouse_button = button + 1; /* For mouse emulation, PEN_DOWN counts as button 1, so the first actual button is mouse button 2 */ - SDL_Window *window; - - if (!pen) { - return SDL_FALSE; - } - window = pen->header.window; - - if ((state == SDL_PRESSED) && !(window && SDL_MousePositionInWindow(window, last->x, last->y))) { - return SDL_FALSE; - } - - if (state == SDL_PRESSED) { - event.pbutton.type = SDL_EVENT_PEN_BUTTON_DOWN; - pen->last.buttons |= (1 << (button - 1)); - } else { - event.pbutton.type = SDL_EVENT_PEN_BUTTON_UP; - pen->last.buttons &= ~(1 << (button - 1)); - } - - if (SDL_EventEnabled(event.pbutton.type)) { - event_setup(pen, window, timestamp, &pen->last, &event); - - event.pbutton.button = button; - event.pbutton.state = state == SDL_PRESSED ? SDL_PRESSED : SDL_RELEASED; - - posted = SDL_PushEvent(&event) > 0; - - if (!posted) { - return SDL_FALSE; + SDL_LockRWLockForWriting(pen_device_rwlock); + if (pen_device_count > 0) { + SDL_assert(pen_devices != NULL); + for (int i = 0; i < pen_device_count; i++) { + callback(pen_devices[i].instance_id, pen_devices[i].driverdata, userdata); + SDL_free(pen_devices[i].name); } } - - /* Mouse emulation */ - if (pen_delay_mouse_button_mode) { - /* Can only change active mouse button while not touching the surface */ - if (!(pen->header.flags & SDL_PEN_DOWN_MASK)) { - if (state == SDL_RELEASED) { - pen->last_mouse_button = 0; - } else { - pen->last_mouse_button = mouse_button; - } + SDL_free(pen_devices); + pen_devices = NULL; + SDL_UnlockRWLock(pen_device_rwlock); +} + +void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, bool eraser, bool down) +{ + bool send_event = false; + SDL_PenInputFlags input_state = 0; + float x = 0.0f; + float y = 0.0f; + + // note that this locks for _reading_ because the lock protects the + // pen_devices array from being reallocated from under us, not the data in it; + // we assume only one thread (in the backend) is modifying an individual pen at + // a time, so it can update input state cleanly here. + SDL_LockRWLockForReading(pen_device_rwlock); + SDL_Pen *pen = FindPenByInstanceId(instance_id); + if (pen) { + input_state = pen->input_state; + x = pen->x; + y = pen->y; + + if (down && ((input_state & SDL_PEN_INPUT_DOWN) == 0)) { + input_state |= SDL_PEN_INPUT_DOWN; + send_event = true; + } else if (!down && (input_state & SDL_PEN_INPUT_DOWN)) { + input_state &= ~SDL_PEN_INPUT_DOWN; + send_event = true; } - /* Defer emulation event */ - return SDL_TRUE; - } - - switch (pen_mouse_emulation_mode) { - case PEN_MOUSE_EMULATE: - return (SDL_SendMouseButton(timestamp, window, SDL_PEN_MOUSEID, state, mouse_button)) || posted; - - case PEN_MOUSE_STATELESS: - /* Report mouse event without updating mouse state */ - event.button.type = state == SDL_PRESSED ? SDL_EVENT_MOUSE_BUTTON_DOWN : SDL_EVENT_MOUSE_BUTTON_UP; - if (SDL_EventEnabled(event.button.type)) { - event.button.windowID = window ? window->id : 0; - event.button.timestamp = timestamp; - event.button.which = SDL_PEN_MOUSEID; - event.button.state = state; - event.button.button = mouse_button; - event.button.clicks = 1; - event.button.x = last->x; - event.button.y = last->y; - return (SDL_PushEvent(&event) > 0) || posted; + if (eraser && ((input_state & SDL_PEN_INPUT_ERASER_TIP) == 0)) { + input_state |= SDL_PEN_INPUT_ERASER_TIP; + send_event = true; + } else if (!down && (input_state & SDL_PEN_INPUT_ERASER_TIP)) { + input_state &= ~SDL_PEN_INPUT_ERASER_TIP; + send_event = true; } - break; - default: - break; - } - return posted; -} - -int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window) -{ - SDL_EventType event_id = window ? SDL_EVENT_WINDOW_PEN_ENTER : SDL_EVENT_WINDOW_PEN_LEAVE; - SDL_Event event = { 0 }; - SDL_Pen *pen = SDL_GetPenPtr(instance_id); - SDL_bool posted; - - if (!pen) { - return SDL_FALSE; - } - - if (pen->header.window == window) { /* (TRIVIAL-EVENT) Nothing new to report */ - return SDL_FALSE; - } - - if (timestamp == 0) { - /* Generate timestamp ourselves, if needed, so that we report the same timestamp - for the pen event and for any emulated mouse event */ - timestamp = SDL_GetTicksNS(); - } - - event.window.type = event_id; - /* If window == NULL and not (TRIVIAL-EVENT), then pen->header.window != NULL */ - event.window.timestamp = timestamp; - event.window.windowID = window ? window->id : pen->header.window->id; - event.window.data1 = instance_id; - posted = (SDL_PushEvent(&event) > 0); - - /* Update after assembling event */ - pen->header.window = window; - - switch (pen_mouse_emulation_mode) { - case PEN_MOUSE_EMULATE: - SDL_SetMouseFocus(event_id == SDL_EVENT_WINDOW_PEN_ENTER ? window : NULL); - break; - - case PEN_MOUSE_STATELESS: - /* Send event without going through mouse API */ - if (event_id == SDL_EVENT_WINDOW_PEN_ENTER) { - event.window.type = SDL_EVENT_WINDOW_MOUSE_ENTER; - } else { - event.window.type = SDL_EVENT_WINDOW_MOUSE_LEAVE; + pen->input_state = input_state; // we could do an SDL_SetAtomicInt here if we run into trouble... + } + SDL_UnlockRWLock(pen_device_rwlock); + + if (send_event) { + const SDL_EventType evtype = down ? SDL_EVENT_PEN_DOWN : SDL_EVENT_PEN_UP; + if (SDL_EventEnabled(evtype)) { + SDL_Event event; + SDL_zero(event); + event.ptouch.type = evtype; + event.ptouch.timestamp = timestamp; + event.ptouch.windowID = window ? window->id : 0; + event.ptouch.which = instance_id; + event.ptouch.pen_state = input_state; + event.ptouch.x = x; + event.ptouch.y = y; + event.ptouch.eraser = eraser; + event.ptouch.down = down; + SDL_PushEvent(&event); } - posted = posted || (SDL_PushEvent(&event) > 0); - break; - - default: - break; - } - - return posted; -} - -static void SDLCALL SDL_PenUpdateHint(void *userdata, const char *name, const char *oldvalue, const char *newvalue) -{ - int *var = (int *)userdata; - if (newvalue == NULL) { - return; - } - - if (0 == SDL_strcmp("2", newvalue)) { - *var = 2; - } else if (0 == SDL_strcmp("1", newvalue)) { - *var = 1; - } else if (0 == SDL_strcmp("0", newvalue)) { - *var = 0; - } else { - SDL_Log("Unexpected value for pen hint: '%s'", newvalue); } } -void SDL_PenInit(void) +void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, SDL_PenAxis axis, float value) { -#if (SDL_PEN_DEBUG_NOID | SDL_PEN_DEBUG_NONWACOM | SDL_PEN_DEBUG_UNKNOWN_WACOM) - printf("[pen] Debugging enabled: noid=%d nonwacom=%d unknown-wacom=%d\n", - SDL_PEN_DEBUG_NOID, SDL_PEN_DEBUG_NONWACOM, SDL_PEN_DEBUG_UNKNOWN_WACOM); -#endif - SDL_AddHintCallback(SDL_HINT_PEN_NOT_MOUSE, - SDL_PenUpdateHint, &pen_mouse_emulation_mode); + SDL_assert((axis >= 0) && (axis < SDL_PEN_AXIS_COUNT)); // fix the backend if this triggers. - SDL_AddHintCallback(SDL_HINT_PEN_DELAY_MOUSE_BUTTON, - SDL_PenUpdateHint, &pen_delay_mouse_button_mode); -#ifndef SDL_THREADS_DISABLED - SDL_pen_access_lock = SDL_CreateMutex(); -#endif -} + bool send_event = false; + SDL_PenInputFlags input_state = 0; + float x = 0.0f; + float y = 0.0f; -void SDL_PenQuit(void) -{ - unsigned int i; - - SDL_DelHintCallback(SDL_HINT_PEN_NOT_MOUSE, - SDL_PenUpdateHint, &pen_mouse_emulation_mode); - - SDL_DelHintCallback(SDL_HINT_PEN_DELAY_MOUSE_BUTTON, - SDL_PenUpdateHint, &pen_delay_mouse_button_mode); -#ifndef SDL_THREADS_DISABLED - SDL_DestroyMutex(SDL_pen_access_lock); - SDL_pen_access_lock = NULL; -#endif - - if (pen_handler.pens) { - for (i = 0; i < pen_handler.pens_known; ++i) { - SDL_free(pen_handler.pens[i].name); + // note that this locks for _reading_ because the lock protects the + // pen_devices array from being reallocated from under us, not the data in it; + // we assume only one thread (in the backend) is modifying an individual pen at + // a time, so it can update input state cleanly here. + SDL_LockRWLockForReading(pen_device_rwlock); + SDL_Pen *pen = FindPenByInstanceId(instance_id); + if (pen) { + if (pen->axes[axis] != value) { + pen->axes[axis] = value; // we could do an SDL_SetAtomicInt here if we run into trouble... + input_state = pen->input_state; + x = pen->x; + y = pen->y; + send_event = true; } - SDL_free(pen_handler.pens); - /* Reset static pen information */ - SDL_memset(&pen_handler, 0, sizeof(pen_handler)); } -} - -SDL_bool SDL_PenPerformHitTest(void) -{ - return pen_mouse_emulation_mode == PEN_MOUSE_EMULATE; -} - -/* Vendor-specific bits */ - -/* Default pen names */ -#define PEN_NAME_AES 0 -#define PEN_NAME_ART 1 -#define PEN_NAME_AIRBRUSH 2 -#define PEN_NAME_GENERAL 3 -#define PEN_NAME_GRIP 4 -#define PEN_NAME_INKING 5 -#define PEN_NAME_PRO 6 -#define PEN_NAME_PRO2 7 -#define PEN_NAME_PRO3 8 -#define PEN_NAME_PRO3D 9 -#define PEN_NAME_PRO_SLIM 10 -#define PEN_NAME_STROKE 11 - -#define PEN_NAME_LAST PEN_NAME_STROKE -#define PEN_NUM_NAMES (PEN_NAME_LAST + 1) - -static const char *default_pen_names[] = { - /* PEN_NAME_AES */ - "AES Pen", - /* PEN_NAME_ART */ - "Art Pen", - /* PEN_NAME_AIRBRUSH */ - "Airbrush Pen", - /* PEN_NAME_GENERAL */ - "Pen", - /* PEN_NAME_GRIP */ - "Grip Pen", - /* PEN_NAME_INKING */ - "Inking Pen", - /* PEN_NAME_PRO */ - "Pro Pen", - /* PEN_NAME_PRO2 */ - "Pro Pen 2", - /* PEN_NAME_PRO3 */ - "Pro Pen 3", - /* PEN_NAME_PRO3D */ - "Pro Pen 3D", - /* PEN_NAME_PRO_SLIM */ - "Pro Pen Slim", - /* PEN_NAME_STROKE */ - "Stroke Pen" -}; -SDL_COMPILE_TIME_ASSERT(default_pen_names, SDL_arraysize(default_pen_names) == PEN_NUM_NAMES); - -#define PEN_SPEC_TYPE_SHIFT 0 -#define PEN_SPEC_TYPE_MASK 0x0000000fu -#define PEN_SPEC_BUTTONS_SHIFT 4 -#define PEN_SPEC_BUTTONS_MASK 0x000000f0u -#define PEN_SPEC_NAME_SHIFT 8 -#define PEN_SPEC_NAME_MASK 0x00000f00u -#define PEN_SPEC_AXES_SHIFT 0 -#define PEN_SPEC_AXES_MASK 0xffff0000u - -#define PEN_WACOM_ID_INVALID 0xffffffffu /* Generic "invalid ID" marker */ - -#define PEN_SPEC(name, buttons, type, axes) (0 | (PEN_SPEC_NAME_MASK & ((name) << PEN_SPEC_NAME_SHIFT)) | (PEN_SPEC_BUTTONS_MASK & ((buttons) << PEN_SPEC_BUTTONS_SHIFT)) | (PEN_SPEC_TYPE_MASK & ((type) << PEN_SPEC_TYPE_SHIFT)) | (PEN_SPEC_AXES_MASK & ((axes) << PEN_SPEC_AXES_SHIFT))) - -/* Returns a suitable pen name string from default_pen_names on success, otherwise NULL. */ -static const char *pen_wacom_identify_tool(Uint32 requested_wacom_id, int *num_buttons, int *tool_type, int *axes) -{ - int i; - - /* List of known Wacom pens, extracted from libwacom.stylus and wacom_wac.c in the Linux kernel. - Could be complemented by dlopen()ing libwacom, in the future (if new pens get added). */ - struct - { - /* Compress properties to 8 bytes per device in order to keep memory cost well below 1k. - Could be compressed further with more complex code. */ - Uint32 wacom_id; /* Must be != PEN_WACOM_ID_INVALID */ - Uint32 properties; - } tools[] = { - { 0x0001, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0011, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0019, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0021, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0031, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0039, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0049, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0071, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0200, PEN_SPEC(PEN_NAME_PRO3, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0221, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0231, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0271, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0421, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0431, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0621, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0631, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK) }, - { 0x0801, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0802, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0804, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, - { 0x080a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x080c, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0812, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0813, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x081b, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0822, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0823, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x082a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x082b, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0832, PEN_SPEC(PEN_NAME_STROKE, 0, SDL_PEN_TYPE_BRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0842, PEN_SPEC(PEN_NAME_PRO2, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x084a, PEN_SPEC(PEN_NAME_PRO2, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0852, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x085a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0862, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0885, PEN_SPEC(PEN_NAME_ART, 0, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, - { 0x08e2, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0902, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, - { 0x090a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0912, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, - { 0x0913, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x091a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x091b, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x0d12, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, - { 0x0d1a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x8051, PEN_SPEC(PEN_NAME_AES, 0, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x805b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x806b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x807b, PEN_SPEC(PEN_NAME_GENERAL, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x826b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x846b, PEN_SPEC(PEN_NAME_AES, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK) }, - { 0x2802, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x4200, PEN_SPEC(PEN_NAME_PRO3, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x4802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x480a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x8842, PEN_SPEC(PEN_NAME_PRO3D, 3, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x10802, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x10804, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_ROTATION_MASK) }, - { 0x1080a, PEN_SPEC(PEN_NAME_GRIP, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x1080c, PEN_SPEC(PEN_NAME_ART, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x10842, PEN_SPEC(PEN_NAME_PRO_SLIM, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x1084a, PEN_SPEC(PEN_NAME_PRO_SLIM, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x10902, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_AIRBRUSH, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK | SDL_PEN_AXIS_SLIDER_MASK) }, - { 0x1090a, PEN_SPEC(PEN_NAME_AIRBRUSH, 1, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x12802, PEN_SPEC(PEN_NAME_INKING, 0, SDL_PEN_TYPE_PENCIL, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x14802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x1480a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x16802, PEN_SPEC(PEN_NAME_PRO, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x1680a, PEN_SPEC(PEN_NAME_PRO, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x18802, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_PEN, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0x1880a, PEN_SPEC(PEN_NAME_GENERAL, 2, SDL_PEN_TYPE_ERASER, SDL_PEN_AXIS_PRESSURE_MASK | SDL_PEN_AXIS_XTILT_MASK | SDL_PEN_AXIS_YTILT_MASK | SDL_PEN_AXIS_DISTANCE_MASK) }, - { 0, 0 } - }; - - /* The list of pens is sorted, so we could do binary search, but this call should be pretty rare. */ - for (i = 0; tools[i].wacom_id; ++i) { - if (tools[i].wacom_id == requested_wacom_id) { - Uint32 properties = tools[i].properties; - int name_index = (properties & PEN_SPEC_NAME_MASK) >> PEN_SPEC_NAME_SHIFT; - - *num_buttons = (properties & PEN_SPEC_BUTTONS_MASK) >> PEN_SPEC_BUTTONS_SHIFT; - *tool_type = (properties & PEN_SPEC_TYPE_MASK) >> PEN_SPEC_TYPE_SHIFT; - *axes = (properties & PEN_SPEC_AXES_MASK) >> PEN_SPEC_AXES_SHIFT; - - return default_pen_names[name_index]; + SDL_UnlockRWLock(pen_device_rwlock); + + if (send_event && SDL_EventEnabled(SDL_EVENT_PEN_AXIS)) { + SDL_Event event; + SDL_zero(event); + event.paxis.type = SDL_EVENT_PEN_AXIS; + event.paxis.timestamp = timestamp; + event.paxis.windowID = window ? window->id : 0; + event.paxis.which = instance_id; + event.paxis.pen_state = input_state; + event.paxis.x = x; + event.paxis.y = y; + event.paxis.axis = axis; + event.paxis.value = value; + SDL_PushEvent(&event); + } +} + +void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, float x, float y) +{ + bool send_event = false; + SDL_PenInputFlags input_state = 0; + + // note that this locks for _reading_ because the lock protects the + // pen_devices array from being reallocated from under us, not the data in it; + // we assume only one thread (in the backend) is modifying an individual pen at + // a time, so it can update input state cleanly here. + SDL_LockRWLockForReading(pen_device_rwlock); + SDL_Pen *pen = FindPenByInstanceId(instance_id); + if (pen) { + if ((pen->x != x) || (pen->y != y)) { + pen->x = x; // we could do an SDL_SetAtomicInt here if we run into trouble... + pen->y = y; // we could do an SDL_SetAtomicInt here if we run into trouble... + input_state = pen->input_state; + send_event = true; } } - return NULL; -} - -void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower) -{ - int i; + SDL_UnlockRWLock(pen_device_rwlock); - for (i = 0; i < 4; ++i) { - guid->data[8 + i] = (lower >> (i * 8)) & 0xff; - } - - for (i = 0; i < 4; ++i) { - guid->data[12 + i] = (upper >> (i * 8)) & 0xff; - } -} - -void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype) -{ - guid->data[7] = pentype; -} - -void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id) -{ - int i; - - for (i = 0; i < 4; ++i) { - guid->data[0 + i] = (wacom_serial_id >> (i * 8)) & 0xff; - } - - for (i = 0; i < 3; ++i) { /* 24 bit values */ - guid->data[4 + i] = (wacom_devicetype_id >> (i * 8)) & 0xff; - } -} - -int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags) -{ - const char *name = NULL; - int num_buttons = 0; - int tool_type = 0; - int axes = 0; - -#if SDL_PEN_DEBUG_UNKNOWN_WACOM - wacom_devicetype_id = PEN_WACOM_ID_INVALID; /* force detection to fail */ -#endif - -#if defined(SDL_PLATFORM_LINUX) || defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_NETBSD) || defined(SDL_PLATFORM_OPENBSD) - /* According to Ping Cheng, the curent Wacom for Linux maintainer, device IDs on Linux - squeeze a "0" nibble after the 3rd (least significant) nibble. - This may also affect the *BSDs, so they are heuristically included here. - On those platforms, we first try the "patched" ID: */ - if (0 == (wacom_devicetype_id & 0x0000f000u)) { - const Uint32 lower_mask = 0xfffu; - int wacom_devicetype_alt_id = ((wacom_devicetype_id & ~lower_mask) >> 4) | (wacom_devicetype_id & lower_mask); - - name = pen_wacom_identify_tool(wacom_devicetype_alt_id, &num_buttons, &tool_type, &axes); - if (name) { - wacom_devicetype_id = wacom_devicetype_alt_id; + if (send_event && SDL_EventEnabled(SDL_EVENT_PEN_MOTION)) { + SDL_Event event; + SDL_zero(event); + event.pmotion.type = SDL_EVENT_PEN_MOTION; + event.pmotion.timestamp = timestamp; + event.pmotion.windowID = window ? window->id : 0; + event.pmotion.which = instance_id; + event.pmotion.pen_state = input_state; + event.pmotion.x = x; + event.pmotion.y = y; + SDL_PushEvent(&event); + } +} + +void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, Uint8 button, bool down) +{ + bool send_event = false; + SDL_PenInputFlags input_state = 0; + float x = 0.0f; + float y = 0.0f; + + if ((button < 1) || (button > 5)) { + return; // clamp for now. + } + + // note that this locks for _reading_ because the lock protects the + // pen_devices array from being reallocated from under us, not the data in it; + // we assume only one thread (in the backend) is modifying an individual pen at + // a time, so it can update input state cleanly here. + SDL_LockRWLockForReading(pen_device_rwlock); + SDL_Pen *pen = FindPenByInstanceId(instance_id); + if (pen) { + input_state = pen->input_state; + const Uint32 flag = (Uint32) (1u << button); + const bool current = ((input_state & flag) != 0); + x = pen->x; + y = pen->y; + if (down && !current) { + input_state |= flag; + send_event = true; + } else if (!down && current) { + input_state &= ~flag; + send_event = true; + } + pen->input_state = input_state; // we could do an SDL_SetAtomicInt here if we run into trouble... + } + SDL_UnlockRWLock(pen_device_rwlock); + + if (send_event) { + const SDL_EventType evtype = down ? SDL_EVENT_PEN_BUTTON_DOWN : SDL_EVENT_PEN_BUTTON_UP; + if (SDL_EventEnabled(evtype)) { + SDL_Event event; + SDL_zero(event); + event.pbutton.type = evtype; + event.pbutton.timestamp = timestamp; + event.pbutton.windowID = window ? window->id : 0; + event.pbutton.which = instance_id; + event.pbutton.pen_state = input_state; + event.pbutton.x = x; + event.pbutton.y = y; + event.pbutton.button = button; + event.pbutton.down = down; + SDL_PushEvent(&event); } } -#endif - if (name == NULL) { - name = pen_wacom_identify_tool(wacom_devicetype_id, &num_buttons, &tool_type, &axes); - } - - if (!name) { - *axis_flags = 0; - return SDL_FALSE; - } - - *axis_flags = axes; - - /* Override defaults */ - if (pen->info.num_buttons == SDL_PEN_INFO_UNKNOWN) { - pen->info.num_buttons = (Sint8)SDL_min(num_buttons, SDL_MAX_SINT8); - } - if (pen->type == SDL_PEN_TYPE_PEN) { - pen->type = (SDL_PenSubtype)tool_type; - } - if (pen->info.max_tilt == SDL_PEN_INFO_UNKNOWN) { - /* supposedly: 64 degrees left, 63 right, as reported by the Wacom X11 driver */ - pen->info.max_tilt = 64.0f; - } - pen->info.wacom_id = wacom_devicetype_id; - if (0 == pen->name[0]) { - SDL_snprintf(pen->name, SDL_PEN_MAX_NAME, - "Wacom %s%s", name, (tool_type == SDL_PEN_TYPE_ERASER) ? " Eraser" : ""); - } - return SDL_TRUE; } + diff --git a/libs/SDL3/src/events/SDL_pen_c.h b/libs/SDL3/src/events/SDL_pen_c.h index a82b345db..7e069b000 100644 --- a/libs/SDL3/src/events/SDL_pen_c.h +++ b/libs/SDL3/src/events/SDL_pen_c.h @@ -24,320 +24,73 @@ #ifndef SDL_pen_c_h_ #define SDL_pen_c_h_ -#include "../../include/SDL3/SDL_pen.h" #include "SDL_mouse_c.h" -/* For testing alternate code paths: */ -#define SDL_PEN_DEBUG_NOID 0 /* Pretend that pen device does not supply ID / ID is some default value \ - affects: SDL_x11pen.c \ - SDL_waylandevents.c */ -#define SDL_PEN_DEBUG_NONWACOM 0 /* Pretend that no attached device is a Wacom device \ - affects: SDL_x11pen.c \ - SDL_waylandevents.c */ -#define SDL_PEN_DEBUG_UNKNOWN_WACOM 0 /* Pretend that any attached Wacom device is of an unknown make \ - affects: SDL_PenModifyFromWacomID() */ -#define SDL_PEN_DEBUG_NOSERIAL_WACOM 0 /* Pretend that any attached Wacom device has serial number 0 \ - affects: SDL_x11pen.c \ - SDL_waylandevents.c */ - -#define SDL_PEN_TYPE_NONE 0 /**< Pen type for non-pens (use to cancel pen registration) */ - -#define SDL_PEN_MAX_NAME 64 - -#define SDL_PEN_FLAG_ERROR (1ul << 28) /* Printed an internal API usage error about this pen (used to prevent spamming) */ -#define SDL_PEN_FLAG_NEW (1ul << 29) /* Pen was registered in most recent call to SDL_PenRegisterBegin() */ -#define SDL_PEN_FLAG_DETACHED (1ul << 30) /* Detached (not re-registered before last SDL_PenGCSweep()) */ -#define SDL_PEN_FLAG_STALE (1ul << 31) /* Not re-registered since last SDL_PenGCMark() */ - -typedef struct SDL_PenStatusInfo +typedef Uint32 SDL_PenCapabilityFlags; +#define SDL_PEN_CAPABILITY_PRESSURE (1u << 0) /**< Provides pressure information on SDL_PEN_AXIS_PRESSURE. */ +#define SDL_PEN_CAPABILITY_XTILT (1u << 1) /**< Provides horizontal tilt information on SDL_PEN_AXIS_XTILT. */ +#define SDL_PEN_CAPABILITY_YTILT (1u << 2) /**< Provides vertical tilt information on SDL_PEN_AXIS_YTILT. */ +#define SDL_PEN_CAPABILITY_DISTANCE (1u << 3) /**< Provides distance to drawing tablet on SDL_PEN_AXIS_DISTANCE. */ +#define SDL_PEN_CAPABILITY_ROTATION (1u << 4) /**< Provides barrel rotation info on SDL_PEN_AXIS_ROTATION. */ +#define SDL_PEN_CAPABILITY_SLIDER (1u << 5) /**< Provides slider/finger wheel/etc on SDL_PEN_AXIS_SLIDER. */ +#define SDL_PEN_CAPABILITY_TANGENTIAL_PRESSURE (1u << 6) /**< Provides barrel pressure on SDL_PEN_AXIS_TANGENTIAL_PRESSURE. */ +#define SDL_PEN_CAPABILITY_ERASER (1u << 7) /**< Pen also has an eraser tip. */ + +typedef enum SDL_PenSubtype { - float x, y; - float axes[SDL_PEN_NUM_AXES]; - Uint16 buttons; /* SDL_BUTTON(1) | SDL_BUTTON(2) | ... | SDL_PEN_DOWN_MASK */ -} SDL_PenStatusInfo; - -typedef struct + SDL_PEN_TYPE_UNKNOWN, /**< Unknown pen device */ + SDL_PEN_TYPE_ERASER, /**< Eraser */ + SDL_PEN_TYPE_PEN, /**< Generic pen; this is the default. */ + SDL_PEN_TYPE_PENCIL, /**< Pencil */ + SDL_PEN_TYPE_BRUSH, /**< Brush-like device */ + SDL_PEN_TYPE_AIRBRUSH /**< Airbrush device that "sprays" ink */ +} SDL_PenSubtype; + +typedef struct SDL_PenInfo { - SDL_PenID id; /* id determines sort order unless SDL_PEN_FLAG_DETACHED is set */ - Uint32 flags; /* SDL_PEN_FLAG_* | SDK_PEN_DOWN_MASK | SDL_PEN_INK_MASK | SDL_PEN_ERASER_MASK | SDL_PEN_AXIS_* */ - SDL_Window *window; /* Current SDL window for this pen, or NULL */ -} SDL_PenHeader; - -/** - * Internal (backend driver-independent) pen representation - * - * Implementation-specific backend drivers may read and write most of this structure, and - * are expected to initialise parts of it when registering a new pen. They must not write - * to the "header" section. - */ -typedef struct SDL_Pen -{ - /* Backend driver MUST NOT not write to: */ - SDL_PenHeader header; - - SDL_PenStatusInfo last; /* Last reported status, normally read-only for backend */ - - /* Backend: MUST initialise this block when pen is first registered: */ - SDL_GUID guid; /* GUID, MUST be set by backend. - MUST be unique (no other pen ID with same GUID). - SHOULD be persistent across sessions. */ - - /* Backend: SHOULD initialise this block when pen is first registered if it can - Otherwise: Set to sane default values during SDL_PenModifyEnd() */ - SDL_PenCapabilityInfo info; /* Detail information about the pen (buttons, tilt) */ - SDL_PenSubtype type; - Uint8 last_mouse_button; /* For mouse button emulation: last emulated button */ - char *name; /* Preallocated; set via SDL_strlcpy(pen->name, src, SDL_PEN_MAX_NAME) */ - /* We hand this exact pointer to client code, so it must not be modified after - creation. */ - - void *deviceinfo; /* implementation-specific information */ -} SDL_Pen; - -/* ---- API for backend driver only ---- */ - -/** - * (Only for backend driver) Look up a pen by pen ID - * - * \param instance_id A Uint32 pen identifier (driver-dependent meaning). Must not be 0 = SDL_PEN_INVALID. - * The same ID is exposed to clients as SDL_PenID. - * - * The pen pointer is only valid until the next call to SDL_PenModifyEnd() or SDL_PenGCSweep() - * - * \return pen, if it exists, or NULL - */ -extern SDL_Pen *SDL_GetPenPtr(Uint32 instance_id); - -/** - * (Only for backend driver) Start registering a new pen or updating an existing pen. - * - * Acquires the pen mutex, which is held until the next call to SDL_PenModifyEnd() . - * - * If the PenID already exists, returns the existing entry. Otherwise initialise fresh SDL_Pen. - * For new pens, sets SDL_PEN_FLAG_NEW. - * - * Usage: - * - SDL_PenModifyStart() - * - update pen object, in any order: - * - SDL_PenModifyAddCapabilities() - * - pen->guid (MUST be set for new pens, e.g. via ::SDL_PenUpdateGUIDForGeneric and related operations) - * - pen->info.num_buttons - * - pen->info.max_tilt - * - pen->type - * - pen->name - * - pen->deviceinfo (backend-specific) - * - SDL_PenModifyEnd() - * - * For new pens, sets defaults for: - * - num_buttons (SDL_PEN_INFO_UNKNOWN) - * - max_tilt (SDL_PEN_INFO_UNKNOWN) - * - pen_type (SDL_PEN_TYPE_PEN) - * - Zeroes all other (non-header) fields - * - * \param instance_id Pen ID to allocate (must not be 0 = SDL_PEN_ID_INVALID) - * \returns SDL_Pen pointer; only valid until the call to SDL_PenModifyEnd() - */ -extern SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id); - -/** - * (Only for backend driver) Add capabilities to a pen (cf. SDL_PenModifyBegin()). - * - * Adds capabilities to a pen obtained via SDL_PenModifyBegin(). Can be called more than once. - * - * \param pen The pen to update - * \param capabilities Capabilities flags, out of: SDL_PEN_AXIS_*, SDL_PEN_ERASER_MASK, SDL_PEN_INK_MASK - * Setting SDL_PEN_ERASER_MASK will clear SDL_PEN_INK_MASK, and vice versa. - */ -extern void SDL_PenModifyAddCapabilities(SDL_Pen *pen, Uint32 capabilities); - -/** - * Set up a pen structure for a Wacom device. - * - * Some backends (e.g., XInput2, Wayland) can only partially identify the capabilities of a given - * pen but can identify Wacom pens and obtain their Wacom-specific device type identifiers. - * This function partly automates device setup in those cases. - * - * This function does NOT set up the pen's GUID. Use ::SD_PenModifyGUIDForWacom instead. - * - * This function does NOT call SDL_PenModifyAddCapabilities() ifself, since some backends may - * not have access to all pen axes (e.g., Xinput2). - * - * \param pen The pen to initialise - * \param wacom_devicetype_id The Wacom-specific device type identifier - * \param[out] axis_flags The set of physically supported axes for this pen, suitable for passing to - * SDL_PenModifyAddCapabilities() - * - * \returns SDL_TRUE if the device ID could be identified, otherwise SDL_FALSE - */ -extern int SDL_PenModifyForWacomID(SDL_Pen *pen, Uint32 wacom_devicetype_id, Uint32 *axis_flags); - -/** - * Updates a GUID for a generic pen device. - * - * Assumes that the GUID has been pre-initialised (typically to 0). - * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForType - * - * \param[out] guid The GUID to update - * \param upper Upper half of the device ID (assume lower entropy than "lower"; pass 0 if not available) - * \param lower Lower half of the device ID (assume higher entropy than "upper") - */ -extern void SDL_PenUpdateGUIDForGeneric(SDL_GUID *guid, Uint32 upper, Uint32 lower); - -/** - * Updates a GUID based on a pen type - * - * Assumes that the GUID has been pre-initialised (typically to 0). - * Idempotent, and commutative with ::SDL_PenUpdateGUIDForWacom and ::SDL_PenUpdateGUIDForGeneric - * - * \param[out] guid The GUID to update - * \param pentype The pen type to insert - */ -extern void SDL_PenUpdateGUIDForType(SDL_GUID *guid, SDL_PenSubtype pentype); + SDL_PenCapabilityFlags capabilities; /**< bitflags of device capabilities */ + float max_tilt; /**< Physical maximum tilt angle, for XTILT and YTILT, or -1.0f if unknown. Pens cannot typically tilt all the way to 90 degrees, so this value is usually less than 90.0. */ + Uint32 wacom_id; /**< For Wacom devices: wacom tool type ID, otherwise 0 (useful e.g. with libwacom) */ + int num_buttons; /**< Number of pen buttons (not counting the pen tip), or -1 if unknown. */ + SDL_PenSubtype subtype; /**< type of pen device */ +} SDL_PenInfo; -/** - * Updates a GUID for a Wacom pen device. - * - * Assumes that the GUID has been pre-initialised (typically to 0). - * Idempotent, and commutative with ::SDL_PenUpdateGUIDForType and ::SDL_PenUpdateGUIDForGeneric - * - * This update is identical to the one written by ::SDL_PenModifyFromWacomID . - * - * \param[out] guid The GUID to update - * \param wacom_devicetype_id The Wacom-specific device type identifier - * \param wacom_serial_id The Wacom-specific serial number - */ -extern void SDL_PenUpdateGUIDForWacom(SDL_GUID *guid, Uint32 wacom_devicetype_id, Uint32 wacom_serial_id); +// Backend calls this when a new pen device is hotplugged, plus once for each pen already connected at startup. +// Note that name and info are copied but currently unused; this is placeholder for a potentially more robust API later. +// Both are allowed to be NULL. +extern SDL_PenID SDL_AddPenDevice(Uint64 timestamp, const char *name, const SDL_PenInfo *info, void *handle); -/** - * (Only for backend driver) Finish updating a pen. - * - * Releases the pen mutex acquired by SDL_PenModifyBegin() . - * - * If pen->type == SDL_PEN_TYPE_NONE, removes the pen entirely (only - * for new pens). This allows backends to start registering a - * potential pen device and to abort if the device turns out to not be - * a pen. - * - * For new pens, this call will also set the following: - * - name (default name, if not yet set) - * - * \param pen The pen to register. That pointer is no longer valid after this call. - * \param attach Whether the pen should be attached (SDL_TRUE) or detached (SDL_FALSE). - * - * If the pen is detached or removed, it is the caller's responsibility to free - * and null "deviceinfo". - */ -extern void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach); +// Backend calls this when an existing pen device is disconnected during runtime. They must free their own stuff separately. +extern void SDL_RemovePenDevice(Uint64 timestamp, SDL_PenID instance_id); -/** - * (Only for backend driver) Mark all current pens for garbage collection. - * - * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ). - * - * SDL_PenGCMark() / SDL_PenGCSweep() provide a simple mechanism for - * detaching all known pens that are not discoverable. This allows - * backends to use the same code for pen discovery and for - * hotplugging: - * - * - SDL_PenGCMark() and start backend-specific discovery - * - for each discovered pen: SDL_PenModifyBegin() + SDL_PenModifyEnd() (this will retain existing state) - * - SDL_PenGCSweep() (will now detach all pens that were not re-registered). - */ -extern void SDL_PenGCMark(void); +// Backend can call this to remove all pens, probably during shutdown, with a callback to let them free their own handle. +extern void SDL_RemoveAllPenDevices(void (*callback)(SDL_PenID instance_id, void *handle, void *userdata), void *userdata); -/** - * (Only for backend driver) Detach pens that haven't been reported attached since the last call to SDL_PenGCMark(). - * - * Must not be called while the pen mutex is held (by SDL_PenModifyBegin() ). - * - * See SDL_PenGCMark() for details. - * - * \param context Extra parameter to pass through to "free_deviceinfo" - * \param free_deviceinfo Operation to call on any non-NULL "backend.deviceinfo". - * - * \sa SDL_PenGCMark() - */ -extern void SDL_PenGCSweep(void *context, void (*free_deviceinfo)(Uint32 instance_id, void *deviceinfo, void *context)); +// Backend calls this when a pen's button changes, to generate events and update state. +extern void SDL_SendPenTouch(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, bool eraser, bool down); -/** - * (Only for backend driver) Send a pen motion event. - * - * Suppresses pen motion events that do not change the current pen state. - * May also send a mouse motion event, if mouse emulation is enabled and the pen position has - * changed sufficiently for the motion to be visible to mouse event listeners. - * - * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . - * While 0 is safe to report, your backends may be able to report more precise - * timing information. - * Keep in mind that you should never report timestamps that are greater than - * SDL_GetTicksNS() . In particular, SDL_GetTicksNS() reports nanoseconds since the start - * of the SDL session, and your backend may use a different starting point as "timestamp zero". - * \param instance_id Pen - * \param window_relative Coordinates are already window-relative - * \param status Coordinates and axes (buttons are ignored) - * - * \returns SDL_TRUE if at least one event was sent - */ -extern int SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, SDL_bool window_relative, const SDL_PenStatusInfo *status); +// Backend calls this when a pen moves on the tablet, to generate events and update state. +extern void SDL_SendPenMotion(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, float x, float y); -/** - * (Only for backend driver) Send a pen button event - * - * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . - * See SDL_SendPenMotion() for a discussion about how to handle timestamps. - * \param instance_id Pen - * \param state SDL_PRESSED or SDL_RELEASED - * \param button Button number: 1 (first physical button) etc. - * - * \returns SDL_TRUE if at least one event was sent - */ -extern int SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, Uint8 state, Uint8 button); +// Backend calls this when a pen's axis changes, to generate events and update state. +extern void SDL_SendPenAxis(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, SDL_PenAxis axis, float value); -/** - * (Only for backend driver) Send a pen tip event (touching or no longer touching the surface) - * - * Note: the backend should perform hit testing on window decoration elements to allow the pen - * to e.g. resize/move the window, just as for mouse events, unless ::SDL_SendPenTipEvent is false. - * - * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . - * See SDL_SendPenMotion() for a discussion about how to handle timestamps. - * \param instance_id Pen - * \param state SDL_PRESSED (for PEN_DOWN) or SDL_RELEASED (for PEN_UP) - * - * \returns SDL_TRUE if at least one event was sent - */ -extern int SDL_SendPenTipEvent(Uint64 timestamp, SDL_PenID instance_id, Uint8 state); +// Backend calls this when a pen's button changes, to generate events and update state. +extern void SDL_SendPenButton(Uint64 timestamp, SDL_PenID instance_id, const SDL_Window *window, Uint8 button, bool down); -/** - * (Only for backend driver) Check if a PEN_DOWN event should perform hit box testing. - * - * \returns SDL_TRUE if and only if the backend should perform hit testing - */ -extern SDL_bool SDL_PenPerformHitTest(void); +// Backend can optionally use this to find the SDL_PenID for the `handle` that was passed to SDL_AddPenDevice. +extern SDL_PenID SDL_FindPenByHandle(void *handle); -/** - * (Only for backend driver) Send a pen window event. - * - * Tracks when a pen has entered/left a window. - * Don't call this when reporting new pens or removing known pens; those cases are handled automatically. - * - * \param timestamp Event timestamp in nanoseconds, or 0 to ask SDL to use SDL_GetTicksNS() . - * See SDL_SendPenMotion() for a discussion about how to handle timestamps. - * \param instance_id Pen - * \param window Window to enter, or NULL to exit - */ -extern int SDL_SendPenWindowEvent(Uint64 timestamp, SDL_PenID instance_id, SDL_Window *window); +// Backend can optionally use this to find a SDL_PenID, selected by a callback examining all devices. Zero if not found. +extern SDL_PenID SDL_FindPenByCallback(bool (*callback)(void *handle, void *userdata), void *userdata); -/** - * Initialises the pen subsystem. - */ -extern void SDL_PenInit(void); +// Backend can use this to map an axis to a capability bit. +SDL_PenCapabilityFlags SDL_GetPenCapabilityFromAxis(SDL_PenAxis axis); -/** - * De-initialises the pen subsystem. - */ -extern void SDL_PenQuit(void); +// Higher-level SDL video subsystem code calls this when starting up. Backends shouldn't. +extern bool SDL_InitPen(void); -#endif /* SDL_pen_c_h_ */ +// Higher-level SDL video subsystem code calls this when shutting down. Backends shouldn't. +extern void SDL_QuitPen(void); -/* vi: set ts=4 sw=4 expandtab: */ +#endif // SDL_pen_c_h_ diff --git a/libs/SDL3/src/events/SDL_quit.c b/libs/SDL3/src/events/SDL_quit.c index e4928d379..c408291eb 100644 --- a/libs/SDL3/src/events/SDL_quit.c +++ b/libs/SDL3/src/events/SDL_quit.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* General quit handling code for SDL */ +// General quit handling code for SDL #ifdef HAVE_SIGNAL_H #include @@ -33,37 +33,37 @@ #endif #ifdef HAVE_SIGNAL_SUPPORT -static SDL_bool disable_signals = SDL_FALSE; -static SDL_bool send_quit_pending = SDL_FALSE; +static bool disable_signals = false; +static bool send_quit_pending = false; #ifdef SDL_BACKGROUNDING_SIGNAL -static SDL_bool send_backgrounding_pending = SDL_FALSE; +static bool send_backgrounding_pending = false; #endif #ifdef SDL_FOREGROUNDING_SIGNAL -static SDL_bool send_foregrounding_pending = SDL_FALSE; +static bool send_foregrounding_pending = false; #endif static void SDL_HandleSIG(int sig) { - /* Reset the signal handler */ + // Reset the signal handler (void)signal(sig, SDL_HandleSIG); - /* Send a quit event next time the event loop pumps. */ - /* We can't send it in signal handler; SDL_malloc() might be interrupted! */ + // Send a quit event next time the event loop pumps. + // We can't send it in signal handler; SDL_malloc() might be interrupted! if ((sig == SIGINT) || (sig == SIGTERM)) { - send_quit_pending = SDL_TRUE; + send_quit_pending = true; } #ifdef SDL_BACKGROUNDING_SIGNAL else if (sig == SDL_BACKGROUNDING_SIGNAL) { - send_backgrounding_pending = SDL_TRUE; + send_backgrounding_pending = true; } #endif #ifdef SDL_FOREGROUNDING_SIGNAL else if (sig == SDL_FOREGROUNDING_SIGNAL) { - send_foregrounding_pending = SDL_TRUE; + send_foregrounding_pending = true; } #endif } @@ -104,14 +104,14 @@ static void SDL_EventSignal_Quit(const int sig) if (ohandler != SDL_HandleSIG) { signal(sig, ohandler); } -#endif /* HAVE_SIGNAL_H */ +#endif // HAVE_SIGNAL_H } -/* Public functions */ -static int SDL_QuitInit_Internal(void) +// Public functions +static bool SDL_QuitInit_Internal(void) { - /* Both SIGINT and SIGTERM are translated into quit interrupts */ - /* and SDL can be built to simulate iOS/Android semantics with arbitrary signals. */ + // Both SIGINT and SIGTERM are translated into quit interrupts + // and SDL can be built to simulate iOS/Android semantics with arbitrary signals. SDL_EventSignal_Init(SIGINT); SDL_EventSignal_Init(SIGTERM); @@ -123,8 +123,8 @@ static int SDL_QuitInit_Internal(void) SDL_EventSignal_Init(SDL_FOREGROUNDING_SIGNAL); #endif - /* That's it! */ - return 0; + // That's it! + return true; } static void SDL_QuitQuit_Internal(void) @@ -142,14 +142,14 @@ static void SDL_QuitQuit_Internal(void) } #endif -int SDL_InitQuit(void) +bool SDL_InitQuit(void) { #ifdef HAVE_SIGNAL_SUPPORT - if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) { + if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { return SDL_QuitInit_Internal(); } #endif - return 0; + return true; } void SDL_QuitQuit(void) @@ -171,25 +171,24 @@ void SDL_SendPendingSignalEvents(void) #ifdef SDL_BACKGROUNDING_SIGNAL if (send_backgrounding_pending) { - send_backgrounding_pending = SDL_FALSE; - SDL_OnApplicationWillResignActive(); + send_backgrounding_pending = false; + SDL_OnApplicationWillEnterBackground(); } #endif #ifdef SDL_FOREGROUNDING_SIGNAL if (send_foregrounding_pending) { - send_foregrounding_pending = SDL_FALSE; - SDL_OnApplicationDidBecomeActive(); + send_foregrounding_pending = false; + SDL_OnApplicationDidEnterForeground(); } #endif #endif } -/* This function returns 1 if it's okay to close the application window */ -int SDL_SendQuit(void) +void SDL_SendQuit(void) { #ifdef HAVE_SIGNAL_SUPPORT - send_quit_pending = SDL_FALSE; + send_quit_pending = false; #endif - return SDL_SendAppEvent(SDL_EVENT_QUIT); + SDL_SendAppEvent(SDL_EVENT_QUIT); } diff --git a/libs/SDL3/src/events/SDL_scancode_tables.c b/libs/SDL3/src/events/SDL_scancode_tables.c index c09d9797e..03c536886 100644 --- a/libs/SDL3/src/events/SDL_scancode_tables.c +++ b/libs/SDL3/src/events/SDL_scancode_tables.c @@ -68,4 +68,4 @@ SDL_Scancode SDL_GetScancodeFromTable(SDL_ScancodeTable table, int keycode) return scancode; } -#endif /* SDL_INPUT_LINUXEV || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11 */ +#endif // SDL_INPUT_LINUXEV || SDL_VIDEO_DRIVER_WAYLAND || SDL_VIDEO_DRIVER_X11 diff --git a/libs/SDL3/src/events/SDL_touch.c b/libs/SDL3/src/events/SDL_touch.c index 98975e9ca..3ad041d81 100644 --- a/libs/SDL3/src/events/SDL_touch.c +++ b/libs/SDL3/src/events/SDL_touch.c @@ -20,7 +20,7 @@ */ #include "SDL_internal.h" -/* General touch handling code for SDL */ +// General touch handling code for SDL #include "SDL_events_c.h" #include "../video/SDL_sysvideo.h" @@ -28,23 +28,23 @@ static int SDL_num_touch = 0; static SDL_Touch **SDL_touchDevices = NULL; -/* for mapping touch events to mice */ +// for mapping touch events to mice #define SYNTHESIZE_TOUCH_TO_MOUSE 1 #if SYNTHESIZE_TOUCH_TO_MOUSE -static SDL_bool finger_touching = SDL_FALSE; +static bool finger_touching = false; static SDL_FingerID track_fingerid; static SDL_TouchID track_touchid; #endif -/* Public functions */ -int SDL_InitTouch(void) +// Public functions +bool SDL_InitTouch(void) { - return 0; + return true; } -SDL_bool SDL_TouchDevicesAvailable(void) +bool SDL_TouchDevicesAvailable(void) { return SDL_num_touch > 0; } @@ -56,18 +56,18 @@ SDL_TouchID *SDL_GetTouchDevices(int *count) } const int total = SDL_num_touch; - SDL_TouchID *retval = (SDL_TouchID *) SDL_malloc(sizeof (SDL_TouchID) * (total + 1)); - if (retval) { + SDL_TouchID *result = (SDL_TouchID *) SDL_malloc(sizeof (SDL_TouchID) * (total + 1)); + if (result) { for (int i = 0; i < total; i++) { - retval[i] = SDL_touchDevices[i]->id; + result[i] = SDL_touchDevices[i]->id; } - retval[total] = 0; + result[total] = 0; if (count) { *count = SDL_num_touch; } } - return retval; + return result; } static int SDL_GetTouchIndex(SDL_TouchID id) @@ -102,7 +102,10 @@ SDL_Touch *SDL_GetTouch(SDL_TouchID id) const char *SDL_GetTouchDeviceName(SDL_TouchID id) { SDL_Touch *touch = SDL_GetTouch(id); - return touch ? touch->name : NULL; + if (!touch) { + return NULL; + } + return SDL_GetPersistentString(touch->name); } SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id) @@ -131,26 +134,37 @@ static SDL_Finger *SDL_GetFinger(const SDL_Touch *touch, SDL_FingerID id) return touch->fingers[index]; } -int SDL_GetNumTouchFingers(SDL_TouchID touchID) +SDL_Finger **SDL_GetTouchFingers(SDL_TouchID touchID, int *count) { - SDL_Touch *touch = SDL_GetTouch(touchID); - if (touch) { - return touch->num_fingers; + SDL_Finger **fingers; + SDL_Finger *finger_data; + + if (count) { + *count = 0; } - return 0; -} -SDL_Finger *SDL_GetTouchFinger(SDL_TouchID touchID, int index) -{ SDL_Touch *touch = SDL_GetTouch(touchID); if (!touch) { return NULL; } - if (index < 0 || index >= touch->num_fingers) { - SDL_SetError("Unknown touch finger"); + + // Create a snapshot of the current finger state + fingers = (SDL_Finger **)SDL_malloc((touch->num_fingers + 1) * sizeof(*fingers) + touch->num_fingers * sizeof(**fingers)); + if (!fingers) { return NULL; } - return touch->fingers[index]; + finger_data = (SDL_Finger *)(fingers + (touch->num_fingers + 1)); + + for (int i = 0; i < touch->num_fingers; ++i) { + fingers[i] = &finger_data[i]; + SDL_copyp(fingers[i], touch->fingers[i]); + } + fingers[touch->num_fingers] = NULL; + + if (count) { + *count = touch->num_fingers; + } + return fingers; } int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name) @@ -165,7 +179,7 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name return index; } - /* Add the touch to the list of touch */ + // Add the touch to the list of touch touchDevices = (SDL_Touch **)SDL_realloc(SDL_touchDevices, (SDL_num_touch + 1) * sizeof(*touchDevices)); if (!touchDevices) { @@ -180,10 +194,10 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name return -1; } - /* Added touch to list */ + // Added touch to list ++SDL_num_touch; - /* we're setting the touch properties */ + // we're setting the touch properties SDL_touchDevices[index]->id = touchID; SDL_touchDevices[index]->type = type; SDL_touchDevices[index]->num_fingers = 0; @@ -194,7 +208,7 @@ int SDL_AddTouch(SDL_TouchID touchID, SDL_TouchDeviceType type, const char *name return index; } -static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure) +static bool SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float y, float pressure) { SDL_Finger *finger; @@ -204,12 +218,12 @@ static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float SDL_Finger **new_fingers; new_fingers = (SDL_Finger **)SDL_realloc(touch->fingers, (touch->max_fingers + 1) * sizeof(*touch->fingers)); if (!new_fingers) { - return -1; + return false; } touch->fingers = new_fingers; touch->fingers[touch->max_fingers] = (SDL_Finger *)SDL_malloc(sizeof(*finger)); if (!touch->fingers[touch->max_fingers]) { - return -1; + return false; } touch->max_fingers++; } @@ -219,52 +233,53 @@ static int SDL_AddFinger(SDL_Touch *touch, SDL_FingerID fingerid, float x, float finger->x = x; finger->y = y; finger->pressure = pressure; - return 0; + return true; } -static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid) +static void SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid) { - SDL_Finger *temp; - int index = SDL_GetFingerIndex(touch, fingerid); if (index < 0) { - return -1; + return; } - touch->num_fingers--; - temp = touch->fingers[index]; - touch->fingers[index] = touch->fingers[touch->num_fingers]; - touch->fingers[touch->num_fingers] = temp; - return 0; + --touch->num_fingers; + if (index < (touch->num_fingers)) { + // Move the deleted finger to just past the end of the active fingers array and shift the active fingers by one. + // This ensures that the descriptor for the now-deleted finger is located at `touch->fingers[touch->num_fingers]` + // and is ready for use in SDL_AddFinger. + SDL_Finger *deleted_finger = touch->fingers[index]; + SDL_memmove(&touch->fingers[index], &touch->fingers[index + 1], (touch->num_fingers - index) * sizeof(touch->fingers[index])); + touch->fingers[touch->num_fingers] = deleted_finger; + } } -int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_bool down, float x, float y, float pressure) +void SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, bool down, float x, float y, float pressure) { - int posted; SDL_Finger *finger; SDL_Mouse *mouse; SDL_Touch *touch = SDL_GetTouch(id); if (!touch) { - return -1; + return; } mouse = SDL_GetMouse(); #if SYNTHESIZE_TOUCH_TO_MOUSE - /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */ - /* SDL_HINT_VITA_TOUCH_MOUSE_DEVICE: controlling which touchpad should generate synthetic mouse events, PSVita-only */ + // SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events + // SDL_HINT_VITA_TOUCH_MOUSE_DEVICE: controlling which touchpad should generate synthetic mouse events, PSVita-only { #ifdef SDL_PLATFORM_VITA if (mouse->touch_mouse_events && ((mouse->vita_touch_mouse_device == id) || (mouse->vita_touch_mouse_device == 2))) { #else if (mouse->touch_mouse_events) { #endif - /* FIXME: maybe we should only restrict to a few SDL_TouchDeviceType */ + // FIXME: maybe we should only restrict to a few SDL_TouchDeviceType if (id != SDL_MOUSE_TOUCHID) { if (window) { if (down) { - if (finger_touching == SDL_FALSE) { + if (finger_touching == false) { float pos_x = (x * (float)window->w); float pos_y = (y * (float)window->h); if (pos_x < 0) { @@ -279,24 +294,24 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W if (pos_y > (float)(window->h - 1)) { pos_y = (float)(window->h - 1); } - SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, SDL_FALSE, pos_x, pos_y); - SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT); + SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, false, pos_x, pos_y); + SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_BUTTON_LEFT, true); } } else { - if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { - SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT); + if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) { + SDL_SendMouseButton(timestamp, window, SDL_TOUCH_MOUSEID, SDL_BUTTON_LEFT, false); } } } if (down) { - if (finger_touching == SDL_FALSE) { - finger_touching = SDL_TRUE; + if (finger_touching == false) { + finger_touching = true; track_touchid = id; track_fingerid = fingerid; } } else { - if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { - finger_touching = SDL_FALSE; + if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) { + finger_touching = false; } } } @@ -304,10 +319,10 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W } #endif - /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */ + // SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer if (mouse->mouse_touch_events == 0) { if (id == SDL_MOUSE_TOUCHID) { - return 0; + return; } } @@ -316,14 +331,13 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W if (finger) { /* This finger is already down. Assume the finger-up for the previous touch was lost, and send it. */ - SDL_SendTouch(timestamp, id, fingerid, window, SDL_FALSE, x, y, pressure); + SDL_SendTouch(timestamp, id, fingerid, window, false, x, y, pressure); } - if (SDL_AddFinger(touch, fingerid, x, y, pressure) < 0) { - return 0; + if (!SDL_AddFinger(touch, fingerid, x, y, pressure)) { + return; } - posted = 0; if (SDL_EventEnabled(SDL_EVENT_FINGER_DOWN)) { SDL_Event event; event.type = SDL_EVENT_FINGER_DOWN; @@ -336,59 +350,56 @@ int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_W event.tfinger.dy = 0; event.tfinger.pressure = pressure; event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } } else { if (!finger) { - /* This finger is already up */ - return 0; + // This finger is already up + return; } - posted = 0; if (SDL_EventEnabled(SDL_EVENT_FINGER_UP)) { SDL_Event event; event.type = SDL_EVENT_FINGER_UP; event.common.timestamp = timestamp; event.tfinger.touchID = id; event.tfinger.fingerID = fingerid; - /* I don't trust the coordinates passed on fingerUp */ + // I don't trust the coordinates passed on fingerUp event.tfinger.x = finger->x; event.tfinger.y = finger->y; event.tfinger.dx = 0; event.tfinger.dy = 0; event.tfinger.pressure = pressure; event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } SDL_DelFinger(touch, fingerid); } - return posted; } -int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, +void SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure) { SDL_Touch *touch; SDL_Finger *finger; SDL_Mouse *mouse; - int posted; float xrel, yrel, prel; touch = SDL_GetTouch(id); if (!touch) { - return -1; + return; } mouse = SDL_GetMouse(); #if SYNTHESIZE_TOUCH_TO_MOUSE - /* SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events */ + // SDL_HINT_TOUCH_MOUSE_EVENTS: controlling whether touch events should generate synthetic mouse events { if (mouse->touch_mouse_events) { if (id != SDL_MOUSE_TOUCHID) { if (window) { - if (finger_touching == SDL_TRUE && track_touchid == id && track_fingerid == fingerid) { + if (finger_touching == true && track_touchid == id && track_fingerid == fingerid) { float pos_x = (x * (float)window->w); float pos_y = (y * (float)window->h); if (pos_x < 0.0f) { @@ -403,7 +414,7 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, if (pos_y > (float)(window->h - 1)) { pos_y = (float)(window->h - 1); } - SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, SDL_FALSE, pos_x, pos_y); + SDL_SendMouseMotion(timestamp, window, SDL_TOUCH_MOUSEID, false, pos_x, pos_y); } } } @@ -411,37 +422,37 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, } #endif - /* SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer */ + // SDL_HINT_MOUSE_TOUCH_EVENTS: if not set, discard synthetic touch events coming from platform layer if (mouse->mouse_touch_events == 0) { if (id == SDL_MOUSE_TOUCHID) { - return 0; + return; } } finger = SDL_GetFinger(touch, fingerid); if (!finger) { - return SDL_SendTouch(timestamp, id, fingerid, window, SDL_TRUE, x, y, pressure); + SDL_SendTouch(timestamp, id, fingerid, window, true, x, y, pressure); + return; } xrel = x - finger->x; yrel = y - finger->y; prel = pressure - finger->pressure; - /* Drop events that don't change state */ + // Drop events that don't change state if (xrel == 0.0f && yrel == 0.0f && prel == 0.0f) { #if 0 printf("Touch event didn't change state - dropped!\n"); #endif - return 0; + return; } - /* Update internal touch coordinates */ + // Update internal touch coordinates finger->x = x; finger->y = y; finger->pressure = pressure; - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_FINGER_MOTION)) { SDL_Event event; event.type = SDL_EVENT_FINGER_MOTION; @@ -454,9 +465,8 @@ int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, event.tfinger.dy = yrel; event.tfinger.pressure = pressure; event.tfinger.windowID = window ? SDL_GetWindowID(window) : 0; - posted = (SDL_PushEvent(&event) > 0); + SDL_PushEvent(&event); } - return posted; } void SDL_DelTouch(SDL_TouchID id) @@ -465,7 +475,7 @@ void SDL_DelTouch(SDL_TouchID id) SDL_Touch *touch; if (SDL_num_touch == 0) { - /* We've already cleaned up, we won't find this device */ + // We've already cleaned up, we won't find this device return; } diff --git a/libs/SDL3/src/events/SDL_touch_c.h b/libs/SDL3/src/events/SDL_touch_c.h index dda6adc14..43e4fd172 100644 --- a/libs/SDL3/src/events/SDL_touch_c.h +++ b/libs/SDL3/src/events/SDL_touch_c.h @@ -33,28 +33,28 @@ typedef struct SDL_Touch char *name; } SDL_Touch; -/* Initialize the touch subsystem */ -extern int SDL_InitTouch(void); +// Initialize the touch subsystem +extern bool SDL_InitTouch(void); -/* Returns SDL_TRUE if _any_ connected touch devices are known to SDL */ -extern SDL_bool SDL_TouchDevicesAvailable(void); +// Returns true if _any_ connected touch devices are known to SDL +extern bool SDL_TouchDevicesAvailable(void); -/* Add a touch, returning the index of the touch, or -1 if there was an error. */ +// Add a touch, returning the index of the touch, or -1 if there was an error. extern int SDL_AddTouch(SDL_TouchID id, SDL_TouchDeviceType type, const char *name); -/* Get the touch with a given id */ +// Get the touch with a given id extern SDL_Touch *SDL_GetTouch(SDL_TouchID id); -/* Send a touch down/up event for a touch */ -extern int SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, SDL_bool down, float x, float y, float pressure); +// Send a touch down/up event for a touch +extern void SDL_SendTouch(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, bool down, float x, float y, float pressure); -/* Send a touch motion event for a touch */ -extern int SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure); +// Send a touch motion event for a touch +extern void SDL_SendTouchMotion(Uint64 timestamp, SDL_TouchID id, SDL_FingerID fingerid, SDL_Window *window, float x, float y, float pressure); -/* Remove a touch */ +// Remove a touch extern void SDL_DelTouch(SDL_TouchID id); -/* Shutdown the touch subsystem */ +// Shutdown the touch subsystem extern void SDL_QuitTouch(void); -#endif /* SDL_touch_c_h_ */ +#endif // SDL_touch_c_h_ diff --git a/libs/SDL3/src/events/SDL_windowevents.c b/libs/SDL3/src/events/SDL_windowevents.c index 9a184bc85..01a09ab7e 100644 --- a/libs/SDL3/src/events/SDL_windowevents.c +++ b/libs/SDL3/src/events/SDL_windowevents.c @@ -20,45 +20,46 @@ */ #include "SDL_internal.h" -/* Window event handling code for SDL */ +// Window event handling code for SDL #include "SDL_events_c.h" #include "SDL_mouse_c.h" -static int SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event) +static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event) { SDL_Event *new_event = (SDL_Event *)userdata; if (event->type == new_event->type && event->window.windowID == new_event->window.windowID) { - /* We're about to post a new move event, drop the old one */ - return 0; + // We're about to post a new move event, drop the old one + return false; } - return 1; + return true; } -int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, - int data1, int data2) +bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2) { - int posted; + bool posted = false; if (!window) { - return 0; + return false; } + SDL_assert(SDL_ObjectValid(window, SDL_OBJECT_TYPE_WINDOW)); + if (window->is_destroying && windowevent != SDL_EVENT_WINDOW_DESTROYED) { - return 0; + return false; } switch (windowevent) { case SDL_EVENT_WINDOW_SHOWN: if (!(window->flags & SDL_WINDOW_HIDDEN)) { - return 0; + return false; } window->flags &= ~(SDL_WINDOW_HIDDEN | SDL_WINDOW_MINIMIZED); break; case SDL_EVENT_WINDOW_HIDDEN: if (window->flags & SDL_WINDOW_HIDDEN) { - return 0; + return false; } window->flags |= SDL_WINDOW_HIDDEN; break; @@ -66,19 +67,19 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, window->flags &= ~SDL_WINDOW_OCCLUDED; break; case SDL_EVENT_WINDOW_MOVED: - window->undefined_x = SDL_FALSE; - window->undefined_y = SDL_FALSE; + window->undefined_x = false; + window->undefined_y = false; if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { window->windowed.x = data1; window->windowed.y = data2; - if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->state_not_floating) { + if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) { window->floating.x = data1; window->floating.y = data2; } } if (data1 == window->x && data2 == window->y) { - return 0; + return false; } window->x = data1; window->y = data2; @@ -88,90 +89,90 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, window->windowed.w = data1; window->windowed.h = data2; - if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->state_not_floating) { + if (!(window->flags & SDL_WINDOW_MAXIMIZED) && !window->tiled) { window->floating.w = data1; window->floating.h = data2; } } if (data1 == window->w && data2 == window->h) { SDL_CheckWindowPixelSizeChanged(window); - return 0; + return false; } window->w = data1; window->h = data2; break; case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: if (data1 == window->last_pixel_w && data2 == window->last_pixel_h) { - return 0; + return false; } window->last_pixel_w = data1; window->last_pixel_h = data2; break; case SDL_EVENT_WINDOW_MINIMIZED: if (window->flags & SDL_WINDOW_MINIMIZED) { - return 0; + return false; } window->flags &= ~SDL_WINDOW_MAXIMIZED; window->flags |= SDL_WINDOW_MINIMIZED; break; case SDL_EVENT_WINDOW_MAXIMIZED: if (window->flags & SDL_WINDOW_MAXIMIZED) { - return 0; + return false; } window->flags &= ~SDL_WINDOW_MINIMIZED; window->flags |= SDL_WINDOW_MAXIMIZED; break; case SDL_EVENT_WINDOW_RESTORED: if (!(window->flags & (SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED))) { - return 0; + return false; } window->flags &= ~(SDL_WINDOW_MINIMIZED | SDL_WINDOW_MAXIMIZED); break; case SDL_EVENT_WINDOW_MOUSE_ENTER: if (window->flags & SDL_WINDOW_MOUSE_FOCUS) { - return 0; + return false; } window->flags |= SDL_WINDOW_MOUSE_FOCUS; break; case SDL_EVENT_WINDOW_MOUSE_LEAVE: if (!(window->flags & SDL_WINDOW_MOUSE_FOCUS)) { - return 0; + return false; } window->flags &= ~SDL_WINDOW_MOUSE_FOCUS; break; case SDL_EVENT_WINDOW_FOCUS_GAINED: if (window->flags & SDL_WINDOW_INPUT_FOCUS) { - return 0; + return false; } window->flags |= SDL_WINDOW_INPUT_FOCUS; break; case SDL_EVENT_WINDOW_FOCUS_LOST: if (!(window->flags & SDL_WINDOW_INPUT_FOCUS)) { - return 0; + return false; } window->flags &= ~SDL_WINDOW_INPUT_FOCUS; break; case SDL_EVENT_WINDOW_DISPLAY_CHANGED: if (data1 == 0 || (SDL_DisplayID)data1 == window->last_displayID) { - return 0; + return false; } window->last_displayID = (SDL_DisplayID)data1; break; case SDL_EVENT_WINDOW_OCCLUDED: if (window->flags & SDL_WINDOW_OCCLUDED) { - return 0; + return false; } window->flags |= SDL_WINDOW_OCCLUDED; break; case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: if (window->flags & SDL_WINDOW_FULLSCREEN) { - return 0; + return false; } window->flags |= SDL_WINDOW_FULLSCREEN; break; case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: if (!(window->flags & SDL_WINDOW_FULLSCREEN)) { - return 0; + return false; } window->flags &= ~SDL_WINDOW_FULLSCREEN; break; @@ -179,8 +180,7 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, break; } - /* Post the event, if desired */ - posted = 0; + // Post the event, if desired if (SDL_EventEnabled(windowevent)) { SDL_Event event; event.type = windowevent; @@ -189,15 +189,16 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, event.window.data2 = data2; event.window.windowID = window->id; - /* Fixes queue overflow with move/resize events that aren't processed */ + // Fixes queue overflow with move/resize events that aren't processed if (windowevent == SDL_EVENT_WINDOW_MOVED || windowevent == SDL_EVENT_WINDOW_RESIZED || windowevent == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED || + windowevent == SDL_EVENT_WINDOW_SAFE_AREA_CHANGED || windowevent == SDL_EVENT_WINDOW_EXPOSED || windowevent == SDL_EVENT_WINDOW_OCCLUDED) { SDL_FilterEvents(RemoveSupercededWindowEvents, &event); } - posted = (SDL_PushEvent(&event) > 0); + posted = SDL_PushEvent(&event); } switch (windowevent) { @@ -248,14 +249,14 @@ int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int toplevel_count = 0; SDL_Window *n; for (n = SDL_GetVideoDevice()->windows; n; n = n->next) { - if (!n->parent) { + if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) { ++toplevel_count; } } - if (toplevel_count == 1) { - if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, SDL_TRUE)) { - SDL_SendQuit(); /* This is the last toplevel window in the list so send the SDL_EVENT_QUIT event */ + if (toplevel_count <= 1) { + if (SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) { + SDL_SendQuit(); // This is the last toplevel window in the list so send the SDL_EVENT_QUIT event } } } diff --git a/libs/SDL3/src/events/SDL_windowevents_c.h b/libs/SDL3/src/events/SDL_windowevents_c.h index 93e950934..addab6efe 100644 --- a/libs/SDL3/src/events/SDL_windowevents_c.h +++ b/libs/SDL3/src/events/SDL_windowevents_c.h @@ -23,7 +23,6 @@ #ifndef SDL_windowevents_c_h_ #define SDL_windowevents_c_h_ -extern int SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, - int data1, int data2); +extern bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data1, int data2); -#endif /* SDL_windowevents_c_h_ */ +#endif // SDL_windowevents_c_h_ diff --git a/libs/SDL3/src/events/default_cursor.h b/libs/SDL3/src/events/default_cursor.h index 4e30aff2a..5068f0692 100644 --- a/libs/SDL3/src/events/default_cursor.h +++ b/libs/SDL3/src/events/default_cursor.h @@ -27,7 +27,7 @@ #define DEFAULT_CHOTX 0 #define DEFAULT_CHOTY 0 -/* Added a real MacOS cursor, at the request of Luc-Olivier de Charrière */ +// Added a real MacOS cursor, at the request of Luc-Olivier de Charrière #define USE_MACOS_CURSOR #ifdef USE_MACOS_CURSOR @@ -110,4 +110,4 @@ static const unsigned char default_cmask[] = { 0x03, 0x00 }; -#endif /* USE_MACOS_CURSOR */ +#endif // USE_MACOS_CURSOR diff --git a/libs/SDL3/src/events/scancodes_ascii.h b/libs/SDL3/src/events/scancodes_ascii.h deleted file mode 100644 index ee49ab881..000000000 --- a/libs/SDL3/src/events/scancodes_ascii.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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. -*/ - -/* - This file is used to convert between characters passed in from an ASCII - virtual keyboard in US layout and tuples of SDL_Scancode and SDL_keymods. - - For example ASCIIKeyInfoTable['a'] would give you the scan code and keymod - for lower case a. -*/ - -typedef struct -{ - SDL_Scancode code; - uint16_t mod; -} ASCIIKeyInfo; - -static ASCIIKeyInfo SDL_ASCIIKeyInfoTable[] = { - /* 0 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 1 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 2 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 3 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 4 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 5 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 6 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 7 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 8 */ { SDL_SCANCODE_BACKSPACE, 0 }, - /* 9 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 10 */ { SDL_SCANCODE_RETURN, 0 }, - /* 11 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 12 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 13 */ { SDL_SCANCODE_RETURN, 0 }, - /* 14 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 15 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 16 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 17 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 18 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 19 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 20 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 21 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 22 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 23 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 24 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 25 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 26 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 27 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 28 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 29 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 30 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 31 */ { SDL_SCANCODE_UNKNOWN, 0 }, - /* 32 */ { SDL_SCANCODE_SPACE, 0 }, - /* 33 */ { SDL_SCANCODE_1, SDL_KMOD_SHIFT }, /* plus shift modifier '!' */ - /* 34 */ { SDL_SCANCODE_APOSTROPHE, SDL_KMOD_SHIFT }, /* plus shift modifier '"' */ - /* 35 */ { SDL_SCANCODE_3, SDL_KMOD_SHIFT }, /* plus shift modifier '#' */ - /* 36 */ { SDL_SCANCODE_4, SDL_KMOD_SHIFT }, /* plus shift modifier '$' */ - /* 37 */ { SDL_SCANCODE_5, SDL_KMOD_SHIFT }, /* plus shift modifier '%' */ - /* 38 */ { SDL_SCANCODE_7, SDL_KMOD_SHIFT }, /* plus shift modifier '&' */ - /* 39 */ { SDL_SCANCODE_APOSTROPHE, 0 }, /* ''' */ - /* 40 */ { SDL_SCANCODE_9, SDL_KMOD_SHIFT }, /* plus shift modifier '(' */ - /* 41 */ { SDL_SCANCODE_0, SDL_KMOD_SHIFT }, /* plus shift modifier ')' */ - /* 42 */ { SDL_SCANCODE_8, SDL_KMOD_SHIFT }, /* '*' */ - /* 43 */ { SDL_SCANCODE_EQUALS, SDL_KMOD_SHIFT }, /* plus shift modifier '+' */ - /* 44 */ { SDL_SCANCODE_COMMA, 0 }, /* ',' */ - /* 45 */ { SDL_SCANCODE_MINUS, 0 }, /* '-' */ - /* 46 */ { SDL_SCANCODE_PERIOD, 0 }, /* '.' */ - /* 47 */ { SDL_SCANCODE_SLASH, 0 }, /* '/' */ - /* 48 */ { SDL_SCANCODE_0, 0 }, - /* 49 */ { SDL_SCANCODE_1, 0 }, - /* 50 */ { SDL_SCANCODE_2, 0 }, - /* 51 */ { SDL_SCANCODE_3, 0 }, - /* 52 */ { SDL_SCANCODE_4, 0 }, - /* 53 */ { SDL_SCANCODE_5, 0 }, - /* 54 */ { SDL_SCANCODE_6, 0 }, - /* 55 */ { SDL_SCANCODE_7, 0 }, - /* 56 */ { SDL_SCANCODE_8, 0 }, - /* 57 */ { SDL_SCANCODE_9, 0 }, - /* 58 */ { SDL_SCANCODE_SEMICOLON, SDL_KMOD_SHIFT }, /* plus shift modifier ';' */ - /* 59 */ { SDL_SCANCODE_SEMICOLON, 0 }, - /* 60 */ { SDL_SCANCODE_COMMA, SDL_KMOD_SHIFT }, /* plus shift modifier '<' */ - /* 61 */ { SDL_SCANCODE_EQUALS, 0 }, - /* 62 */ { SDL_SCANCODE_PERIOD, SDL_KMOD_SHIFT }, /* plus shift modifier '>' */ - /* 63 */ { SDL_SCANCODE_SLASH, SDL_KMOD_SHIFT }, /* plus shift modifier '?' */ - /* 64 */ { SDL_SCANCODE_2, SDL_KMOD_SHIFT }, /* plus shift modifier '@' */ - /* 65 */ { SDL_SCANCODE_A, SDL_KMOD_SHIFT }, /* all the following need shift modifiers */ - /* 66 */ { SDL_SCANCODE_B, SDL_KMOD_SHIFT }, - /* 67 */ { SDL_SCANCODE_C, SDL_KMOD_SHIFT }, - /* 68 */ { SDL_SCANCODE_D, SDL_KMOD_SHIFT }, - /* 69 */ { SDL_SCANCODE_E, SDL_KMOD_SHIFT }, - /* 70 */ { SDL_SCANCODE_F, SDL_KMOD_SHIFT }, - /* 71 */ { SDL_SCANCODE_G, SDL_KMOD_SHIFT }, - /* 72 */ { SDL_SCANCODE_H, SDL_KMOD_SHIFT }, - /* 73 */ { SDL_SCANCODE_I, SDL_KMOD_SHIFT }, - /* 74 */ { SDL_SCANCODE_J, SDL_KMOD_SHIFT }, - /* 75 */ { SDL_SCANCODE_K, SDL_KMOD_SHIFT }, - /* 76 */ { SDL_SCANCODE_L, SDL_KMOD_SHIFT }, - /* 77 */ { SDL_SCANCODE_M, SDL_KMOD_SHIFT }, - /* 78 */ { SDL_SCANCODE_N, SDL_KMOD_SHIFT }, - /* 79 */ { SDL_SCANCODE_O, SDL_KMOD_SHIFT }, - /* 80 */ { SDL_SCANCODE_P, SDL_KMOD_SHIFT }, - /* 81 */ { SDL_SCANCODE_Q, SDL_KMOD_SHIFT }, - /* 82 */ { SDL_SCANCODE_R, SDL_KMOD_SHIFT }, - /* 83 */ { SDL_SCANCODE_S, SDL_KMOD_SHIFT }, - /* 84 */ { SDL_SCANCODE_T, SDL_KMOD_SHIFT }, - /* 85 */ { SDL_SCANCODE_U, SDL_KMOD_SHIFT }, - /* 86 */ { SDL_SCANCODE_V, SDL_KMOD_SHIFT }, - /* 87 */ { SDL_SCANCODE_W, SDL_KMOD_SHIFT }, - /* 88 */ { SDL_SCANCODE_X, SDL_KMOD_SHIFT }, - /* 89 */ { SDL_SCANCODE_Y, SDL_KMOD_SHIFT }, - /* 90 */ { SDL_SCANCODE_Z, SDL_KMOD_SHIFT }, - /* 91 */ { SDL_SCANCODE_LEFTBRACKET, 0 }, - /* 92 */ { SDL_SCANCODE_BACKSLASH, 0 }, - /* 93 */ { SDL_SCANCODE_RIGHTBRACKET, 0 }, - /* 94 */ { SDL_SCANCODE_6, SDL_KMOD_SHIFT }, /* plus shift modifier '^' */ - /* 95 */ { SDL_SCANCODE_MINUS, SDL_KMOD_SHIFT }, /* plus shift modifier '_' */ - /* 96 */ { SDL_SCANCODE_GRAVE, SDL_KMOD_SHIFT }, /* '`' */ - /* 97 */ { SDL_SCANCODE_A, 0 }, - /* 98 */ { SDL_SCANCODE_B, 0 }, - /* 99 */ { SDL_SCANCODE_C, 0 }, - /* 100 */ { SDL_SCANCODE_D, 0 }, - /* 101 */ { SDL_SCANCODE_E, 0 }, - /* 102 */ { SDL_SCANCODE_F, 0 }, - /* 103 */ { SDL_SCANCODE_G, 0 }, - /* 104 */ { SDL_SCANCODE_H, 0 }, - /* 105 */ { SDL_SCANCODE_I, 0 }, - /* 106 */ { SDL_SCANCODE_J, 0 }, - /* 107 */ { SDL_SCANCODE_K, 0 }, - /* 108 */ { SDL_SCANCODE_L, 0 }, - /* 109 */ { SDL_SCANCODE_M, 0 }, - /* 110 */ { SDL_SCANCODE_N, 0 }, - /* 111 */ { SDL_SCANCODE_O, 0 }, - /* 112 */ { SDL_SCANCODE_P, 0 }, - /* 113 */ { SDL_SCANCODE_Q, 0 }, - /* 114 */ { SDL_SCANCODE_R, 0 }, - /* 115 */ { SDL_SCANCODE_S, 0 }, - /* 116 */ { SDL_SCANCODE_T, 0 }, - /* 117 */ { SDL_SCANCODE_U, 0 }, - /* 118 */ { SDL_SCANCODE_V, 0 }, - /* 119 */ { SDL_SCANCODE_W, 0 }, - /* 120 */ { SDL_SCANCODE_X, 0 }, - /* 121 */ { SDL_SCANCODE_Y, 0 }, - /* 122 */ { SDL_SCANCODE_Z, 0 }, - /* 123 */ { SDL_SCANCODE_LEFTBRACKET, SDL_KMOD_SHIFT }, /* plus shift modifier '{' */ - /* 124 */ { SDL_SCANCODE_BACKSLASH, SDL_KMOD_SHIFT }, /* plus shift modifier '|' */ - /* 125 */ { SDL_SCANCODE_RIGHTBRACKET, SDL_KMOD_SHIFT }, /* plus shift modifier '}' */ - /* 126 */ { SDL_SCANCODE_GRAVE, SDL_KMOD_SHIFT }, /* plus shift modifier '~' */ - /* 127 */ { SDL_SCANCODE_BACKSPACE, SDL_KMOD_SHIFT } -}; diff --git a/libs/SDL3/src/events/scancodes_darwin.h b/libs/SDL3/src/events/scancodes_darwin.h index c38ed60ef..0006070d2 100644 --- a/libs/SDL3/src/events/scancodes_darwin.h +++ b/libs/SDL3/src/events/scancodes_darwin.h @@ -25,7 +25,7 @@ - Apple USB keyboard driver source - experimentation on various ADB and USB ISO keyboards and one ADB ANSI keyboard */ -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static const SDL_Scancode darwin_scancode_table[] = { /* 0 */ SDL_SCANCODE_A, /* 1 */ SDL_SCANCODE_S, @@ -37,7 +37,7 @@ static const SDL_Scancode darwin_scancode_table[] = { /* 7 */ SDL_SCANCODE_X, /* 8 */ SDL_SCANCODE_C, /* 9 */ SDL_SCANCODE_V, - /* 10 */ SDL_SCANCODE_NONUSBACKSLASH, /* SDL_SCANCODE_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_SCANCODE_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard type when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.) */ + /* 10 */ SDL_SCANCODE_NONUSBACKSLASH, // SDL_SCANCODE_NONUSBACKSLASH on ANSI and JIS keyboards (if this key would exist there), SDL_SCANCODE_GRAVE on ISO. (The USB keyboard driver actually translates these usage codes to different virtual key codes depending on whether the keyboard is ISO/ANSI/JIS. That's why you have to help it identify the keyboard type when you plug in a PC USB keyboard. It's a historical thing - ADB keyboards are wired this way.) /* 11 */ SDL_SCANCODE_B, /* 12 */ SDL_SCANCODE_Q, /* 13 */ SDL_SCANCODE_W, @@ -77,9 +77,9 @@ static const SDL_Scancode darwin_scancode_table[] = { /* 47 */ SDL_SCANCODE_PERIOD, /* 48 */ SDL_SCANCODE_TAB, /* 49 */ SDL_SCANCODE_SPACE, - /* 50 */ SDL_SCANCODE_GRAVE, /* SDL_SCANCODE_GRAVE on ANSI and JIS keyboards, SDL_SCANCODE_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above) */ + /* 50 */ SDL_SCANCODE_GRAVE, // SDL_SCANCODE_GRAVE on ANSI and JIS keyboards, SDL_SCANCODE_NONUSBACKSLASH on ISO (see comment about virtual key code 10 above) /* 51 */ SDL_SCANCODE_BACKSPACE, - /* 52 */ SDL_SCANCODE_KP_ENTER, /* keyboard enter on portables */ + /* 52 */ SDL_SCANCODE_KP_ENTER, // keyboard enter on portables /* 53 */ SDL_SCANCODE_ESCAPE, /* 54 */ SDL_SCANCODE_RGUI, /* 55 */ SDL_SCANCODE_LGUI, @@ -90,21 +90,21 @@ static const SDL_Scancode darwin_scancode_table[] = { /* 60 */ SDL_SCANCODE_RSHIFT, /* 61 */ SDL_SCANCODE_RALT, /* 62 */ SDL_SCANCODE_RCTRL, - /* 63 */ SDL_SCANCODE_RGUI, /* fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R */ + /* 63 */ SDL_SCANCODE_RGUI, // fn on portables, acts as a hardware-level modifier already, so we don't generate events for it, also XK_Meta_R /* 64 */ SDL_SCANCODE_F17, /* 65 */ SDL_SCANCODE_KP_PERIOD, - /* 66 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 66 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 67 */ SDL_SCANCODE_KP_MULTIPLY, - /* 68 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 68 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 69 */ SDL_SCANCODE_KP_PLUS, - /* 70 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 70 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 71 */ SDL_SCANCODE_NUMLOCKCLEAR, /* 72 */ SDL_SCANCODE_VOLUMEUP, /* 73 */ SDL_SCANCODE_VOLUMEDOWN, /* 74 */ SDL_SCANCODE_MUTE, /* 75 */ SDL_SCANCODE_KP_DIVIDE, - /* 76 */ SDL_SCANCODE_KP_ENTER, /* keypad enter on external keyboards, fn-return on portables */ - /* 77 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 76 */ SDL_SCANCODE_KP_ENTER, // keypad enter on external keyboards, fn-return on portables + /* 77 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 78 */ SDL_SCANCODE_KP_MINUS, /* 79 */ SDL_SCANCODE_F18, /* 80 */ SDL_SCANCODE_F19, @@ -117,31 +117,31 @@ static const SDL_Scancode darwin_scancode_table[] = { /* 87 */ SDL_SCANCODE_KP_5, /* 88 */ SDL_SCANCODE_KP_6, /* 89 */ SDL_SCANCODE_KP_7, - /* 90 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 90 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 91 */ SDL_SCANCODE_KP_8, /* 92 */ SDL_SCANCODE_KP_9, - /* 93 */ SDL_SCANCODE_INTERNATIONAL3, /* Cosmo_USB2ADB.c says "Yen (JIS)" */ - /* 94 */ SDL_SCANCODE_INTERNATIONAL1, /* Cosmo_USB2ADB.c says "Ro (JIS)" */ - /* 95 */ SDL_SCANCODE_KP_COMMA, /* Cosmo_USB2ADB.c says ", JIS only" */ + /* 93 */ SDL_SCANCODE_INTERNATIONAL3, // Cosmo_USB2ADB.c says "Yen (JIS)" + /* 94 */ SDL_SCANCODE_INTERNATIONAL1, // Cosmo_USB2ADB.c says "Ro (JIS)" + /* 95 */ SDL_SCANCODE_KP_COMMA, // Cosmo_USB2ADB.c says ", JIS only" /* 96 */ SDL_SCANCODE_F5, /* 97 */ SDL_SCANCODE_F6, /* 98 */ SDL_SCANCODE_F7, /* 99 */ SDL_SCANCODE_F3, /* 100 */ SDL_SCANCODE_F8, /* 101 */ SDL_SCANCODE_F9, - /* 102 */ SDL_SCANCODE_LANG2, /* Cosmo_USB2ADB.c says "Eisu" */ + /* 102 */ SDL_SCANCODE_LANG2, // Cosmo_USB2ADB.c says "Eisu" /* 103 */ SDL_SCANCODE_F11, - /* 104 */ SDL_SCANCODE_LANG1, /* Cosmo_USB2ADB.c says "Kana" */ - /* 105 */ SDL_SCANCODE_PRINTSCREEN, /* On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_SCANCODE_F13). I decided to use SDL_SCANCODE_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key. */ + /* 104 */ SDL_SCANCODE_LANG1, // Cosmo_USB2ADB.c says "Kana" + /* 105 */ SDL_SCANCODE_PRINTSCREEN, // On ADB keyboards, this key is labeled "F13/print screen". Problem: USB has different usage codes for these two functions. On Apple USB keyboards, the key is labeled "F13" and sends the F13 usage code (SDL_SCANCODE_F13). I decided to use SDL_SCANCODE_PRINTSCREEN here nevertheless since SDL applications are more likely to assume the presence of a print screen key than an F13 key. /* 106 */ SDL_SCANCODE_F16, - /* 107 */ SDL_SCANCODE_SCROLLLOCK, /* F14/scroll lock, see comment about F13/print screen above */ - /* 108 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ + /* 107 */ SDL_SCANCODE_SCROLLLOCK, // F14/scroll lock, see comment about F13/print screen above + /* 108 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) /* 109 */ SDL_SCANCODE_F10, - /* 110 */ SDL_SCANCODE_APPLICATION, /* windows contextual menu key, fn-enter on portables */ + /* 110 */ SDL_SCANCODE_APPLICATION, // windows contextual menu key, fn-enter on portables /* 111 */ SDL_SCANCODE_F12, - /* 112 */ SDL_SCANCODE_UNKNOWN, /* unknown (unused?) */ - /* 113 */ SDL_SCANCODE_PAUSE, /* F15/pause, see comment about F13/print screen above */ - /* 114 */ SDL_SCANCODE_INSERT, /* the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards */ + /* 112 */ SDL_SCANCODE_UNKNOWN, // unknown (unused?) + /* 113 */ SDL_SCANCODE_PAUSE, // F15/pause, see comment about F13/print screen above + /* 114 */ SDL_SCANCODE_INSERT, // the key is actually labeled "help" on Apple keyboards, and works as such in Mac OS, but it sends the "insert" usage code even on Apple USB keyboards /* 115 */ SDL_SCANCODE_HOME, /* 116 */ SDL_SCANCODE_PAGEUP, /* 117 */ SDL_SCANCODE_DELETE, @@ -156,4 +156,4 @@ static const SDL_Scancode darwin_scancode_table[] = { /* 126 */ SDL_SCANCODE_UP, /* 127 */ SDL_SCANCODE_POWER }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on diff --git a/libs/SDL3/src/events/scancodes_linux.h b/libs/SDL3/src/events/scancodes_linux.h index a9869a8d0..e90bbf1cb 100644 --- a/libs/SDL3/src/events/scancodes_linux.h +++ b/libs/SDL3/src/events/scancodes_linux.h @@ -24,257 +24,257 @@ Sources: - Linux kernel source input.h */ -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static SDL_Scancode const linux_scancode_table[] = { - /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED */ - /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, /* KEY_ESC */ - /* 2, 0x002 */ SDL_SCANCODE_1, /* KEY_1 */ - /* 3, 0x003 */ SDL_SCANCODE_2, /* KEY_2 */ - /* 4, 0x004 */ SDL_SCANCODE_3, /* KEY_3 */ - /* 5, 0x005 */ SDL_SCANCODE_4, /* KEY_4 */ - /* 6, 0x006 */ SDL_SCANCODE_5, /* KEY_5 */ - /* 7, 0x007 */ SDL_SCANCODE_6, /* KEY_6 */ - /* 8, 0x008 */ SDL_SCANCODE_7, /* KEY_7 */ - /* 9, 0x009 */ SDL_SCANCODE_8, /* KEY_8 */ - /* 10, 0x00a */ SDL_SCANCODE_9, /* KEY_9 */ - /* 11, 0x00b */ SDL_SCANCODE_0, /* KEY_0 */ - /* 12, 0x00c */ SDL_SCANCODE_MINUS, /* KEY_MINUS */ - /* 13, 0x00d */ SDL_SCANCODE_EQUALS, /* KEY_EQUAL */ - /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE */ - /* 15, 0x00f */ SDL_SCANCODE_TAB, /* KEY_TAB */ - /* 16, 0x010 */ SDL_SCANCODE_Q, /* KEY_Q */ - /* 17, 0x011 */ SDL_SCANCODE_W, /* KEY_W */ - /* 18, 0x012 */ SDL_SCANCODE_E, /* KEY_E */ - /* 19, 0x013 */ SDL_SCANCODE_R, /* KEY_R */ - /* 20, 0x014 */ SDL_SCANCODE_T, /* KEY_T */ - /* 21, 0x015 */ SDL_SCANCODE_Y, /* KEY_Y */ - /* 22, 0x016 */ SDL_SCANCODE_U, /* KEY_U */ - /* 23, 0x017 */ SDL_SCANCODE_I, /* KEY_I */ - /* 24, 0x018 */ SDL_SCANCODE_O, /* KEY_O */ - /* 25, 0x019 */ SDL_SCANCODE_P, /* KEY_P */ - /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE */ - /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE */ - /* 28, 0x01c */ SDL_SCANCODE_RETURN, /* KEY_ENTER */ - /* 29, 0x01d */ SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL */ - /* 30, 0x01e */ SDL_SCANCODE_A, /* KEY_A */ - /* 31, 0x01f */ SDL_SCANCODE_S, /* KEY_S */ - /* 32, 0x020 */ SDL_SCANCODE_D, /* KEY_D */ - /* 33, 0x021 */ SDL_SCANCODE_F, /* KEY_F */ - /* 34, 0x022 */ SDL_SCANCODE_G, /* KEY_G */ - /* 35, 0x023 */ SDL_SCANCODE_H, /* KEY_H */ - /* 36, 0x024 */ SDL_SCANCODE_J, /* KEY_J */ - /* 37, 0x025 */ SDL_SCANCODE_K, /* KEY_K */ - /* 38, 0x026 */ SDL_SCANCODE_L, /* KEY_L */ - /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON */ - /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE */ - /* 41, 0x029 */ SDL_SCANCODE_GRAVE, /* KEY_GRAVE */ - /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT */ - /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH */ - /* 44, 0x02c */ SDL_SCANCODE_Z, /* KEY_Z */ - /* 45, 0x02d */ SDL_SCANCODE_X, /* KEY_X */ - /* 46, 0x02e */ SDL_SCANCODE_C, /* KEY_C */ - /* 47, 0x02f */ SDL_SCANCODE_V, /* KEY_V */ - /* 48, 0x030 */ SDL_SCANCODE_B, /* KEY_B */ - /* 49, 0x031 */ SDL_SCANCODE_N, /* KEY_N */ - /* 50, 0x032 */ SDL_SCANCODE_M, /* KEY_M */ - /* 51, 0x033 */ SDL_SCANCODE_COMMA, /* KEY_COMMA */ - /* 52, 0x034 */ SDL_SCANCODE_PERIOD, /* KEY_DOT */ - /* 53, 0x035 */ SDL_SCANCODE_SLASH, /* KEY_SLASH */ - /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT */ - /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK */ - /* 56, 0x038 */ SDL_SCANCODE_LALT, /* KEY_LEFTALT */ - /* 57, 0x039 */ SDL_SCANCODE_SPACE, /* KEY_SPACE */ - /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK */ - /* 59, 0x03b */ SDL_SCANCODE_F1, /* KEY_F1 */ - /* 60, 0x03c */ SDL_SCANCODE_F2, /* KEY_F2 */ - /* 61, 0x03d */ SDL_SCANCODE_F3, /* KEY_F3 */ - /* 62, 0x03e */ SDL_SCANCODE_F4, /* KEY_F4 */ - /* 63, 0x03f */ SDL_SCANCODE_F5, /* KEY_F5 */ - /* 64, 0x040 */ SDL_SCANCODE_F6, /* KEY_F6 */ - /* 65, 0x041 */ SDL_SCANCODE_F7, /* KEY_F7 */ - /* 66, 0x042 */ SDL_SCANCODE_F8, /* KEY_F8 */ - /* 67, 0x043 */ SDL_SCANCODE_F9, /* KEY_F9 */ - /* 68, 0x044 */ SDL_SCANCODE_F10, /* KEY_F10 */ - /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK */ - /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK */ - /* 71, 0x047 */ SDL_SCANCODE_KP_7, /* KEY_KP7 */ - /* 72, 0x048 */ SDL_SCANCODE_KP_8, /* KEY_KP8 */ - /* 73, 0x049 */ SDL_SCANCODE_KP_9, /* KEY_KP9 */ - /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS */ - /* 75, 0x04b */ SDL_SCANCODE_KP_4, /* KEY_KP4 */ - /* 76, 0x04c */ SDL_SCANCODE_KP_5, /* KEY_KP5 */ - /* 77, 0x04d */ SDL_SCANCODE_KP_6, /* KEY_KP6 */ - /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS */ - /* 79, 0x04f */ SDL_SCANCODE_KP_1, /* KEY_KP1 */ - /* 80, 0x050 */ SDL_SCANCODE_KP_2, /* KEY_KP2 */ - /* 81, 0x051 */ SDL_SCANCODE_KP_3, /* KEY_KP3 */ - /* 82, 0x052 */ SDL_SCANCODE_KP_0, /* KEY_KP0 */ - /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT */ + /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, // KEY_RESERVED + /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, // KEY_ESC + /* 2, 0x002 */ SDL_SCANCODE_1, // KEY_1 + /* 3, 0x003 */ SDL_SCANCODE_2, // KEY_2 + /* 4, 0x004 */ SDL_SCANCODE_3, // KEY_3 + /* 5, 0x005 */ SDL_SCANCODE_4, // KEY_4 + /* 6, 0x006 */ SDL_SCANCODE_5, // KEY_5 + /* 7, 0x007 */ SDL_SCANCODE_6, // KEY_6 + /* 8, 0x008 */ SDL_SCANCODE_7, // KEY_7 + /* 9, 0x009 */ SDL_SCANCODE_8, // KEY_8 + /* 10, 0x00a */ SDL_SCANCODE_9, // KEY_9 + /* 11, 0x00b */ SDL_SCANCODE_0, // KEY_0 + /* 12, 0x00c */ SDL_SCANCODE_MINUS, // KEY_MINUS + /* 13, 0x00d */ SDL_SCANCODE_EQUALS, // KEY_EQUAL + /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, // KEY_BACKSPACE + /* 15, 0x00f */ SDL_SCANCODE_TAB, // KEY_TAB + /* 16, 0x010 */ SDL_SCANCODE_Q, // KEY_Q + /* 17, 0x011 */ SDL_SCANCODE_W, // KEY_W + /* 18, 0x012 */ SDL_SCANCODE_E, // KEY_E + /* 19, 0x013 */ SDL_SCANCODE_R, // KEY_R + /* 20, 0x014 */ SDL_SCANCODE_T, // KEY_T + /* 21, 0x015 */ SDL_SCANCODE_Y, // KEY_Y + /* 22, 0x016 */ SDL_SCANCODE_U, // KEY_U + /* 23, 0x017 */ SDL_SCANCODE_I, // KEY_I + /* 24, 0x018 */ SDL_SCANCODE_O, // KEY_O + /* 25, 0x019 */ SDL_SCANCODE_P, // KEY_P + /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, // KEY_LEFTBRACE + /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, // KEY_RIGHTBRACE + /* 28, 0x01c */ SDL_SCANCODE_RETURN, // KEY_ENTER + /* 29, 0x01d */ SDL_SCANCODE_LCTRL, // KEY_LEFTCTRL + /* 30, 0x01e */ SDL_SCANCODE_A, // KEY_A + /* 31, 0x01f */ SDL_SCANCODE_S, // KEY_S + /* 32, 0x020 */ SDL_SCANCODE_D, // KEY_D + /* 33, 0x021 */ SDL_SCANCODE_F, // KEY_F + /* 34, 0x022 */ SDL_SCANCODE_G, // KEY_G + /* 35, 0x023 */ SDL_SCANCODE_H, // KEY_H + /* 36, 0x024 */ SDL_SCANCODE_J, // KEY_J + /* 37, 0x025 */ SDL_SCANCODE_K, // KEY_K + /* 38, 0x026 */ SDL_SCANCODE_L, // KEY_L + /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, // KEY_SEMICOLON + /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, // KEY_APOSTROPHE + /* 41, 0x029 */ SDL_SCANCODE_GRAVE, // KEY_GRAVE + /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, // KEY_LEFTSHIFT + /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, // KEY_BACKSLASH + /* 44, 0x02c */ SDL_SCANCODE_Z, // KEY_Z + /* 45, 0x02d */ SDL_SCANCODE_X, // KEY_X + /* 46, 0x02e */ SDL_SCANCODE_C, // KEY_C + /* 47, 0x02f */ SDL_SCANCODE_V, // KEY_V + /* 48, 0x030 */ SDL_SCANCODE_B, // KEY_B + /* 49, 0x031 */ SDL_SCANCODE_N, // KEY_N + /* 50, 0x032 */ SDL_SCANCODE_M, // KEY_M + /* 51, 0x033 */ SDL_SCANCODE_COMMA, // KEY_COMMA + /* 52, 0x034 */ SDL_SCANCODE_PERIOD, // KEY_DOT + /* 53, 0x035 */ SDL_SCANCODE_SLASH, // KEY_SLASH + /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, // KEY_RIGHTSHIFT + /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, // KEY_KPASTERISK + /* 56, 0x038 */ SDL_SCANCODE_LALT, // KEY_LEFTALT + /* 57, 0x039 */ SDL_SCANCODE_SPACE, // KEY_SPACE + /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, // KEY_CAPSLOCK + /* 59, 0x03b */ SDL_SCANCODE_F1, // KEY_F1 + /* 60, 0x03c */ SDL_SCANCODE_F2, // KEY_F2 + /* 61, 0x03d */ SDL_SCANCODE_F3, // KEY_F3 + /* 62, 0x03e */ SDL_SCANCODE_F4, // KEY_F4 + /* 63, 0x03f */ SDL_SCANCODE_F5, // KEY_F5 + /* 64, 0x040 */ SDL_SCANCODE_F6, // KEY_F6 + /* 65, 0x041 */ SDL_SCANCODE_F7, // KEY_F7 + /* 66, 0x042 */ SDL_SCANCODE_F8, // KEY_F8 + /* 67, 0x043 */ SDL_SCANCODE_F9, // KEY_F9 + /* 68, 0x044 */ SDL_SCANCODE_F10, // KEY_F10 + /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, // KEY_NUMLOCK + /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, // KEY_SCROLLLOCK + /* 71, 0x047 */ SDL_SCANCODE_KP_7, // KEY_KP7 + /* 72, 0x048 */ SDL_SCANCODE_KP_8, // KEY_KP8 + /* 73, 0x049 */ SDL_SCANCODE_KP_9, // KEY_KP9 + /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, // KEY_KPMINUS + /* 75, 0x04b */ SDL_SCANCODE_KP_4, // KEY_KP4 + /* 76, 0x04c */ SDL_SCANCODE_KP_5, // KEY_KP5 + /* 77, 0x04d */ SDL_SCANCODE_KP_6, // KEY_KP6 + /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, // KEY_KPPLUS + /* 79, 0x04f */ SDL_SCANCODE_KP_1, // KEY_KP1 + /* 80, 0x050 */ SDL_SCANCODE_KP_2, // KEY_KP2 + /* 81, 0x051 */ SDL_SCANCODE_KP_3, // KEY_KP3 + /* 82, 0x052 */ SDL_SCANCODE_KP_0, // KEY_KP0 + /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, // KEY_KPDOT /* 84, 0x054 */ SDL_SCANCODE_UNKNOWN, - /* 85, 0x055 */ SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU */ - /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, /* KEY_102ND */ - /* 87, 0x057 */ SDL_SCANCODE_F11, /* KEY_F11 */ - /* 88, 0x058 */ SDL_SCANCODE_F12, /* KEY_F12 */ - /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, /* KEY_RO */ - /* 90, 0x05a */ SDL_SCANCODE_LANG3, /* KEY_KATAKANA */ - /* 91, 0x05b */ SDL_SCANCODE_LANG4, /* KEY_HIRAGANA */ - /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, /* KEY_HENKAN */ - /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, /* KEY_KATAKANAHIRAGANA */ - /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, /* KEY_MUHENKAN */ - /* 95, 0x05f */ SDL_SCANCODE_INTERNATIONAL5, /* KEY_KPJPCOMMA */ - /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER */ - /* 97, 0x061 */ SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL */ - /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH */ - /* 99, 0x063 */ SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ */ - /* 100, 0x064 */ SDL_SCANCODE_RALT, /* KEY_RIGHTALT */ - /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED */ - /* 102, 0x066 */ SDL_SCANCODE_HOME, /* KEY_HOME */ - /* 103, 0x067 */ SDL_SCANCODE_UP, /* KEY_UP */ - /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP */ - /* 105, 0x069 */ SDL_SCANCODE_LEFT, /* KEY_LEFT */ - /* 106, 0x06a */ SDL_SCANCODE_RIGHT, /* KEY_RIGHT */ - /* 107, 0x06b */ SDL_SCANCODE_END, /* KEY_END */ - /* 108, 0x06c */ SDL_SCANCODE_DOWN, /* KEY_DOWN */ - /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN */ - /* 110, 0x06e */ SDL_SCANCODE_INSERT, /* KEY_INSERT */ - /* 111, 0x06f */ SDL_SCANCODE_DELETE, /* KEY_DELETE */ - /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO */ - /* 113, 0x071 */ SDL_SCANCODE_MUTE, /* KEY_MUTE */ - /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN */ - /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP */ - /* 116, 0x074 */ SDL_SCANCODE_POWER, /* KEY_POWER */ - /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL */ - /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, /* KEY_KPPLUSMINUS */ - /* 119, 0x077 */ SDL_SCANCODE_PAUSE, /* KEY_PAUSE */ - /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCALE */ - /* 121, 0x079 */ SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA */ - /* 122, 0x07a */ SDL_SCANCODE_LANG1, /* KEY_HANGEUL */ - /* 123, 0x07b */ SDL_SCANCODE_LANG2, /* KEY_HANJA */ - /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, /* KEY_YEN */ - /* 125, 0x07d */ SDL_SCANCODE_LGUI, /* KEY_LEFTMETA */ - /* 126, 0x07e */ SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA */ - /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE */ - /* 128, 0x080 */ SDL_SCANCODE_STOP, /* KEY_STOP */ - /* 129, 0x081 */ SDL_SCANCODE_AGAIN, /* KEY_AGAIN */ - /* 130, 0x082 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROPS */ - /* 131, 0x083 */ SDL_SCANCODE_UNDO, /* KEY_UNDO */ - /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, /* KEY_FRONT */ - /* 133, 0x085 */ SDL_SCANCODE_COPY, /* KEY_COPY */ - /* 134, 0x086 */ SDL_SCANCODE_UNKNOWN, /* KEY_OPEN */ - /* 135, 0x087 */ SDL_SCANCODE_PASTE, /* KEY_PASTE */ - /* 136, 0x088 */ SDL_SCANCODE_FIND, /* KEY_FIND */ - /* 137, 0x089 */ SDL_SCANCODE_CUT, /* KEY_CUT */ - /* 138, 0x08a */ SDL_SCANCODE_HELP, /* KEY_HELP */ - /* 139, 0x08b */ SDL_SCANCODE_MENU, /* KEY_MENU */ - /* 140, 0x08c */ SDL_SCANCODE_CALCULATOR, /* KEY_CALC */ - /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, /* KEY_SETUP */ - /* 142, 0x08e */ SDL_SCANCODE_SLEEP, /* KEY_SLEEP */ - /* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP */ - /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, /* KEY_FILE */ - /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE */ - /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE */ - /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, /* KEY_XFER */ - /* 148, 0x094 */ SDL_SCANCODE_APP1, /* KEY_PROG1 */ - /* 149, 0x095 */ SDL_SCANCODE_APP2, /* KEY_PROG2 */ - /* 150, 0x096 */ SDL_SCANCODE_WWW, /* KEY_WWW */ - /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS */ - /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE */ - /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, /* KEY_ROTATE_DISPLAY */ - /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS */ - /* 155, 0x09b */ SDL_SCANCODE_MAIL, /* KEY_MAIL */ - /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS */ - /* 157, 0x09d */ SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER */ - /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, /* KEY_BACK */ - /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD */ - /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD */ - /* 161, 0x0a1 */ SDL_SCANCODE_EJECT, /* KEY_EJECTCD */ - /* 162, 0x0a2 */ SDL_SCANCODE_EJECT, /* KEY_EJECTCLOSECD */ - /* 163, 0x0a3 */ SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG */ - /* 164, 0x0a4 */ SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE */ - /* 165, 0x0a5 */ SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG */ - /* 166, 0x0a6 */ SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD */ - /* 167, 0x0a7 */ SDL_SCANCODE_UNKNOWN, /* KEY_RECORD */ - /* 168, 0x0a8 */ SDL_SCANCODE_AUDIOREWIND, /* KEY_REWIND */ - /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, /* KEY_PHONE */ - /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, /* KEY_ISO */ - /* 171, 0x0ab */ SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG */ - /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE */ - /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH */ - /* 174, 0x0ae */ SDL_SCANCODE_UNKNOWN, /* KEY_EXIT */ - /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, /* KEY_MOVE */ - /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, /* KEY_EDIT */ - /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP */ - /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN */ - /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN */ - /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN */ - /* 181, 0x0b5 */ SDL_SCANCODE_UNKNOWN, /* KEY_NEW */ - /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, /* KEY_REDO */ - /* 183, 0x0b7 */ SDL_SCANCODE_F13, /* KEY_F13 */ - /* 184, 0x0b8 */ SDL_SCANCODE_F14, /* KEY_F14 */ - /* 185, 0x0b9 */ SDL_SCANCODE_F15, /* KEY_F15 */ - /* 186, 0x0ba */ SDL_SCANCODE_F16, /* KEY_F16 */ - /* 187, 0x0bb */ SDL_SCANCODE_F17, /* KEY_F17 */ - /* 188, 0x0bc */ SDL_SCANCODE_F18, /* KEY_F18 */ - /* 189, 0x0bd */ SDL_SCANCODE_F19, /* KEY_F19 */ - /* 190, 0x0be */ SDL_SCANCODE_F20, /* KEY_F20 */ - /* 191, 0x0bf */ SDL_SCANCODE_F21, /* KEY_F21 */ - /* 192, 0x0c0 */ SDL_SCANCODE_F22, /* KEY_F22 */ - /* 193, 0x0c1 */ SDL_SCANCODE_F23, /* KEY_F23 */ - /* 194, 0x0c2 */ SDL_SCANCODE_F24, /* KEY_F24 */ + /* 85, 0x055 */ SDL_SCANCODE_LANG5, // KEY_ZENKAKUHANKAKU + /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, // KEY_102ND + /* 87, 0x057 */ SDL_SCANCODE_F11, // KEY_F11 + /* 88, 0x058 */ SDL_SCANCODE_F12, // KEY_F12 + /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, // KEY_RO + /* 90, 0x05a */ SDL_SCANCODE_LANG3, // KEY_KATAKANA + /* 91, 0x05b */ SDL_SCANCODE_LANG4, // KEY_HIRAGANA + /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, // KEY_HENKAN + /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, // KEY_KATAKANAHIRAGANA + /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, // KEY_MUHENKAN + /* 95, 0x05f */ SDL_SCANCODE_INTERNATIONAL5, // KEY_KPJPCOMMA + /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, // KEY_KPENTER + /* 97, 0x061 */ SDL_SCANCODE_RCTRL, // KEY_RIGHTCTRL + /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, // KEY_KPSLASH + /* 99, 0x063 */ SDL_SCANCODE_SYSREQ, // KEY_SYSRQ + /* 100, 0x064 */ SDL_SCANCODE_RALT, // KEY_RIGHTALT + /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, // KEY_LINEFEED + /* 102, 0x066 */ SDL_SCANCODE_HOME, // KEY_HOME + /* 103, 0x067 */ SDL_SCANCODE_UP, // KEY_UP + /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, // KEY_PAGEUP + /* 105, 0x069 */ SDL_SCANCODE_LEFT, // KEY_LEFT + /* 106, 0x06a */ SDL_SCANCODE_RIGHT, // KEY_RIGHT + /* 107, 0x06b */ SDL_SCANCODE_END, // KEY_END + /* 108, 0x06c */ SDL_SCANCODE_DOWN, // KEY_DOWN + /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, // KEY_PAGEDOWN + /* 110, 0x06e */ SDL_SCANCODE_INSERT, // KEY_INSERT + /* 111, 0x06f */ SDL_SCANCODE_DELETE, // KEY_DELETE + /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO + /* 113, 0x071 */ SDL_SCANCODE_MUTE, // KEY_MUTE + /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, // KEY_VOLUMEDOWN + /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, // KEY_VOLUMEUP + /* 116, 0x074 */ SDL_SCANCODE_POWER, // KEY_POWER + /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, // KEY_KPEQUAL + /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, // KEY_KPPLUSMINUS + /* 119, 0x077 */ SDL_SCANCODE_PAUSE, // KEY_PAUSE + /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, // KEY_SCALE + /* 121, 0x079 */ SDL_SCANCODE_KP_COMMA, // KEY_KPCOMMA + /* 122, 0x07a */ SDL_SCANCODE_LANG1, // KEY_HANGEUL + /* 123, 0x07b */ SDL_SCANCODE_LANG2, // KEY_HANJA + /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, // KEY_YEN + /* 125, 0x07d */ SDL_SCANCODE_LGUI, // KEY_LEFTMETA + /* 126, 0x07e */ SDL_SCANCODE_RGUI, // KEY_RIGHTMETA + /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, // KEY_COMPOSE + /* 128, 0x080 */ SDL_SCANCODE_STOP, // KEY_STOP + /* 129, 0x081 */ SDL_SCANCODE_AGAIN, // KEY_AGAIN + /* 130, 0x082 */ SDL_SCANCODE_AC_PROPERTIES, // KEY_PROPS + /* 131, 0x083 */ SDL_SCANCODE_UNDO, // KEY_UNDO + /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, // KEY_FRONT + /* 133, 0x085 */ SDL_SCANCODE_COPY, // KEY_COPY + /* 134, 0x086 */ SDL_SCANCODE_AC_OPEN, // KEY_OPEN + /* 135, 0x087 */ SDL_SCANCODE_PASTE, // KEY_PASTE + /* 136, 0x088 */ SDL_SCANCODE_FIND, // KEY_FIND + /* 137, 0x089 */ SDL_SCANCODE_CUT, // KEY_CUT + /* 138, 0x08a */ SDL_SCANCODE_HELP, // KEY_HELP + /* 139, 0x08b */ SDL_SCANCODE_MENU, // KEY_MENU + /* 140, 0x08c */ SDL_SCANCODE_UNKNOWN, // KEY_CALC + /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, // KEY_SETUP + /* 142, 0x08e */ SDL_SCANCODE_SLEEP, // KEY_SLEEP + /* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, // KEY_WAKEUP + /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, // KEY_FILE + /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, // KEY_SENDFILE + /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, // KEY_DELETEFILE + /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, // KEY_XFER + /* 148, 0x094 */ SDL_SCANCODE_UNKNOWN, // KEY_PROG1 + /* 149, 0x095 */ SDL_SCANCODE_UNKNOWN, // KEY_PROG2 + /* 150, 0x096 */ SDL_SCANCODE_UNKNOWN, // KEY_WWW + /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, // KEY_MSDOS + /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, // KEY_COFFEE + /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, // KEY_ROTATE_DISPLAY + /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, // KEY_CYCLEWINDOWS + /* 155, 0x09b */ SDL_SCANCODE_UNKNOWN, // KEY_MAIL + /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, // KEY_BOOKMARKS + /* 157, 0x09d */ SDL_SCANCODE_UNKNOWN, // KEY_COMPUTER + /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, // KEY_BACK + /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, // KEY_FORWARD + /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, // KEY_CLOSECD + /* 161, 0x0a1 */ SDL_SCANCODE_MEDIA_EJECT, // KEY_EJECTCD + /* 162, 0x0a2 */ SDL_SCANCODE_MEDIA_EJECT, // KEY_EJECTCLOSECD + /* 163, 0x0a3 */ SDL_SCANCODE_MEDIA_NEXT_TRACK, // KEY_NEXTSONG + /* 164, 0x0a4 */ SDL_SCANCODE_MEDIA_PLAY_PAUSE, // KEY_PLAYPAUSE + /* 165, 0x0a5 */ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, // KEY_PREVIOUSSONG + /* 166, 0x0a6 */ SDL_SCANCODE_MEDIA_STOP, // KEY_STOPCD + /* 167, 0x0a7 */ SDL_SCANCODE_MEDIA_RECORD, // KEY_RECORD + /* 168, 0x0a8 */ SDL_SCANCODE_MEDIA_REWIND, // KEY_REWIND + /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, // KEY_PHONE + /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, // KEY_ISO + /* 171, 0x0ab */ SDL_SCANCODE_UNKNOWN, // KEY_CONFIG + /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, // KEY_HOMEPAGE + /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, // KEY_REFRESH + /* 174, 0x0ae */ SDL_SCANCODE_AC_EXIT, // KEY_EXIT + /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, // KEY_MOVE + /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, // KEY_EDIT + /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, // KEY_SCROLLUP + /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, // KEY_SCROLLDOWN + /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, // KEY_KPLEFTPAREN + /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, // KEY_KPRIGHTPAREN + /* 181, 0x0b5 */ SDL_SCANCODE_AC_NEW, // KEY_NEW + /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, // KEY_REDO + /* 183, 0x0b7 */ SDL_SCANCODE_F13, // KEY_F13 + /* 184, 0x0b8 */ SDL_SCANCODE_F14, // KEY_F14 + /* 185, 0x0b9 */ SDL_SCANCODE_F15, // KEY_F15 + /* 186, 0x0ba */ SDL_SCANCODE_F16, // KEY_F16 + /* 187, 0x0bb */ SDL_SCANCODE_F17, // KEY_F17 + /* 188, 0x0bc */ SDL_SCANCODE_F18, // KEY_F18 + /* 189, 0x0bd */ SDL_SCANCODE_F19, // KEY_F19 + /* 190, 0x0be */ SDL_SCANCODE_F20, // KEY_F20 + /* 191, 0x0bf */ SDL_SCANCODE_F21, // KEY_F21 + /* 192, 0x0c0 */ SDL_SCANCODE_F22, // KEY_F22 + /* 193, 0x0c1 */ SDL_SCANCODE_F23, // KEY_F23 + /* 194, 0x0c2 */ SDL_SCANCODE_F24, // KEY_F24 /* 195, 0x0c3 */ SDL_SCANCODE_UNKNOWN, /* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, /* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, /* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN, /* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN, - /* 200, 0x0c8 */ SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYCD */ - /* 201, 0x0c9 */ SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD */ - /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 */ - /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 */ - /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, /* KEY_ALL_APPLICATIONS */ - /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND */ - /* 206, 0x0ce */ SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE */ - /* 207, 0x0cf */ SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAY */ - /* 208, 0x0d0 */ SDL_SCANCODE_AUDIOFASTFORWARD, /* KEY_FASTFORWARD */ - /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST */ - /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, /* KEY_PRINT */ - /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, /* KEY_HP */ - /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA */ - /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, /* KEY_SOUND */ - /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION */ - /* 215, 0x0d7 */ SDL_SCANCODE_MAIL, /* KEY_EMAIL */ - /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, /* KEY_CHAT */ - /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, /* KEY_SEARCH */ - /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT */ - /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE */ - /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, /* KEY_SPORT */ - /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, /* KEY_SHOP */ - /* 222, 0x0de */ SDL_SCANCODE_ALTERASE, /* KEY_ALTERASE */ - /* 223, 0x0df */ SDL_SCANCODE_CANCEL, /* KEY_CANCEL */ - /* 224, 0x0e0 */ SDL_SCANCODE_BRIGHTNESSDOWN, /* KEY_BRIGHTNESSDOWN */ - /* 225, 0x0e1 */ SDL_SCANCODE_BRIGHTNESSUP, /* KEY_BRIGHTNESSUP */ - /* 226, 0x0e2 */ SDL_SCANCODE_MEDIASELECT, /* KEY_MEDIA */ - /* 227, 0x0e3 */ SDL_SCANCODE_DISPLAYSWITCH, /* KEY_SWITCHVIDEOMODE */ - /* 228, 0x0e4 */ SDL_SCANCODE_KBDILLUMTOGGLE, /* KEY_KBDILLUMTOGGLE */ - /* 229, 0x0e5 */ SDL_SCANCODE_KBDILLUMDOWN, /* KEY_KBDILLUMDOWN */ - /* 230, 0x0e6 */ SDL_SCANCODE_KBDILLUMUP, /* KEY_KBDILLUMUP */ - /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, /* KEY_SEND */ - /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, /* KEY_REPLY */ - /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL */ - /* 234, 0x0ea */ SDL_SCANCODE_UNKNOWN, /* KEY_SAVE */ - /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS */ - /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY */ - /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH */ - /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, /* KEY_WLAN */ - /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, /* KEY_UWB */ - /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN */ - /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT */ - /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV */ - /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE */ - /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_AUTO */ - /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF */ - /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, /* KEY_WWAN */ - /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL */ - /* 248, 0x0f8 */ SDL_SCANCODE_UNKNOWN, /* KEY_MICMUTE */ + /* 200, 0x0c8 */ SDL_SCANCODE_MEDIA_PLAY, // KEY_PLAYCD + /* 201, 0x0c9 */ SDL_SCANCODE_MEDIA_PAUSE, // KEY_PAUSECD + /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, // KEY_PROG3 + /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, // KEY_PROG4 + /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, // KEY_ALL_APPLICATIONS + /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, // KEY_SUSPEND + /* 206, 0x0ce */ SDL_SCANCODE_AC_CLOSE, // KEY_CLOSE + /* 207, 0x0cf */ SDL_SCANCODE_MEDIA_PLAY, // KEY_PLAY + /* 208, 0x0d0 */ SDL_SCANCODE_MEDIA_FAST_FORWARD, // KEY_FASTFORWARD + /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, // KEY_BASSBOOST + /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, // KEY_PRINT + /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, // KEY_HP + /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA + /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, // KEY_SOUND + /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, // KEY_QUESTION + /* 215, 0x0d7 */ SDL_SCANCODE_UNKNOWN, // KEY_EMAIL + /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, // KEY_CHAT + /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, // KEY_SEARCH + /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, // KEY_CONNECT + /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, // KEY_FINANCE + /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, // KEY_SPORT + /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, // KEY_SHOP + /* 222, 0x0de */ SDL_SCANCODE_ALTERASE, // KEY_ALTERASE + /* 223, 0x0df */ SDL_SCANCODE_CANCEL, // KEY_CANCEL + /* 224, 0x0e0 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESSDOWN + /* 225, 0x0e1 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESSUP + /* 226, 0x0e2 */ SDL_SCANCODE_MEDIA_SELECT, // KEY_MEDIA + /* 227, 0x0e3 */ SDL_SCANCODE_UNKNOWN, // KEY_SWITCHVIDEOMODE + /* 228, 0x0e4 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMTOGGLE + /* 229, 0x0e5 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMDOWN + /* 230, 0x0e6 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDILLUMUP + /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, // KEY_SEND + /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, // KEY_REPLY + /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, // KEY_FORWARDMAIL + /* 234, 0x0ea */ SDL_SCANCODE_AC_SAVE, // KEY_SAVE + /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, // KEY_DOCUMENTS + /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, // KEY_BATTERY + /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, // KEY_BLUETOOTH + /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, // KEY_WLAN + /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, // KEY_UWB + /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, // KEY_UNKNOWN + /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO_NEXT + /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO_PREV + /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_CYCLE + /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_AUTO + /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, // KEY_DISPLAY_OFF + /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, // KEY_WWAN + /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, // KEY_RFKILL + /* 248, 0x0f8 */ SDL_SCANCODE_UNKNOWN, // KEY_MICMUTE /* 249, 0x0f9 */ SDL_SCANCODE_UNKNOWN, /* 250, 0x0fa */ SDL_SCANCODE_UNKNOWN, /* 251, 0x0fb */ SDL_SCANCODE_UNKNOWN, @@ -282,7 +282,7 @@ static SDL_Scancode const linux_scancode_table[] = { /* 253, 0x0fd */ SDL_SCANCODE_UNKNOWN, /* 254, 0x0fe */ SDL_SCANCODE_UNKNOWN, /* 255, 0x0ff */ SDL_SCANCODE_UNKNOWN, -#if 0 /* We don't have any mapped scancodes after this point (yet) */ +#if 0 // We don't have any mapped scancodes after this point (yet) /* 256, 0x100 */ SDL_SCANCODE_UNKNOWN, /* 257, 0x101 */ SDL_SCANCODE_UNKNOWN, /* 258, 0x102 */ SDL_SCANCODE_UNKNOWN, @@ -379,106 +379,106 @@ static SDL_Scancode const linux_scancode_table[] = { /* 349, 0x15d */ SDL_SCANCODE_UNKNOWN, /* 350, 0x15e */ SDL_SCANCODE_UNKNOWN, /* 351, 0x15f */ SDL_SCANCODE_UNKNOWN, - /* 352, 0x160 */ SDL_SCANCODE_UNKNOWN, /* KEY_OK */ - /* 353, 0x161 */ SDL_SCANCODE_UNKNOWN, /* KEY_SELECT */ - /* 354, 0x162 */ SDL_SCANCODE_UNKNOWN, /* KEY_GOTO */ - /* 355, 0x163 */ SDL_SCANCODE_UNKNOWN, /* KEY_CLEAR */ - /* 356, 0x164 */ SDL_SCANCODE_UNKNOWN, /* KEY_POWER2 */ - /* 357, 0x165 */ SDL_SCANCODE_UNKNOWN, /* KEY_OPTION */ - /* 358, 0x166 */ SDL_SCANCODE_UNKNOWN, /* KEY_INFO */ - /* 359, 0x167 */ SDL_SCANCODE_UNKNOWN, /* KEY_TIME */ - /* 360, 0x168 */ SDL_SCANCODE_UNKNOWN, /* KEY_VENDOR */ - /* 361, 0x169 */ SDL_SCANCODE_UNKNOWN, /* KEY_ARCHIVE */ - /* 362, 0x16a */ SDL_SCANCODE_UNKNOWN, /* KEY_PROGRAM */ - /* 363, 0x16b */ SDL_SCANCODE_UNKNOWN, /* KEY_CHANNEL */ - /* 364, 0x16c */ SDL_SCANCODE_UNKNOWN, /* KEY_FAVORITES */ - /* 365, 0x16d */ SDL_SCANCODE_UNKNOWN, /* KEY_EPG */ - /* 366, 0x16e */ SDL_SCANCODE_UNKNOWN, /* KEY_PVR */ - /* 367, 0x16f */ SDL_SCANCODE_UNKNOWN, /* KEY_MHP */ - /* 368, 0x170 */ SDL_SCANCODE_UNKNOWN, /* KEY_LANGUAGE */ - /* 369, 0x171 */ SDL_SCANCODE_UNKNOWN, /* KEY_TITLE */ - /* 370, 0x172 */ SDL_SCANCODE_UNKNOWN, /* KEY_SUBTITLE */ - /* 371, 0x173 */ SDL_SCANCODE_UNKNOWN, /* KEY_ANGLE */ - /* 372, 0x174 */ SDL_SCANCODE_UNKNOWN, /* KEY_FULL_SCREEN */ - /* 373, 0x175 */ SDL_SCANCODE_UNKNOWN, /* KEY_MODE */ - /* 374, 0x176 */ SDL_SCANCODE_UNKNOWN, /* KEY_KEYBOARD */ - /* 375, 0x177 */ SDL_SCANCODE_UNKNOWN, /* KEY_ASPECT_RATIO */ - /* 376, 0x178 */ SDL_SCANCODE_UNKNOWN, /* KEY_PC */ - /* 377, 0x179 */ SDL_SCANCODE_UNKNOWN, /* KEY_TV */ - /* 378, 0x17a */ SDL_SCANCODE_UNKNOWN, /* KEY_TV2 */ - /* 379, 0x17b */ SDL_SCANCODE_UNKNOWN, /* KEY_VCR */ - /* 380, 0x17c */ SDL_SCANCODE_UNKNOWN, /* KEY_VCR2 */ - /* 381, 0x17d */ SDL_SCANCODE_UNKNOWN, /* KEY_SAT */ - /* 382, 0x17e */ SDL_SCANCODE_UNKNOWN, /* KEY_SAT2 */ - /* 383, 0x17f */ SDL_SCANCODE_UNKNOWN, /* KEY_CD */ - /* 384, 0x180 */ SDL_SCANCODE_UNKNOWN, /* KEY_TAPE */ - /* 385, 0x181 */ SDL_SCANCODE_UNKNOWN, /* KEY_RADIO */ - /* 386, 0x182 */ SDL_SCANCODE_UNKNOWN, /* KEY_TUNER */ - /* 387, 0x183 */ SDL_SCANCODE_UNKNOWN, /* KEY_PLAYER */ - /* 388, 0x184 */ SDL_SCANCODE_UNKNOWN, /* KEY_TEXT */ - /* 389, 0x185 */ SDL_SCANCODE_UNKNOWN, /* KEY_DVD */ - /* 390, 0x186 */ SDL_SCANCODE_UNKNOWN, /* KEY_AUX */ - /* 391, 0x187 */ SDL_SCANCODE_UNKNOWN, /* KEY_MP3 */ - /* 392, 0x188 */ SDL_SCANCODE_UNKNOWN, /* KEY_AUDIO */ - /* 393, 0x189 */ SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO */ - /* 394, 0x18a */ SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTORY */ - /* 395, 0x18b */ SDL_SCANCODE_UNKNOWN, /* KEY_LIST */ - /* 396, 0x18c */ SDL_SCANCODE_UNKNOWN, /* KEY_MEMO */ - /* 397, 0x18d */ SDL_SCANCODE_UNKNOWN, /* KEY_CALENDAR */ - /* 398, 0x18e */ SDL_SCANCODE_UNKNOWN, /* KEY_RED */ - /* 399, 0x18f */ SDL_SCANCODE_UNKNOWN, /* KEY_GREEN */ - /* 400, 0x190 */ SDL_SCANCODE_UNKNOWN, /* KEY_YELLOW */ - /* 401, 0x191 */ SDL_SCANCODE_UNKNOWN, /* KEY_BLUE */ - /* 402, 0x192 */ SDL_SCANCODE_UNKNOWN, /* KEY_CHANNELUP */ - /* 403, 0x193 */ SDL_SCANCODE_UNKNOWN, /* KEY_CHANNELDOWN */ - /* 404, 0x194 */ SDL_SCANCODE_UNKNOWN, /* KEY_FIRST */ - /* 405, 0x195 */ SDL_SCANCODE_UNKNOWN, /* KEY_LAST */ - /* 406, 0x196 */ SDL_SCANCODE_UNKNOWN, /* KEY_AB */ - /* 407, 0x197 */ SDL_SCANCODE_UNKNOWN, /* KEY_NEXT */ - /* 408, 0x198 */ SDL_SCANCODE_UNKNOWN, /* KEY_RESTART */ - /* 409, 0x199 */ SDL_SCANCODE_UNKNOWN, /* KEY_SLOW */ - /* 410, 0x19a */ SDL_SCANCODE_UNKNOWN, /* KEY_SHUFFLE */ - /* 411, 0x19b */ SDL_SCANCODE_UNKNOWN, /* KEY_BREAK */ - /* 412, 0x19c */ SDL_SCANCODE_UNKNOWN, /* KEY_PREVIOUS */ - /* 413, 0x19d */ SDL_SCANCODE_UNKNOWN, /* KEY_DIGITS */ - /* 414, 0x19e */ SDL_SCANCODE_UNKNOWN, /* KEY_TEEN */ - /* 415, 0x19f */ SDL_SCANCODE_UNKNOWN, /* KEY_TWEN */ - /* 416, 0x1a0 */ SDL_SCANCODE_UNKNOWN, /* KEY_VIDEOPHONE */ - /* 417, 0x1a1 */ SDL_SCANCODE_UNKNOWN, /* KEY_GAMES */ - /* 418, 0x1a2 */ SDL_SCANCODE_UNKNOWN, /* KEY_ZOOMIN */ - /* 419, 0x1a3 */ SDL_SCANCODE_UNKNOWN, /* KEY_ZOOMOUT */ - /* 420, 0x1a4 */ SDL_SCANCODE_UNKNOWN, /* KEY_ZOOMRESET */ - /* 421, 0x1a5 */ SDL_SCANCODE_UNKNOWN, /* KEY_WORDPROCESSOR */ - /* 422, 0x1a6 */ SDL_SCANCODE_UNKNOWN, /* KEY_EDITOR */ - /* 423, 0x1a7 */ SDL_SCANCODE_UNKNOWN, /* KEY_SPREADSHEET */ - /* 424, 0x1a8 */ SDL_SCANCODE_UNKNOWN, /* KEY_GRAPHICSEDITOR */ - /* 425, 0x1a9 */ SDL_SCANCODE_UNKNOWN, /* KEY_PRESENTATION */ - /* 426, 0x1aa */ SDL_SCANCODE_UNKNOWN, /* KEY_DATABASE */ - /* 427, 0x1ab */ SDL_SCANCODE_UNKNOWN, /* KEY_NEWS */ - /* 428, 0x1ac */ SDL_SCANCODE_UNKNOWN, /* KEY_VOICEMAIL */ - /* 429, 0x1ad */ SDL_SCANCODE_UNKNOWN, /* KEY_ADDRESSBOOK */ - /* 430, 0x1ae */ SDL_SCANCODE_UNKNOWN, /* KEY_MESSENGER */ - /* 431, 0x1af */ SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAYTOGGLE */ - /* 432, 0x1b0 */ SDL_SCANCODE_UNKNOWN, /* KEY_SPELLCHECK */ - /* 433, 0x1b1 */ SDL_SCANCODE_UNKNOWN, /* KEY_LOGOFF */ - /* 434, 0x1b2 */ SDL_SCANCODE_UNKNOWN, /* KEY_DOLLAR */ - /* 435, 0x1b3 */ SDL_SCANCODE_UNKNOWN, /* KEY_EURO */ - /* 436, 0x1b4 */ SDL_SCANCODE_UNKNOWN, /* KEY_FRAMEBACK */ - /* 437, 0x1b5 */ SDL_SCANCODE_UNKNOWN, /* KEY_FRAMEFORWARD */ - /* 438, 0x1b6 */ SDL_SCANCODE_UNKNOWN, /* KEY_CONTEXT_MENU */ - /* 439, 0x1b7 */ SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA_REPEAT */ - /* 440, 0x1b8 */ SDL_SCANCODE_UNKNOWN, /* KEY_10CHANNELSUP */ - /* 441, 0x1b9 */ SDL_SCANCODE_UNKNOWN, /* KEY_10CHANNELSDOWN */ - /* 442, 0x1ba */ SDL_SCANCODE_UNKNOWN, /* KEY_IMAGES */ + /* 352, 0x160 */ SDL_SCANCODE_UNKNOWN, // KEY_OK + /* 353, 0x161 */ SDL_SCANCODE_UNKNOWN, // KEY_SELECT + /* 354, 0x162 */ SDL_SCANCODE_UNKNOWN, // KEY_GOTO + /* 355, 0x163 */ SDL_SCANCODE_UNKNOWN, // KEY_CLEAR + /* 356, 0x164 */ SDL_SCANCODE_UNKNOWN, // KEY_POWER2 + /* 357, 0x165 */ SDL_SCANCODE_UNKNOWN, // KEY_OPTION + /* 358, 0x166 */ SDL_SCANCODE_UNKNOWN, // KEY_INFO + /* 359, 0x167 */ SDL_SCANCODE_UNKNOWN, // KEY_TIME + /* 360, 0x168 */ SDL_SCANCODE_UNKNOWN, // KEY_VENDOR + /* 361, 0x169 */ SDL_SCANCODE_UNKNOWN, // KEY_ARCHIVE + /* 362, 0x16a */ SDL_SCANCODE_UNKNOWN, // KEY_PROGRAM + /* 363, 0x16b */ SDL_SCANCODE_UNKNOWN, // KEY_CHANNEL + /* 364, 0x16c */ SDL_SCANCODE_UNKNOWN, // KEY_FAVORITES + /* 365, 0x16d */ SDL_SCANCODE_UNKNOWN, // KEY_EPG + /* 366, 0x16e */ SDL_SCANCODE_UNKNOWN, // KEY_PVR + /* 367, 0x16f */ SDL_SCANCODE_UNKNOWN, // KEY_MHP + /* 368, 0x170 */ SDL_SCANCODE_UNKNOWN, // KEY_LANGUAGE + /* 369, 0x171 */ SDL_SCANCODE_UNKNOWN, // KEY_TITLE + /* 370, 0x172 */ SDL_SCANCODE_UNKNOWN, // KEY_SUBTITLE + /* 371, 0x173 */ SDL_SCANCODE_UNKNOWN, // KEY_ANGLE + /* 372, 0x174 */ SDL_SCANCODE_UNKNOWN, // KEY_FULL_SCREEN + /* 373, 0x175 */ SDL_SCANCODE_UNKNOWN, // KEY_MODE + /* 374, 0x176 */ SDL_SCANCODE_UNKNOWN, // KEY_KEYBOARD + /* 375, 0x177 */ SDL_SCANCODE_UNKNOWN, // KEY_ASPECT_RATIO + /* 376, 0x178 */ SDL_SCANCODE_UNKNOWN, // KEY_PC + /* 377, 0x179 */ SDL_SCANCODE_UNKNOWN, // KEY_TV + /* 378, 0x17a */ SDL_SCANCODE_UNKNOWN, // KEY_TV2 + /* 379, 0x17b */ SDL_SCANCODE_UNKNOWN, // KEY_VCR + /* 380, 0x17c */ SDL_SCANCODE_UNKNOWN, // KEY_VCR2 + /* 381, 0x17d */ SDL_SCANCODE_UNKNOWN, // KEY_SAT + /* 382, 0x17e */ SDL_SCANCODE_UNKNOWN, // KEY_SAT2 + /* 383, 0x17f */ SDL_SCANCODE_UNKNOWN, // KEY_CD + /* 384, 0x180 */ SDL_SCANCODE_UNKNOWN, // KEY_TAPE + /* 385, 0x181 */ SDL_SCANCODE_UNKNOWN, // KEY_RADIO + /* 386, 0x182 */ SDL_SCANCODE_UNKNOWN, // KEY_TUNER + /* 387, 0x183 */ SDL_SCANCODE_UNKNOWN, // KEY_PLAYER + /* 388, 0x184 */ SDL_SCANCODE_UNKNOWN, // KEY_TEXT + /* 389, 0x185 */ SDL_SCANCODE_UNKNOWN, // KEY_DVD + /* 390, 0x186 */ SDL_SCANCODE_UNKNOWN, // KEY_AUX + /* 391, 0x187 */ SDL_SCANCODE_UNKNOWN, // KEY_MP3 + /* 392, 0x188 */ SDL_SCANCODE_UNKNOWN, // KEY_AUDIO + /* 393, 0x189 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEO + /* 394, 0x18a */ SDL_SCANCODE_UNKNOWN, // KEY_DIRECTORY + /* 395, 0x18b */ SDL_SCANCODE_UNKNOWN, // KEY_LIST + /* 396, 0x18c */ SDL_SCANCODE_UNKNOWN, // KEY_MEMO + /* 397, 0x18d */ SDL_SCANCODE_UNKNOWN, // KEY_CALENDAR + /* 398, 0x18e */ SDL_SCANCODE_UNKNOWN, // KEY_RED + /* 399, 0x18f */ SDL_SCANCODE_UNKNOWN, // KEY_GREEN + /* 400, 0x190 */ SDL_SCANCODE_UNKNOWN, // KEY_YELLOW + /* 401, 0x191 */ SDL_SCANCODE_UNKNOWN, // KEY_BLUE + /* 402, 0x192 */ SDL_SCANCODE_UNKNOWN, // KEY_CHANNELUP + /* 403, 0x193 */ SDL_SCANCODE_UNKNOWN, // KEY_CHANNELDOWN + /* 404, 0x194 */ SDL_SCANCODE_UNKNOWN, // KEY_FIRST + /* 405, 0x195 */ SDL_SCANCODE_UNKNOWN, // KEY_LAST + /* 406, 0x196 */ SDL_SCANCODE_UNKNOWN, // KEY_AB + /* 407, 0x197 */ SDL_SCANCODE_UNKNOWN, // KEY_NEXT + /* 408, 0x198 */ SDL_SCANCODE_UNKNOWN, // KEY_RESTART + /* 409, 0x199 */ SDL_SCANCODE_UNKNOWN, // KEY_SLOW + /* 410, 0x19a */ SDL_SCANCODE_UNKNOWN, // KEY_SHUFFLE + /* 411, 0x19b */ SDL_SCANCODE_UNKNOWN, // KEY_BREAK + /* 412, 0x19c */ SDL_SCANCODE_UNKNOWN, // KEY_PREVIOUS + /* 413, 0x19d */ SDL_SCANCODE_UNKNOWN, // KEY_DIGITS + /* 414, 0x19e */ SDL_SCANCODE_UNKNOWN, // KEY_TEEN + /* 415, 0x19f */ SDL_SCANCODE_UNKNOWN, // KEY_TWEN + /* 416, 0x1a0 */ SDL_SCANCODE_UNKNOWN, // KEY_VIDEOPHONE + /* 417, 0x1a1 */ SDL_SCANCODE_UNKNOWN, // KEY_GAMES + /* 418, 0x1a2 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMIN + /* 419, 0x1a3 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMOUT + /* 420, 0x1a4 */ SDL_SCANCODE_UNKNOWN, // KEY_ZOOMRESET + /* 421, 0x1a5 */ SDL_SCANCODE_UNKNOWN, // KEY_WORDPROCESSOR + /* 422, 0x1a6 */ SDL_SCANCODE_UNKNOWN, // KEY_EDITOR + /* 423, 0x1a7 */ SDL_SCANCODE_UNKNOWN, // KEY_SPREADSHEET + /* 424, 0x1a8 */ SDL_SCANCODE_UNKNOWN, // KEY_GRAPHICSEDITOR + /* 425, 0x1a9 */ SDL_SCANCODE_UNKNOWN, // KEY_PRESENTATION + /* 426, 0x1aa */ SDL_SCANCODE_UNKNOWN, // KEY_DATABASE + /* 427, 0x1ab */ SDL_SCANCODE_UNKNOWN, // KEY_NEWS + /* 428, 0x1ac */ SDL_SCANCODE_UNKNOWN, // KEY_VOICEMAIL + /* 429, 0x1ad */ SDL_SCANCODE_UNKNOWN, // KEY_ADDRESSBOOK + /* 430, 0x1ae */ SDL_SCANCODE_UNKNOWN, // KEY_MESSENGER + /* 431, 0x1af */ SDL_SCANCODE_UNKNOWN, // KEY_DISPLAYTOGGLE + /* 432, 0x1b0 */ SDL_SCANCODE_UNKNOWN, // KEY_SPELLCHECK + /* 433, 0x1b1 */ SDL_SCANCODE_UNKNOWN, // KEY_LOGOFF + /* 434, 0x1b2 */ SDL_SCANCODE_UNKNOWN, // KEY_DOLLAR + /* 435, 0x1b3 */ SDL_SCANCODE_UNKNOWN, // KEY_EURO + /* 436, 0x1b4 */ SDL_SCANCODE_UNKNOWN, // KEY_FRAMEBACK + /* 437, 0x1b5 */ SDL_SCANCODE_UNKNOWN, // KEY_FRAMEFORWARD + /* 438, 0x1b6 */ SDL_SCANCODE_UNKNOWN, // KEY_CONTEXT_MENU + /* 439, 0x1b7 */ SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_REPEAT + /* 440, 0x1b8 */ SDL_SCANCODE_UNKNOWN, // KEY_10CHANNELSUP + /* 441, 0x1b9 */ SDL_SCANCODE_UNKNOWN, // KEY_10CHANNELSDOWN + /* 442, 0x1ba */ SDL_SCANCODE_UNKNOWN, // KEY_IMAGES /* 443, 0x1bb */ SDL_SCANCODE_UNKNOWN, - /* 444, 0x1bc */ SDL_SCANCODE_UNKNOWN, /* KEY_NOTIFICATION_CENTER */ - /* 445, 0x1bd */ SDL_SCANCODE_UNKNOWN, /* KEY_PICKUP_PHONE */ - /* 446, 0x1be */ SDL_SCANCODE_UNKNOWN, /* KEY_HANGUP_PHONE */ + /* 444, 0x1bc */ SDL_SCANCODE_UNKNOWN, // KEY_NOTIFICATION_CENTER + /* 445, 0x1bd */ SDL_SCANCODE_UNKNOWN, // KEY_PICKUP_PHONE + /* 446, 0x1be */ SDL_SCANCODE_UNKNOWN, // KEY_HANGUP_PHONE /* 447, 0x1bf */ SDL_SCANCODE_UNKNOWN, - /* 448, 0x1c0 */ SDL_SCANCODE_UNKNOWN, /* KEY_DEL_EOL */ - /* 449, 0x1c1 */ SDL_SCANCODE_UNKNOWN, /* KEY_DEL_EOS */ - /* 450, 0x1c2 */ SDL_SCANCODE_UNKNOWN, /* KEY_INS_LINE */ - /* 451, 0x1c3 */ SDL_SCANCODE_UNKNOWN, /* KEY_DEL_LINE */ + /* 448, 0x1c0 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_EOL + /* 449, 0x1c1 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_EOS + /* 450, 0x1c2 */ SDL_SCANCODE_UNKNOWN, // KEY_INS_LINE + /* 451, 0x1c3 */ SDL_SCANCODE_UNKNOWN, // KEY_DEL_LINE /* 452, 0x1c4 */ SDL_SCANCODE_UNKNOWN, /* 453, 0x1c5 */ SDL_SCANCODE_UNKNOWN, /* 454, 0x1c6 */ SDL_SCANCODE_UNKNOWN, @@ -491,28 +491,28 @@ static SDL_Scancode const linux_scancode_table[] = { /* 461, 0x1cd */ SDL_SCANCODE_UNKNOWN, /* 462, 0x1ce */ SDL_SCANCODE_UNKNOWN, /* 463, 0x1cf */ SDL_SCANCODE_UNKNOWN, - /* 464, 0x1d0 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN */ - /* 465, 0x1d1 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_ESC */ - /* 466, 0x1d2 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F1 */ - /* 467, 0x1d3 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F2 */ - /* 468, 0x1d4 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F3 */ - /* 469, 0x1d5 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F4 */ - /* 470, 0x1d6 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F5 */ - /* 471, 0x1d7 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F6 */ - /* 472, 0x1d8 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F7 */ - /* 473, 0x1d9 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F8 */ - /* 474, 0x1da */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F9 */ - /* 475, 0x1db */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F10 */ - /* 476, 0x1dc */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F11 */ - /* 477, 0x1dd */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F12 */ - /* 478, 0x1de */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_1 */ - /* 479, 0x1df */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_2 */ - /* 480, 0x1e0 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_D */ - /* 481, 0x1e1 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_E */ - /* 482, 0x1e2 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_F */ - /* 483, 0x1e3 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_S */ - /* 484, 0x1e4 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_B */ - /* 485, 0x1e5 */ SDL_SCANCODE_UNKNOWN, /* KEY_FN_RIGHT_SHIFT */ + /* 464, 0x1d0 */ SDL_SCANCODE_UNKNOWN, // KEY_FN + /* 465, 0x1d1 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_ESC + /* 466, 0x1d2 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F1 + /* 467, 0x1d3 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F2 + /* 468, 0x1d4 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F3 + /* 469, 0x1d5 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F4 + /* 470, 0x1d6 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F5 + /* 471, 0x1d7 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F6 + /* 472, 0x1d8 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F7 + /* 473, 0x1d9 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F8 + /* 474, 0x1da */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F9 + /* 475, 0x1db */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F10 + /* 476, 0x1dc */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F11 + /* 477, 0x1dd */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F12 + /* 478, 0x1de */ SDL_SCANCODE_UNKNOWN, // KEY_FN_1 + /* 479, 0x1df */ SDL_SCANCODE_UNKNOWN, // KEY_FN_2 + /* 480, 0x1e0 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_D + /* 481, 0x1e1 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_E + /* 482, 0x1e2 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_F + /* 483, 0x1e3 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_S + /* 484, 0x1e4 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_B + /* 485, 0x1e5 */ SDL_SCANCODE_UNKNOWN, // KEY_FN_RIGHT_SHIFT /* 486, 0x1e6 */ SDL_SCANCODE_UNKNOWN, /* 487, 0x1e7 */ SDL_SCANCODE_UNKNOWN, /* 488, 0x1e8 */ SDL_SCANCODE_UNKNOWN, @@ -524,52 +524,52 @@ static SDL_Scancode const linux_scancode_table[] = { /* 494, 0x1ee */ SDL_SCANCODE_UNKNOWN, /* 495, 0x1ef */ SDL_SCANCODE_UNKNOWN, /* 496, 0x1f0 */ SDL_SCANCODE_UNKNOWN, - /* 497, 0x1f1 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT1 */ - /* 498, 0x1f2 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT2 */ - /* 499, 0x1f3 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT3 */ - /* 500, 0x1f4 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT4 */ - /* 501, 0x1f5 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT5 */ - /* 502, 0x1f6 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT6 */ - /* 503, 0x1f7 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT7 */ - /* 504, 0x1f8 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT8 */ - /* 505, 0x1f9 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT9 */ - /* 506, 0x1fa */ SDL_SCANCODE_UNKNOWN, /* KEY_BRL_DOT10 */ + /* 497, 0x1f1 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT1 + /* 498, 0x1f2 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT2 + /* 499, 0x1f3 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT3 + /* 500, 0x1f4 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT4 + /* 501, 0x1f5 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT5 + /* 502, 0x1f6 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT6 + /* 503, 0x1f7 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT7 + /* 504, 0x1f8 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT8 + /* 505, 0x1f9 */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT9 + /* 506, 0x1fa */ SDL_SCANCODE_UNKNOWN, // KEY_BRL_DOT10 /* 507, 0x1fb */ SDL_SCANCODE_UNKNOWN, /* 508, 0x1fc */ SDL_SCANCODE_UNKNOWN, /* 509, 0x1fd */ SDL_SCANCODE_UNKNOWN, /* 510, 0x1fe */ SDL_SCANCODE_UNKNOWN, /* 511, 0x1ff */ SDL_SCANCODE_UNKNOWN, - /* 512, 0x200 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_0 */ - /* 513, 0x201 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_1 */ - /* 514, 0x202 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_2 */ - /* 515, 0x203 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_3 */ - /* 516, 0x204 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_4 */ - /* 517, 0x205 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_5 */ - /* 518, 0x206 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_6 */ - /* 519, 0x207 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_7 */ - /* 520, 0x208 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_8 */ - /* 521, 0x209 */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_9 */ - /* 522, 0x20a */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_STAR */ - /* 523, 0x20b */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_POUND */ - /* 524, 0x20c */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_A */ - /* 525, 0x20d */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_B */ - /* 526, 0x20e */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_C */ - /* 527, 0x20f */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_D */ - /* 528, 0x210 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_FOCUS */ - /* 529, 0x211 */ SDL_SCANCODE_UNKNOWN, /* KEY_WPS_BUTTON */ - /* 530, 0x212 */ SDL_SCANCODE_UNKNOWN, /* KEY_TOUCHPAD_TOGGLE */ - /* 531, 0x213 */ SDL_SCANCODE_UNKNOWN, /* KEY_TOUCHPAD_ON */ - /* 532, 0x214 */ SDL_SCANCODE_UNKNOWN, /* KEY_TOUCHPAD_OFF */ - /* 533, 0x215 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_ZOOMIN */ - /* 534, 0x216 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_ZOOMOUT */ - /* 535, 0x217 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_UP */ - /* 536, 0x218 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_DOWN */ - /* 537, 0x219 */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_LEFT */ - /* 538, 0x21a */ SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA_RIGHT */ - /* 539, 0x21b */ SDL_SCANCODE_UNKNOWN, /* KEY_ATTENDANT_ON */ - /* 540, 0x21c */ SDL_SCANCODE_UNKNOWN, /* KEY_ATTENDANT_OFF */ - /* 541, 0x21d */ SDL_SCANCODE_UNKNOWN, /* KEY_ATTENDANT_TOGGLE */ - /* 542, 0x21e */ SDL_SCANCODE_UNKNOWN, /* KEY_LIGHTS_TOGGLE */ + /* 512, 0x200 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_0 + /* 513, 0x201 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_1 + /* 514, 0x202 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_2 + /* 515, 0x203 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_3 + /* 516, 0x204 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_4 + /* 517, 0x205 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_5 + /* 518, 0x206 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_6 + /* 519, 0x207 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_7 + /* 520, 0x208 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_8 + /* 521, 0x209 */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_9 + /* 522, 0x20a */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_STAR + /* 523, 0x20b */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_POUND + /* 524, 0x20c */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_A + /* 525, 0x20d */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_B + /* 526, 0x20e */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_C + /* 527, 0x20f */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_D + /* 528, 0x210 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_FOCUS + /* 529, 0x211 */ SDL_SCANCODE_UNKNOWN, // KEY_WPS_BUTTON + /* 530, 0x212 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_TOGGLE + /* 531, 0x213 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_ON + /* 532, 0x214 */ SDL_SCANCODE_UNKNOWN, // KEY_TOUCHPAD_OFF + /* 533, 0x215 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_ZOOMIN + /* 534, 0x216 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_ZOOMOUT + /* 535, 0x217 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_UP + /* 536, 0x218 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_DOWN + /* 537, 0x219 */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_LEFT + /* 538, 0x21a */ SDL_SCANCODE_UNKNOWN, // KEY_CAMERA_RIGHT + /* 539, 0x21b */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_ON + /* 540, 0x21c */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_OFF + /* 541, 0x21d */ SDL_SCANCODE_UNKNOWN, // KEY_ATTENDANT_TOGGLE + /* 542, 0x21e */ SDL_SCANCODE_UNKNOWN, // KEY_LIGHTS_TOGGLE /* 543, 0x21f */ SDL_SCANCODE_UNKNOWN, /* 544, 0x220 */ SDL_SCANCODE_UNKNOWN, /* 545, 0x221 */ SDL_SCANCODE_UNKNOWN, @@ -587,8 +587,8 @@ static SDL_Scancode const linux_scancode_table[] = { /* 557, 0x22d */ SDL_SCANCODE_UNKNOWN, /* 558, 0x22e */ SDL_SCANCODE_UNKNOWN, /* 559, 0x22f */ SDL_SCANCODE_UNKNOWN, - /* 560, 0x230 */ SDL_SCANCODE_UNKNOWN, /* KEY_ALS_TOGGLE */ - /* 561, 0x231 */ SDL_SCANCODE_UNKNOWN, /* KEY_ROTATE_LOCK_TOGGLE */ + /* 560, 0x230 */ SDL_SCANCODE_UNKNOWN, // KEY_ALS_TOGGLE + /* 561, 0x231 */ SDL_SCANCODE_UNKNOWN, // KEY_ROTATE_LOCK_TOGGLE /* 562, 0x232 */ SDL_SCANCODE_UNKNOWN, /* 563, 0x233 */ SDL_SCANCODE_UNKNOWN, /* 564, 0x234 */ SDL_SCANCODE_UNKNOWN, @@ -603,24 +603,24 @@ static SDL_Scancode const linux_scancode_table[] = { /* 573, 0x23d */ SDL_SCANCODE_UNKNOWN, /* 574, 0x23e */ SDL_SCANCODE_UNKNOWN, /* 575, 0x23f */ SDL_SCANCODE_UNKNOWN, - /* 576, 0x240 */ SDL_SCANCODE_UNKNOWN, /* KEY_BUTTONCONFIG */ - /* 577, 0x241 */ SDL_SCANCODE_UNKNOWN, /* KEY_TASKMANAGER */ - /* 578, 0x242 */ SDL_SCANCODE_UNKNOWN, /* KEY_JOURNAL */ - /* 579, 0x243 */ SDL_SCANCODE_UNKNOWN, /* KEY_CONTROLPANEL */ - /* 580, 0x244 */ SDL_SCANCODE_UNKNOWN, /* KEY_APPSELECT */ - /* 581, 0x245 */ SDL_SCANCODE_UNKNOWN, /* KEY_SCREENSAVER */ - /* 582, 0x246 */ SDL_SCANCODE_UNKNOWN, /* KEY_VOICECOMMAND */ - /* 583, 0x247 */ SDL_SCANCODE_UNKNOWN, /* KEY_ASSISTANT */ - /* 584, 0x248 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LAYOUT_NEXT */ - /* 585, 0x249 */ SDL_SCANCODE_UNKNOWN, /* KEY_EMOJI_PICKER */ - /* 586, 0x24a */ SDL_SCANCODE_UNKNOWN, /* KEY_DICTATE */ + /* 576, 0x240 */ SDL_SCANCODE_UNKNOWN, // KEY_BUTTONCONFIG + /* 577, 0x241 */ SDL_SCANCODE_UNKNOWN, // KEY_TASKMANAGER + /* 578, 0x242 */ SDL_SCANCODE_UNKNOWN, // KEY_JOURNAL + /* 579, 0x243 */ SDL_SCANCODE_UNKNOWN, // KEY_CONTROLPANEL + /* 580, 0x244 */ SDL_SCANCODE_UNKNOWN, // KEY_APPSELECT + /* 581, 0x245 */ SDL_SCANCODE_UNKNOWN, // KEY_SCREENSAVER + /* 582, 0x246 */ SDL_SCANCODE_UNKNOWN, // KEY_VOICECOMMAND + /* 583, 0x247 */ SDL_SCANCODE_UNKNOWN, // KEY_ASSISTANT + /* 584, 0x248 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LAYOUT_NEXT + /* 585, 0x249 */ SDL_SCANCODE_UNKNOWN, // KEY_EMOJI_PICKER + /* 586, 0x24a */ SDL_SCANCODE_UNKNOWN, // KEY_DICTATE /* 587, 0x24b */ SDL_SCANCODE_UNKNOWN, /* 588, 0x24c */ SDL_SCANCODE_UNKNOWN, /* 589, 0x24d */ SDL_SCANCODE_UNKNOWN, /* 590, 0x24e */ SDL_SCANCODE_UNKNOWN, /* 591, 0x24f */ SDL_SCANCODE_UNKNOWN, - /* 592, 0x250 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_MIN */ - /* 593, 0x251 */ SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_MAX */ + /* 592, 0x250 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MIN + /* 593, 0x251 */ SDL_SCANCODE_UNKNOWN, // KEY_BRIGHTNESS_MAX /* 594, 0x252 */ SDL_SCANCODE_UNKNOWN, /* 595, 0x253 */ SDL_SCANCODE_UNKNOWN, /* 596, 0x254 */ SDL_SCANCODE_UNKNOWN, @@ -635,33 +635,33 @@ static SDL_Scancode const linux_scancode_table[] = { /* 605, 0x25d */ SDL_SCANCODE_UNKNOWN, /* 606, 0x25e */ SDL_SCANCODE_UNKNOWN, /* 607, 0x25f */ SDL_SCANCODE_UNKNOWN, - /* 608, 0x260 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_PREV */ - /* 609, 0x261 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_NEXT */ - /* 610, 0x262 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_PREVGROUP */ - /* 611, 0x263 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_NEXTGROUP */ - /* 612, 0x264 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_ACCEPT */ - /* 613, 0x265 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBDINPUTASSIST_CANCEL */ - /* 614, 0x266 */ SDL_SCANCODE_UNKNOWN, /* KEY_RIGHT_UP */ - /* 615, 0x267 */ SDL_SCANCODE_UNKNOWN, /* KEY_RIGHT_DOWN */ - /* 616, 0x268 */ SDL_SCANCODE_UNKNOWN, /* KEY_LEFT_UP */ - /* 617, 0x269 */ SDL_SCANCODE_UNKNOWN, /* KEY_LEFT_DOWN */ - /* 618, 0x26a */ SDL_SCANCODE_UNKNOWN, /* KEY_ROOT_MENU */ - /* 619, 0x26b */ SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA_TOP_MENU */ - /* 620, 0x26c */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_11 */ - /* 621, 0x26d */ SDL_SCANCODE_UNKNOWN, /* KEY_NUMERIC_12 */ - /* 622, 0x26e */ SDL_SCANCODE_UNKNOWN, /* KEY_AUDIO_DESC */ - /* 623, 0x26f */ SDL_SCANCODE_UNKNOWN, /* KEY_3D_MODE */ - /* 624, 0x270 */ SDL_SCANCODE_UNKNOWN, /* KEY_NEXT_FAVORITE */ - /* 625, 0x271 */ SDL_SCANCODE_UNKNOWN, /* KEY_STOP_RECORD */ - /* 626, 0x272 */ SDL_SCANCODE_UNKNOWN, /* KEY_PAUSE_RECORD */ - /* 627, 0x273 */ SDL_SCANCODE_UNKNOWN, /* KEY_VOD */ - /* 628, 0x274 */ SDL_SCANCODE_UNKNOWN, /* KEY_UNMUTE */ - /* 629, 0x275 */ SDL_SCANCODE_UNKNOWN, /* KEY_FASTREVERSE */ - /* 630, 0x276 */ SDL_SCANCODE_UNKNOWN, /* KEY_SLOWREVERSE */ - /* 631, 0x277 */ SDL_SCANCODE_UNKNOWN, /* KEY_DATA */ - /* 632, 0x278 */ SDL_SCANCODE_UNKNOWN, /* KEY_ONSCREEN_KEYBOARD */ - /* 633, 0x279 */ SDL_SCANCODE_UNKNOWN, /* KEY_PRIVACY_SCREEN_TOGGLE */ - /* 634, 0x27a */ SDL_SCANCODE_UNKNOWN, /* KEY_SELECTIVE_SCREENSHOT */ + /* 608, 0x260 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_PREV + /* 609, 0x261 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_NEXT + /* 610, 0x262 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_PREVGROUP + /* 611, 0x263 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_NEXTGROUP + /* 612, 0x264 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_ACCEPT + /* 613, 0x265 */ SDL_SCANCODE_UNKNOWN, // KEY_KBDINPUTASSIST_CANCEL + /* 614, 0x266 */ SDL_SCANCODE_UNKNOWN, // KEY_RIGHT_UP + /* 615, 0x267 */ SDL_SCANCODE_UNKNOWN, // KEY_RIGHT_DOWN + /* 616, 0x268 */ SDL_SCANCODE_UNKNOWN, // KEY_LEFT_UP + /* 617, 0x269 */ SDL_SCANCODE_UNKNOWN, // KEY_LEFT_DOWN + /* 618, 0x26a */ SDL_SCANCODE_UNKNOWN, // KEY_ROOT_MENU + /* 619, 0x26b */ SDL_SCANCODE_UNKNOWN, // KEY_MEDIA_TOP_MENU + /* 620, 0x26c */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_11 + /* 621, 0x26d */ SDL_SCANCODE_UNKNOWN, // KEY_NUMERIC_12 + /* 622, 0x26e */ SDL_SCANCODE_UNKNOWN, // KEY_AUDIO_DESC + /* 623, 0x26f */ SDL_SCANCODE_UNKNOWN, // KEY_3D_MODE + /* 624, 0x270 */ SDL_SCANCODE_UNKNOWN, // KEY_NEXT_FAVORITE + /* 625, 0x271 */ SDL_SCANCODE_UNKNOWN, // KEY_STOP_RECORD + /* 626, 0x272 */ SDL_SCANCODE_UNKNOWN, // KEY_PAUSE_RECORD + /* 627, 0x273 */ SDL_SCANCODE_UNKNOWN, // KEY_VOD + /* 628, 0x274 */ SDL_SCANCODE_UNKNOWN, // KEY_UNMUTE + /* 629, 0x275 */ SDL_SCANCODE_UNKNOWN, // KEY_FASTREVERSE + /* 630, 0x276 */ SDL_SCANCODE_UNKNOWN, // KEY_SLOWREVERSE + /* 631, 0x277 */ SDL_SCANCODE_UNKNOWN, // KEY_DATA + /* 632, 0x278 */ SDL_SCANCODE_UNKNOWN, // KEY_ONSCREEN_KEYBOARD + /* 633, 0x279 */ SDL_SCANCODE_UNKNOWN, // KEY_PRIVACY_SCREEN_TOGGLE + /* 634, 0x27a */ SDL_SCANCODE_UNKNOWN, // KEY_SELECTIVE_SCREENSHOT /* 635, 0x27b */ SDL_SCANCODE_UNKNOWN, /* 636, 0x27c */ SDL_SCANCODE_UNKNOWN, /* 637, 0x27d */ SDL_SCANCODE_UNKNOWN, @@ -683,51 +683,51 @@ static SDL_Scancode const linux_scancode_table[] = { /* 653, 0x28d */ SDL_SCANCODE_UNKNOWN, /* 654, 0x28e */ SDL_SCANCODE_UNKNOWN, /* 655, 0x28f */ SDL_SCANCODE_UNKNOWN, - /* 656, 0x290 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO1 */ - /* 657, 0x291 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO2 */ - /* 658, 0x292 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO3 */ - /* 659, 0x293 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO4 */ - /* 660, 0x294 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO5 */ - /* 661, 0x295 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO6 */ - /* 662, 0x296 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO7 */ - /* 663, 0x297 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO8 */ - /* 664, 0x298 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO9 */ - /* 665, 0x299 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO10 */ - /* 666, 0x29a */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO11 */ - /* 667, 0x29b */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO12 */ - /* 668, 0x29c */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO13 */ - /* 669, 0x29d */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO14 */ - /* 670, 0x29e */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO15 */ - /* 671, 0x29f */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO16 */ - /* 672, 0x2a0 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO17 */ - /* 673, 0x2a1 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO18 */ - /* 674, 0x2a2 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO19 */ - /* 675, 0x2a3 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO20 */ - /* 676, 0x2a4 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO21 */ - /* 677, 0x2a5 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO22 */ - /* 678, 0x2a6 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO23 */ - /* 679, 0x2a7 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO24 */ - /* 680, 0x2a8 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO25 */ - /* 681, 0x2a9 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO26 */ - /* 682, 0x2aa */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO27 */ - /* 683, 0x2ab */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO28 */ - /* 684, 0x2ac */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO29 */ - /* 685, 0x2ad */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO30 */ + /* 656, 0x290 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO1 + /* 657, 0x291 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO2 + /* 658, 0x292 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO3 + /* 659, 0x293 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO4 + /* 660, 0x294 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO5 + /* 661, 0x295 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO6 + /* 662, 0x296 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO7 + /* 663, 0x297 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO8 + /* 664, 0x298 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO9 + /* 665, 0x299 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO10 + /* 666, 0x29a */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO11 + /* 667, 0x29b */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO12 + /* 668, 0x29c */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO13 + /* 669, 0x29d */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO14 + /* 670, 0x29e */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO15 + /* 671, 0x29f */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO16 + /* 672, 0x2a0 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO17 + /* 673, 0x2a1 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO18 + /* 674, 0x2a2 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO19 + /* 675, 0x2a3 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO20 + /* 676, 0x2a4 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO21 + /* 677, 0x2a5 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO22 + /* 678, 0x2a6 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO23 + /* 679, 0x2a7 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO24 + /* 680, 0x2a8 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO25 + /* 681, 0x2a9 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO26 + /* 682, 0x2aa */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO27 + /* 683, 0x2ab */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO28 + /* 684, 0x2ac */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO29 + /* 685, 0x2ad */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO30 /* 686, 0x2ae */ SDL_SCANCODE_UNKNOWN, /* 687, 0x2af */ SDL_SCANCODE_UNKNOWN, - /* 688, 0x2b0 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_RECORD_START */ - /* 689, 0x2b1 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_RECORD_STOP */ - /* 690, 0x2b2 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_PRESET_CYCLE */ - /* 691, 0x2b3 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_PRESET1 */ - /* 692, 0x2b4 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_PRESET2 */ - /* 693, 0x2b5 */ SDL_SCANCODE_UNKNOWN, /* KEY_MACRO_PRESET3 */ + /* 688, 0x2b0 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_RECORD_START + /* 689, 0x2b1 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_RECORD_STOP + /* 690, 0x2b2 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET_CYCLE + /* 691, 0x2b3 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET1 + /* 692, 0x2b4 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET2 + /* 693, 0x2b5 */ SDL_SCANCODE_UNKNOWN, // KEY_MACRO_PRESET3 /* 694, 0x2b6 */ SDL_SCANCODE_UNKNOWN, /* 695, 0x2b7 */ SDL_SCANCODE_UNKNOWN, - /* 696, 0x2b8 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LCD_MENU1 */ - /* 697, 0x2b9 */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LCD_MENU2 */ - /* 698, 0x2ba */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LCD_MENU3 */ - /* 699, 0x2bb */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LCD_MENU4 */ - /* 700, 0x2bc */ SDL_SCANCODE_UNKNOWN, /* KEY_KBD_LCD_MENU5 */ + /* 696, 0x2b8 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU1 + /* 697, 0x2b9 */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU2 + /* 698, 0x2ba */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU3 + /* 699, 0x2bb */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU4 + /* 700, 0x2bc */ SDL_SCANCODE_UNKNOWN, // KEY_KBD_LCD_MENU5 /* 701, 0x2bd */ SDL_SCANCODE_UNKNOWN, /* 702, 0x2be */ SDL_SCANCODE_UNKNOWN, /* 703, 0x2bf */ SDL_SCANCODE_UNKNOWN, @@ -794,11 +794,11 @@ static SDL_Scancode const linux_scancode_table[] = { /* 764, 0x2fc */ SDL_SCANCODE_UNKNOWN, /* 765, 0x2fd */ SDL_SCANCODE_UNKNOWN, /* 766, 0x2fe */ SDL_SCANCODE_UNKNOWN, - /* 767, 0x2ff */ SDL_SCANCODE_UNKNOWN, /* KEY_MAX */ -#endif /* 0 */ + /* 767, 0x2ff */ SDL_SCANCODE_UNKNOWN, // KEY_MAX +#endif // 0 }; -#if 0 /* A shell script to update the Linux key names in this file */ +#if 0 // A shell script to update the Linux key names in this file #!/bin/bash function get_keyname @@ -823,13 +823,13 @@ grep -F SDL_SCANCODE scancodes_linux.h | while read line; do fi echo " $line" done -#endif /* end script */ +#endif // end script -#if 0 /* A shell script to get comments from the Linux header for these keys */ +#if 0 // A shell script to get comments from the Linux header for these keys #!/bin/bash function get_comment -{ +{ name=$(echo "$1" | awk '{print $7}') if [ "$name" != "" ]; then grep -E "$name\s" /usr/include/linux/input-event-codes.h | grep -F "/*" | sed 's,[^/]*/,/,' @@ -842,7 +842,7 @@ grep -F SDL_SCANCODE scancodes_linux.h | while read line; do echo " $line $comment" fi done -#endif /* end script */ +#endif // end script -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on diff --git a/libs/SDL3/src/events/scancodes_windows.h b/libs/SDL3/src/events/scancodes_windows.h index 75635e6d7..3d00d9dc5 100644 --- a/libs/SDL3/src/events/scancodes_windows.h +++ b/libs/SDL3/src/events/scancodes_windows.h @@ -24,7 +24,7 @@ * Windows scancode to SDL scancode mapping table * https://learn.microsoft.com/windows/win32/inputdev/about-keyboard-input#scan-codes */ -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static const SDL_Scancode windows_scancode_table[] = { /*0x00*/ SDL_SCANCODE_UNKNOWN, /*0x01*/ SDL_SCANCODE_ESCAPE, @@ -164,22 +164,22 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe007*/ SDL_SCANCODE_UNKNOWN, /*0xe008*/ SDL_SCANCODE_UNKNOWN, /*0xe009*/ SDL_SCANCODE_UNKNOWN, - /*0xe00a*/ SDL_SCANCODE_UNKNOWN, + /*0xe00a*/ SDL_SCANCODE_PASTE, /*0xe00b*/ SDL_SCANCODE_UNKNOWN, /*0xe00c*/ SDL_SCANCODE_UNKNOWN, /*0xe00d*/ SDL_SCANCODE_UNKNOWN, /*0xe00e*/ SDL_SCANCODE_UNKNOWN, /*0xe00f*/ SDL_SCANCODE_UNKNOWN, - /*0xe010*/ SDL_SCANCODE_AUDIOPREV, + /*0xe010*/ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, /*0xe011*/ SDL_SCANCODE_UNKNOWN, /*0xe012*/ SDL_SCANCODE_UNKNOWN, /*0xe013*/ SDL_SCANCODE_UNKNOWN, /*0xe014*/ SDL_SCANCODE_UNKNOWN, /*0xe015*/ SDL_SCANCODE_UNKNOWN, /*0xe016*/ SDL_SCANCODE_UNKNOWN, - /*0xe017*/ SDL_SCANCODE_UNKNOWN, - /*0xe018*/ SDL_SCANCODE_UNKNOWN, - /*0xe019*/ SDL_SCANCODE_AUDIONEXT, + /*0xe017*/ SDL_SCANCODE_CUT, + /*0xe018*/ SDL_SCANCODE_COPY, + /*0xe019*/ SDL_SCANCODE_MEDIA_NEXT_TRACK, /*0xe01a*/ SDL_SCANCODE_UNKNOWN, /*0xe01b*/ SDL_SCANCODE_UNKNOWN, /*0xe01c*/ SDL_SCANCODE_KP_ENTER, @@ -187,10 +187,10 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe01e*/ SDL_SCANCODE_UNKNOWN, /*0xe01f*/ SDL_SCANCODE_UNKNOWN, /*0xe020*/ SDL_SCANCODE_MUTE, - /*0xe021*/ SDL_SCANCODE_CALCULATOR, - /*0xe022*/ SDL_SCANCODE_AUDIOPLAY, + /*0xe021*/ SDL_SCANCODE_UNKNOWN, // LaunchApp2 + /*0xe022*/ SDL_SCANCODE_MEDIA_PLAY_PAUSE, /*0xe023*/ SDL_SCANCODE_UNKNOWN, - /*0xe024*/ SDL_SCANCODE_AUDIOSTOP, + /*0xe024*/ SDL_SCANCODE_MEDIA_STOP, /*0xe025*/ SDL_SCANCODE_UNKNOWN, /*0xe026*/ SDL_SCANCODE_UNKNOWN, /*0xe027*/ SDL_SCANCODE_UNKNOWN, @@ -198,7 +198,7 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe029*/ SDL_SCANCODE_UNKNOWN, /*0xe02a*/ SDL_SCANCODE_UNKNOWN, /*0xe02b*/ SDL_SCANCODE_UNKNOWN, - /*0xe02c*/ SDL_SCANCODE_UNKNOWN, + /*0xe02c*/ SDL_SCANCODE_MEDIA_EJECT, /*0xe02d*/ SDL_SCANCODE_UNKNOWN, /*0xe02e*/ SDL_SCANCODE_VOLUMEDOWN, /*0xe02f*/ SDL_SCANCODE_UNKNOWN, @@ -213,7 +213,7 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe038*/ SDL_SCANCODE_RALT, /*0xe039*/ SDL_SCANCODE_UNKNOWN, /*0xe03a*/ SDL_SCANCODE_UNKNOWN, - /*0xe03b*/ SDL_SCANCODE_UNKNOWN, + /*0xe03b*/ SDL_SCANCODE_HELP, /*0xe03c*/ SDL_SCANCODE_UNKNOWN, /*0xe03d*/ SDL_SCANCODE_UNKNOWN, /*0xe03e*/ SDL_SCANCODE_UNKNOWN, @@ -261,9 +261,9 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe068*/ SDL_SCANCODE_AC_STOP, /*0xe069*/ SDL_SCANCODE_AC_FORWARD, /*0xe06a*/ SDL_SCANCODE_AC_BACK, - /*0xe06b*/ SDL_SCANCODE_COMPUTER, - /*0xe06c*/ SDL_SCANCODE_MAIL, - /*0xe06d*/ SDL_SCANCODE_MEDIASELECT, + /*0xe06b*/ SDL_SCANCODE_UNKNOWN, // LaunchApp1 + /*0xe06c*/ SDL_SCANCODE_UNKNOWN, // LaunchMail + /*0xe06d*/ SDL_SCANCODE_MEDIA_SELECT, /*0xe06e*/ SDL_SCANCODE_UNKNOWN, /*0xe06f*/ SDL_SCANCODE_UNKNOWN, /*0xe070*/ SDL_SCANCODE_UNKNOWN, @@ -283,4 +283,4 @@ static const SDL_Scancode windows_scancode_table[] = { /*0xe07e*/ SDL_SCANCODE_UNKNOWN, /*0xe07f*/ SDL_SCANCODE_UNKNOWN }; -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on diff --git a/libs/SDL3/src/events/scancodes_xfree86.h b/libs/SDL3/src/events/scancodes_xfree86.h index f3001d832..beefffbd1 100644 --- a/libs/SDL3/src/events/scancodes_xfree86.h +++ b/libs/SDL3/src/events/scancodes_xfree86.h @@ -27,7 +27,7 @@ Sources: - atKeyNames.h from XFree86 source code */ -/* *INDENT-OFF* */ /* clang-format off */ +/* *INDENT-OFF* */ // clang-format off static const SDL_Scancode xfree86_scancode_table[] = { /* 0 */ SDL_SCANCODE_UNKNOWN, /* 1 */ SDL_SCANCODE_ESCAPE, @@ -122,7 +122,7 @@ static const SDL_Scancode xfree86_scancode_table[] = { /* 90 */ SDL_SCANCODE_UP, /* 91 */ SDL_SCANCODE_PAGEUP, /* 92 */ SDL_SCANCODE_LEFT, - /* 93 */ SDL_SCANCODE_BRIGHTNESSDOWN, /* on PowerBook G4 / KEY_Begin */ + /* 93 */ SDL_SCANCODE_UNKNOWN, // on PowerBook G4 / KEY_Begin /* 94 */ SDL_SCANCODE_RIGHT, /* 95 */ SDL_SCANCODE_END, /* 96 */ SDL_SCANCODE_DOWN, @@ -135,7 +135,7 @@ static const SDL_Scancode xfree86_scancode_table[] = { /* 103 */ SDL_SCANCODE_PRINTSCREEN, /* 104 */ SDL_SCANCODE_KP_DIVIDE, /* 105 */ SDL_SCANCODE_RALT, - /* 106 */ SDL_SCANCODE_UNKNOWN, /* BREAK */ + /* 106 */ SDL_SCANCODE_UNKNOWN, // BREAK /* 107 */ SDL_SCANCODE_LGUI, /* 108 */ SDL_SCANCODE_RGUI, /* 109 */ SDL_SCANCODE_APPLICATION, @@ -144,17 +144,17 @@ static const SDL_Scancode xfree86_scancode_table[] = { /* 112 */ SDL_SCANCODE_F15, /* 113 */ SDL_SCANCODE_F16, /* 114 */ SDL_SCANCODE_F17, - /* 115 */ SDL_SCANCODE_INTERNATIONAL1, /* \_ */ + /* 115 */ SDL_SCANCODE_INTERNATIONAL1, // \_ /* 116 */ SDL_SCANCODE_UNKNOWN, /* is translated to XK_ISO_Level3_Shift by my X server, but I have no keyboard that generates this code, so I don't know what the correct SDL_SCANCODE_* for it is */ /* 117 */ SDL_SCANCODE_UNKNOWN, /* 118 */ SDL_SCANCODE_KP_EQUALS, /* 119 */ SDL_SCANCODE_UNKNOWN, /* 120 */ SDL_SCANCODE_UNKNOWN, - /* 121 */ SDL_SCANCODE_INTERNATIONAL4, /* Henkan_Mode */ + /* 121 */ SDL_SCANCODE_INTERNATIONAL4, // Henkan_Mode /* 122 */ SDL_SCANCODE_UNKNOWN, - /* 123 */ SDL_SCANCODE_INTERNATIONAL5, /* Muhenkan */ + /* 123 */ SDL_SCANCODE_INTERNATIONAL5, // Muhenkan /* 124 */ SDL_SCANCODE_UNKNOWN, - /* 125 */ SDL_SCANCODE_INTERNATIONAL3, /* Yen */ + /* 125 */ SDL_SCANCODE_INTERNATIONAL3, // Yen /* 126 */ SDL_SCANCODE_UNKNOWN, /* 127 */ SDL_SCANCODE_UNKNOWN, /* 128 */ SDL_SCANCODE_UNKNOWN, @@ -168,276 +168,276 @@ static const SDL_Scancode xfree86_scancode_table[] = { /* 136 */ SDL_SCANCODE_HELP, /* 137 */ SDL_SCANCODE_STOP, /* 138 */ SDL_SCANCODE_AGAIN, - /* 139 */ SDL_SCANCODE_UNKNOWN, /* PROPS */ + /* 139 */ SDL_SCANCODE_UNKNOWN, // PROPS /* 140 */ SDL_SCANCODE_UNDO, - /* 141 */ SDL_SCANCODE_UNKNOWN, /* FRONT */ + /* 141 */ SDL_SCANCODE_UNKNOWN, // FRONT /* 142 */ SDL_SCANCODE_COPY, - /* 143 */ SDL_SCANCODE_UNKNOWN, /* OPEN */ + /* 143 */ SDL_SCANCODE_UNKNOWN, // OPEN /* 144 */ SDL_SCANCODE_PASTE, /* 145 */ SDL_SCANCODE_FIND, /* 146 */ SDL_SCANCODE_CUT, }; -/* This is largely identical to the Linux keycode mapping */ +// This is largely identical to the Linux keycode mapping static const SDL_Scancode xfree86_scancode_table2[] = { - /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, /* Escape */ - /* 2, 0x002 */ SDL_SCANCODE_1, /* 1 */ - /* 3, 0x003 */ SDL_SCANCODE_2, /* 2 */ - /* 4, 0x004 */ SDL_SCANCODE_3, /* 3 */ - /* 5, 0x005 */ SDL_SCANCODE_4, /* 4 */ - /* 6, 0x006 */ SDL_SCANCODE_5, /* 5 */ - /* 7, 0x007 */ SDL_SCANCODE_6, /* 6 */ - /* 8, 0x008 */ SDL_SCANCODE_7, /* 7 */ - /* 9, 0x009 */ SDL_SCANCODE_8, /* 8 */ - /* 10, 0x00a */ SDL_SCANCODE_9, /* 9 */ - /* 11, 0x00b */ SDL_SCANCODE_0, /* 0 */ - /* 12, 0x00c */ SDL_SCANCODE_MINUS, /* minus */ - /* 13, 0x00d */ SDL_SCANCODE_EQUALS, /* equal */ - /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, /* BackSpace */ - /* 15, 0x00f */ SDL_SCANCODE_TAB, /* Tab */ - /* 16, 0x010 */ SDL_SCANCODE_Q, /* q */ - /* 17, 0x011 */ SDL_SCANCODE_W, /* w */ - /* 18, 0x012 */ SDL_SCANCODE_E, /* e */ - /* 19, 0x013 */ SDL_SCANCODE_R, /* r */ - /* 20, 0x014 */ SDL_SCANCODE_T, /* t */ - /* 21, 0x015 */ SDL_SCANCODE_Y, /* y */ - /* 22, 0x016 */ SDL_SCANCODE_U, /* u */ - /* 23, 0x017 */ SDL_SCANCODE_I, /* i */ - /* 24, 0x018 */ SDL_SCANCODE_O, /* o */ - /* 25, 0x019 */ SDL_SCANCODE_P, /* p */ - /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, /* bracketleft */ - /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, /* bracketright */ - /* 28, 0x01c */ SDL_SCANCODE_RETURN, /* Return */ - /* 29, 0x01d */ SDL_SCANCODE_LCTRL, /* Control_L */ - /* 30, 0x01e */ SDL_SCANCODE_A, /* a */ - /* 31, 0x01f */ SDL_SCANCODE_S, /* s */ - /* 32, 0x020 */ SDL_SCANCODE_D, /* d */ - /* 33, 0x021 */ SDL_SCANCODE_F, /* f */ - /* 34, 0x022 */ SDL_SCANCODE_G, /* g */ - /* 35, 0x023 */ SDL_SCANCODE_H, /* h */ - /* 36, 0x024 */ SDL_SCANCODE_J, /* j */ - /* 37, 0x025 */ SDL_SCANCODE_K, /* k */ - /* 38, 0x026 */ SDL_SCANCODE_L, /* l */ - /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, /* semicolon */ - /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, /* apostrophe */ - /* 41, 0x029 */ SDL_SCANCODE_GRAVE, /* grave */ - /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, /* Shift_L */ - /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, /* backslash */ - /* 44, 0x02c */ SDL_SCANCODE_Z, /* z */ - /* 45, 0x02d */ SDL_SCANCODE_X, /* x */ - /* 46, 0x02e */ SDL_SCANCODE_C, /* c */ - /* 47, 0x02f */ SDL_SCANCODE_V, /* v */ - /* 48, 0x030 */ SDL_SCANCODE_B, /* b */ - /* 49, 0x031 */ SDL_SCANCODE_N, /* n */ - /* 50, 0x032 */ SDL_SCANCODE_M, /* m */ - /* 51, 0x033 */ SDL_SCANCODE_COMMA, /* comma */ - /* 52, 0x034 */ SDL_SCANCODE_PERIOD, /* period */ - /* 53, 0x035 */ SDL_SCANCODE_SLASH, /* slash */ - /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, /* Shift_R */ - /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, /* KP_Multiply */ - /* 56, 0x038 */ SDL_SCANCODE_LALT, /* Alt_L */ - /* 57, 0x039 */ SDL_SCANCODE_SPACE, /* space */ - /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, /* Caps_Lock */ - /* 59, 0x03b */ SDL_SCANCODE_F1, /* F1 */ - /* 60, 0x03c */ SDL_SCANCODE_F2, /* F2 */ - /* 61, 0x03d */ SDL_SCANCODE_F3, /* F3 */ - /* 62, 0x03e */ SDL_SCANCODE_F4, /* F4 */ - /* 63, 0x03f */ SDL_SCANCODE_F5, /* F5 */ - /* 64, 0x040 */ SDL_SCANCODE_F6, /* F6 */ - /* 65, 0x041 */ SDL_SCANCODE_F7, /* F7 */ - /* 66, 0x042 */ SDL_SCANCODE_F8, /* F8 */ - /* 67, 0x043 */ SDL_SCANCODE_F9, /* F9 */ - /* 68, 0x044 */ SDL_SCANCODE_F10, /* F10 */ - /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, /* Num_Lock */ - /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, /* Scroll_Lock */ - /* 71, 0x047 */ SDL_SCANCODE_KP_7, /* KP_Home */ - /* 72, 0x048 */ SDL_SCANCODE_KP_8, /* KP_Up */ - /* 73, 0x049 */ SDL_SCANCODE_KP_9, /* KP_Prior */ - /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, /* KP_Subtract */ - /* 75, 0x04b */ SDL_SCANCODE_KP_4, /* KP_Left */ - /* 76, 0x04c */ SDL_SCANCODE_KP_5, /* KP_Begin */ - /* 77, 0x04d */ SDL_SCANCODE_KP_6, /* KP_Right */ - /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, /* KP_Add */ - /* 79, 0x04f */ SDL_SCANCODE_KP_1, /* KP_End */ - /* 80, 0x050 */ SDL_SCANCODE_KP_2, /* KP_Down */ - /* 81, 0x051 */ SDL_SCANCODE_KP_3, /* KP_Next */ - /* 82, 0x052 */ SDL_SCANCODE_KP_0, /* KP_Insert */ - /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, /* KP_Delete */ - /* 84, 0x054 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift */ - /* 85, 0x055 */ SDL_SCANCODE_MODE, /* ???? */ - /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, /* less */ - /* 87, 0x057 */ SDL_SCANCODE_F11, /* F11 */ - /* 88, 0x058 */ SDL_SCANCODE_F12, /* F12 */ - /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, /* \_ */ - /* 90, 0x05a */ SDL_SCANCODE_LANG3, /* Katakana */ - /* 91, 0x05b */ SDL_SCANCODE_LANG4, /* Hiragana */ - /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, /* Henkan_Mode */ - /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, /* Hiragana_Katakana */ - /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, /* Muhenkan */ - /* 95, 0x05f */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, /* KP_Enter */ - /* 97, 0x061 */ SDL_SCANCODE_RCTRL, /* Control_R */ - /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, /* KP_Divide */ - /* 99, 0x063 */ SDL_SCANCODE_PRINTSCREEN, /* Print */ - /* 100, 0x064 */ SDL_SCANCODE_RALT, /* ISO_Level3_Shift, ALTGR, RALT */ - /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, /* Linefeed */ - /* 102, 0x066 */ SDL_SCANCODE_HOME, /* Home */ - /* 103, 0x067 */ SDL_SCANCODE_UP, /* Up */ - /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, /* Prior */ - /* 105, 0x069 */ SDL_SCANCODE_LEFT, /* Left */ - /* 106, 0x06a */ SDL_SCANCODE_RIGHT, /* Right */ - /* 107, 0x06b */ SDL_SCANCODE_END, /* End */ - /* 108, 0x06c */ SDL_SCANCODE_DOWN, /* Down */ - /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, /* Next */ - /* 110, 0x06e */ SDL_SCANCODE_INSERT, /* Insert */ - /* 111, 0x06f */ SDL_SCANCODE_DELETE, /* Delete */ - /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 113, 0x071 */ SDL_SCANCODE_MUTE, /* XF86AudioMute */ - /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, /* XF86AudioLowerVolume */ - /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, /* XF86AudioRaiseVolume */ - /* 116, 0x074 */ SDL_SCANCODE_POWER, /* XF86PowerOff */ - /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, /* KP_Equal */ - /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, /* plusminus */ - /* 119, 0x077 */ SDL_SCANCODE_PAUSE, /* Pause */ - /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchA */ - /* 121, 0x079 */ SDL_SCANCODE_KP_PERIOD, /* KP_Decimal */ - /* 122, 0x07a */ SDL_SCANCODE_LANG1, /* Hangul */ - /* 123, 0x07b */ SDL_SCANCODE_LANG2, /* Hangul_Hanja */ - /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, /* Yen */ - /* 125, 0x07d */ SDL_SCANCODE_LGUI, /* Super_L */ - /* 126, 0x07e */ SDL_SCANCODE_RGUI, /* Super_R */ - /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, /* Menu */ - /* 128, 0x080 */ SDL_SCANCODE_CANCEL, /* Cancel */ - /* 129, 0x081 */ SDL_SCANCODE_AGAIN, /* Redo */ - /* 130, 0x082 */ SDL_SCANCODE_UNKNOWN, /* SunProps */ - /* 131, 0x083 */ SDL_SCANCODE_UNDO, /* Undo */ - /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, /* SunFront */ - /* 133, 0x085 */ SDL_SCANCODE_COPY, /* XF86Copy */ - /* 134, 0x086 */ SDL_SCANCODE_UNKNOWN, /* SunOpen, XF86Open */ - /* 135, 0x087 */ SDL_SCANCODE_PASTE, /* XF86Paste */ - /* 136, 0x088 */ SDL_SCANCODE_FIND, /* Find */ - /* 137, 0x089 */ SDL_SCANCODE_CUT, /* XF86Cut */ - /* 138, 0x08a */ SDL_SCANCODE_HELP, /* Help */ - /* 139, 0x08b */ SDL_SCANCODE_MENU, /* XF86MenuKB */ - /* 140, 0x08c */ SDL_SCANCODE_CALCULATOR, /* XF86Calculator */ - /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 142, 0x08e */ SDL_SCANCODE_SLEEP, /* XF86Sleep */ - /* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, /* XF86WakeUp */ - /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, /* XF86Explorer */ - /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */ - /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, /* XF86Xfer */ - /* 148, 0x094 */ SDL_SCANCODE_APP1, /* XF86Launch1 */ - /* 149, 0x095 */ SDL_SCANCODE_APP2, /* XF86Launch2 */ - /* 150, 0x096 */ SDL_SCANCODE_WWW, /* XF86WWW */ - /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, /* XF86DOS */ - /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, /* XF86ScreenSaver */ - /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, /* XF86RotateWindows */ - /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, /* XF86TaskPane */ - /* 155, 0x09b */ SDL_SCANCODE_MAIL, /* XF86Mail */ - /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, /* XF86Favorites */ - /* 157, 0x09d */ SDL_SCANCODE_COMPUTER, /* XF86MyComputer */ - /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, /* XF86Back */ - /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, /* XF86Forward */ - /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 161, 0x0a1 */ SDL_SCANCODE_EJECT, /* XF86Eject */ - /* 162, 0x0a2 */ SDL_SCANCODE_EJECT, /* XF86Eject */ - /* 163, 0x0a3 */ SDL_SCANCODE_AUDIONEXT, /* XF86AudioNext */ - /* 164, 0x0a4 */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */ - /* 165, 0x0a5 */ SDL_SCANCODE_AUDIOPREV, /* XF86AudioPrev */ - /* 166, 0x0a6 */ SDL_SCANCODE_AUDIOSTOP, /* XF86AudioStop */ - /* 167, 0x0a7 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioRecord */ - /* 168, 0x0a8 */ SDL_SCANCODE_AUDIOREWIND, /* XF86AudioRewind */ - /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, /* XF86Phone */ - /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 171, 0x0ab */ SDL_SCANCODE_F13, /* XF86Tools */ - /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, /* XF86HomePage */ - /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, /* XF86Reload */ - /* 174, 0x0ae */ SDL_SCANCODE_UNKNOWN, /* XF86Close */ - /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollUp */ - /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, /* XF86ScrollDown */ - /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, /* parenleft */ - /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, /* parenright */ - /* 181, 0x0b5 */ SDL_SCANCODE_UNKNOWN, /* XF86New */ - /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, /* Redo */ - /* 183, 0x0b7 */ SDL_SCANCODE_F13, /* XF86Tools */ - /* 184, 0x0b8 */ SDL_SCANCODE_F14, /* XF86Launch5 */ - /* 185, 0x0b9 */ SDL_SCANCODE_F15, /* XF86Launch6 */ - /* 186, 0x0ba */ SDL_SCANCODE_F16, /* XF86Launch7 */ - /* 187, 0x0bb */ SDL_SCANCODE_F17, /* XF86Launch8 */ - /* 188, 0x0bc */ SDL_SCANCODE_F18, /* XF86Launch9 */ - /* 189, 0x0bd */ SDL_SCANCODE_F19, /* NoSymbol */ - /* 190, 0x0be */ SDL_SCANCODE_F20, /* XF86AudioMicMute */ - /* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadToggle */ - /* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadOn */ - /* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, /* XF86TouchpadOff */ - /* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 195, 0x0c3 */ SDL_SCANCODE_MODE, /* Mode_switch */ - /* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 200, 0x0c8 */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */ - /* 201, 0x0c9 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPause */ - /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, /* XF86Launch3 */ - /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, /* XF86Launch4 */ - /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, /* XF86LaunchB */ - /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, /* XF86Suspend */ - /* 206, 0x0ce */ SDL_SCANCODE_UNKNOWN, /* XF86Close */ - /* 207, 0x0cf */ SDL_SCANCODE_AUDIOPLAY, /* XF86AudioPlay */ - /* 208, 0x0d0 */ SDL_SCANCODE_AUDIOFASTFORWARD, /* XF86AudioForward */ - /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, /* Print */ - /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, /* XF86WebCam */ - /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, /* XF86AudioPreset */ - /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 215, 0x0d7 */ SDL_SCANCODE_MAIL, /* XF86Mail */ - /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, /* XF86Messenger */ - /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, /* XF86Search */ - /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, /* XF86Go */ - /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, /* XF86Finance */ - /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, /* XF86Game */ - /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, /* XF86Shop */ - /* 222, 0x0de */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 223, 0x0df */ SDL_SCANCODE_CANCEL, /* Cancel */ - /* 224, 0x0e0 */ SDL_SCANCODE_BRIGHTNESSDOWN, /* XF86MonBrightnessDown */ - /* 225, 0x0e1 */ SDL_SCANCODE_BRIGHTNESSUP, /* XF86MonBrightnessUp */ - /* 226, 0x0e2 */ SDL_SCANCODE_MEDIASELECT, /* XF86AudioMedia */ - /* 227, 0x0e3 */ SDL_SCANCODE_DISPLAYSWITCH, /* XF86Display */ - /* 228, 0x0e4 */ SDL_SCANCODE_KBDILLUMTOGGLE, /* XF86KbdLightOnOff */ - /* 229, 0x0e5 */ SDL_SCANCODE_KBDILLUMDOWN, /* XF86KbdBrightnessDown */ - /* 230, 0x0e6 */ SDL_SCANCODE_KBDILLUMUP, /* XF86KbdBrightnessUp */ - /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, /* XF86Send */ - /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, /* XF86Reply */ - /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, /* XF86MailForward */ - /* 234, 0x0ea */ SDL_SCANCODE_UNKNOWN, /* XF86Save */ - /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, /* XF86Documents */ - /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, /* XF86Battery */ - /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, /* XF86Bluetooth */ - /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, /* XF86WLAN */ - /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, /* XF86UWB */ - /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, /* NoSymbol */ - /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, /* XF86Next_VMode */ - /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, /* XF86Prev_VMode */ - /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, /* XF86MonBrightnessCycle */ - /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, /* XF86BrightnessAuto */ - /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, /* XF86DisplayOff */ - /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, /* XF86WWAN */ - /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, /* XF86RFKill */ + /* 0, 0x000 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 1, 0x001 */ SDL_SCANCODE_ESCAPE, // Escape + /* 2, 0x002 */ SDL_SCANCODE_1, // 1 + /* 3, 0x003 */ SDL_SCANCODE_2, // 2 + /* 4, 0x004 */ SDL_SCANCODE_3, // 3 + /* 5, 0x005 */ SDL_SCANCODE_4, // 4 + /* 6, 0x006 */ SDL_SCANCODE_5, // 5 + /* 7, 0x007 */ SDL_SCANCODE_6, // 6 + /* 8, 0x008 */ SDL_SCANCODE_7, // 7 + /* 9, 0x009 */ SDL_SCANCODE_8, // 8 + /* 10, 0x00a */ SDL_SCANCODE_9, // 9 + /* 11, 0x00b */ SDL_SCANCODE_0, // 0 + /* 12, 0x00c */ SDL_SCANCODE_MINUS, // minus + /* 13, 0x00d */ SDL_SCANCODE_EQUALS, // equal + /* 14, 0x00e */ SDL_SCANCODE_BACKSPACE, // BackSpace + /* 15, 0x00f */ SDL_SCANCODE_TAB, // Tab + /* 16, 0x010 */ SDL_SCANCODE_Q, // q + /* 17, 0x011 */ SDL_SCANCODE_W, // w + /* 18, 0x012 */ SDL_SCANCODE_E, // e + /* 19, 0x013 */ SDL_SCANCODE_R, // r + /* 20, 0x014 */ SDL_SCANCODE_T, // t + /* 21, 0x015 */ SDL_SCANCODE_Y, // y + /* 22, 0x016 */ SDL_SCANCODE_U, // u + /* 23, 0x017 */ SDL_SCANCODE_I, // i + /* 24, 0x018 */ SDL_SCANCODE_O, // o + /* 25, 0x019 */ SDL_SCANCODE_P, // p + /* 26, 0x01a */ SDL_SCANCODE_LEFTBRACKET, // bracketleft + /* 27, 0x01b */ SDL_SCANCODE_RIGHTBRACKET, // bracketright + /* 28, 0x01c */ SDL_SCANCODE_RETURN, // Return + /* 29, 0x01d */ SDL_SCANCODE_LCTRL, // Control_L + /* 30, 0x01e */ SDL_SCANCODE_A, // a + /* 31, 0x01f */ SDL_SCANCODE_S, // s + /* 32, 0x020 */ SDL_SCANCODE_D, // d + /* 33, 0x021 */ SDL_SCANCODE_F, // f + /* 34, 0x022 */ SDL_SCANCODE_G, // g + /* 35, 0x023 */ SDL_SCANCODE_H, // h + /* 36, 0x024 */ SDL_SCANCODE_J, // j + /* 37, 0x025 */ SDL_SCANCODE_K, // k + /* 38, 0x026 */ SDL_SCANCODE_L, // l + /* 39, 0x027 */ SDL_SCANCODE_SEMICOLON, // semicolon + /* 40, 0x028 */ SDL_SCANCODE_APOSTROPHE, // apostrophe + /* 41, 0x029 */ SDL_SCANCODE_GRAVE, // grave + /* 42, 0x02a */ SDL_SCANCODE_LSHIFT, // Shift_L + /* 43, 0x02b */ SDL_SCANCODE_BACKSLASH, // backslash + /* 44, 0x02c */ SDL_SCANCODE_Z, // z + /* 45, 0x02d */ SDL_SCANCODE_X, // x + /* 46, 0x02e */ SDL_SCANCODE_C, // c + /* 47, 0x02f */ SDL_SCANCODE_V, // v + /* 48, 0x030 */ SDL_SCANCODE_B, // b + /* 49, 0x031 */ SDL_SCANCODE_N, // n + /* 50, 0x032 */ SDL_SCANCODE_M, // m + /* 51, 0x033 */ SDL_SCANCODE_COMMA, // comma + /* 52, 0x034 */ SDL_SCANCODE_PERIOD, // period + /* 53, 0x035 */ SDL_SCANCODE_SLASH, // slash + /* 54, 0x036 */ SDL_SCANCODE_RSHIFT, // Shift_R + /* 55, 0x037 */ SDL_SCANCODE_KP_MULTIPLY, // KP_Multiply + /* 56, 0x038 */ SDL_SCANCODE_LALT, // Alt_L + /* 57, 0x039 */ SDL_SCANCODE_SPACE, // space + /* 58, 0x03a */ SDL_SCANCODE_CAPSLOCK, // Caps_Lock + /* 59, 0x03b */ SDL_SCANCODE_F1, // F1 + /* 60, 0x03c */ SDL_SCANCODE_F2, // F2 + /* 61, 0x03d */ SDL_SCANCODE_F3, // F3 + /* 62, 0x03e */ SDL_SCANCODE_F4, // F4 + /* 63, 0x03f */ SDL_SCANCODE_F5, // F5 + /* 64, 0x040 */ SDL_SCANCODE_F6, // F6 + /* 65, 0x041 */ SDL_SCANCODE_F7, // F7 + /* 66, 0x042 */ SDL_SCANCODE_F8, // F8 + /* 67, 0x043 */ SDL_SCANCODE_F9, // F9 + /* 68, 0x044 */ SDL_SCANCODE_F10, // F10 + /* 69, 0x045 */ SDL_SCANCODE_NUMLOCKCLEAR, // Num_Lock + /* 70, 0x046 */ SDL_SCANCODE_SCROLLLOCK, // Scroll_Lock + /* 71, 0x047 */ SDL_SCANCODE_KP_7, // KP_Home + /* 72, 0x048 */ SDL_SCANCODE_KP_8, // KP_Up + /* 73, 0x049 */ SDL_SCANCODE_KP_9, // KP_Prior + /* 74, 0x04a */ SDL_SCANCODE_KP_MINUS, // KP_Subtract + /* 75, 0x04b */ SDL_SCANCODE_KP_4, // KP_Left + /* 76, 0x04c */ SDL_SCANCODE_KP_5, // KP_Begin + /* 77, 0x04d */ SDL_SCANCODE_KP_6, // KP_Right + /* 78, 0x04e */ SDL_SCANCODE_KP_PLUS, // KP_Add + /* 79, 0x04f */ SDL_SCANCODE_KP_1, // KP_End + /* 80, 0x050 */ SDL_SCANCODE_KP_2, // KP_Down + /* 81, 0x051 */ SDL_SCANCODE_KP_3, // KP_Next + /* 82, 0x052 */ SDL_SCANCODE_KP_0, // KP_Insert + /* 83, 0x053 */ SDL_SCANCODE_KP_PERIOD, // KP_Delete + /* 84, 0x054 */ SDL_SCANCODE_RALT, // ISO_Level3_Shift + /* 85, 0x055 */ SDL_SCANCODE_MODE, // ???? + /* 86, 0x056 */ SDL_SCANCODE_NONUSBACKSLASH, // less + /* 87, 0x057 */ SDL_SCANCODE_F11, // F11 + /* 88, 0x058 */ SDL_SCANCODE_F12, // F12 + /* 89, 0x059 */ SDL_SCANCODE_INTERNATIONAL1, // \_ + /* 90, 0x05a */ SDL_SCANCODE_LANG3, // Katakana + /* 91, 0x05b */ SDL_SCANCODE_LANG4, // Hiragana + /* 92, 0x05c */ SDL_SCANCODE_INTERNATIONAL4, // Henkan_Mode + /* 93, 0x05d */ SDL_SCANCODE_INTERNATIONAL2, // Hiragana_Katakana + /* 94, 0x05e */ SDL_SCANCODE_INTERNATIONAL5, // Muhenkan + /* 95, 0x05f */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 96, 0x060 */ SDL_SCANCODE_KP_ENTER, // KP_Enter + /* 97, 0x061 */ SDL_SCANCODE_RCTRL, // Control_R + /* 98, 0x062 */ SDL_SCANCODE_KP_DIVIDE, // KP_Divide + /* 99, 0x063 */ SDL_SCANCODE_PRINTSCREEN, // Print + /* 100, 0x064 */ SDL_SCANCODE_RALT, // ISO_Level3_Shift, ALTGR, RALT + /* 101, 0x065 */ SDL_SCANCODE_UNKNOWN, // Linefeed + /* 102, 0x066 */ SDL_SCANCODE_HOME, // Home + /* 103, 0x067 */ SDL_SCANCODE_UP, // Up + /* 104, 0x068 */ SDL_SCANCODE_PAGEUP, // Prior + /* 105, 0x069 */ SDL_SCANCODE_LEFT, // Left + /* 106, 0x06a */ SDL_SCANCODE_RIGHT, // Right + /* 107, 0x06b */ SDL_SCANCODE_END, // End + /* 108, 0x06c */ SDL_SCANCODE_DOWN, // Down + /* 109, 0x06d */ SDL_SCANCODE_PAGEDOWN, // Next + /* 110, 0x06e */ SDL_SCANCODE_INSERT, // Insert + /* 111, 0x06f */ SDL_SCANCODE_DELETE, // Delete + /* 112, 0x070 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 113, 0x071 */ SDL_SCANCODE_MUTE, // XF86AudioMute + /* 114, 0x072 */ SDL_SCANCODE_VOLUMEDOWN, // XF86AudioLowerVolume + /* 115, 0x073 */ SDL_SCANCODE_VOLUMEUP, // XF86AudioRaiseVolume + /* 116, 0x074 */ SDL_SCANCODE_POWER, // XF86PowerOff + /* 117, 0x075 */ SDL_SCANCODE_KP_EQUALS, // KP_Equal + /* 118, 0x076 */ SDL_SCANCODE_KP_PLUSMINUS, // plusminus + /* 119, 0x077 */ SDL_SCANCODE_PAUSE, // Pause + /* 120, 0x078 */ SDL_SCANCODE_UNKNOWN, // XF86LaunchA + /* 121, 0x079 */ SDL_SCANCODE_KP_PERIOD, // KP_Decimal + /* 122, 0x07a */ SDL_SCANCODE_LANG1, // Hangul + /* 123, 0x07b */ SDL_SCANCODE_LANG2, // Hangul_Hanja + /* 124, 0x07c */ SDL_SCANCODE_INTERNATIONAL3, // Yen + /* 125, 0x07d */ SDL_SCANCODE_LGUI, // Super_L + /* 126, 0x07e */ SDL_SCANCODE_RGUI, // Super_R + /* 127, 0x07f */ SDL_SCANCODE_APPLICATION, // Menu + /* 128, 0x080 */ SDL_SCANCODE_CANCEL, // Cancel + /* 129, 0x081 */ SDL_SCANCODE_AGAIN, // Redo + /* 130, 0x082 */ SDL_SCANCODE_UNKNOWN, // SunProps + /* 131, 0x083 */ SDL_SCANCODE_UNDO, // Undo + /* 132, 0x084 */ SDL_SCANCODE_UNKNOWN, // SunFront + /* 133, 0x085 */ SDL_SCANCODE_COPY, // XF86Copy + /* 134, 0x086 */ SDL_SCANCODE_UNKNOWN, // SunOpen, XF86Open + /* 135, 0x087 */ SDL_SCANCODE_PASTE, // XF86Paste + /* 136, 0x088 */ SDL_SCANCODE_FIND, // Find + /* 137, 0x089 */ SDL_SCANCODE_CUT, // XF86Cut + /* 138, 0x08a */ SDL_SCANCODE_HELP, // Help + /* 139, 0x08b */ SDL_SCANCODE_MENU, // XF86MenuKB + /* 140, 0x08c */ SDL_SCANCODE_UNKNOWN, // XF86Calculator + /* 141, 0x08d */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 142, 0x08e */ SDL_SCANCODE_SLEEP, // XF86Sleep + /* 143, 0x08f */ SDL_SCANCODE_UNKNOWN, // XF86WakeUp + /* 144, 0x090 */ SDL_SCANCODE_UNKNOWN, // XF86Explorer + /* 145, 0x091 */ SDL_SCANCODE_UNKNOWN, // XF86Send + /* 146, 0x092 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 147, 0x093 */ SDL_SCANCODE_UNKNOWN, // XF86Xfer + /* 148, 0x094 */ SDL_SCANCODE_UNKNOWN, // XF86Launch1 + /* 149, 0x095 */ SDL_SCANCODE_UNKNOWN, // XF86Launch2 + /* 150, 0x096 */ SDL_SCANCODE_UNKNOWN, // XF86WWW + /* 151, 0x097 */ SDL_SCANCODE_UNKNOWN, // XF86DOS + /* 152, 0x098 */ SDL_SCANCODE_UNKNOWN, // XF86ScreenSaver + /* 153, 0x099 */ SDL_SCANCODE_UNKNOWN, // XF86RotateWindows + /* 154, 0x09a */ SDL_SCANCODE_UNKNOWN, // XF86TaskPane + /* 155, 0x09b */ SDL_SCANCODE_UNKNOWN, // XF86Mail + /* 156, 0x09c */ SDL_SCANCODE_AC_BOOKMARKS, // XF86Favorites + /* 157, 0x09d */ SDL_SCANCODE_UNKNOWN, // XF86MyComputer + /* 158, 0x09e */ SDL_SCANCODE_AC_BACK, // XF86Back + /* 159, 0x09f */ SDL_SCANCODE_AC_FORWARD, // XF86Forward + /* 160, 0x0a0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 161, 0x0a1 */ SDL_SCANCODE_MEDIA_EJECT, // XF86Eject + /* 162, 0x0a2 */ SDL_SCANCODE_MEDIA_EJECT, // XF86Eject + /* 163, 0x0a3 */ SDL_SCANCODE_MEDIA_NEXT_TRACK, // XF86AudioNext + /* 164, 0x0a4 */ SDL_SCANCODE_MEDIA_PLAY_PAUSE, // XF86AudioPlay + /* 165, 0x0a5 */ SDL_SCANCODE_MEDIA_PREVIOUS_TRACK, // XF86AudioPrev + /* 166, 0x0a6 */ SDL_SCANCODE_MEDIA_STOP, // XF86AudioStop + /* 167, 0x0a7 */ SDL_SCANCODE_MEDIA_RECORD, // XF86AudioRecord + /* 168, 0x0a8 */ SDL_SCANCODE_MEDIA_REWIND, // XF86AudioRewind + /* 169, 0x0a9 */ SDL_SCANCODE_UNKNOWN, // XF86Phone + /* 170, 0x0aa */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 171, 0x0ab */ SDL_SCANCODE_F13, // XF86Tools + /* 172, 0x0ac */ SDL_SCANCODE_AC_HOME, // XF86HomePage + /* 173, 0x0ad */ SDL_SCANCODE_AC_REFRESH, // XF86Reload + /* 174, 0x0ae */ SDL_SCANCODE_UNKNOWN, // XF86Close + /* 175, 0x0af */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 176, 0x0b0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 177, 0x0b1 */ SDL_SCANCODE_UNKNOWN, // XF86ScrollUp + /* 178, 0x0b2 */ SDL_SCANCODE_UNKNOWN, // XF86ScrollDown + /* 179, 0x0b3 */ SDL_SCANCODE_KP_LEFTPAREN, // parenleft + /* 180, 0x0b4 */ SDL_SCANCODE_KP_RIGHTPAREN, // parenright + /* 181, 0x0b5 */ SDL_SCANCODE_AC_NEW, // XF86New + /* 182, 0x0b6 */ SDL_SCANCODE_AGAIN, // Redo + /* 183, 0x0b7 */ SDL_SCANCODE_F13, // XF86Tools + /* 184, 0x0b8 */ SDL_SCANCODE_F14, // XF86Launch5 + /* 185, 0x0b9 */ SDL_SCANCODE_F15, // XF86Launch6 + /* 186, 0x0ba */ SDL_SCANCODE_F16, // XF86Launch7 + /* 187, 0x0bb */ SDL_SCANCODE_F17, // XF86Launch8 + /* 188, 0x0bc */ SDL_SCANCODE_F18, // XF86Launch9 + /* 189, 0x0bd */ SDL_SCANCODE_F19, // NoSymbol + /* 190, 0x0be */ SDL_SCANCODE_F20, // XF86AudioMicMute + /* 191, 0x0bf */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadToggle + /* 192, 0x0c0 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOn + /* 193, 0x0c1 */ SDL_SCANCODE_UNKNOWN, // XF86TouchpadOff + /* 194, 0x0c2 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 195, 0x0c3 */ SDL_SCANCODE_MODE, // Mode_switch + /* 196, 0x0c4 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 197, 0x0c5 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 198, 0x0c6 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 199, 0x0c7 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 200, 0x0c8 */ SDL_SCANCODE_MEDIA_PLAY, // XF86AudioPlay + /* 201, 0x0c9 */ SDL_SCANCODE_MEDIA_PAUSE, // XF86AudioPause + /* 202, 0x0ca */ SDL_SCANCODE_UNKNOWN, // XF86Launch3 + /* 203, 0x0cb */ SDL_SCANCODE_UNKNOWN, // XF86Launch4 + /* 204, 0x0cc */ SDL_SCANCODE_UNKNOWN, // XF86LaunchB + /* 205, 0x0cd */ SDL_SCANCODE_UNKNOWN, // XF86Suspend + /* 206, 0x0ce */ SDL_SCANCODE_AC_CLOSE, // XF86Close + /* 207, 0x0cf */ SDL_SCANCODE_MEDIA_PLAY, // XF86AudioPlay + /* 208, 0x0d0 */ SDL_SCANCODE_MEDIA_FAST_FORWARD, // XF86AudioForward + /* 209, 0x0d1 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 210, 0x0d2 */ SDL_SCANCODE_PRINTSCREEN, // Print + /* 211, 0x0d3 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 212, 0x0d4 */ SDL_SCANCODE_UNKNOWN, // XF86WebCam + /* 213, 0x0d5 */ SDL_SCANCODE_UNKNOWN, // XF86AudioPreset + /* 214, 0x0d6 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 215, 0x0d7 */ SDL_SCANCODE_UNKNOWN, // XF86Mail + /* 216, 0x0d8 */ SDL_SCANCODE_UNKNOWN, // XF86Messenger + /* 217, 0x0d9 */ SDL_SCANCODE_AC_SEARCH, // XF86Search + /* 218, 0x0da */ SDL_SCANCODE_UNKNOWN, // XF86Go + /* 219, 0x0db */ SDL_SCANCODE_UNKNOWN, // XF86Finance + /* 220, 0x0dc */ SDL_SCANCODE_UNKNOWN, // XF86Game + /* 221, 0x0dd */ SDL_SCANCODE_UNKNOWN, // XF86Shop + /* 222, 0x0de */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 223, 0x0df */ SDL_SCANCODE_CANCEL, // Cancel + /* 224, 0x0e0 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessDown + /* 225, 0x0e1 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessUp + /* 226, 0x0e2 */ SDL_SCANCODE_MEDIA_SELECT, // XF86AudioMedia + /* 227, 0x0e3 */ SDL_SCANCODE_UNKNOWN, // XF86Display + /* 228, 0x0e4 */ SDL_SCANCODE_UNKNOWN, // XF86KbdLightOnOff + /* 229, 0x0e5 */ SDL_SCANCODE_UNKNOWN, // XF86KbdBrightnessDown + /* 230, 0x0e6 */ SDL_SCANCODE_UNKNOWN, // XF86KbdBrightnessUp + /* 231, 0x0e7 */ SDL_SCANCODE_UNKNOWN, // XF86Send + /* 232, 0x0e8 */ SDL_SCANCODE_UNKNOWN, // XF86Reply + /* 233, 0x0e9 */ SDL_SCANCODE_UNKNOWN, // XF86MailForward + /* 234, 0x0ea */ SDL_SCANCODE_UNKNOWN, // XF86Save + /* 235, 0x0eb */ SDL_SCANCODE_UNKNOWN, // XF86Documents + /* 236, 0x0ec */ SDL_SCANCODE_UNKNOWN, // XF86Battery + /* 237, 0x0ed */ SDL_SCANCODE_UNKNOWN, // XF86Bluetooth + /* 238, 0x0ee */ SDL_SCANCODE_UNKNOWN, // XF86WLAN + /* 239, 0x0ef */ SDL_SCANCODE_UNKNOWN, // XF86UWB + /* 240, 0x0f0 */ SDL_SCANCODE_UNKNOWN, // NoSymbol + /* 241, 0x0f1 */ SDL_SCANCODE_UNKNOWN, // XF86Next_VMode + /* 242, 0x0f2 */ SDL_SCANCODE_UNKNOWN, // XF86Prev_VMode + /* 243, 0x0f3 */ SDL_SCANCODE_UNKNOWN, // XF86MonBrightnessCycle + /* 244, 0x0f4 */ SDL_SCANCODE_UNKNOWN, // XF86BrightnessAuto + /* 245, 0x0f5 */ SDL_SCANCODE_UNKNOWN, // XF86DisplayOff + /* 246, 0x0f6 */ SDL_SCANCODE_UNKNOWN, // XF86WWAN + /* 247, 0x0f7 */ SDL_SCANCODE_UNKNOWN, // XF86RFKill }; -/* Xvnc / Xtightvnc scancodes from xmodmap -pk */ +// Xvnc / Xtightvnc scancodes from xmodmap -pk static const SDL_Scancode xvnc_scancode_table[] = { /* 0 */ SDL_SCANCODE_LCTRL, /* 1 */ SDL_SCANCODE_RCTRL, /* 2 */ SDL_SCANCODE_LSHIFT, /* 3 */ SDL_SCANCODE_RSHIFT, - /* 4 */ SDL_SCANCODE_UNKNOWN, /* Meta_L */ - /* 5 */ SDL_SCANCODE_UNKNOWN, /* Meta_R */ + /* 4 */ SDL_SCANCODE_UNKNOWN, // Meta_L + /* 5 */ SDL_SCANCODE_UNKNOWN, // Meta_R /* 6 */ SDL_SCANCODE_LALT, /* 7 */ SDL_SCANCODE_RALT, /* 8 */ SDL_SCANCODE_SPACE, @@ -515,6 +515,6 @@ static const SDL_Scancode xvnc_scancode_table[] = { /* 80 */ SDL_SCANCODE_F12, }; -#endif /* scancodes_xfree86_h_ */ +#endif // scancodes_xfree86_h_ -/* *INDENT-ON* */ /* clang-format on */ +/* *INDENT-ON* */ // clang-format on diff --git a/libs/SDL3/src/file/SDL_iostream.c b/libs/SDL3/src/file/SDL_iostream.c index d261094f3..db9f05d9a 100644 --- a/libs/SDL3/src/file/SDL_iostream.c +++ b/libs/SDL3/src/file/SDL_iostream.c @@ -20,18 +20,27 @@ */ #include "SDL_internal.h" -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT) +#if defined(SDL_PLATFORM_WINDOWS) #include "../core/windows/SDL_windows.h" +#else +#include #endif #ifdef HAVE_STDIO_H #include +#include #include #endif #ifdef HAVE_LIMITS_H #include #endif +#ifdef SDL_PLATFORM_APPLE +#include +#endif + +#include "SDL_iostream_c.h" + /* This file provides a general interface for SDL to read and write data sources. It can easily be extended to files, memory, etc. */ @@ -44,41 +53,38 @@ struct SDL_IOStream SDL_PropertiesID props; }; - -#ifdef SDL_PLATFORM_APPLE -#include "cocoa/SDL_iostreambundlesupport.h" -#endif /* SDL_PLATFORM_APPLE */ - #ifdef SDL_PLATFORM_3DS #include "n3ds/SDL_iostreamromfs.h" -#endif /* SDL_PLATFORM_3DS */ +#endif // SDL_PLATFORM_3DS #ifdef SDL_PLATFORM_ANDROID +#include #include "../core/android/SDL_android.h" #endif -#if defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT) +#if defined(SDL_PLATFORM_WINDOWS) typedef struct IOStreamWindowsData { - SDL_bool append; HANDLE h; void *data; size_t size; size_t left; + bool append; + bool autoclose; } IOStreamWindowsData; -/* Functions to read/write Win32 API file pointers */ +// Functions to read/write Win32 API file pointers #ifndef INVALID_SET_FILE_POINTER #define INVALID_SET_FILE_POINTER 0xFFFFFFFF #endif #define READAHEAD_BUFFER_SIZE 1024 -static int SDLCALL windows_file_open(IOStreamWindowsData *iodata, const char *filename, const char *mode) +static HANDLE SDLCALL windows_file_open(const char *filename, const char *mode) { -#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT) +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) UINT old_error_mode; #endif HANDLE h; @@ -86,15 +92,12 @@ static int SDLCALL windows_file_open(IOStreamWindowsData *iodata, const char *fi DWORD must_exist, truncate; int a_mode; - SDL_zerop(iodata); - iodata->h = INVALID_HANDLE_VALUE; /* mark this as unusable */ - - /* "r" = reading, file must exist */ - /* "w" = writing, truncate existing, file may not exist */ - /* "r+"= reading or writing, file must exist */ - /* "a" = writing, append file may not exist */ - /* "a+"= append + read, file may not exist */ - /* "w+" = read, write, truncate. file may not exist */ + // "r" = reading, file must exist + // "w" = writing, truncate existing, file may not exist + // "r+"= reading or writing, file must exist + // "a" = writing, append file may not exist + // "a+"= append + read, file may not exist + // "w+" = read, write, truncate. file may not exist must_exist = (SDL_strchr(mode, 'r') != NULL) ? OPEN_EXISTING : 0; truncate = (SDL_strchr(mode, 'w') != NULL) ? CREATE_ALWAYS : 0; @@ -103,59 +106,36 @@ static int SDLCALL windows_file_open(IOStreamWindowsData *iodata, const char *fi w_right = (a_mode || SDL_strchr(mode, '+') || truncate) ? GENERIC_WRITE : 0; if (!r_right && !w_right) { - return -1; /* inconsistent mode */ + return INVALID_HANDLE_VALUE; // inconsistent mode } - /* failed (invalid call) */ + // failed (invalid call) - iodata->data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); - if (!iodata->data) { - return -1; - } -#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT) - /* Do not open a dialog box if failure */ - old_error_mode = - SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) + // Do not open a dialog box if failure + old_error_mode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS); #endif { - LPTSTR tstr = WIN_UTF8ToString(filename); -#if defined(SDL_PLATFORM_WINRT) - CREATEFILE2_EXTENDED_PARAMETERS extparams; - SDL_zero(extparams); - extparams.dwSize = sizeof(extparams); - extparams.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; - h = CreateFile2(tstr, - (w_right | r_right), - (w_right) ? 0 : FILE_SHARE_READ, - (must_exist | truncate | a_mode), - &extparams); -#else - h = CreateFile(tstr, + LPWSTR str = WIN_UTF8ToStringW(filename); + h = CreateFileW(str, (w_right | r_right), (w_right) ? 0 : FILE_SHARE_READ, NULL, (must_exist | truncate | a_mode), FILE_ATTRIBUTE_NORMAL, NULL); -#endif - SDL_free(tstr); + SDL_free(str); } -#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) && !defined(SDL_PLATFORM_WINRT) - /* restore old behavior */ +#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) + // restore old behavior SetErrorMode(old_error_mode); #endif if (h == INVALID_HANDLE_VALUE) { - SDL_free(iodata->data); - iodata->data = NULL; SDL_SetError("Couldn't open %s", filename); - return -2; /* failed (CreateFile) */ } - iodata->h = h; - iodata->append = a_mode ? SDL_TRUE : SDL_FALSE; - - return 0; /* ok */ + return h; } static Sint64 SDLCALL windows_file_size(void *userdata) @@ -170,7 +150,7 @@ static Sint64 SDLCALL windows_file_size(void *userdata) return size.QuadPart; } -static Sint64 SDLCALL windows_file_seek(void *userdata, Sint64 offset, int whence) +static Sint64 SDLCALL windows_file_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) { IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; DWORD windowswhence; @@ -193,12 +173,13 @@ static Sint64 SDLCALL windows_file_seek(void *userdata, Sint64 offset, int whenc windowswhence = FILE_END; break; default: - return SDL_SetError("windows_file_seek: Unknown value for 'whence'"); + SDL_SetError("windows_file_seek: Unknown value for 'whence'"); + return -1; } windowsoffset.QuadPart = offset; if (!SetFilePointerEx(iodata->h, windowsoffset, &windowsoffset, windowswhence)) { - return WIN_SetError("windows_file_seek"); + return WIN_SetError("Error seeking in datastream"); } return windowsoffset.QuadPart; } @@ -229,7 +210,18 @@ static size_t SDLCALL windows_file_read(void *userdata, void *ptr, size_t size, if (total_need < READAHEAD_BUFFER_SIZE) { if (!ReadFile(iodata->h, iodata->data, READAHEAD_BUFFER_SIZE, &bytes, NULL)) { - SDL_Error(SDL_EFREAD); + DWORD error = GetLastError(); + switch (error) { + case ERROR_BROKEN_PIPE: + case ERROR_HANDLE_EOF: + break; + case ERROR_NO_DATA: + *status = SDL_IO_STATUS_NOT_READY; + break; + default: + WIN_SetError("Error reading from datastream"); + break; + } return 0; } read_ahead = SDL_min(total_need, bytes); @@ -239,7 +231,18 @@ static size_t SDLCALL windows_file_read(void *userdata, void *ptr, size_t size, total_read += read_ahead; } else { if (!ReadFile(iodata->h, ptr, (DWORD)total_need, &bytes, NULL)) { - SDL_Error(SDL_EFREAD); + DWORD error = GetLastError(); + switch (error) { + case ERROR_BROKEN_PIPE: + case ERROR_HANDLE_EOF: + break; + case ERROR_NO_DATA: + *status = SDL_IO_STATUS_NOT_READY; + break; + default: + WIN_SetError("Error reading from datastream"); + break; + } return 0; } total_read += bytes; @@ -250,56 +253,271 @@ static size_t SDLCALL windows_file_read(void *userdata, void *ptr, size_t size, static size_t SDLCALL windows_file_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) { IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; - const size_t total_bytes = size; DWORD bytes; if (iodata->left) { if (!SetFilePointer(iodata->h, -(LONG)iodata->left, NULL, FILE_CURRENT)) { - SDL_Error(SDL_EFSEEK); + WIN_SetError("Error seeking in datastream"); return 0; } iodata->left = 0; } - /* if in append mode, we must go to the EOF before write */ + // if in append mode, we must go to the EOF before write if (iodata->append) { LARGE_INTEGER windowsoffset; windowsoffset.QuadPart = 0; if (!SetFilePointerEx(iodata->h, windowsoffset, &windowsoffset, FILE_END)) { - SDL_Error(SDL_EFSEEK); + WIN_SetError("Error seeking in datastream"); return 0; } } - if (!WriteFile(iodata->h, ptr, (DWORD)total_bytes, &bytes, NULL)) { - SDL_Error(SDL_EFWRITE); + if (!WriteFile(iodata->h, ptr, (DWORD)size, &bytes, NULL)) { + WIN_SetError("Error writing to datastream"); return 0; } - + if (bytes == 0 && size > 0) { + *status = SDL_IO_STATUS_NOT_READY; + } return bytes; } -static int SDLCALL windows_file_close(void *userdata) +static bool SDLCALL windows_file_flush(void *userdata, SDL_IOStatus *status) +{ + IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; + if (!FlushFileBuffers(iodata->h)) { + return WIN_SetError("Error flushing datastream"); + } + return true; +} + +static bool SDLCALL windows_file_close(void *userdata) { IOStreamWindowsData *iodata = (IOStreamWindowsData *) userdata; if (iodata->h != INVALID_HANDLE_VALUE) { - CloseHandle(iodata->h); - iodata->h = INVALID_HANDLE_VALUE; /* to be sure */ + if (iodata->autoclose) { + CloseHandle(iodata->h); + } + iodata->h = INVALID_HANDLE_VALUE; // to be sure } SDL_free(iodata->data); SDL_free(iodata); - return 0; + return true; +} + +SDL_IOStream *SDL_IOFromHandle(HANDLE handle, const char *mode, bool autoclose) +{ + IOStreamWindowsData *iodata = (IOStreamWindowsData *) SDL_calloc(1, sizeof (*iodata)); + if (!iodata) { + if (autoclose) { + CloseHandle(handle); + } + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_INIT_INTERFACE(&iface); + if (GetFileType(handle) == FILE_TYPE_DISK) { + iface.size = windows_file_size; + iface.seek = windows_file_seek; + } + iface.read = windows_file_read; + iface.write = windows_file_write; + iface.flush = windows_file_flush; + iface.close = windows_file_close; + + iodata->h = handle; + iodata->append = (SDL_strchr(mode, 'a') != NULL); + iodata->autoclose = autoclose; + + iodata->data = (char *)SDL_malloc(READAHEAD_BUFFER_SIZE); + if (!iodata->data) { + iface.close(iodata); + return NULL; + } + + SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); + if (!iostr) { + iface.close(iodata); + } else { + const SDL_PropertiesID props = SDL_GetIOProperties(iostr); + if (props) { + SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER, iodata->h); + } + } + + return iostr; +} +#endif // defined(SDL_PLATFORM_WINDOWS) + +#if !defined(SDL_PLATFORM_WINDOWS) + +// Functions to read/write file descriptors. Not used for windows. + +typedef struct IOStreamFDData +{ + int fd; + bool autoclose; + bool regular_file; +} IOStreamFDData; + +static int SDL_fdatasync(int fd) +{ + int result = 0; + +#if defined(SDL_PLATFORM_APPLE) // Apple doesn't have fdatasync (rather, the symbol exists as an incompatible system call). + result = fcntl(fd, F_FULLFSYNC); +#elif defined(SDL_PLATFORM_HAIKU) + result = fsync(fd); +#elif defined(_POSIX_SYNCHRONIZED_IO) // POSIX defines this if fdatasync() exists, so we don't need a CMake test. +#ifndef SDL_PLATFORM_RISCOS // !!! FIXME: however, RISCOS doesn't have the symbol...maybe we need to link to an extra library or something? + result = fdatasync(fd); +#endif +#endif + return result; +} + +static Sint64 SDLCALL fd_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) +{ + IOStreamFDData *iodata = (IOStreamFDData *) userdata; + int fdwhence; + + switch (whence) { + case SDL_IO_SEEK_SET: + fdwhence = SEEK_SET; + break; + case SDL_IO_SEEK_CUR: + fdwhence = SEEK_CUR; + break; + case SDL_IO_SEEK_END: + fdwhence = SEEK_END; + break; + default: + SDL_SetError("Unknown value for 'whence'"); + return -1; + } + + off_t result = lseek(iodata->fd, (off_t)offset, fdwhence); + if (result < 0) { + SDL_SetError("Couldn't get stream offset: %s", strerror(errno)); + } + return result; +} + +static size_t SDLCALL fd_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamFDData *iodata = (IOStreamFDData *) userdata; + ssize_t bytes; + do { + bytes = read(iodata->fd, ptr, size); + } while (bytes < 0 && errno == EINTR); + + if (bytes < 0) { + if (errno == EAGAIN) { + *status = SDL_IO_STATUS_NOT_READY; + } else { + SDL_SetError("Error reading from datastream: %s", strerror(errno)); + } + bytes = 0; + } + return (size_t)bytes; +} + +static size_t SDLCALL fd_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) +{ + IOStreamFDData *iodata = (IOStreamFDData *) userdata; + ssize_t bytes; + do { + bytes = write(iodata->fd, ptr, size); + } while (bytes < 0 && errno == EINTR); + + if (bytes < 0) { + if (errno == EAGAIN) { + *status = SDL_IO_STATUS_NOT_READY; + } else { + SDL_SetError("Error writing to datastream: %s", strerror(errno)); + } + bytes = 0; + } + return (size_t)bytes; +} + +static bool SDLCALL fd_flush(void *userdata, SDL_IOStatus *status) +{ + IOStreamFDData *iodata = (IOStreamFDData *) userdata; + int result; + do { + result = SDL_fdatasync(iodata->fd); + } while (result < 0 && errno == EINTR); + + if (result < 0) { + return SDL_SetError("Error flushing datastream: %s", strerror(errno)); + } + return true; +} + +static bool SDLCALL fd_close(void *userdata) +{ + IOStreamFDData *iodata = (IOStreamFDData *) userdata; + bool status = true; + if (iodata->autoclose) { + if (close(iodata->fd) < 0) { + status = SDL_SetError("Error closing datastream: %s", strerror(errno)); + } + } + SDL_free(iodata); + return status; +} + +SDL_IOStream *SDL_IOFromFD(int fd, bool autoclose) +{ + IOStreamFDData *iodata = (IOStreamFDData *) SDL_calloc(1, sizeof (*iodata)); + if (!iodata) { + if (autoclose) { + close(fd); + } + return NULL; + } + + SDL_IOStreamInterface iface; + SDL_INIT_INTERFACE(&iface); + // There's no fd_size because SDL_GetIOSize emulates it the same way we'd do it for fd anyhow. + iface.seek = fd_seek; + iface.read = fd_read; + iface.write = fd_write; + iface.flush = fd_flush; + iface.close = fd_close; + + iodata->fd = fd; + iodata->autoclose = autoclose; + + struct stat st; + iodata->regular_file = ((fstat(fd, &st) == 0) && S_ISREG(st.st_mode)); + + SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); + if (!iostr) { + iface.close(iodata); + } else { + const SDL_PropertiesID props = SDL_GetIOProperties(iostr); + if (props) { + SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, fd); + } + } + + return iostr; } -#endif /* defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) */ +#endif // !defined(SDL_PLATFORM_WINDOWS) -#if defined(HAVE_STDIO_H) && !(defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK)) +#if defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINDOWS) -/* Functions to read/write stdio file pointers. Not used for windows. */ +// Functions to read/write stdio file pointers. Not used for windows. typedef struct IOStreamStdioData { FILE *fp; - SDL_bool autoclose; + bool autoclose; + bool regular_file; } IOStreamStdioData; #ifdef HAVE_FOPEN64 @@ -338,7 +556,7 @@ typedef struct IOStreamStdioData #define fseek_off_t long #endif -static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence) +static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) { IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; int stdiowhence; @@ -354,23 +572,30 @@ static Sint64 SDLCALL stdio_seek(void *userdata, Sint64 offset, int whence) stdiowhence = SEEK_END; break; default: - return SDL_SetError("Unknown value for 'whence'"); + SDL_SetError("Unknown value for 'whence'"); + return -1; } #if defined(FSEEK_OFF_MIN) && defined(FSEEK_OFF_MAX) if (offset < (Sint64)(FSEEK_OFF_MIN) || offset > (Sint64)(FSEEK_OFF_MAX)) { - return SDL_SetError("Seek offset out of range"); + SDL_SetError("Seek offset out of range"); + return -1; } #endif - if (fseek(iodata->fp, (fseek_off_t)offset, stdiowhence) == 0) { + // don't make a possibly-costly API call for the noop seek from SDL_TellIO + const bool is_noop = (whence == SDL_IO_SEEK_CUR) && (offset == 0); + + if (is_noop || fseek(iodata->fp, (fseek_off_t)offset, stdiowhence) == 0) { const Sint64 pos = ftell(iodata->fp); if (pos < 0) { - return SDL_SetError("Couldn't get stream offset"); + SDL_SetError("Couldn't get stream offset: %s", strerror(errno)); + return -1; } return pos; } - return SDL_Error(SDL_EFSEEK); + SDL_SetError("Error seeking in datastream: %s", strerror(errno)); + return -1; } static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOStatus *status) @@ -378,7 +603,12 @@ static size_t SDLCALL stdio_read(void *userdata, void *ptr, size_t size, SDL_IOS IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; const size_t bytes = fread(ptr, 1, size, iodata->fp); if (bytes == 0 && ferror(iodata->fp)) { - SDL_Error(SDL_EFREAD); + if (errno == EAGAIN) { + *status = SDL_IO_STATUS_NOT_READY; + clearerr(iodata->fp); + } else { + SDL_SetError("Error reading from datastream: %s", strerror(errno)); + } } return bytes; } @@ -388,57 +618,94 @@ static size_t SDLCALL stdio_write(void *userdata, const void *ptr, size_t size, IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; const size_t bytes = fwrite(ptr, 1, size, iodata->fp); if (bytes == 0 && ferror(iodata->fp)) { - SDL_Error(SDL_EFWRITE); + if (errno == EAGAIN) { + *status = SDL_IO_STATUS_NOT_READY; + clearerr(iodata->fp); + } else { + SDL_SetError("Error writing to datastream: %s", strerror(errno)); + } } return bytes; } -static int SDLCALL stdio_close(void *userdata) +static bool SDLCALL stdio_flush(void *userdata, SDL_IOStatus *status) { IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; - int status = 0; + if (fflush(iodata->fp) != 0) { + if (errno == EAGAIN) { + *status = SDL_IO_STATUS_NOT_READY; + return false; + } else { + return SDL_SetError("Error flushing datastream: %s", strerror(errno)); + } + } + + int result; + int fd = fileno(iodata->fp); + do { + result = SDL_fdatasync(fd); + } while (result < 0 && errno == EINTR); + + if (result < 0) { + return SDL_SetError("Error flushing datastream: %s", strerror(errno)); + } + return true; +} + +static bool SDLCALL stdio_close(void *userdata) +{ + IOStreamStdioData *iodata = (IOStreamStdioData *) userdata; + bool status = true; if (iodata->autoclose) { if (fclose(iodata->fp) != 0) { - status = SDL_Error(SDL_EFWRITE); + status = SDL_SetError("Error closing datastream: %s", strerror(errno)); } } SDL_free(iodata); return status; } -static SDL_IOStream *SDL_IOFromFP(FILE *fp, SDL_bool autoclose) +SDL_IOStream *SDL_IOFromFP(FILE *fp, bool autoclose) { - IOStreamStdioData *iodata = (IOStreamStdioData *) SDL_malloc(sizeof (*iodata)); + IOStreamStdioData *iodata = (IOStreamStdioData *) SDL_calloc(1, sizeof (*iodata)); if (!iodata) { + if (autoclose) { + fclose(fp); + } return NULL; } SDL_IOStreamInterface iface; - SDL_zero(iface); + SDL_INIT_INTERFACE(&iface); // There's no stdio_size because SDL_GetIOSize emulates it the same way we'd do it for stdio anyhow. iface.seek = stdio_seek; iface.read = stdio_read; iface.write = stdio_write; + iface.flush = stdio_flush; iface.close = stdio_close; iodata->fp = fp; iodata->autoclose = autoclose; + struct stat st; + iodata->regular_file = ((fstat(fileno(fp), &st) == 0) && S_ISREG(st.st_mode)); + SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); if (!iostr) { iface.close(iodata); } else { const SDL_PropertiesID props = SDL_GetIOProperties(iostr); if (props) { - SDL_SetProperty(props, SDL_PROP_IOSTREAM_STDIO_FILE_POINTER, fp); + SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_STDIO_FILE_POINTER, fp); + SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_FILE_DESCRIPTOR_NUMBER, fileno(fp)); } } return iostr; } -#endif /* !HAVE_STDIO_H && !(SDL_PLATFORM_WIN32 || SDL_PLATFORM_GDK) */ +#endif // !HAVE_STDIO_H && !defined(SDL_PLATFORM_WINDOWS) -/* Functions to read/write memory pointers */ +// Functions to read/write memory pointers typedef struct IOStreamMemData { @@ -453,7 +720,7 @@ static Sint64 SDLCALL mem_size(void *userdata) return (iodata->stop - iodata->base); } -static Sint64 SDLCALL mem_seek(void *userdata, Sint64 offset, int whence) +static Sint64 SDLCALL mem_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) { IOStreamMemData *iodata = (IOStreamMemData *) userdata; Uint8 *newpos; @@ -469,7 +736,8 @@ static Sint64 SDLCALL mem_seek(void *userdata, Sint64 offset, int whence) newpos = iodata->stop + offset; break; default: - return SDL_SetError("Unknown value for 'whence'"); + SDL_SetError("Unknown value for 'whence'"); + return -1; } if (newpos < iodata->base) { newpos = iodata->base; @@ -505,30 +773,22 @@ static size_t SDLCALL mem_write(void *userdata, const void *ptr, size_t size, SD return mem_io(userdata, iodata->here, ptr, size); } -static int SDLCALL mem_close(void *userdata) +static bool SDLCALL mem_close(void *userdata) { SDL_free(userdata); - return 0; + return true; } -/* Functions to create SDL_IOStream structures from various data sources */ +// Functions to create SDL_IOStream structures from various data sources #if defined(HAVE_STDIO_H) && !defined(SDL_PLATFORM_WINDOWS) -static SDL_bool IsRegularFileOrPipe(FILE *f) +static bool IsRegularFileOrPipe(FILE *f) { - #ifdef SDL_PLATFORM_WINRT - struct __stat64 st; - if (_fstat64(_fileno(f), &st) < 0 || - !((st.st_mode & _S_IFMT) == _S_IFREG || (st.st_mode & _S_IFMT) == _S_IFIFO)) { - return SDL_FALSE; - } - #else struct stat st; if (fstat(fileno(f), &st) < 0 || !(S_ISREG(st.st_mode) || S_ISFIFO(st.st_mode))) { - return SDL_FALSE; + return false; } - #endif - return SDL_TRUE; + return true; } #endif @@ -547,7 +807,7 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode) #ifdef SDL_PLATFORM_ANDROID #ifdef HAVE_STDIO_H - /* Try to open the file on the filesystem first */ + // Try to open the file on the filesystem first if (*file == '/') { FILE *fp = fopen(file, mode); if (fp) { @@ -556,39 +816,52 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode) SDL_SetError("%s is not a regular file or pipe", file); return NULL; } - return SDL_IOFromFP(fp, 1); + return SDL_IOFromFP(fp, true); + } + } else if (SDL_strncmp(file, "content://", 10) == 0) { + // Try opening content:// URI + int fd = Android_JNI_OpenFileDescriptor(file, mode); + if (fd == -1) { + // SDL error is already set. + return NULL; } + + FILE *fp = fdopen(fd, mode); + if (!fp) { + close(fd); + SDL_SetError("Unable to open file descriptor (%d) from URI %s: %s", fd, file, strerror(errno)); + return NULL; + } + + return SDL_IOFromFP(fp, true); } else { - /* Try opening it from internal storage if it's a relative path */ - // !!! FIXME: why not just "char path[PATH_MAX];" - char *path = SDL_stack_alloc(char, PATH_MAX); + // Try opening it from internal storage if it's a relative path + char *path = NULL; + SDL_asprintf(&path, "%s/%s", SDL_GetAndroidInternalStoragePath(), file); if (path) { - SDL_snprintf(path, PATH_MAX, "%s/%s", - SDL_AndroidGetInternalStoragePath(), file); FILE *fp = fopen(path, mode); - SDL_stack_free(path); + SDL_free(path); if (fp) { if (!IsRegularFileOrPipe(fp)) { fclose(fp); SDL_SetError("%s is not a regular file or pipe", path); return NULL; } - return SDL_IOFromFP(fp, 1); + return SDL_IOFromFP(fp, true); } } } -#endif /* HAVE_STDIO_H */ +#endif // HAVE_STDIO_H - /* Try to open the file from the asset system */ + // Try to open the file from the asset system void *iodata = NULL; - if (Android_JNI_FileOpen(&iodata, file, mode) < 0) { - SDL_CloseIO(iostr); + if (!Android_JNI_FileOpen(&iodata, file, mode)) { return NULL; } SDL_IOStreamInterface iface; - SDL_zero(iface); + SDL_INIT_INTERFACE(&iface); iface.size = Android_JNI_FileSize; iface.seek = Android_JNI_FileSeek; iface.read = Android_JNI_FileRead; @@ -601,66 +874,38 @@ SDL_IOStream *SDL_IOFromFile(const char *file, const char *mode) } else { const SDL_PropertiesID props = SDL_GetIOProperties(iostr); if (props) { - SDL_SetProperty(props, SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER, iodata); + SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_ANDROID_AASSET_POINTER, iodata); } } -#elif defined(SDL_PLATFORM_WIN32) || defined(SDL_PLATFORM_GDK) || defined(SDL_PLATFORM_WINRT) - IOStreamWindowsData *iodata = (IOStreamWindowsData *) SDL_malloc(sizeof (*iodata)); - if (!iodata) { - return NULL; - } - - if (windows_file_open(iodata, file, mode) < 0) { - SDL_CloseIO(iostr); - return NULL; - } - - SDL_IOStreamInterface iface; - SDL_zero(iface); - iface.size = windows_file_size; - iface.seek = windows_file_seek; - iface.read = windows_file_read; - iface.write = windows_file_write; - iface.close = windows_file_close; - - iostr = SDL_OpenIO(&iface, iodata); - if (!iostr) { - windows_file_close(iodata); - } else { - const SDL_PropertiesID props = SDL_GetIOProperties(iostr); - if (props) { - SDL_SetProperty(props, SDL_PROP_IOSTREAM_WINDOWS_HANDLE_POINTER, iodata->h); - } +#elif defined(SDL_PLATFORM_WINDOWS) + HANDLE handle = windows_file_open(file, mode); + if (handle != INVALID_HANDLE_VALUE) { + iostr = SDL_IOFromHandle(handle, mode, true); } #elif defined(HAVE_STDIO_H) { - #if defined(SDL_PLATFORM_APPLE) - FILE *fp = SDL_OpenFPFromBundleOrFallback(file, mode); - #elif defined(SDL_PLATFORM_WINRT) - FILE *fp = NULL; - fopen_s(&fp, file, mode); - #elif defined(SDL_PLATFORM_3DS) + #if defined(SDL_PLATFORM_3DS) FILE *fp = N3DS_FileOpen(file, mode); #else FILE *fp = fopen(file, mode); #endif if (!fp) { - SDL_SetError("Couldn't open %s", file); + SDL_SetError("Couldn't open %s: %s", file, strerror(errno)); } else if (!IsRegularFileOrPipe(fp)) { fclose(fp); fp = NULL; SDL_SetError("%s is not a regular file or pipe", file); } else { - iostr = SDL_IOFromFP(fp, SDL_TRUE); + iostr = SDL_IOFromFP(fp, true); } } #else SDL_SetError("SDL not compiled with stdio support"); -#endif /* !HAVE_STDIO_H */ +#endif // !HAVE_STDIO_H return iostr; } @@ -675,13 +920,13 @@ SDL_IOStream *SDL_IOFromMem(void *mem, size_t size) return NULL; } - IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata)); + IOStreamMemData *iodata = (IOStreamMemData *) SDL_calloc(1, sizeof (*iodata)); if (!iodata) { return NULL; } SDL_IOStreamInterface iface; - SDL_zero(iface); + SDL_INIT_INTERFACE(&iface); iface.size = mem_size; iface.seek = mem_seek; iface.read = mem_read; @@ -695,6 +940,12 @@ SDL_IOStream *SDL_IOFromMem(void *mem, size_t size) SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); if (!iostr) { SDL_free(iodata); + } else { + const SDL_PropertiesID props = SDL_GetIOProperties(iostr); + if (props) { + SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, mem); + SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER, size); + } } return iostr; } @@ -709,13 +960,13 @@ SDL_IOStream *SDL_IOFromConstMem(const void *mem, size_t size) return NULL; } - IOStreamMemData *iodata = (IOStreamMemData *) SDL_malloc(sizeof (*iodata)); + IOStreamMemData *iodata = (IOStreamMemData *) SDL_calloc(1, sizeof (*iodata)); if (!iodata) { return NULL; } SDL_IOStreamInterface iface; - SDL_zero(iface); + SDL_INIT_INTERFACE(&iface); iface.size = mem_size; iface.seek = mem_seek; iface.read = mem_read; @@ -729,6 +980,12 @@ SDL_IOStream *SDL_IOFromConstMem(const void *mem, size_t size) SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); if (!iostr) { SDL_free(iodata); + } else { + const SDL_PropertiesID props = SDL_GetIOProperties(iostr); + if (props) { + SDL_SetPointerProperty(props, SDL_PROP_IOSTREAM_MEMORY_POINTER, (void *)mem); + SDL_SetNumberProperty(props, SDL_PROP_IOSTREAM_MEMORY_SIZE_NUMBER, size); + } } return iostr; } @@ -746,7 +1003,7 @@ static Sint64 SDLCALL dynamic_mem_size(void *userdata) return mem_size(&iodata->data); } -static Sint64 SDLCALL dynamic_mem_seek(void *userdata, Sint64 offset, int whence) +static Sint64 SDLCALL dynamic_mem_seek(void *userdata, Sint64 offset, SDL_IOWhence whence) { IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; return mem_seek(&iodata->data, offset, whence); @@ -758,7 +1015,7 @@ static size_t SDLCALL dynamic_mem_read(void *userdata, void *ptr, size_t size, S return mem_io(&iodata->data, ptr, iodata->data.here, size); } -static int dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size) +static bool dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size) { size_t chunksize = (size_t)SDL_GetNumberProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_CHUNKSIZE_NUMBER, 0); if (!chunksize) { @@ -770,7 +1027,7 @@ static int dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size) size_t length = (chunks * chunksize); Uint8 *base = (Uint8 *)SDL_realloc(iodata->data.base, length); if (!base) { - return -1; + return false; } size_t here_offset = (iodata->data.here - iodata->data.base); @@ -779,7 +1036,7 @@ static int dynamic_mem_realloc(IOStreamDynamicMemData *iodata, size_t size) iodata->data.here = base + here_offset; iodata->data.stop = base + stop_offset; iodata->end = base + length; - return SDL_SetProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, base); + return SDL_SetPointerProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, base); } static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t size, SDL_IOStatus *status) @@ -787,7 +1044,7 @@ static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; if (size > (size_t)(iodata->data.stop - iodata->data.here)) { if (size > (size_t)(iodata->end - iodata->data.here)) { - if (dynamic_mem_realloc(iodata, size) < 0) { + if (!dynamic_mem_realloc(iodata, size)) { return 0; } } @@ -796,37 +1053,32 @@ static size_t SDLCALL dynamic_mem_write(void *userdata, const void *ptr, size_t return mem_io(&iodata->data, iodata->data.here, ptr, size); } -static int SDLCALL dynamic_mem_close(void *userdata) +static bool SDLCALL dynamic_mem_close(void *userdata) { const IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) userdata; - void *mem = SDL_GetProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL); + void *mem = SDL_GetPointerProperty(SDL_GetIOProperties(iodata->stream), SDL_PROP_IOSTREAM_DYNAMIC_MEMORY_POINTER, NULL); if (mem) { SDL_free(mem); } SDL_free(userdata); - return 0; + return true; } SDL_IOStream *SDL_IOFromDynamicMem(void) { - IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) SDL_malloc(sizeof (*iodata)); + IOStreamDynamicMemData *iodata = (IOStreamDynamicMemData *) SDL_calloc(1, sizeof (*iodata)); if (!iodata) { return NULL; } SDL_IOStreamInterface iface; - SDL_zero(iface); + SDL_INIT_INTERFACE(&iface); iface.size = dynamic_mem_size; iface.seek = dynamic_mem_seek; iface.read = dynamic_mem_read; iface.write = dynamic_mem_write; iface.close = dynamic_mem_close; - iodata->data.base = NULL; - iodata->data.here = NULL; - iodata->data.stop = NULL; - iodata->end = NULL; - SDL_IOStream *iostr = SDL_OpenIO(&iface, iodata); if (iostr) { iodata->stream = iostr; @@ -851,6 +1103,11 @@ SDL_IOStream *SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata) SDL_InvalidParamError("iface"); return NULL; } + if (iface->version < sizeof(*iface)) { + // Update this to handle older versions of this interface + SDL_SetError("Invalid interface, should be initialized with SDL_INIT_INTERFACE()"); + return NULL; + } SDL_IOStream *iostr = (SDL_IOStream *)SDL_calloc(1, sizeof(*iostr)); if (iostr) { @@ -860,27 +1117,27 @@ SDL_IOStream *SDL_OpenIO(const SDL_IOStreamInterface *iface, void *userdata) return iostr; } -int SDL_CloseIO(SDL_IOStream *iostr) +bool SDL_CloseIO(SDL_IOStream *iostr) { - int retval = 0; + bool result = true; if (iostr) { if (iostr->iface.close) { - retval = iostr->iface.close(iostr->userdata); + result = iostr->iface.close(iostr->userdata); } SDL_DestroyProperties(iostr->props); SDL_free(iostr); } - return retval; + return result; } -/* Load all the data from an SDL data stream */ -void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio) +// Load all the data from an SDL data stream +void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, bool closeio) { const int FILE_CHUNK_SIZE = 1024; Sint64 size, size_total = 0; size_t size_read; char *data = NULL, *newdata; - SDL_bool loading_chunks = SDL_FALSE; + bool loading_chunks = false; if (!src) { SDL_InvalidParamError("src"); @@ -890,7 +1147,7 @@ void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio) size = SDL_GetIOSize(src); if (size < 0) { size = FILE_CHUNK_SIZE; - loading_chunks = SDL_TRUE; + loading_chunks = true; } if (size >= SDL_SIZE_MAX) { goto done; @@ -923,9 +1180,13 @@ void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio) if (size_read > 0) { size_total += size_read; continue; + } else if (SDL_GetIOStatus(src) == SDL_IO_STATUS_NOT_READY) { + // Wait for the stream to be ready + SDL_Delay(1); + continue; } - /* The stream status will remain set for the caller to check */ + // The stream status will remain set for the caller to check break; } @@ -943,7 +1204,7 @@ void *SDL_LoadFile_IO(SDL_IOStream *src, size_t *datasize, SDL_bool closeio) void *SDL_LoadFile(const char *file, size_t *datasize) { - return SDL_LoadFile_IO(SDL_IOFromFile(file, "rb"), datasize, SDL_TRUE); + return SDL_LoadFile_IO(SDL_IOFromFile(file, "rb"), datasize, true); } SDL_PropertiesID SDL_GetIOProperties(SDL_IOStream *context) @@ -979,12 +1240,14 @@ Sint64 SDL_GetIOSize(SDL_IOStream *context) return context->iface.size(context->userdata); } -Sint64 SDL_SeekIO(SDL_IOStream *context, Sint64 offset, int whence) +Sint64 SDL_SeekIO(SDL_IOStream *context, Sint64 offset, SDL_IOWhence whence) { if (!context) { - return SDL_InvalidParamError("context"); + SDL_InvalidParamError("context"); + return -1; } else if (!context->iface.seek) { - return SDL_Unsupported(); + SDL_Unsupported(); + return -1; } return context->iface.seek(context->userdata, offset, whence); } @@ -1087,15 +1350,35 @@ size_t SDL_IOvprintf(SDL_IOStream *context, SDL_PRINTF_FORMAT_STRING const char return bytes; } -/* Functions for dynamically reading and writing endian-specific values */ +bool SDL_FlushIO(SDL_IOStream *context) +{ + bool result = true; + + if (!context) { + return SDL_InvalidParamError("context"); + } + + context->status = SDL_IO_STATUS_READY; + SDL_ClearError(); + + if (context->iface.flush) { + result = context->iface.flush(context->userdata, &context->status); + } + if (!result && (context->status == SDL_IO_STATUS_READY)) { + context->status = SDL_IO_STATUS_ERROR; + } + return result; +} + +// Functions for dynamically reading and writing endian-specific values -SDL_bool SDL_ReadU8(SDL_IOStream *src, Uint8 *value) +bool SDL_ReadU8(SDL_IOStream *src, Uint8 *value) { Uint8 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { *value = data; @@ -1103,187 +1386,206 @@ SDL_bool SDL_ReadU8(SDL_IOStream *src, Uint8 *value) return result; } -SDL_bool SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value) +bool SDL_ReadS8(SDL_IOStream *src, Sint8 *value) +{ + Sint8 data = 0; + bool result = false; + + if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { + result = true; + } + if (value) { + *value = data; + } + return result; +} + +bool SDL_ReadU16LE(SDL_IOStream *src, Uint16 *value) { Uint16 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapLE16(data); + *value = SDL_Swap16LE(data); } return result; } -SDL_bool SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value) +bool SDL_ReadS16LE(SDL_IOStream *src, Sint16 *value) { return SDL_ReadU16LE(src, (Uint16 *)value); } -SDL_bool SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value) +bool SDL_ReadU16BE(SDL_IOStream *src, Uint16 *value) { Uint16 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapBE16(data); + *value = SDL_Swap16BE(data); } return result; } -SDL_bool SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value) +bool SDL_ReadS16BE(SDL_IOStream *src, Sint16 *value) { return SDL_ReadU16BE(src, (Uint16 *)value); } -SDL_bool SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value) +bool SDL_ReadU32LE(SDL_IOStream *src, Uint32 *value) { Uint32 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapLE32(data); + *value = SDL_Swap32LE(data); } return result; } -SDL_bool SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value) +bool SDL_ReadS32LE(SDL_IOStream *src, Sint32 *value) { return SDL_ReadU32LE(src, (Uint32 *)value); } -SDL_bool SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value) +bool SDL_ReadU32BE(SDL_IOStream *src, Uint32 *value) { Uint32 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapBE32(data); + *value = SDL_Swap32BE(data); } return result; } -SDL_bool SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value) +bool SDL_ReadS32BE(SDL_IOStream *src, Sint32 *value) { return SDL_ReadU32BE(src, (Uint32 *)value); } -SDL_bool SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value) +bool SDL_ReadU64LE(SDL_IOStream *src, Uint64 *value) { Uint64 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapLE64(data); + *value = SDL_Swap64LE(data); } return result; } -SDL_bool SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value) +bool SDL_ReadS64LE(SDL_IOStream *src, Sint64 *value) { return SDL_ReadU64LE(src, (Uint64 *)value); } -SDL_bool SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value) +bool SDL_ReadU64BE(SDL_IOStream *src, Uint64 *value) { Uint64 data = 0; - SDL_bool result = SDL_FALSE; + bool result = false; if (SDL_ReadIO(src, &data, sizeof(data)) == sizeof(data)) { - result = SDL_TRUE; + result = true; } if (value) { - *value = SDL_SwapBE64(data); + *value = SDL_Swap64BE(data); } return result; } -SDL_bool SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value) +bool SDL_ReadS64BE(SDL_IOStream *src, Sint64 *value) { return SDL_ReadU64BE(src, (Uint64 *)value); } -SDL_bool SDL_WriteU8(SDL_IOStream *dst, Uint8 value) +bool SDL_WriteU8(SDL_IOStream *dst, Uint8 value) +{ + return (SDL_WriteIO(dst, &value, sizeof(value)) == sizeof(value)); +} + +bool SDL_WriteS8(SDL_IOStream *dst, Sint8 value) { return (SDL_WriteIO(dst, &value, sizeof(value)) == sizeof(value)); } -SDL_bool SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value) +bool SDL_WriteU16LE(SDL_IOStream *dst, Uint16 value) { - const Uint16 swapped = SDL_SwapLE16(value); + const Uint16 swapped = SDL_Swap16LE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value) +bool SDL_WriteS16LE(SDL_IOStream *dst, Sint16 value) { return SDL_WriteU16LE(dst, (Uint16)value); } -SDL_bool SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value) +bool SDL_WriteU16BE(SDL_IOStream *dst, Uint16 value) { - const Uint16 swapped = SDL_SwapBE16(value); + const Uint16 swapped = SDL_Swap16BE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value) +bool SDL_WriteS16BE(SDL_IOStream *dst, Sint16 value) { return SDL_WriteU16BE(dst, (Uint16)value); } -SDL_bool SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value) +bool SDL_WriteU32LE(SDL_IOStream *dst, Uint32 value) { - const Uint32 swapped = SDL_SwapLE32(value); + const Uint32 swapped = SDL_Swap32LE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value) +bool SDL_WriteS32LE(SDL_IOStream *dst, Sint32 value) { return SDL_WriteU32LE(dst, (Uint32)value); } -SDL_bool SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value) +bool SDL_WriteU32BE(SDL_IOStream *dst, Uint32 value) { - const Uint32 swapped = SDL_SwapBE32(value); + const Uint32 swapped = SDL_Swap32BE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value) +bool SDL_WriteS32BE(SDL_IOStream *dst, Sint32 value) { return SDL_WriteU32BE(dst, (Uint32)value); } -SDL_bool SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value) +bool SDL_WriteU64LE(SDL_IOStream *dst, Uint64 value) { - const Uint64 swapped = SDL_SwapLE64(value); + const Uint64 swapped = SDL_Swap64LE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value) +bool SDL_WriteS64LE(SDL_IOStream *dst, Sint64 value) { return SDL_WriteU64LE(dst, (Uint64)value); } -SDL_bool SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value) +bool SDL_WriteU64BE(SDL_IOStream *dst, Uint64 value) { - const Uint64 swapped = SDL_SwapBE64(value); + const Uint64 swapped = SDL_Swap64BE(value); return (SDL_WriteIO(dst, &swapped, sizeof(swapped)) == sizeof(swapped)); } -SDL_bool SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value) +bool SDL_WriteS64BE(SDL_IOStream *dst, Sint64 value) { return SDL_WriteU64BE(dst, (Uint64)value); } diff --git a/libs/SDL3/src/video/winrt/SDL_winrtgamebar_cpp.h b/libs/SDL3/src/file/SDL_iostream_c.h similarity index 73% rename from libs/SDL3/src/video/winrt/SDL_winrtgamebar_cpp.h rename to libs/SDL3/src/file/SDL_iostream_c.h index 51c54628c..a6782d5c3 100644 --- a/libs/SDL3/src/video/winrt/SDL_winrtgamebar_cpp.h +++ b/libs/SDL3/src/file/SDL_iostream_c.h @@ -20,14 +20,16 @@ */ #include "SDL_internal.h" -#ifndef SDL_winrtgamebar_h_ -#define SDL_winrtgamebar_h_ +#ifndef SDL_iostream_c_h_ +#define SDL_iostream_c_h_ -#ifdef __cplusplus -/* These are exported as C++ functions, rather than C, to fix a compilation - bug with MSVC 2013, for Windows 8.x builds. */ -extern void WINRT_InitGameBar(SDL_VideoDevice *_this); -extern void WINRT_QuitGameBar(SDL_VideoDevice *_this); +#if defined(SDL_PLATFORM_WINDOWS) +SDL_IOStream *SDL_IOFromHandle(HANDLE handle, const char *mode, bool autoclose); +#else +#if defined(HAVE_STDIO_H) +extern SDL_IOStream *SDL_IOFromFP(FILE *fp, bool autoclose); +#endif +extern SDL_IOStream *SDL_IOFromFD(int fd, bool autoclose); #endif -#endif /* SDL_winrtgamebar_h_ */ +#endif // SDL_iostream_c_h_ diff --git a/libs/SDL3/src/file/cocoa/SDL_iostreambundlesupport.m b/libs/SDL3/src/file/cocoa/SDL_iostreambundlesupport.m deleted file mode 100644 index 93a7b4349..000000000 --- a/libs/SDL3/src/file/cocoa/SDL_iostreambundlesupport.m +++ /dev/null @@ -1,65 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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_PLATFORM_APPLE -#import - -#include "SDL_iostreambundlesupport.h" - -/* For proper macOS applications, the resources are contained inside the application bundle. - So the strategy is to first check the application bundle for the file, then fallback to the current working directory. - Note: One additional corner-case is if the resource is in a framework's resource bundle instead of the app. - We might want to use bundle identifiers, e.g. org.libsdl.sdl to get the bundle for the framework, - but we would somehow need to know what the bundle identifiers we need to search are. - Also, note the bundle layouts are different for iPhone and Mac. -*/ -FILE *SDL_OpenFPFromBundleOrFallback(const char *file, const char *mode) -{ - @autoreleasepool { - FILE *fp = NULL; - NSFileManager *file_manager; - NSString *resource_path; - NSString *ns_string_file_component; - NSString *full_path_with_file_to_try; - - /* If the file mode is writable, skip all the bundle stuff because generally the bundle is read-only. */ - if (SDL_strchr(mode, 'r') == NULL) { - return fopen(file, mode); - } - - file_manager = [NSFileManager defaultManager]; - resource_path = [[NSBundle mainBundle] resourcePath]; - - ns_string_file_component = [file_manager stringWithFileSystemRepresentation:file length:strlen(file)]; - - full_path_with_file_to_try = [resource_path stringByAppendingPathComponent:ns_string_file_component]; - if ([file_manager fileExistsAtPath:full_path_with_file_to_try]) { - fp = fopen([full_path_with_file_to_try fileSystemRepresentation], mode); - } else { - fp = fopen(file, mode); - } - - return fp; - } -} - -#endif /* SDL_PLATFORM_APPLE */ diff --git a/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.c b/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.c index 3af006b4b..984b093e0 100644 --- a/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.c +++ b/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.c @@ -21,11 +21,11 @@ #include "SDL_iostreamromfs.h" -/* Checks if the mode is a kind of reading */ -static SDL_bool IsReadMode(const char *mode); +// Checks if the mode is a kind of reading +static bool IsReadMode(const char *mode); -/* Checks if the file starts with the given prefix */ -static SDL_bool HasPrefix(const char *file, const char *prefix); +// Checks if the file starts with the given prefix +static bool HasPrefix(const char *file, const char *prefix); static FILE *TryOpenFile(const char *file, const char *mode); static FILE *TryOpenInRomfs(const char *file, const char *mode); @@ -37,12 +37,12 @@ static FILE *TryOpenInRomfs(const char *file, const char *mode); */ FILE *N3DS_FileOpen(const char *file, const char *mode) { - /* romfs are read-only */ + // romfs are read-only if (!IsReadMode(mode)) { return fopen(file, mode); } - /* If the path has an explicit prefix, we skip the guess work */ + // If the path has an explicit prefix, we skip the guess work if (HasPrefix(file, "romfs:/") || HasPrefix(file, "sdmc:/")) { return fopen(file, mode); } @@ -50,12 +50,12 @@ FILE *N3DS_FileOpen(const char *file, const char *mode) return TryOpenFile(file, mode); } -static SDL_bool IsReadMode(const char *mode) +static bool IsReadMode(const char *mode) { return SDL_strchr(mode, 'r') != NULL; } -static SDL_bool HasPrefix(const char *file, const char *prefix) +static bool HasPrefix(const char *file, const char *prefix) { return SDL_strncmp(prefix, file, SDL_strlen(prefix)) == 0; } diff --git a/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.h b/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.h index 4f8827fab..251d4803b 100644 --- a/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.h +++ b/libs/SDL3/src/file/n3ds/SDL_iostreamromfs.h @@ -25,4 +25,4 @@ FILE *N3DS_FileOpen(const char *file, const char *mode); -#endif /* SDL_iostreamromfs_h_ */ +#endif // SDL_iostreamromfs_h_ diff --git a/libs/SDL3/src/filesystem/SDL_filesystem.c b/libs/SDL3/src/filesystem/SDL_filesystem.c index 2a8667ffa..a29ae38fd 100644 --- a/libs/SDL3/src/filesystem/SDL_filesystem.c +++ b/libs/SDL3/src/filesystem/SDL_filesystem.c @@ -20,9 +20,12 @@ */ #include "SDL_internal.h" + +#include "SDL_filesystem_c.h" #include "SDL_sysfilesystem.h" +#include "../stdlib/SDL_sysstdlib.h" -int SDL_RemovePath(const char *path) +bool SDL_RemovePath(const char *path) { if (!path) { return SDL_InvalidParamError("path"); @@ -30,7 +33,7 @@ int SDL_RemovePath(const char *path) return SDL_SYS_RemovePath(path); } -int SDL_RenamePath(const char *oldpath, const char *newpath) +bool SDL_RenamePath(const char *oldpath, const char *newpath) { if (!oldpath) { return SDL_InvalidParamError("oldpath"); @@ -40,16 +43,75 @@ int SDL_RenamePath(const char *oldpath, const char *newpath) return SDL_SYS_RenamePath(oldpath, newpath); } -int SDL_CreateDirectory(const char *path) +bool SDL_CopyFile(const char *oldpath, const char *newpath) +{ + if (!oldpath) { + return SDL_InvalidParamError("oldpath"); + } else if (!newpath) { + return SDL_InvalidParamError("newpath"); + } + return SDL_SYS_CopyFile(oldpath, newpath); +} + +bool SDL_CreateDirectory(const char *path) { - /* TODO: Recursively create subdirectories */ if (!path) { return SDL_InvalidParamError("path"); } - return SDL_SYS_CreateDirectory(path); + + bool retval = SDL_SYS_CreateDirectory(path); + if (!retval && *path) { // maybe we're missing parent directories? + char *parents = SDL_strdup(path); + if (!parents) { + return false; // oh well. + } + + // in case there was a separator at the end of the path and it was + // upsetting something, chop it off. + const size_t slen = SDL_strlen(parents); + #ifdef SDL_PLATFORM_WINDOWS + if ((parents[slen - 1] == '/') || (parents[slen - 1] == '\\')) + #else + if (parents[slen - 1] == '/') + #endif + { + parents[slen - 1] = '\0'; + retval = SDL_SYS_CreateDirectory(parents); + } + + if (!retval) { + for (char *ptr = parents; *ptr; ptr++) { + const char ch = *ptr; + #ifdef SDL_PLATFORM_WINDOWS + const bool issep = (ch == '/') || (ch == '\\'); + if (issep && ((ptr - parents) == 2) && (parents[1] == ':')) { + continue; // it's just the drive letter, skip it. + } + #else + const bool issep = (ch == '/'); + #endif + + if (issep) { + *ptr = '\0'; + // (this does not fail if the path already exists as a directory.) + retval = SDL_SYS_CreateDirectory(parents); + if (!retval) { // still failing when making parents? Give up. + break; + } + *ptr = ch; + } + } + + // last chance: did it work this time? + retval = SDL_SYS_CreateDirectory(parents); + } + + SDL_free(parents); + } + return retval; } -int SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata) +bool SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata) { if (!path) { return SDL_InvalidParamError("path"); @@ -59,7 +121,7 @@ int SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback call return SDL_SYS_EnumerateDirectory(path, path, callback, userdata); } -int SDL_GetPathInfo(const char *path, SDL_PathInfo *info) +bool SDL_GetPathInfo(const char *path, SDL_PathInfo *info) { SDL_PathInfo dummy; @@ -74,3 +136,382 @@ int SDL_GetPathInfo(const char *path, SDL_PathInfo *info) return SDL_SYS_GetPathInfo(path, info); } + +static bool EverythingMatch(const char *pattern, const char *str, bool *matched_to_dir) +{ + SDL_assert(pattern == NULL); + SDL_assert(str != NULL); + SDL_assert(matched_to_dir != NULL); + + *matched_to_dir = true; + return true; // everything matches! +} + +// this is just '*' and '?', with '/' matching nothing. +static bool WildcardMatch(const char *pattern, const char *str, bool *matched_to_dir) +{ + SDL_assert(pattern != NULL); + SDL_assert(str != NULL); + SDL_assert(matched_to_dir != NULL); + + const char *str_backtrack = NULL; + const char *pattern_backtrack = NULL; + char sch_backtrack = 0; + char sch = *str; + char pch = *pattern; + + while (sch) { + if (pch == '*') { + str_backtrack = str; + pattern_backtrack = ++pattern; + sch_backtrack = sch; + pch = *pattern; + } else if (pch == sch) { + if (pch == '/') { + str_backtrack = pattern_backtrack = NULL; + } + sch = *(++str); + pch = *(++pattern); + } else if ((pch == '?') && (sch != '/')) { // end of string (checked at `while`) or path separator do not match '?'. + sch = *(++str); + pch = *(++pattern); + } else if (!pattern_backtrack || (sch_backtrack == '/')) { // we didn't have a match. Are we in a '*' and NOT on a path separator? Keep going. Otherwise, fail. + *matched_to_dir = false; + return false; + } else { // still here? Wasn't a match, but we're definitely in a '*' pattern. + str = ++str_backtrack; + pattern = pattern_backtrack; + sch_backtrack = sch; + sch = *str; + pch = *pattern; + } + } + + // '*' at the end can be ignored, they are allowed to match nothing. + while (pch == '*') { + pch = *(++pattern); + } + + *matched_to_dir = ((pch == '/') || (pch == '\0')); // end of string and the pattern is complete or failed at a '/'? We should descend into this directory. + + return (pch == '\0'); // survived the whole pattern? That's a match! +} + + +// Note that this will currently encode illegal codepoints: UTF-16 surrogates, 0xFFFE, and 0xFFFF. +// and a codepoint > 0x10FFFF will fail the same as if there wasn't enough memory. +// clean this up if you want to move this to SDL_string.c. +static size_t EncodeCodepointToUtf8(char *ptr, Uint32 cp, size_t remaining) +{ + if (cp < 0x80) { // fits in a single UTF-8 byte. + if (remaining) { + *ptr = (char) cp; + return 1; + } + } else if (cp < 0x800) { // fits in 2 bytes. + if (remaining >= 2) { + ptr[0] = (char) ((cp >> 6) | 128 | 64); + ptr[1] = (char) (cp & 0x3F) | 128; + return 2; + } + } else if (cp < 0x10000) { // fits in 3 bytes. + if (remaining >= 3) { + ptr[0] = (char) ((cp >> 12) | 128 | 64 | 32); + ptr[1] = (char) ((cp >> 6) & 0x3F) | 128; + ptr[2] = (char) (cp & 0x3F) | 128; + return 3; + } + } else if (cp <= 0x10FFFF) { // fits in 4 bytes. + if (remaining >= 4) { + ptr[0] = (char) ((cp >> 18) | 128 | 64 | 32 | 16); + ptr[1] = (char) ((cp >> 12) & 0x3F) | 128; + ptr[2] = (char) ((cp >> 6) & 0x3F) | 128; + ptr[3] = (char) (cp & 0x3F) | 128; + return 4; + } + } + + return 0; +} + +static char *CaseFoldUtf8String(const char *fname) +{ + SDL_assert(fname != NULL); + const size_t allocation = (SDL_strlen(fname) + 1) * 3 * 4; + char *result = (char *) SDL_malloc(allocation); // lazy: just allocating the max needed. + if (!result) { + return NULL; + } + + Uint32 codepoint; + char *ptr = result; + size_t remaining = allocation; + while ((codepoint = SDL_StepUTF8(&fname, NULL)) != 0) { + Uint32 folded[3]; + const int num_folded = SDL_CaseFoldUnicode(codepoint, folded); + SDL_assert(num_folded > 0); + SDL_assert(num_folded <= SDL_arraysize(folded)); + for (int i = 0; i < num_folded; i++) { + SDL_assert(remaining > 0); + const size_t rc = EncodeCodepointToUtf8(ptr, folded[i], remaining); + SDL_assert(rc > 0); + SDL_assert(rc < remaining); + remaining -= rc; + ptr += rc; + } + } + + SDL_assert(remaining > 0); + remaining--; + *ptr = '\0'; + + if (remaining > 0) { + SDL_assert(allocation > remaining); + ptr = (char *)SDL_realloc(result, allocation - remaining); // shrink it down. + if (ptr) { // shouldn't fail, but if it does, `result` is still valid. + result = ptr; + } + } + + return result; +} + + +typedef struct GlobDirCallbackData +{ + bool (*matcher)(const char *pattern, const char *str, bool *matched_to_dir); + const char *pattern; + int num_entries; + SDL_GlobFlags flags; + SDL_GlobEnumeratorFunc enumerator; + SDL_GlobGetPathInfoFunc getpathinfo; + void *fsuserdata; + size_t basedirlen; + SDL_IOStream *string_stream; +} GlobDirCallbackData; + +static SDL_EnumerationResult SDLCALL GlobDirectoryCallback(void *userdata, const char *dirname, const char *fname) +{ + SDL_assert(userdata != NULL); + SDL_assert(dirname != NULL); + SDL_assert(fname != NULL); + + //SDL_Log("GlobDirectoryCallback('%s', '%s')", dirname, fname); + + GlobDirCallbackData *data = (GlobDirCallbackData *) userdata; + + // !!! FIXME: if we're careful, we can keep a single buffer in `data` that we push and pop paths off the end of as we walk the tree, + // !!! FIXME: and only casefold the new pieces instead of allocating and folding full paths for all of this. + + char *fullpath = NULL; + if (SDL_asprintf(&fullpath, "%s/%s", dirname, fname) < 0) { + return SDL_ENUM_FAILURE; + } + + char *folded = NULL; + if (data->flags & SDL_GLOB_CASEINSENSITIVE) { + folded = CaseFoldUtf8String(fullpath); + if (!folded) { + return SDL_ENUM_FAILURE; + } + } + + bool matched_to_dir = false; + const bool matched = data->matcher(data->pattern, (folded ? folded : fullpath) + data->basedirlen, &matched_to_dir); + //SDL_Log("GlobDirectoryCallback: Considered %spath='%s' vs pattern='%s': %smatched (matched_to_dir=%s)", folded ? "(folded) " : "", (folded ? folded : fullpath) + data->basedirlen, data->pattern, matched ? "" : "NOT ", matched_to_dir ? "TRUE" : "FALSE"); + SDL_free(folded); + + if (matched) { + const char *subpath = fullpath + data->basedirlen; + const size_t slen = SDL_strlen(subpath) + 1; + if (SDL_WriteIO(data->string_stream, subpath, slen) != slen) { + SDL_free(fullpath); + return SDL_ENUM_FAILURE; // stop enumerating, return failure to the app. + } + data->num_entries++; + } + + SDL_EnumerationResult result = SDL_ENUM_CONTINUE; // keep enumerating by default. + if (matched_to_dir) { + SDL_PathInfo info; + if (data->getpathinfo(fullpath, &info, data->fsuserdata) && (info.type == SDL_PATHTYPE_DIRECTORY)) { + //SDL_Log("GlobDirectoryCallback: Descending into subdir '%s'", fname); + if (!data->enumerator(fullpath, GlobDirectoryCallback, data, data->fsuserdata)) { + result = SDL_ENUM_FAILURE; + } + } + } + + SDL_free(fullpath); + + return result; +} + +char **SDL_InternalGlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count, SDL_GlobEnumeratorFunc enumerator, SDL_GlobGetPathInfoFunc getpathinfo, void *userdata) +{ + int dummycount; + if (!count) { + count = &dummycount; + } + *count = 0; + + if (!path) { + SDL_InvalidParamError("path"); + return NULL; + } + + // if path ends with any '/', chop them off, so we don't confuse the pattern matcher later. + char *pathcpy = NULL; + size_t pathlen = SDL_strlen(path); + if ((pathlen > 1) && (path[pathlen-1] == '/')) { + pathcpy = SDL_strdup(path); + if (!pathcpy) { + return NULL; + } + char *ptr = &pathcpy[pathlen-1]; + while ((ptr >= pathcpy) && (*ptr == '/')) { + *(ptr--) = '\0'; + } + path = pathcpy; + } + + if (!pattern) { + flags &= ~SDL_GLOB_CASEINSENSITIVE; // avoid some unnecessary allocations and work later. + } + + char *folded = NULL; + if (flags & SDL_GLOB_CASEINSENSITIVE) { + SDL_assert(pattern != NULL); + folded = CaseFoldUtf8String(pattern); + if (!folded) { + SDL_free(pathcpy); + return NULL; + } + } + + GlobDirCallbackData data; + SDL_zero(data); + data.string_stream = SDL_IOFromDynamicMem(); + if (!data.string_stream) { + SDL_free(folded); + SDL_free(pathcpy); + return NULL; + } + + if (!pattern) { + data.matcher = EverythingMatch; // no pattern? Everything matches. + + // !!! FIXME + //} else if (flags & SDL_GLOB_GITIGNORE) { + // data.matcher = GitIgnoreMatch; + + } else { + data.matcher = WildcardMatch; + } + + data.pattern = folded ? folded : pattern; + data.flags = flags; + data.enumerator = enumerator; + data.getpathinfo = getpathinfo; + data.fsuserdata = userdata; + data.basedirlen = SDL_strlen(path) + 1; // +1 for the '/' we'll be adding. + + char **result = NULL; + if (data.enumerator(path, GlobDirectoryCallback, &data, data.fsuserdata)) { + const size_t streamlen = (size_t) SDL_GetIOSize(data.string_stream); + const size_t buflen = streamlen + ((data.num_entries + 1) * sizeof (char *)); // +1 for NULL terminator at end of array. + result = (char **) SDL_malloc(buflen); + if (result) { + if (data.num_entries > 0) { + Sint64 iorc = SDL_SeekIO(data.string_stream, 0, SDL_IO_SEEK_SET); + SDL_assert(iorc == 0); // this should never fail for a memory stream! + char *ptr = (char *) (result + (data.num_entries + 1)); + iorc = SDL_ReadIO(data.string_stream, ptr, streamlen); + SDL_assert(iorc == (Sint64) streamlen); // this should never fail for a memory stream! + for (int i = 0; i < data.num_entries; i++) { + result[i] = ptr; + ptr += SDL_strlen(ptr) + 1; + } + } + result[data.num_entries] = NULL; // NULL terminate the list. + *count = data.num_entries; + } + } + + SDL_CloseIO(data.string_stream); + SDL_free(folded); + SDL_free(pathcpy); + + return result; +} + +static bool GlobDirectoryGetPathInfo(const char *path, SDL_PathInfo *info, void *userdata) +{ + return SDL_GetPathInfo(path, info); +} + +static bool GlobDirectoryEnumerator(const char *path, SDL_EnumerateDirectoryCallback cb, void *cbuserdata, void *userdata) +{ + return SDL_EnumerateDirectory(path, cb, cbuserdata); +} + +char **SDL_GlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count) +{ + //SDL_Log("SDL_GlobDirectory('%s', '%s') ...", path, pattern); + return SDL_InternalGlobDirectory(path, pattern, flags, count, GlobDirectoryEnumerator, GlobDirectoryGetPathInfo, NULL); +} + + +static char *CachedBasePath = NULL; + +const char *SDL_GetBasePath(void) +{ + if (!CachedBasePath) { + CachedBasePath = SDL_SYS_GetBasePath(); + } + return CachedBasePath; +} + + +static char *CachedUserFolders[SDL_FOLDER_COUNT]; + +const char *SDL_GetUserFolder(SDL_Folder folder) +{ + const int idx = (int) folder; + if ((idx < 0) || (idx >= SDL_arraysize(CachedUserFolders))) { + SDL_InvalidParamError("folder"); + return NULL; + } + + if (!CachedUserFolders[idx]) { + CachedUserFolders[idx] = SDL_SYS_GetUserFolder(folder); + } + return CachedUserFolders[idx]; +} + + +char *SDL_GetPrefPath(const char *org, const char *app) +{ + char *path = SDL_SYS_GetPrefPath(org, app); + return path; +} + + +void SDL_InitFilesystem(void) +{ +} + +void SDL_QuitFilesystem(void) +{ + if (CachedBasePath) { + SDL_free(CachedBasePath); + CachedBasePath = NULL; + } + for (int i = 0; i < SDL_arraysize(CachedUserFolders); i++) { + if (CachedUserFolders[i]) { + SDL_free(CachedUserFolders[i]); + CachedUserFolders[i] = NULL; + } + } +} + diff --git a/libs/SDL3/src/thread/stdcpp/SDL_systhread_c.h b/libs/SDL3/src/filesystem/SDL_filesystem_c.h similarity index 86% rename from libs/SDL3/src/thread/stdcpp/SDL_systhread_c.h rename to libs/SDL3/src/filesystem/SDL_filesystem_c.h index 49aa4e85f..4cf8725c2 100644 --- a/libs/SDL3/src/thread/stdcpp/SDL_systhread_c.h +++ b/libs/SDL3/src/filesystem/SDL_filesystem_c.h @@ -18,7 +18,12 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ -#include "SDL_internal.h" -/* For a thread handle, use a void pointer to a std::thread */ -typedef void *SYS_ThreadHandle; +#ifndef SDL_filesystem_c_h_ +#define SDL_filesystem_c_h_ + +extern void SDL_InitFilesystem(void); +extern void SDL_QuitFilesystem(void); + +#endif + diff --git a/libs/SDL3/src/filesystem/SDL_sysfilesystem.h b/libs/SDL3/src/filesystem/SDL_sysfilesystem.h index 97f009fd2..e0fe9c604 100644 --- a/libs/SDL3/src/filesystem/SDL_sysfilesystem.h +++ b/libs/SDL3/src/filesystem/SDL_sysfilesystem.h @@ -22,11 +22,21 @@ #ifndef SDL_sysfilesystem_h_ #define SDL_sysfilesystem_h_ -int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata); -int SDL_SYS_RemovePath(const char *path); -int SDL_SYS_RenamePath(const char *oldpath, const char *newpath); -int SDL_SYS_CreateDirectory(const char *path); -int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info); +// return a string that we can SDL_free(). It will be cached at the higher level. +extern char *SDL_SYS_GetBasePath(void); +extern char *SDL_SYS_GetPrefPath(const char *org, const char *app); +extern char *SDL_SYS_GetUserFolder(SDL_Folder folder); + +extern bool SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata); +extern bool SDL_SYS_RemovePath(const char *path); +extern bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath); +extern bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath); +extern bool SDL_SYS_CreateDirectory(const char *path); +extern bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info); + +typedef bool (*SDL_GlobEnumeratorFunc)(const char *path, SDL_EnumerateDirectoryCallback cb, void *cbuserdata, void *userdata); +typedef bool (*SDL_GlobGetPathInfoFunc)(const char *path, SDL_PathInfo *info, void *userdata); +extern char **SDL_InternalGlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count, SDL_GlobEnumeratorFunc enumerator, SDL_GlobGetPathInfoFunc getpathinfo, void *userdata); #endif diff --git a/libs/SDL3/src/filesystem/android/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/android/SDL_sysfilesystem.c index 4d5fb5dec..b97bda2be 100644 --- a/libs/SDL3/src/filesystem/android/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/android/SDL_sysfilesystem.c @@ -23,20 +23,22 @@ #ifdef SDL_FILESYSTEM_ANDROID /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - /* The current working directory is / on Android */ + // The current working directory is / on Android SDL_Unsupported(); return NULL; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { - const char *path = SDL_AndroidGetInternalStoragePath(); + const char *path = SDL_GetAndroidInternalStoragePath(); if (path) { size_t pathlen = SDL_strlen(path) + 2; char *fullpath = (char *)SDL_malloc(pathlen); @@ -49,7 +51,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { /* TODO: see https://developer.android.com/reference/android/os/Environment#lfields and https://stackoverflow.com/questions/39332085/get-path-to-pictures-directory */ @@ -57,4 +59,4 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } -#endif /* SDL_FILESYSTEM_ANDROID */ +#endif // SDL_FILESYSTEM_ANDROID diff --git a/libs/SDL3/src/filesystem/cocoa/SDL_sysfilesystem.m b/libs/SDL3/src/filesystem/cocoa/SDL_sysfilesystem.m index aef0217d2..07a75ff74 100644 --- a/libs/SDL3/src/filesystem/cocoa/SDL_sysfilesystem.m +++ b/libs/SDL3/src/filesystem/cocoa/SDL_sysfilesystem.m @@ -23,19 +23,21 @@ #ifdef SDL_FILESYSTEM_COCOA /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include #include #include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { @autoreleasepool { NSBundle *bundle = [NSBundle mainBundle]; const char *baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String]; const char *base = NULL; - char *retval = NULL; + char *result = NULL; if (baseType == NULL) { baseType = "resource"; @@ -45,26 +47,26 @@ } else if (SDL_strcasecmp(baseType, "parent") == 0) { base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation]; } else { - /* this returns the exedir for non-bundled and the resourceDir for bundled apps */ + // this returns the exedir for non-bundled and the resourceDir for bundled apps base = [[bundle resourcePath] fileSystemRepresentation]; } if (base) { const size_t len = SDL_strlen(base) + 2; - retval = (char *)SDL_malloc(len); - if (retval != NULL) { - SDL_snprintf(retval, len, "%s/", base); + result = (char *)SDL_malloc(len); + if (result != NULL) { + SDL_snprintf(result, len, "%s/", base); } } - return retval; + return result; } } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { @autoreleasepool { - char *retval = NULL; + char *result = NULL; NSArray *array; if (!app) { @@ -87,53 +89,53 @@ * actually stick around, you'll need to use iCloud storage. */ { - static SDL_bool shown = SDL_FALSE; + static bool shown = false; if (!shown) { - shown = SDL_TRUE; + shown = true; SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.\n"); } } array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); -#endif /* !SDL_PLATFORM_TVOS */ +#endif // !SDL_PLATFORM_TVOS - if ([array count] > 0) { /* we only want the first item in the list. */ + if ([array count] > 0) { // we only want the first item in the list. NSString *str = [array objectAtIndex:0]; const char *base = [str fileSystemRepresentation]; if (base) { const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; - retval = (char *)SDL_malloc(len); - if (retval != NULL) { + result = (char *)SDL_malloc(len); + if (result != NULL) { char *ptr; if (*org) { - SDL_snprintf(retval, len, "%s/%s/%s/", base, org, app); + SDL_snprintf(result, len, "%s/%s/%s/", base, org, app); } else { - SDL_snprintf(retval, len, "%s/%s/", base, app); + SDL_snprintf(result, len, "%s/%s/", base, app); } - for (ptr = retval + 1; *ptr; ptr++) { + for (ptr = result + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; - mkdir(retval, 0700); + mkdir(result, 0700); *ptr = '/'; } } - mkdir(retval, 0700); + mkdir(result, 0700); } } } - return retval; + return result; } } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { @autoreleasepool { #ifdef SDL_PLATFORM_TVOS SDL_SetError("tvOS does not have persistent storage"); return NULL; #else - char *retval = NULL; + char *result = NULL; const char* base; NSArray *array; NSSearchPathDirectory dir; @@ -146,9 +148,10 @@ if (!base) { SDL_SetError("No $HOME environment variable available"); + return NULL; } - return SDL_strdup(base); + goto append_slash; case SDL_FOLDER_DESKTOP: dir = NSDesktopDirectory; @@ -209,23 +212,29 @@ return NULL; } - retval = SDL_strdup(base); - if (retval == NULL) { +append_slash: + result = SDL_malloc(SDL_strlen(base) + 2); + if (result == NULL) { + return NULL; + } + + if (SDL_snprintf(result, SDL_strlen(base) + 2, "%s/", base) < 0) { + SDL_SetError("Couldn't snprintf folder path for Cocoa: %s", base); + SDL_free(result); return NULL; } - for (ptr = retval + 1; *ptr; ptr++) { + for (ptr = result + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; - mkdir(retval, 0700); + mkdir(result, 0700); *ptr = '/'; } } - mkdir(retval, 0700); - return retval; -#endif /* SDL_PLATFORM_TVOS */ + return result; +#endif // SDL_PLATFORM_TVOS } } -#endif /* SDL_FILESYSTEM_COCOA */ +#endif // SDL_FILESYSTEM_COCOA diff --git a/libs/SDL3/src/filesystem/dummy/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/dummy/SDL_sysfilesystem.c index 442728223..0c74b5986 100644 --- a/libs/SDL3/src/filesystem/dummy/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/dummy/SDL_sysfilesystem.c @@ -23,24 +23,26 @@ #if defined(SDL_FILESYSTEM_DUMMY) || defined(SDL_FILESYSTEM_DISABLED) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines -char *SDL_GetBasePath(void) +#include "../SDL_sysfilesystem.h" + +char *SDL_SYS_GetBasePath(void) { SDL_Unsupported(); return NULL; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { SDL_Unsupported(); return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; } -#endif /* SDL_FILESYSTEM_DUMMY || SDL_FILESYSTEM_DISABLED */ +#endif // SDL_FILESYSTEM_DUMMY || SDL_FILESYSTEM_DISABLED diff --git a/libs/SDL3/src/filesystem/dummy/SDL_sysfsops.c b/libs/SDL3/src/filesystem/dummy/SDL_sysfsops.c index 63bd709a4..a7c40fe0b 100644 --- a/libs/SDL3/src/filesystem/dummy/SDL_sysfsops.c +++ b/libs/SDL3/src/filesystem/dummy/SDL_sysfsops.c @@ -23,29 +23,37 @@ #if defined(SDL_FSOPS_DUMMY) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// System dependent filesystem routines + #include "../SDL_sysfilesystem.h" -int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +bool SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +{ + return SDL_Unsupported(); +} + +bool SDL_SYS_RemovePath(const char *path) { return SDL_Unsupported(); } -int SDL_SYS_RemovePath(const char *path) +bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath) { return SDL_Unsupported(); } -int SDL_SYS_RenamePath(const char *oldpath, const char *newpath) +bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath) { return SDL_Unsupported(); } -int SDL_SYS_CreateDirectory(const char *path) +bool SDL_SYS_CreateDirectory(const char *path) { return SDL_Unsupported(); } -int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) { return SDL_Unsupported(); } diff --git a/libs/SDL3/src/filesystem/emscripten/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/emscripten/SDL_sysfilesystem.c index 69069e937..e10081c77 100644 --- a/libs/SDL3/src/filesystem/emscripten/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/emscripten/SDL_sysfilesystem.c @@ -23,22 +23,24 @@ #ifdef SDL_FILESYSTEM_EMSCRIPTEN /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" + #include #include #include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - char *retval = "/"; - return SDL_strdup(retval); + return SDL_strdup("/"); } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { const char *append = "/libsdl/"; - char *retval; + char *result; char *ptr = NULL; size_t len = 0; @@ -51,38 +53,38 @@ char *SDL_GetPrefPath(const char *org, const char *app) } len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; - retval = (char *)SDL_malloc(len); - if (!retval) { + result = (char *)SDL_malloc(len); + if (!result) { return NULL; } if (*org) { - SDL_snprintf(retval, len, "%s%s/%s/", append, org, app); + SDL_snprintf(result, len, "%s%s/%s/", append, org, app); } else { - SDL_snprintf(retval, len, "%s%s/", append, app); + SDL_snprintf(result, len, "%s%s/", append, app); } - for (ptr = retval + 1; *ptr; ptr++) { + for (ptr = result + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; - if (mkdir(retval, 0700) != 0 && errno != EEXIST) { + if (mkdir(result, 0700) != 0 && errno != EEXIST) { goto error; } *ptr = '/'; } } - if (mkdir(retval, 0700) != 0 && errno != EEXIST) { + if (mkdir(result, 0700) != 0 && errno != EEXIST) { error: - SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno)); - SDL_free(retval); + SDL_SetError("Couldn't create directory '%s': '%s'", result, strerror(errno)); + SDL_free(result); return NULL; } - return retval; + return result; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *home = NULL; @@ -97,7 +99,18 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - return SDL_strdup(home); + char *result = SDL_malloc(SDL_strlen(home) + 2); + if (!result) { + return NULL; + } + + if (SDL_snprintf(result, SDL_strlen(home) + 2, "%s/", home) < 0) { + SDL_SetError("Couldn't snprintf home path for Emscripten: %s", home); + SDL_free(result); + return NULL; + } + + return result; } -#endif /* SDL_FILESYSTEM_EMSCRIPTEN */ +#endif // SDL_FILESYSTEM_EMSCRIPTEN diff --git a/libs/SDL3/src/filesystem/gdk/SDL_sysfilesystem.cpp b/libs/SDL3/src/filesystem/gdk/SDL_sysfilesystem.cpp index 26f515746..d28110074 100644 --- a/libs/SDL3/src/filesystem/gdk/SDL_sysfilesystem.cpp +++ b/libs/SDL3/src/filesystem/gdk/SDL_sysfilesystem.cpp @@ -20,10 +20,12 @@ */ #include "SDL_internal.h" -#ifdef SDL_FILESYSTEM_XBOX - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +extern "C" { +#include "../SDL_sysfilesystem.h" +} #include "../../core/windows/SDL_windows.h" #include @@ -32,7 +34,7 @@ #include char * -SDL_GetBasePath(void) +SDL_SYS_GetBasePath(void) { /* NOTE: This function is a UTF8 version of the Win32 SDL_GetBasePath()! * The GDK actually _recommends_ the 'A' functions over the 'W' functions :o @@ -42,7 +44,7 @@ SDL_GetBasePath(void) DWORD len = 0; int i; - while (SDL_TRUE) { + while (true) { void *ptr = SDL_realloc(path, buflen * sizeof(CHAR)); if (!ptr) { SDL_free(path); @@ -52,13 +54,13 @@ SDL_GetBasePath(void) path = (CHAR *)ptr; len = GetModuleFileNameA(NULL, path, buflen); - /* if it truncated, then len >= buflen - 1 */ - /* if there was enough room (or failure), len < buflen - 1 */ + // if it truncated, then len >= buflen - 1 + // if there was enough room (or failure), len < buflen - 1 if (len < buflen - 1) { break; } - /* buffer too small? Try again. */ + // buffer too small? Try again. buflen *= 2; } @@ -74,34 +76,33 @@ SDL_GetBasePath(void) } } - SDL_assert(i > 0); /* Should have been an absolute path. */ - path[i + 1] = '\0'; /* chop off filename. */ + SDL_assert(i > 0); // Should have been an absolute path. + path[i + 1] = '\0'; // chop off filename. return path; } -char * -SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { XUserHandle user = NULL; XAsyncBlock block = { 0 }; char *folderPath; HRESULT result; const char *csid = SDL_GetHint("SDL_GDK_SERVICE_CONFIGURATION_ID"); - + if (!app) { SDL_InvalidParamError("app"); return NULL; } - /* This should be set before calling SDL_GetPrefPath! */ + // This should be set before calling SDL_GetPrefPath! if (!csid) { SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Set SDL_GDK_SERVICE_CONFIGURATION_ID before calling SDL_GetPrefPath!"); return SDL_strdup("T:\\"); } - if (SDL_GDKGetDefaultUser(&user) < 0) { - /* Error already set, just return */ + if (!SDL_GetGDKDefaultUser(&user)) { + // Error already set, just return return NULL; } @@ -134,6 +135,9 @@ SDL_GetPrefPath(const char *org, const char *app) return folderPath; } -#endif /* SDL_FILESYSTEM_XBOX */ - -/* vi: set ts=4 sw=4 expandtab: */ +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) +{ + SDL_Unsupported(); + return NULL; +} diff --git a/libs/SDL3/src/filesystem/haiku/SDL_sysfilesystem.cc b/libs/SDL3/src/filesystem/haiku/SDL_sysfilesystem.cc index 893e24a6d..60e7d5b09 100644 --- a/libs/SDL3/src/filesystem/haiku/SDL_sysfilesystem.cc +++ b/libs/SDL3/src/filesystem/haiku/SDL_sysfilesystem.cc @@ -23,7 +23,11 @@ #ifdef SDL_FILESYSTEM_HAIKU /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +extern "C" { +#include "../SDL_sysfilesystem.h" +} #include #include @@ -32,7 +36,7 @@ #include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { char name[MAXPATHLEN]; @@ -42,27 +46,26 @@ char *SDL_GetBasePath(void) BEntry entry(name, true); BPath path; - status_t rc = entry.GetPath(&path); /* (path) now has binary's path. */ + status_t rc = entry.GetPath(&path); // (path) now has binary's path. SDL_assert(rc == B_OK); - rc = path.GetParent(&path); /* chop filename, keep directory. */ + rc = path.GetParent(&path); // chop filename, keep directory. SDL_assert(rc == B_OK); const char *str = path.Path(); SDL_assert(str != NULL); const size_t len = SDL_strlen(str); - char *retval = (char *) SDL_malloc(len + 2); - if (!retval) { - return NULL; + char *result = (char *) SDL_malloc(len + 2); + if (result) { + SDL_memcpy(result, str, len); + result[len] = '/'; + result[len+1] = '\0'; } - SDL_memcpy(retval, str, len); - retval[len] = '/'; - retval[len+1] = '\0'; - return retval; + return result; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { // !!! FIXME: is there a better way to do this? const char *home = SDL_getenv("HOME"); @@ -81,23 +84,23 @@ char *SDL_GetPrefPath(const char *org, const char *app) ++append; // home empty or ends with separator, skip the one from append } len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; - char *retval = (char *) SDL_malloc(len); - if (retval) { + char *result = (char *) SDL_malloc(len); + if (result) { if (*org) { - SDL_snprintf(retval, len, "%s%s%s/%s/", home, append, org, app); + SDL_snprintf(result, len, "%s%s%s/%s/", home, append, org, app); } else { - SDL_snprintf(retval, len, "%s%s%s/", home, append, app); + SDL_snprintf(result, len, "%s%s%s/", home, append, app); } - create_directory(retval, 0700); // Haiku api: creates missing dirs + create_directory(result, 0700); // Haiku api: creates missing dirs } - return retval; + return result; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *home = NULL; - char *retval; + char *result; home = SDL_getenv("HOME"); if (!home) { @@ -107,18 +110,33 @@ char *SDL_GetUserFolder(SDL_Folder folder) switch (folder) { case SDL_FOLDER_HOME: - return SDL_strdup(home); + result = (char *) SDL_malloc(SDL_strlen(home) + 2); + if (!result) { + return NULL; + } - /* TODO: Is Haiku's desktop folder always ~/Desktop/ ? */ + if (SDL_snprintf(result, SDL_strlen(home) + 2, "%s/", home) < 0) { + SDL_SetError("Couldn't snprintf home path for Haiku: %s", home); + SDL_free(result); + return NULL; + } + + return result; + + // TODO: Is Haiku's desktop folder always ~/Desktop/ ? case SDL_FOLDER_DESKTOP: - retval = (char *) SDL_malloc(SDL_strlen(home) + 10); + result = (char *) SDL_malloc(SDL_strlen(home) + 10); + if (!result) { + return NULL; + } - if (retval) { - SDL_strlcpy(retval, home, SDL_strlen(home) + 10); - SDL_strlcat(retval, "/Desktop/", SDL_strlen(home) + 10); + if (SDL_snprintf(result, SDL_strlen(home) + 10, "%s/Desktop/", home) < 0) { + SDL_SetError("Couldn't snprintf desktop path for Haiku: %s/Desktop/", home); + SDL_free(result); + return NULL; } - return retval; + return result; case SDL_FOLDER_DOCUMENTS: case SDL_FOLDER_DOWNLOADS: @@ -135,4 +153,4 @@ char *SDL_GetUserFolder(SDL_Folder folder) } } -#endif /* SDL_FILESYSTEM_HAIKU */ +#endif // SDL_FILESYSTEM_HAIKU diff --git a/libs/SDL3/src/filesystem/n3ds/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/n3ds/SDL_sysfilesystem.c index 689a35bbb..e4a118c95 100644 --- a/libs/SDL3/src/filesystem/n3ds/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/n3ds/SDL_sysfilesystem.c @@ -23,22 +23,24 @@ #ifdef SDL_FILESYSTEM_N3DS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include <3ds.h> #include #include static char *MakePrefPath(const char *app); -static int CreatePrefPathDir(const char *pref); +static bool CreatePrefPathDir(const char *pref); -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { char *base_path = SDL_strdup("romfs:/"); return base_path; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { char *pref_path = NULL; if (!app) { @@ -51,7 +53,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) return NULL; } - if (CreatePrefPathDir(pref_path) < 0) { + if (!CreatePrefPathDir(pref_path)) { SDL_free(pref_path); return NULL; } @@ -59,8 +61,8 @@ char *SDL_GetPrefPath(const char *org, const char *app) return pref_path; } -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; @@ -75,14 +77,14 @@ static char *MakePrefPath(const char *app) return pref_path; } -static int CreatePrefPathDir(const char *pref) +static bool CreatePrefPathDir(const char *pref) { int result = mkdir(pref, 0666); if (result == -1 && errno != EEXIST) { return SDL_SetError("Failed to create '%s' (%s)", pref, strerror(errno)); } - return 0; + return true; } -#endif /* SDL_FILESYSTEM_N3DS */ +#endif // SDL_FILESYSTEM_N3DS diff --git a/libs/SDL3/src/filesystem/posix/SDL_sysfsops.c b/libs/SDL3/src/filesystem/posix/SDL_sysfsops.c index 857782eb6..36f539257 100644 --- a/libs/SDL3/src/filesystem/posix/SDL_sysfsops.c +++ b/libs/SDL3/src/filesystem/posix/SDL_sysfsops.c @@ -23,60 +23,119 @@ #if defined(SDL_FSOPS_POSIX) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" + #include #include #include #include #include -#include "../SDL_sysfilesystem.h" - -int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +bool SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) { - int retval = 1; + SDL_EnumerationResult result = SDL_ENUM_CONTINUE; DIR *dir = opendir(path); if (!dir) { - return SDL_SetError("Can't open directory: %s", strerror(errno)); + SDL_SetError("Can't open directory: %s", strerror(errno)); + return -1; } struct dirent *ent; - while ((retval == 1) && ((ent = readdir(dir)) != NULL)) + while ((result == SDL_ENUM_CONTINUE) && ((ent = readdir(dir)) != NULL)) { const char *name = ent->d_name; if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) { continue; } - retval = cb(userdata, dirname, name); + result = cb(userdata, dirname, name); } closedir(dir); - return retval; + return (result != SDL_ENUM_FAILURE); } -int SDL_SYS_RemovePath(const char *path) +bool SDL_SYS_RemovePath(const char *path) { int rc = remove(path); if (rc < 0) { if (errno == ENOENT) { // It's already gone, this is a success - return 0; + return true; } return SDL_SetError("Can't remove path: %s", strerror(errno)); } - return 0; + return true; } -int SDL_SYS_RenamePath(const char *oldpath, const char *newpath) +bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath) { if (rename(oldpath, newpath) < 0) { return SDL_SetError("Can't remove path: %s", strerror(errno)); } - return 0; + return true; +} + +bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath) +{ + char *buffer = NULL; + SDL_IOStream *input = NULL; + SDL_IOStream *output = NULL; + const size_t maxlen = 4096; + size_t len; + bool result = false; + + input = SDL_IOFromFile(oldpath, "rb"); + if (!input) { + goto done; + } + + output = SDL_IOFromFile(newpath, "wb"); + if (!output) { + goto done; + } + + buffer = (char *)SDL_malloc(maxlen); + if (!buffer) { + goto done; + } + + while ((len = SDL_ReadIO(input, buffer, maxlen)) > 0) { + if (SDL_WriteIO(output, buffer, len) < len) { + goto done; + } + } + if (SDL_GetIOStatus(input) != SDL_IO_STATUS_EOF) { + goto done; + } + + SDL_CloseIO(input); + input = NULL; + + if (!SDL_FlushIO(output)) { + goto done; + } + + result = SDL_CloseIO(output); + output = NULL; // it's gone, even if it failed. + +done: + if (output) { + SDL_CloseIO(output); + } + if (input) { + SDL_CloseIO(input); + } + SDL_free(buffer); + + return result; } -int SDL_SYS_CreateDirectory(const char *path) +bool SDL_SYS_CreateDirectory(const char *path) { const int rc = mkdir(path, 0770); if (rc < 0) { @@ -84,15 +143,15 @@ int SDL_SYS_CreateDirectory(const char *path) if (origerrno == EEXIST) { struct stat statbuf; if ((stat(path, &statbuf) == 0) && (S_ISDIR(statbuf.st_mode))) { - return 0; // it already exists and it's a directory, consider it success. + return true; // it already exists and it's a directory, consider it success. } } return SDL_SetError("Can't create directory: %s", strerror(origerrno)); } - return 0; + return true; } -int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) { struct stat statbuf; const int rc = stat(path, &statbuf); @@ -110,7 +169,7 @@ int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) } #if defined(HAVE_ST_MTIM) - /* POSIX.1-2008 standard */ + // POSIX.1-2008 standard info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctim.tv_sec) + statbuf.st_ctim.tv_nsec; info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtim.tv_sec) + statbuf.st_mtim.tv_nsec; info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atim.tv_sec) + statbuf.st_atim.tv_nsec; @@ -124,7 +183,7 @@ int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtime); info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atime); #endif - return 0; + return true; } #endif // SDL_FSOPS_POSIX diff --git a/libs/SDL3/src/filesystem/ps2/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/ps2/SDL_sysfilesystem.c index d5b2632b2..ee90aabfb 100644 --- a/libs/SDL3/src/filesystem/ps2/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/ps2/SDL_sysfilesystem.c @@ -20,35 +20,37 @@ */ #include "SDL_internal.h" -#include -#include - #ifdef SDL_FILESYSTEM_PS2 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" + +#include +#include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - char *retval; + char *result = NULL; size_t len; char cwd[FILENAME_MAX]; getcwd(cwd, sizeof(cwd)); - len = SDL_strlen(cwd) + 1; - retval = (char *)SDL_malloc(len); - if (retval) { - SDL_memcpy(retval, cwd, len); + len = SDL_strlen(cwd) + 2; + result = (char *)SDL_malloc(len); + if (result) { + SDL_snprintf(result, len, "%s/", cwd); } - return retval; + return result; } -/* Do a recursive mkdir of parents folders */ +// Do a recursive mkdir of parents folders static void recursive_mkdir(const char *dir) { char tmp[FILENAME_MAX]; - char *base = SDL_GetBasePath(); + const char *base = SDL_GetBasePath(); char *p = NULL; size_t len; @@ -62,7 +64,7 @@ static void recursive_mkdir(const char *dir) if (*p == '/') { *p = 0; // Just creating subfolders from current path - if (SDL_strstr(tmp, base) != NULL) { + if (base && SDL_strstr(tmp, base) != NULL) { mkdir(tmp, S_IRWXU); } @@ -70,43 +72,48 @@ static void recursive_mkdir(const char *dir) } } - SDL_free(base); mkdir(tmp, S_IRWXU); } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { - char *retval = NULL; + char *result = NULL; size_t len; - char *base = SDL_GetBasePath(); + if (!app) { SDL_InvalidParamError("app"); return NULL; } + if (!org) { org = ""; } + const char *base = SDL_GetBasePath(); + if (!base) { + return NULL; + } + len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; - retval = (char *)SDL_malloc(len); + result = (char *)SDL_malloc(len); + if (result) { + if (*org) { + SDL_snprintf(result, len, "%s%s/%s/", base, org, app); + } else { + SDL_snprintf(result, len, "%s%s/", base, app); + } - if (*org) { - SDL_snprintf(retval, len, "%s%s/%s/", base, org, app); - } else { - SDL_snprintf(retval, len, "%s%s/", base, app); + recursive_mkdir(result); } - SDL_free(base); - - recursive_mkdir(retval); - return retval; + return result; } -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; } -#endif /* SDL_FILESYSTEM_PS2 */ +#endif // SDL_FILESYSTEM_PS2 diff --git a/libs/SDL3/src/filesystem/psp/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/psp/SDL_sysfilesystem.c index 5386cb53a..8f8d1c3a4 100644 --- a/libs/SDL3/src/filesystem/psp/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/psp/SDL_sysfilesystem.c @@ -20,60 +20,70 @@ */ #include "SDL_internal.h" -#include -#include - #ifdef SDL_FILESYSTEM_PSP /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" + +#include +#include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - char *retval = NULL; + char *result = NULL; size_t len; char cwd[FILENAME_MAX]; getcwd(cwd, sizeof(cwd)); len = SDL_strlen(cwd) + 2; - retval = (char *)SDL_malloc(len); - SDL_snprintf(retval, len, "%s/", cwd); + result = (char *)SDL_malloc(len); + if (result) { + SDL_snprintf(result, len, "%s/", cwd); + } - return retval; + return result; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { - char *retval = NULL; + char *result = NULL; size_t len; - char *base = SDL_GetBasePath(); if (!app) { SDL_InvalidParamError("app"); return NULL; } + + const char *base = SDL_GetBasePath(); + if (!base) { + return NULL; + } + if (!org) { org = ""; } len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4; - retval = (char *)SDL_malloc(len); + result = (char *)SDL_malloc(len); + if (result) { + if (*org) { + SDL_snprintf(result, len, "%s%s/%s/", base, org, app); + } else { + SDL_snprintf(result, len, "%s%s/", base, app); + } - if (*org) { - SDL_snprintf(retval, len, "%s%s/%s/", base, org, app); - } else { - SDL_snprintf(retval, len, "%s%s/", base, app); + mkdir(result, 0755); } - SDL_free(base); - mkdir(retval, 0755); - return retval; + return result; } -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; } -#endif /* SDL_FILESYSTEM_PSP */ +#endif // SDL_FILESYSTEM_PSP diff --git a/libs/SDL3/src/filesystem/riscos/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/riscos/SDL_sysfilesystem.c index bbbc144b0..25e6e2388 100644 --- a/libs/SDL3/src/filesystem/riscos/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/riscos/SDL_sysfilesystem.c @@ -23,16 +23,18 @@ #ifdef SDL_FILESYSTEM_RISCOS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include #include #include -/* Wrapper around __unixify_std that uses SDL's memory allocators */ +// Wrapper around __unixify_std that uses SDL's memory allocators static char *SDL_unixify_std(const char *ro_path, char *buffer, size_t buf_len, int filetype) { - const char *const in_buf = buffer; /* = NULL if we allocate the buffer. */ + const char *const in_buf = buffer; // = NULL if we allocate the buffer. if (!buffer) { /* This matches the logic in __unixify, with an additional byte for the @@ -123,11 +125,11 @@ static _kernel_oserror *createDirectoryRecursive(char *path) return _kernel_swi(OS_File, ®s, ®s); } -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { _kernel_swi_regs regs; _kernel_oserror *error; - char *canon, *ptr, *retval; + char *canon, *ptr, *result; error = _kernel_swi(OS_GetEnv, ®s, ®s); if (error) { @@ -139,20 +141,20 @@ char *SDL_GetBasePath(void) return NULL; } - /* chop off filename. */ + // chop off filename. ptr = SDL_strrchr(canon, '.'); if (ptr) { *ptr = '\0'; } - retval = SDL_unixify_std(canon, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED); + result = SDL_unixify_std(canon, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED); SDL_free(canon); - return retval; + return result; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { - char *canon, *dir, *retval; + char *canon, *dir, *result; size_t len; _kernel_oserror *error; @@ -191,16 +193,16 @@ char *SDL_GetPrefPath(const char *org, const char *app) return NULL; } - retval = SDL_unixify_std(dir, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED); + result = SDL_unixify_std(dir, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED); SDL_free(dir); - return retval; + return result; } -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; } -#endif /* SDL_FILESYSTEM_RISCOS */ +#endif // SDL_FILESYSTEM_RISCOS diff --git a/libs/SDL3/src/filesystem/unix/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/unix/SDL_sysfilesystem.c index 72e061a0d..6f46a5b3f 100644 --- a/libs/SDL3/src/filesystem/unix/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/unix/SDL_sysfilesystem.c @@ -23,7 +23,9 @@ #ifdef SDL_FILESYSTEM_UNIX /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include #include @@ -42,48 +44,49 @@ static char *readSymLink(const char *path) { - char *retval = NULL; + char *result = NULL; ssize_t len = 64; ssize_t rc = -1; while (1) { - char *ptr = (char *)SDL_realloc(retval, (size_t)len); + char *ptr = (char *)SDL_realloc(result, (size_t)len); if (!ptr) { break; } - retval = ptr; + result = ptr; - rc = readlink(path, retval, len); + rc = readlink(path, result, len); if (rc == -1) { - break; /* not a symlink, i/o error, etc. */ + break; // not a symlink, i/o error, etc. } else if (rc < len) { - retval[rc] = '\0'; /* readlink doesn't null-terminate. */ - return retval; /* we're good to go. */ + result[rc] = '\0'; // readlink doesn't null-terminate. + return result; // we're good to go. } - len *= 2; /* grow buffer, try again. */ + len *= 2; // grow buffer, try again. } - SDL_free(retval); + SDL_free(result); return NULL; } #ifdef SDL_PLATFORM_OPENBSD static char *search_path_for_binary(const char *bin) { - char *envr = SDL_getenv("PATH"); + const char *envr_real = SDL_getenv("PATH"); + char *envr; size_t alloc_size; char *exe = NULL; char *start = envr; char *ptr; - if (!envr) { + if (!envr_real) { SDL_SetError("No $PATH set"); return NULL; } - envr = SDL_strdup(envr); + envr = SDL_strdup(envr_real); if (!envr) { return NULL; } @@ -94,48 +97,48 @@ static char *search_path_for_binary(const char *bin) exe = (char *)SDL_malloc(alloc_size); do { - ptr = SDL_strchr(start, ':'); /* find next $PATH separator. */ + ptr = SDL_strchr(start, ':'); // find next $PATH separator. if (ptr != start) { if (ptr) { *ptr = '\0'; } - /* build full binary path... */ + // build full binary path... SDL_snprintf(exe, alloc_size, "%s%s%s", start, (ptr && (ptr[-1] == '/')) ? "" : "/", bin); - if (access(exe, X_OK) == 0) { /* Exists as executable? We're done. */ + if (access(exe, X_OK) == 0) { // Exists as executable? We're done. SDL_free(envr); return exe; } } - start = ptr + 1; /* start points to beginning of next element. */ + start = ptr + 1; // start points to beginning of next element. } while (ptr); SDL_free(envr); SDL_free(exe); SDL_SetError("Process not found in $PATH"); - return NULL; /* doesn't exist in path. */ + return NULL; // doesn't exist in path. } #endif -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - char *retval = NULL; + char *result = NULL; #ifdef SDL_PLATFORM_FREEBSD char fullpath[PATH_MAX]; size_t buflen = sizeof(fullpath); const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; if (sysctl(mib, SDL_arraysize(mib), fullpath, &buflen, NULL, 0) != -1) { - retval = SDL_strdup(fullpath); - if (!retval) { + result = SDL_strdup(fullpath); + if (!result) { return NULL; } } #endif #ifdef SDL_PLATFORM_OPENBSD - /* Please note that this will fail if the process was launched with a relative path and $PWD + the cwd have changed, or argv is altered. So don't do that. Or add a new sysctl to OpenBSD. */ + // Please note that this will fail if the process was launched with a relative path and $PWD + the cwd have changed, or argv is altered. So don't do that. Or add a new sysctl to OpenBSD. char **cmdline; size_t len; const int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV }; @@ -156,7 +159,7 @@ char *SDL_GetBasePath(void) exe = cmdline[0]; pwddst = NULL; - if (SDL_strchr(exe, '/') == NULL) { /* not a relative or absolute path, check $PATH for it */ + if (SDL_strchr(exe, '/') == NULL) { // not a relative or absolute path, check $PATH for it exe = search_path_for_binary(cmdline[0]); } else { if (exe && *exe == '.') { @@ -170,11 +173,11 @@ char *SDL_GetBasePath(void) if (exe) { if (!pwddst) { if (realpath(exe, realpathbuf) != NULL) { - retval = realpathbuf; + result = realpathbuf; } } else { if (realpath(pwddst, realpathbuf) != NULL) { - retval = realpathbuf; + result = realpathbuf; } SDL_free(pwddst); } @@ -184,7 +187,7 @@ char *SDL_GetBasePath(void) } } - if (!retval) { + if (!result) { SDL_free(realpathbuf); } @@ -192,38 +195,38 @@ char *SDL_GetBasePath(void) } #endif - /* is a Linux-style /proc filesystem available? */ - if (!retval && (access("/proc", F_OK) == 0)) { + // is a Linux-style /proc filesystem available? + if (!result && (access("/proc", F_OK) == 0)) { /* !!! FIXME: after 2.0.6 ships, let's delete this code and just use the /proc/%llu version. There's no reason to have two copies of this plus all the #ifdefs. --ryan. */ #ifdef SDL_PLATFORM_FREEBSD - retval = readSymLink("/proc/curproc/file"); + result = readSymLink("/proc/curproc/file"); #elif defined(SDL_PLATFORM_NETBSD) - retval = readSymLink("/proc/curproc/exe"); + result = readSymLink("/proc/curproc/exe"); #elif defined(SDL_PLATFORM_SOLARIS) - retval = readSymLink("/proc/self/path/a.out"); + result = readSymLink("/proc/self/path/a.out"); #else - retval = readSymLink("/proc/self/exe"); /* linux. */ - if (!retval) { - /* older kernels don't have /proc/self ... try PID version... */ + result = readSymLink("/proc/self/exe"); // linux. + if (!result) { + // older kernels don't have /proc/self ... try PID version... char path[64]; const int rc = SDL_snprintf(path, sizeof(path), "/proc/%llu/exe", (unsigned long long)getpid()); if ((rc > 0) && (rc < sizeof(path))) { - retval = readSymLink(path); + result = readSymLink(path); } } #endif } -#ifdef SDL_PLATFORM_SOLARIS /* try this as a fallback if /proc didn't pan out */ - if (!retval) { +#ifdef SDL_PLATFORM_SOLARIS // try this as a fallback if /proc didn't pan out + if (!result) { const char *path = getexecname(); - if ((path) && (path[0] == '/')) { /* must be absolute path... */ - retval = SDL_strdup(path); - if (!retval) { + if ((path) && (path[0] == '/')) { // must be absolute path... + result = SDL_strdup(path); + if (!result) { return NULL; } } @@ -232,28 +235,28 @@ char *SDL_GetBasePath(void) /* If we had access to argv[0] here, we could check it for a path, or troll through $PATH looking for it, too. */ - if (retval) { /* chop off filename. */ - char *ptr = SDL_strrchr(retval, '/'); + if (result) { // chop off filename. + char *ptr = SDL_strrchr(result, '/'); if (ptr) { *(ptr + 1) = '\0'; - } else { /* shouldn't happen, but just in case... */ - SDL_free(retval); - retval = NULL; + } else { // shouldn't happen, but just in case... + SDL_free(result); + result = NULL; } } - if (retval) { - /* try to shrink buffer... */ - char *ptr = (char *)SDL_realloc(retval, SDL_strlen(retval) + 1); + if (result) { + // try to shrink buffer... + char *ptr = (char *)SDL_realloc(result, SDL_strlen(result) + 1); if (ptr) { - retval = ptr; /* oh well if it failed. */ + result = ptr; // oh well if it failed. } } - return retval; + return result; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { /* * We use XDG's base directory spec, even if you're not on Linux. @@ -264,7 +267,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) */ const char *envr = SDL_getenv("XDG_DATA_HOME"); const char *append; - char *retval = NULL; + char *result = NULL; char *ptr = NULL; size_t len = 0; @@ -277,10 +280,10 @@ char *SDL_GetPrefPath(const char *org, const char *app) } if (!envr) { - /* You end up with "$HOME/.local/share/Game Name 2" */ + // You end up with "$HOME/.local/share/Game Name 2" envr = SDL_getenv("HOME"); if (!envr) { - /* we could take heroic measures with /etc/passwd, but oh well. */ + // we could take heroic measures with /etc/passwd, but oh well. SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set"); return NULL; } @@ -295,34 +298,34 @@ char *SDL_GetPrefPath(const char *org, const char *app) } len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3; - retval = (char *)SDL_malloc(len); - if (!retval) { + result = (char *)SDL_malloc(len); + if (!result) { return NULL; } if (*org) { - (void)SDL_snprintf(retval, len, "%s%s%s/%s/", envr, append, org, app); + (void)SDL_snprintf(result, len, "%s%s%s/%s/", envr, append, org, app); } else { - (void)SDL_snprintf(retval, len, "%s%s%s/", envr, append, app); + (void)SDL_snprintf(result, len, "%s%s%s/", envr, append, app); } - for (ptr = retval + 1; *ptr; ptr++) { + for (ptr = result + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; - if (mkdir(retval, 0700) != 0 && errno != EEXIST) { + if (mkdir(result, 0700) != 0 && errno != EEXIST) { goto error; } *ptr = '/'; } } - if (mkdir(retval, 0700) != 0 && errno != EEXIST) { + if (mkdir(result, 0700) != 0 && errno != EEXIST) { error: - SDL_SetError("Couldn't create directory '%s': '%s'", retval, strerror(errno)); - SDL_free(retval); + SDL_SetError("Couldn't create directory '%s': '%s'", result, strerror(errno)); + SDL_free(result); return NULL; } - return retval; + return result; } /* @@ -356,7 +359,8 @@ char *SDL_GetPrefPath(const char *org, const char *app) static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback) { FILE *file; - char *home_dir, *config_home, *config_file; + const char *home_dir, *config_home; + char *config_file; char buffer[512]; char *user_dir; char *p, *d; @@ -364,12 +368,12 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa int relative; size_t l; - home_dir = SDL_getenv ("HOME"); + home_dir = SDL_getenv("HOME"); if (!home_dir) goto error; - config_home = SDL_getenv ("XDG_CONFIG_HOME"); + config_home = SDL_getenv("XDG_CONFIG_HOME"); if (!config_home || config_home[0] == 0) { l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1; @@ -399,7 +403,7 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa user_dir = NULL; while (fgets (buffer, sizeof (buffer), file)) { - /* Remove newline at end */ + // Remove newline at end len = SDL_strlen (buffer); if (len > 0 && buffer[len-1] == '\n') buffer[len-1] = 0; @@ -484,7 +488,8 @@ static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fa static char *xdg_user_dir_lookup (const char *type) { - char *dir, *home_dir, *user_dir; + const char *home_dir; + char *dir, *user_dir; dir = xdg_user_dir_lookup_with_fallback(type, NULL); if (dir) @@ -495,7 +500,7 @@ static char *xdg_user_dir_lookup (const char *type) if (!home_dir) return NULL; - /* Special case desktop for historical compatibility */ + // Special case desktop for historical compatibility if (SDL_strcmp(type, "DESKTOP") == 0) { size_t length = SDL_strlen(home_dir) + SDL_strlen("/Desktop") + 1; user_dir = (char*) SDL_malloc(length); @@ -510,10 +515,11 @@ static char *xdg_user_dir_lookup (const char *type) return NULL; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { const char *param = NULL; - char *retval; + char *result; + char *newresult; /* According to `man xdg-user-dir`, the possible values are: DESKTOP @@ -534,7 +540,8 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - return SDL_strdup(param); + result = SDL_strdup(param); + goto append_slash; case SDL_FOLDER_DESKTOP: param = "DESKTOP"; @@ -587,14 +594,25 @@ char *SDL_GetUserFolder(SDL_Folder folder) return NULL; } - retval = xdg_user_dir_lookup(param); + result = xdg_user_dir_lookup(param); - if (!retval) { + if (!result) { SDL_SetError("XDG directory not available"); return NULL; } - return retval; +append_slash: + newresult = (char *) SDL_realloc(result, SDL_strlen(result) + 2); + + if (!newresult) { + SDL_free(result); + return NULL; + } + + result = newresult; + SDL_strlcat(result, "/", SDL_strlen(result) + 2); + + return result; } -#endif /* SDL_FILESYSTEM_UNIX */ +#endif // SDL_FILESYSTEM_UNIX diff --git a/libs/SDL3/src/filesystem/vita/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/vita/SDL_sysfilesystem.c index 11d320ee4..f91618349 100644 --- a/libs/SDL3/src/filesystem/vita/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/vita/SDL_sysfilesystem.c @@ -23,7 +23,9 @@ #ifdef SDL_FILESYSTEM_VITA /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include #include @@ -34,17 +36,15 @@ #include #include -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { - const char *basepath = "app0:/"; - char *retval = SDL_strdup(basepath); - return retval; + return SDL_strdup("app0:/"); } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { const char *envr = "ux0:/data/"; - char *retval = NULL; + char *result = NULL; char *ptr = NULL; size_t len = 0; @@ -59,34 +59,34 @@ char *SDL_GetPrefPath(const char *org, const char *app) len = SDL_strlen(envr); len += SDL_strlen(org) + SDL_strlen(app) + 3; - retval = (char *)SDL_malloc(len); - if (!retval) { + result = (char *)SDL_malloc(len); + if (!result) { return NULL; } if (*org) { - SDL_snprintf(retval, len, "%s%s/%s/", envr, org, app); + SDL_snprintf(result, len, "%s%s/%s/", envr, org, app); } else { - SDL_snprintf(retval, len, "%s%s/", envr, app); + SDL_snprintf(result, len, "%s%s/", envr, app); } - for (ptr = retval + 1; *ptr; ptr++) { + for (ptr = result + 1; *ptr; ptr++) { if (*ptr == '/') { *ptr = '\0'; - sceIoMkdir(retval, 0777); + sceIoMkdir(result, 0777); *ptr = '/'; } } - sceIoMkdir(retval, 0777); + sceIoMkdir(result, 0777); - return retval; + return result; } -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) +// TODO +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { SDL_Unsupported(); return NULL; } -#endif /* SDL_FILESYSTEM_VITA */ +#endif // SDL_FILESYSTEM_VITA diff --git a/libs/SDL3/src/filesystem/windows/SDL_sysfilesystem.c b/libs/SDL3/src/filesystem/windows/SDL_sysfilesystem.c index f9e236161..cef3c2b02 100644 --- a/libs/SDL3/src/filesystem/windows/SDL_sysfilesystem.c +++ b/libs/SDL3/src/filesystem/windows/SDL_sysfilesystem.c @@ -23,13 +23,15 @@ #ifdef SDL_FILESYSTEM_WINDOWS /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* System dependent filesystem routines */ +// System dependent filesystem routines + +#include "../SDL_sysfilesystem.h" #include "../../core/windows/SDL_windows.h" #include #include -/* These aren't all defined in older SDKs, so define them here */ +// These aren't all defined in older SDKs, so define them here DEFINE_GUID(SDL_FOLDERID_Profile, 0x5E6C858F, 0x0E22, 0x4760, 0x9A, 0xFE, 0xEA, 0x33, 0x17, 0xB6, 0x71, 0x73); DEFINE_GUID(SDL_FOLDERID_Desktop, 0xB4BFCC3A, 0xDB2C, 0x424C, 0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41); DEFINE_GUID(SDL_FOLDERID_Documents, 0xFDD39AD0, 0x238F, 0x46AF, 0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7); @@ -41,15 +43,15 @@ DEFINE_GUID(SDL_FOLDERID_Screenshots, 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x DEFINE_GUID(SDL_FOLDERID_Templates, 0xA63293E8, 0x664E, 0x48DB, 0xA0, 0x79, 0xDF, 0x75, 0x9E, 0x05, 0x09, 0xF7); DEFINE_GUID(SDL_FOLDERID_Videos, 0x18989B1D, 0x99B5, 0x455B, 0x84, 0x1C, 0xAB, 0x7C, 0x74, 0xE4, 0xDD, 0xFC); -char *SDL_GetBasePath(void) +char *SDL_SYS_GetBasePath(void) { DWORD buflen = 128; WCHAR *path = NULL; - char *retval = NULL; + char *result = NULL; DWORD len = 0; int i; - while (SDL_TRUE) { + while (true) { void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR)); if (!ptr) { SDL_free(path); @@ -59,13 +61,13 @@ char *SDL_GetBasePath(void) path = (WCHAR *)ptr; len = GetModuleFileNameW(NULL, path, buflen); - /* if it truncated, then len >= buflen - 1 */ - /* if there was enough room (or failure), len < buflen - 1 */ + // if it truncated, then len >= buflen - 1 + // if there was enough room (or failure), len < buflen - 1 if (len < buflen - 1) { break; } - /* buffer too small? Try again. */ + // buffer too small? Try again. buflen *= 2; } @@ -81,16 +83,16 @@ char *SDL_GetBasePath(void) } } - SDL_assert(i > 0); /* Should have been an absolute path. */ - path[i + 1] = '\0'; /* chop off filename. */ + SDL_assert(i > 0); // Should have been an absolute path. + path[i + 1] = '\0'; // chop off filename. - retval = WIN_StringToUTF8W(path); + result = WIN_StringToUTF8W(path); SDL_free(path); - return retval; + return result; } -char *SDL_GetPrefPath(const char *org, const char *app) +char *SDL_SYS_GetPrefPath(const char *org, const char *app) { /* * Vista and later has a new API for this, but SHGetFolderPath works there, @@ -101,7 +103,7 @@ char *SDL_GetPrefPath(const char *org, const char *app) */ WCHAR path[MAX_PATH]; - char *retval = NULL; + char *result = NULL; WCHAR *worg = NULL; WCHAR *wapp = NULL; size_t new_wpath_len = 0; @@ -169,25 +171,25 @@ char *SDL_GetPrefPath(const char *org, const char *app) SDL_wcslcat(path, L"\\", SDL_arraysize(path)); - retval = WIN_StringToUTF8W(path); + result = WIN_StringToUTF8W(path); - return retval; + return result; } -char *SDL_GetUserFolder(SDL_Folder folder) +char *SDL_SYS_GetUserFolder(SDL_Folder folder) { typedef HRESULT (WINAPI *pfnSHGetKnownFolderPath)(REFGUID /* REFKNOWNFOLDERID */, DWORD, HANDLE, PWSTR*); HMODULE lib = LoadLibrary(L"Shell32.dll"); pfnSHGetKnownFolderPath pSHGetKnownFolderPath = NULL; - char *retval = NULL; + char *result = NULL; if (lib) { pSHGetKnownFolderPath = (pfnSHGetKnownFolderPath)GetProcAddress(lib, "SHGetKnownFolderPath"); } if (pSHGetKnownFolderPath) { - GUID type; /* KNOWNFOLDERID */ - HRESULT result; + GUID type; // KNOWNFOLDERID + HRESULT hr; wchar_t *path; switch (folder) { @@ -240,16 +242,16 @@ char *SDL_GetUserFolder(SDL_Folder folder) goto done; }; - result = pSHGetKnownFolderPath(&type, 0x00008000 /* KF_FLAG_CREATE */, NULL, &path); - if (SUCCEEDED(result)) { - retval = WIN_StringToUTF8W(path); + hr = pSHGetKnownFolderPath(&type, 0x00008000 /* KF_FLAG_CREATE */, NULL, &path); + if (SUCCEEDED(hr)) { + result = WIN_StringToUTF8W(path); } else { - WIN_SetErrorFromHRESULT("Couldn't get folder", result); + WIN_SetErrorFromHRESULT("Couldn't get folder", hr); } } else { int type; - HRESULT result; + HRESULT hr; wchar_t path[MAX_PATH]; switch (folder) { @@ -302,30 +304,43 @@ char *SDL_GetUserFolder(SDL_Folder folder) goto done; }; - /* Create the OS-specific folder if it doesn't already exist */ + // Create the OS-specific folder if it doesn't already exist type |= CSIDL_FLAG_CREATE; #if 0 - /* Apparently the oldest, but not supported in modern Windows */ - HRESULT result = SHGetSpecialFolderPath(NULL, path, type, TRUE); + // Apparently the oldest, but not supported in modern Windows + HRESULT hr = SHGetSpecialFolderPath(NULL, path, type, TRUE); #endif /* Windows 2000/XP and later, deprecated as of Windows 10 (still available), available in Wine (tested 6.0.3) */ - result = SHGetFolderPathW(NULL, type, NULL, SHGFP_TYPE_CURRENT, path); + hr = SHGetFolderPathW(NULL, type, NULL, SHGFP_TYPE_CURRENT, path); - /* use `== TRUE` for SHGetSpecialFolderPath */ - if (SUCCEEDED(result)) { - retval = WIN_StringToUTF8W(path); + // use `== TRUE` for SHGetSpecialFolderPath + if (SUCCEEDED(hr)) { + result = WIN_StringToUTF8W(path); } else { - WIN_SetErrorFromHRESULT("Couldn't get folder", result); + WIN_SetErrorFromHRESULT("Couldn't get folder", hr); } } + if (result) { + char *newresult = (char *) SDL_realloc(result, SDL_strlen(result) + 2); + + if (!newresult) { + SDL_free(result); + result = NULL; // will be returned + goto done; + } + + result = newresult; + SDL_strlcat(result, "\\", SDL_strlen(result) + 2); + } + done: if (lib) { FreeLibrary(lib); } - return retval; + return result; } -#endif /* SDL_FILESYSTEM_WINDOWS */ +#endif // SDL_FILESYSTEM_WINDOWS diff --git a/libs/SDL3/src/filesystem/windows/SDL_sysfsops.c b/libs/SDL3/src/filesystem/windows/SDL_sysfsops.c index b688365d1..f61f93952 100644 --- a/libs/SDL3/src/filesystem/windows/SDL_sysfsops.c +++ b/libs/SDL3/src/filesystem/windows/SDL_sysfsops.c @@ -23,26 +23,29 @@ #if defined(SDL_FSOPS_WINDOWS) +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +// System dependent filesystem routines + #include "../../core/windows/SDL_windows.h" #include "../SDL_sysfilesystem.h" -int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) +bool SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata) { - int retval = 1; + SDL_EnumerationResult result = SDL_ENUM_CONTINUE; if (*path == '\0') { // if empty (completely at the root), we need to enumerate drive letters. const DWORD drives = GetLogicalDrives(); char name[3] = { 0, ':', '\0' }; - for (int i = 'A'; (retval == 1) && (i <= 'Z'); i++) { + for (int i = 'A'; (result == SDL_ENUM_CONTINUE) && (i <= 'Z'); i++) { if (drives & (1 << (i - 'A'))) { name[0] = (char) i; - retval = cb(userdata, dirname, name); + result = cb(userdata, dirname, name); } } } else { const size_t patternlen = SDL_strlen(path) + 3; char *pattern = (char *) SDL_malloc(patternlen); if (!pattern) { - return -1; + return false; } // you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the @@ -50,10 +53,10 @@ int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_Enumer // also prevent any wildcards inserted by the app from being respected. SDL_snprintf(pattern, patternlen, "%s\\*", path); - WCHAR *wpattern = WIN_UTF8ToString(pattern); + WCHAR *wpattern = WIN_UTF8ToStringW(pattern); SDL_free(pattern); if (!wpattern) { - return -1; + return false; } WIN32_FIND_DATAW entw; @@ -72,33 +75,34 @@ int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_Enumer } } - char *utf8fn = WIN_StringToUTF8(fn); + char *utf8fn = WIN_StringToUTF8W(fn); if (!utf8fn) { - retval = -1; + result = SDL_ENUM_FAILURE; } else { - retval = cb(userdata, dirname, utf8fn); + result = cb(userdata, dirname, utf8fn); SDL_free(utf8fn); } - } while ((retval == 1) && (FindNextFileW(dir, &entw) != 0)); + } while ((result == SDL_ENUM_CONTINUE) && (FindNextFileW(dir, &entw) != 0)); FindClose(dir); } - return retval; + return (result != SDL_ENUM_FAILURE); } -int SDL_SYS_RemovePath(const char *path) +bool SDL_SYS_RemovePath(const char *path) { - WCHAR *wpath = WIN_UTF8ToString(path); + WCHAR *wpath = WIN_UTF8ToStringW(path); if (!wpath) { - return -1; + return false; } WIN32_FILE_ATTRIBUTE_DATA info; if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) { + SDL_free(wpath); if (GetLastError() == ERROR_FILE_NOT_FOUND) { // Note that ERROR_PATH_NOT_FOUND means a parent dir is missing, and we consider that an error. - return 0; // thing is already gone, call it a success. + return true; // thing is already gone, call it a success. } return WIN_SetError("Couldn't get path's attributes"); } @@ -106,45 +110,85 @@ int SDL_SYS_RemovePath(const char *path) const int isdir = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); const BOOL rc = isdir ? RemoveDirectoryW(wpath) : DeleteFileW(wpath); SDL_free(wpath); - return !rc ? WIN_SetError("Couldn't remove path") : 0; + if (!rc) { + return WIN_SetError("Couldn't remove path"); + } + return true; } -int SDL_SYS_RenamePath(const char *oldpath, const char *newpath) +bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath) { - WCHAR *woldpath = WIN_UTF8ToString(oldpath); + WCHAR *woldpath = WIN_UTF8ToStringW(oldpath); if (!woldpath) { - return -1; + return false; } - WCHAR *wnewpath = WIN_UTF8ToString(newpath); + WCHAR *wnewpath = WIN_UTF8ToStringW(newpath); if (!wnewpath) { SDL_free(woldpath); - return -1; + return false; } const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING); SDL_free(wnewpath); SDL_free(woldpath); - return !rc ? WIN_SetError("Couldn't rename path") : 0; + if (!rc) { + return WIN_SetError("Couldn't rename path"); + } + return true; } -int SDL_SYS_CreateDirectory(const char *path) +bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath) { - WCHAR *wpath = WIN_UTF8ToString(path); + WCHAR *woldpath = WIN_UTF8ToStringW(oldpath); + if (!woldpath) { + return false; + } + + WCHAR *wnewpath = WIN_UTF8ToStringW(newpath); + if (!wnewpath) { + SDL_free(woldpath); + return false; + } + + const BOOL rc = CopyFileExW(woldpath, wnewpath, NULL, NULL, NULL, COPY_FILE_ALLOW_DECRYPTED_DESTINATION|COPY_FILE_NO_BUFFERING); + SDL_free(wnewpath); + SDL_free(woldpath); + if (!rc) { + return WIN_SetError("Couldn't copy path"); + } + return true; +} + +bool SDL_SYS_CreateDirectory(const char *path) +{ + WCHAR *wpath = WIN_UTF8ToStringW(path); if (!wpath) { - return -1; + return false; + } + + DWORD rc = CreateDirectoryW(wpath, NULL); + if (!rc && (GetLastError() == ERROR_ALREADY_EXISTS)) { + WIN32_FILE_ATTRIBUTE_DATA winstat; + if (GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat)) { + if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + rc = 1; // exists and is already a directory: cool. + } + } } - const DWORD rc = CreateDirectoryW(wpath, NULL); SDL_free(wpath); - return !rc ? WIN_SetError("Couldn't create directory") : 0; + if (!rc) { + return WIN_SetError("Couldn't create directory"); + } + return true; } -int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) +bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) { - WCHAR *wpath = WIN_UTF8ToString(path); + WCHAR *wpath = WIN_UTF8ToStringW(path); if (!wpath) { - return -1; + return false; } WIN32_FILE_ATTRIBUTE_DATA winstat; @@ -169,7 +213,7 @@ int SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) info->modify_time = SDL_TimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime); info->access_time = SDL_TimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime); - return 1; + return true; } #endif // SDL_FSOPS_WINDOWS diff --git a/libs/SDL3/src/filesystem/winrt/SDL_sysfilesystem.cpp b/libs/SDL3/src/filesystem/winrt/SDL_sysfilesystem.cpp deleted file mode 100644 index a21679993..000000000 --- a/libs/SDL3/src/filesystem/winrt/SDL_sysfilesystem.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/* - Simple DirectMedia Layer - Copyright (C) 1997-2024 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" - -/* TODO, WinRT: remove the need to compile this with C++/CX (/ZW) extensions, and if possible, without C++ at all - */ - -#ifdef SDL_PLATFORM_WINRT - -extern "C" { -#include "../../core/windows/SDL_windows.h" -} - -#include -#include - -using namespace std; -using namespace Windows::Storage; - -extern "C" const wchar_t * -SDL_WinRTGetFSPathUNICODE(SDL_WinRT_Path pathType) -{ - switch (pathType) { - case SDL_WINRT_PATH_INSTALLED_LOCATION: - { - static wstring path; - if (path.empty()) { -#if defined(NTDDI_WIN10_19H1) && (NTDDI_VERSION >= NTDDI_WIN10_19H1) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) /* Only PC supports mods */ - /* Windows 1903 supports mods, via the EffectiveLocation API */ - if (Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8, 0)) { - path = Windows::ApplicationModel::Package::Current->EffectiveLocation->Path->Data(); - } else { - path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data(); - } -#else - path = Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data(); -#endif - } - return path.c_str(); - } - - case SDL_WINRT_PATH_LOCAL_FOLDER: - { - static wstring path; - if (path.empty()) { - path = ApplicationData::Current->LocalFolder->Path->Data(); - } - return path.c_str(); - } - -#if !SDL_WINAPI_FAMILY_PHONE || NTDDI_VERSION > NTDDI_WIN8 - case SDL_WINRT_PATH_ROAMING_FOLDER: - { - static wstring path; - if (path.empty()) { - path = ApplicationData::Current->RoamingFolder->Path->Data(); - } - return path.c_str(); - } - - case SDL_WINRT_PATH_TEMP_FOLDER: - { - static wstring path; - if (path.empty()) { - path = ApplicationData::Current->TemporaryFolder->Path->Data(); - } - return path.c_str(); - } -#endif - - default: - break; - } - - SDL_Unsupported(); - return NULL; -} - -extern "C" const char * -SDL_WinRTGetFSPathUTF8(SDL_WinRT_Path pathType) -{ - typedef unordered_map UTF8PathMap; - static UTF8PathMap utf8Paths; - - UTF8PathMap::iterator searchResult = utf8Paths.find(pathType); - if (searchResult != utf8Paths.end()) { - return searchResult->second.c_str(); - } - - const wchar_t *ucs2Path = SDL_WinRTGetFSPathUNICODE(pathType); - if (!ucs2Path) { - return NULL; - } - - char *utf8Path = WIN_StringToUTF8(ucs2Path); - utf8Paths[pathType] = utf8Path; - SDL_free(utf8Path); - return utf8Paths[pathType].c_str(); -} - -extern "C" char * -SDL_GetBasePath(void) -{ - const char *srcPath = SDL_WinRTGetFSPathUTF8(SDL_WINRT_PATH_INSTALLED_LOCATION); - size_t destPathLen; - char *destPath = NULL; - - if (!srcPath) { - SDL_SetError("Couldn't locate our basepath: %s", SDL_GetError()); - return NULL; - } - - destPathLen = SDL_strlen(srcPath) + 2; - destPath = (char *)SDL_malloc(destPathLen); - if (!destPath) { - return NULL; - } - - SDL_snprintf(destPath, destPathLen, "%s\\", srcPath); - return destPath; -} - -extern "C" char * -SDL_GetPrefPath(const char *org, const char *app) -{ - /* WinRT note: The 'SHGetFolderPath' API that is used in Windows 7 and - * earlier is not available on WinRT or Windows Phone. WinRT provides - * a similar API, but SHGetFolderPath can't be called, at least not - * without violating Microsoft's app-store requirements. - */ - - const WCHAR *srcPath = NULL; - WCHAR path[MAX_PATH]; - char *retval = NULL; - WCHAR *worg = NULL; - WCHAR *wapp = NULL; - size_t new_wpath_len = 0; - BOOL api_result = FALSE; - - if (!app) { - SDL_InvalidParamError("app"); - return NULL; - } - if (!org) { - org = ""; - } - - srcPath = SDL_WinRTGetFSPathUNICODE(SDL_WINRT_PATH_LOCAL_FOLDER); - if (!srcPath) { - SDL_SetError("Unable to find a source path"); - return NULL; - } - - if (SDL_wcslen(srcPath) >= MAX_PATH) { - SDL_SetError("Path too long."); - return NULL; - } - SDL_wcslcpy(path, srcPath, SDL_arraysize(path)); - - worg = WIN_UTF8ToString(org); - if (!worg) { - return NULL; - } - - wapp = WIN_UTF8ToString(app); - if (!wapp) { - SDL_free(worg); - return NULL; - } - - new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3; - - if ((new_wpath_len + 1) > MAX_PATH) { - SDL_free(worg); - SDL_free(wapp); - SDL_SetError("Path too long."); - return NULL; - } - - if (*worg) { - SDL_wcslcat(path, L"\\", new_wpath_len + 1); - SDL_wcslcat(path, worg, new_wpath_len + 1); - SDL_free(worg); - } - - api_result = CreateDirectoryW(path, NULL); - if (api_result == FALSE) { - if (GetLastError() != ERROR_ALREADY_EXISTS) { - SDL_free(wapp); - WIN_SetError("Couldn't create a prefpath."); - return NULL; - } - } - - SDL_wcslcat(path, L"\\", new_wpath_len + 1); - SDL_wcslcat(path, wapp, new_wpath_len + 1); - SDL_free(wapp); - - api_result = CreateDirectoryW(path, NULL); - if (api_result == FALSE) { - if (GetLastError() != ERROR_ALREADY_EXISTS) { - WIN_SetError("Couldn't create a prefpath."); - return NULL; - } - } - - SDL_wcslcat(path, L"\\", new_wpath_len + 1); - - retval = WIN_StringToUTF8(path); - - return retval; -} - -/* TODO */ -char *SDL_GetUserFolder(SDL_Folder folder) -{ - SDL_Unsupported(); - return NULL; -} - -#endif /* SDL_PLATFORM_WINRT */ diff --git a/libs/SDL3/src/gpu/SDL_gpu.c b/libs/SDL3/src/gpu/SDL_gpu.c new file mode 100644 index 000000000..a1210a0ea --- /dev/null +++ b/libs/SDL3/src/gpu/SDL_gpu.c @@ -0,0 +1,2755 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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" +#include "SDL_sysgpu.h" + +// FIXME: This could probably use SDL_ObjectValid +#define CHECK_DEVICE_MAGIC(device, retval) \ + if (device == NULL) { \ + SDL_SetError("Invalid GPU device"); \ + return retval; \ + } + +#define CHECK_COMMAND_BUFFER \ + if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ + SDL_assert_release(!"Command buffer already submitted!"); \ + return; \ + } + +#define CHECK_COMMAND_BUFFER_RETURN_FALSE \ + if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ + SDL_assert_release(!"Command buffer already submitted!"); \ + return false; \ + } + +#define CHECK_COMMAND_BUFFER_RETURN_NULL \ + if (((CommandBufferCommonHeader *)command_buffer)->submitted) { \ + SDL_assert_release(!"Command buffer already submitted!"); \ + return NULL; \ + } + +#define CHECK_ANY_PASS_IN_PROGRESS(msg, retval) \ + if ( \ + ((CommandBufferCommonHeader *)command_buffer)->render_pass.in_progress || \ + ((CommandBufferCommonHeader *)command_buffer)->compute_pass.in_progress || \ + ((CommandBufferCommonHeader *)command_buffer)->copy_pass.in_progress) { \ + SDL_assert_release(!msg); \ + return retval; \ + } + +#define CHECK_RENDERPASS \ + if (!((Pass *)render_pass)->in_progress) { \ + SDL_assert_release(!"Render pass not in progress!"); \ + return; \ + } + +#define CHECK_GRAPHICS_PIPELINE_BOUND \ + if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \ + SDL_assert_release(!"Graphics pipeline not bound!"); \ + return; \ + } + +#define CHECK_COMPUTEPASS \ + if (!((Pass *)compute_pass)->in_progress) { \ + SDL_assert_release(!"Compute pass not in progress!"); \ + return; \ + } + +#define CHECK_COMPUTE_PIPELINE_BOUND \ + if (!((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->compute_pipeline_bound) { \ + SDL_assert_release(!"Compute pipeline not bound!"); \ + return; \ + } + +#define CHECK_COPYPASS \ + if (!((Pass *)copy_pass)->in_progress) { \ + SDL_assert_release(!"Copy pass not in progress!"); \ + return; \ + } + +#define CHECK_TEXTUREFORMAT_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_TEXTUREFORMAT_INVALID || enumval >= SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid texture format enum!"); \ + return retval; \ + } + +#define CHECK_VERTEXELEMENTFORMAT_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_VERTEXELEMENTFORMAT_INVALID || enumval >= SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid vertex format enum!"); \ + return retval; \ + } + +#define CHECK_COMPAREOP_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_COMPAREOP_INVALID || enumval >= SDL_GPU_COMPAREOP_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid compare op enum!"); \ + return retval; \ + } + +#define CHECK_STENCILOP_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_STENCILOP_INVALID || enumval >= SDL_GPU_STENCILOP_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid stencil op enum!"); \ + return retval; \ + } + +#define CHECK_BLENDOP_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_BLENDOP_INVALID || enumval >= SDL_GPU_BLENDOP_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid blend op enum!"); \ + return retval; \ + } + +#define CHECK_BLENDFACTOR_ENUM_INVALID(enumval, retval) \ + if (enumval <= SDL_GPU_BLENDFACTOR_INVALID || enumval >= SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid blend factor enum!"); \ + return retval; \ + } + +#define CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(enumval, retval) \ + if (enumval < 0 || enumval >= SDL_GPU_SWAPCHAINCOMPOSITION_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid swapchain composition enum!"); \ + return retval; \ + } + +#define CHECK_PRESENTMODE_ENUM_INVALID(enumval, retval) \ + if (enumval < 0 || enumval >= SDL_GPU_PRESENTMODE_MAX_ENUM_VALUE) { \ + SDL_assert_release(!"Invalid present mode enum!"); \ + return retval; \ + } + +#define COMMAND_BUFFER_DEVICE \ + ((CommandBufferCommonHeader *)command_buffer)->device + +#define RENDERPASS_COMMAND_BUFFER \ + ((Pass *)render_pass)->command_buffer + +#define RENDERPASS_DEVICE \ + ((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->device + +#define COMPUTEPASS_COMMAND_BUFFER \ + ((Pass *)compute_pass)->command_buffer + +#define COMPUTEPASS_DEVICE \ + ((CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER)->device + +#define COPYPASS_COMMAND_BUFFER \ + ((Pass *)copy_pass)->command_buffer + +#define COPYPASS_DEVICE \ + ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->device + +// Drivers + +#ifndef SDL_GPU_DISABLED +static const SDL_GPUBootstrap *backends[] = { +#ifdef SDL_GPU_METAL + &MetalDriver, +#endif +#ifdef SDL_GPU_VULKAN + &VulkanDriver, +#endif +#ifdef SDL_GPU_D3D12 + &D3D12Driver, +#endif +#ifdef SDL_GPU_D3D11 + &D3D11Driver, +#endif + NULL +}; +#endif // !SDL_GPU_DISABLED + +// Internal Utility Functions + +SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline( + SDL_GPUDevice *device, + SDL_GPUTextureType source_texture_type, + SDL_GPUTextureFormat destination_format, + SDL_GPUShader *blit_vertex_shader, + SDL_GPUShader *blit_from_2d_shader, + SDL_GPUShader *blit_from_2d_array_shader, + SDL_GPUShader *blit_from_3d_shader, + SDL_GPUShader *blit_from_cube_shader, + SDL_GPUShader *blit_from_cube_array_shader, + BlitPipelineCacheEntry **blit_pipelines, + Uint32 *blit_pipeline_count, + Uint32 *blit_pipeline_capacity) +{ + SDL_GPUGraphicsPipelineCreateInfo blit_pipeline_create_info; + SDL_GPUColorTargetDescription color_target_desc; + SDL_GPUGraphicsPipeline *pipeline; + + if (blit_pipeline_count == NULL) { + // use pre-created, format-agnostic pipelines + return (*blit_pipelines)[source_texture_type].pipeline; + } + + for (Uint32 i = 0; i < *blit_pipeline_count; i += 1) { + if ((*blit_pipelines)[i].type == source_texture_type && (*blit_pipelines)[i].format == destination_format) { + return (*blit_pipelines)[i].pipeline; + } + } + + // No pipeline found, we'll need to make one! + SDL_zero(blit_pipeline_create_info); + + SDL_zero(color_target_desc); + color_target_desc.blend_state.color_write_mask = 0xF; + color_target_desc.format = destination_format; + + blit_pipeline_create_info.target_info.color_target_descriptions = &color_target_desc; + blit_pipeline_create_info.target_info.num_color_targets = 1; + blit_pipeline_create_info.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary + blit_pipeline_create_info.target_info.has_depth_stencil_target = false; + + blit_pipeline_create_info.vertex_shader = blit_vertex_shader; + if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE) { + blit_pipeline_create_info.fragment_shader = blit_from_cube_shader; + } else if (source_texture_type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + blit_pipeline_create_info.fragment_shader = blit_from_cube_array_shader; + } else if (source_texture_type == SDL_GPU_TEXTURETYPE_2D_ARRAY) { + blit_pipeline_create_info.fragment_shader = blit_from_2d_array_shader; + } else if (source_texture_type == SDL_GPU_TEXTURETYPE_3D) { + blit_pipeline_create_info.fragment_shader = blit_from_3d_shader; + } else { + blit_pipeline_create_info.fragment_shader = blit_from_2d_shader; + } + + blit_pipeline_create_info.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1; + blit_pipeline_create_info.multisample_state.enable_mask = false; + + blit_pipeline_create_info.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + + pipeline = SDL_CreateGPUGraphicsPipeline( + device, + &blit_pipeline_create_info); + + if (pipeline == NULL) { + SDL_SetError("Failed to create GPU pipeline for blit"); + return NULL; + } + + // Cache the new pipeline + EXPAND_ARRAY_IF_NEEDED( + (*blit_pipelines), + BlitPipelineCacheEntry, + *blit_pipeline_count + 1, + *blit_pipeline_capacity, + *blit_pipeline_capacity * 2) + + (*blit_pipelines)[*blit_pipeline_count].pipeline = pipeline; + (*blit_pipelines)[*blit_pipeline_count].type = source_texture_type; + (*blit_pipelines)[*blit_pipeline_count].format = destination_format; + *blit_pipeline_count += 1; + + return pipeline; +} + +void SDL_GPU_BlitCommon( + SDL_GPUCommandBuffer *command_buffer, + const SDL_GPUBlitInfo *info, + SDL_GPUSampler *blit_linear_sampler, + SDL_GPUSampler *blit_nearest_sampler, + SDL_GPUShader *blit_vertex_shader, + SDL_GPUShader *blit_from_2d_shader, + SDL_GPUShader *blit_from_2d_array_shader, + SDL_GPUShader *blit_from_3d_shader, + SDL_GPUShader *blit_from_cube_shader, + SDL_GPUShader *blit_from_cube_array_shader, + BlitPipelineCacheEntry **blit_pipelines, + Uint32 *blit_pipeline_count, + Uint32 *blit_pipeline_capacity) +{ + CommandBufferCommonHeader *cmdbufHeader = (CommandBufferCommonHeader *)command_buffer; + SDL_GPURenderPass *render_pass; + TextureCommonHeader *src_header = (TextureCommonHeader *)info->source.texture; + TextureCommonHeader *dst_header = (TextureCommonHeader *)info->destination.texture; + SDL_GPUGraphicsPipeline *blit_pipeline; + SDL_GPUColorTargetInfo color_target_info; + SDL_GPUViewport viewport; + SDL_GPUTextureSamplerBinding texture_sampler_binding; + BlitFragmentUniforms blit_fragment_uniforms; + Uint32 layer_divisor; + + blit_pipeline = SDL_GPU_FetchBlitPipeline( + cmdbufHeader->device, + src_header->info.type, + dst_header->info.format, + blit_vertex_shader, + blit_from_2d_shader, + blit_from_2d_array_shader, + blit_from_3d_shader, + blit_from_cube_shader, + blit_from_cube_array_shader, + blit_pipelines, + blit_pipeline_count, + blit_pipeline_capacity); + + SDL_assert(blit_pipeline != NULL); + + color_target_info.load_op = info->load_op; + color_target_info.clear_color = info->clear_color; + color_target_info.store_op = SDL_GPU_STOREOP_STORE; + + color_target_info.texture = info->destination.texture; + color_target_info.mip_level = info->destination.mip_level; + color_target_info.layer_or_depth_plane = info->destination.layer_or_depth_plane; + color_target_info.cycle = info->cycle; + + render_pass = SDL_BeginGPURenderPass( + command_buffer, + &color_target_info, + 1, + NULL); + + viewport.x = (float)info->destination.x; + viewport.y = (float)info->destination.y; + viewport.w = (float)info->destination.w; + viewport.h = (float)info->destination.h; + viewport.min_depth = 0; + viewport.max_depth = 1; + + SDL_SetGPUViewport( + render_pass, + &viewport); + + SDL_BindGPUGraphicsPipeline( + render_pass, + blit_pipeline); + + texture_sampler_binding.texture = info->source.texture; + texture_sampler_binding.sampler = + info->filter == SDL_GPU_FILTER_NEAREST ? blit_nearest_sampler : blit_linear_sampler; + + SDL_BindGPUFragmentSamplers( + render_pass, + 0, + &texture_sampler_binding, + 1); + + blit_fragment_uniforms.left = (float)info->source.x / (src_header->info.width >> info->source.mip_level); + blit_fragment_uniforms.top = (float)info->source.y / (src_header->info.height >> info->source.mip_level); + blit_fragment_uniforms.width = (float)info->source.w / (src_header->info.width >> info->source.mip_level); + blit_fragment_uniforms.height = (float)info->source.h / (src_header->info.height >> info->source.mip_level); + blit_fragment_uniforms.mip_level = info->source.mip_level; + + layer_divisor = (src_header->info.type == SDL_GPU_TEXTURETYPE_3D) ? src_header->info.layer_count_or_depth : 1; + blit_fragment_uniforms.layer_or_depth = (float)info->source.layer_or_depth_plane / layer_divisor; + + if (info->flip_mode & SDL_FLIP_HORIZONTAL) { + blit_fragment_uniforms.left += blit_fragment_uniforms.width; + blit_fragment_uniforms.width *= -1; + } + + if (info->flip_mode & SDL_FLIP_VERTICAL) { + blit_fragment_uniforms.top += blit_fragment_uniforms.height; + blit_fragment_uniforms.height *= -1; + } + + SDL_PushGPUFragmentUniformData( + command_buffer, + 0, + &blit_fragment_uniforms, + sizeof(blit_fragment_uniforms)); + + SDL_DrawGPUPrimitives(render_pass, 3, 1, 0, 0); + SDL_EndGPURenderPass(render_pass); +} + +// Driver Functions + +#ifndef SDL_GPU_DISABLED +static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props) +{ + Uint32 i; + SDL_GPUShaderFormat format_flags = 0; + const char *gpudriver; + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + + if (_this == NULL) { + SDL_SetError("Video subsystem not initialized"); + return NULL; + } + + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_PRIVATE; + } + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_SPIRV; + } + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_DXBC; + } + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_DXIL; + } + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_MSL; + } + if (SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOL, false)) { + format_flags |= SDL_GPU_SHADERFORMAT_METALLIB; + } + + gpudriver = SDL_GetHint(SDL_HINT_GPU_DRIVER); + if (gpudriver == NULL) { + gpudriver = SDL_GetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, NULL); + } + + // Environment/Properties override... + if (gpudriver != NULL) { + for (i = 0; backends[i]; i += 1) { + if (SDL_strcasecmp(gpudriver, backends[i]->name) == 0) { + if (!(backends[i]->shader_formats & format_flags)) { + SDL_SetError("Required shader format for backend %s not provided!", gpudriver); + return NULL; + } + if (backends[i]->PrepareDriver(_this)) { + return backends[i]; + } + } + } + + SDL_SetError("SDL_HINT_GPU_DRIVER %s unsupported!", gpudriver); + return NULL; + } + + for (i = 0; backends[i]; i += 1) { + if ((backends[i]->shader_formats & format_flags) == 0) { + // Don't select a backend which doesn't support the app's shaders. + continue; + } + if (backends[i]->PrepareDriver(_this)) { + return backends[i]; + } + } + + SDL_SetError("No supported SDL_GPU backend found!"); + return NULL; +} + +static void SDL_GPU_FillProperties( + SDL_PropertiesID props, + SDL_GPUShaderFormat format_flags, + bool debug_mode, + const char *name) +{ + if (format_flags & SDL_GPU_SHADERFORMAT_PRIVATE) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOL, true); + } + if (format_flags & SDL_GPU_SHADERFORMAT_SPIRV) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOL, true); + } + if (format_flags & SDL_GPU_SHADERFORMAT_DXBC) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOL, true); + } + if (format_flags & SDL_GPU_SHADERFORMAT_DXIL) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOL, true); + } + if (format_flags & SDL_GPU_SHADERFORMAT_MSL) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOL, true); + } + if (format_flags & SDL_GPU_SHADERFORMAT_METALLIB) { + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOL, true); + } + SDL_SetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, debug_mode); + SDL_SetStringProperty(props, SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING, name); +} +#endif // SDL_GPU_DISABLED + +bool SDL_GPUSupportsShaderFormats( + SDL_GPUShaderFormat format_flags, + const char *name) +{ +#ifndef SDL_GPU_DISABLED + bool result; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_GPU_FillProperties(props, format_flags, false, name); + result = SDL_GPUSupportsProperties(props); + SDL_DestroyProperties(props); + return result; +#else + SDL_SetError("SDL not built with GPU support"); + return false; +#endif +} + +bool SDL_GPUSupportsProperties(SDL_PropertiesID props) +{ +#ifndef SDL_GPU_DISABLED + return (SDL_GPUSelectBackend(props) != NULL); +#else + SDL_SetError("SDL not built with GPU support"); + return false; +#endif +} + +SDL_GPUDevice *SDL_CreateGPUDevice( + SDL_GPUShaderFormat format_flags, + bool debug_mode, + const char *name) +{ +#ifndef SDL_GPU_DISABLED + SDL_GPUDevice *result; + SDL_PropertiesID props = SDL_CreateProperties(); + SDL_GPU_FillProperties(props, format_flags, debug_mode, name); + result = SDL_CreateGPUDeviceWithProperties(props); + SDL_DestroyProperties(props); + return result; +#else + SDL_SetError("SDL not built with GPU support"); + return NULL; +#endif // SDL_GPU_DISABLED +} + +SDL_GPUDevice *SDL_CreateGPUDeviceWithProperties(SDL_PropertiesID props) +{ +#ifndef SDL_GPU_DISABLED + bool debug_mode; + bool preferLowPower; + SDL_GPUDevice *result = NULL; + const SDL_GPUBootstrap *selectedBackend; + + selectedBackend = SDL_GPUSelectBackend(props); + if (selectedBackend != NULL) { + debug_mode = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOL, true); + preferLowPower = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOL, false); + + result = selectedBackend->CreateDevice(debug_mode, preferLowPower, props); + if (result != NULL) { + result->backend = selectedBackend->name; + result->shader_formats = selectedBackend->shader_formats; + result->debug_mode = debug_mode; + } + } + return result; +#else + SDL_SetError("SDL not built with GPU support"); + return NULL; +#endif // SDL_GPU_DISABLED +} + +void SDL_DestroyGPUDevice(SDL_GPUDevice *device) +{ + CHECK_DEVICE_MAGIC(device, ); + + device->DestroyDevice(device); +} + +int SDL_GetNumGPUDrivers(void) +{ +#ifndef SDL_GPU_DISABLED + return SDL_arraysize(backends) - 1; +#else + return 0; +#endif +} + +const char * SDL_GetGPUDriver(int index) +{ + if (index < 0 || index >= SDL_GetNumGPUDrivers()) { + SDL_InvalidParamError("index"); + return NULL; + } +#ifndef SDL_GPU_DISABLED + return backends[index]->name; +#else + return NULL; +#endif +} + +const char * SDL_GetGPUDeviceDriver(SDL_GPUDevice *device) +{ + CHECK_DEVICE_MAGIC(device, NULL); + + return device->backend; +} + +SDL_GPUShaderFormat SDL_GetGPUShaderFormats(SDL_GPUDevice *device) +{ + CHECK_DEVICE_MAGIC(device, SDL_GPU_SHADERFORMAT_INVALID); + + return device->shader_formats; +} + +Uint32 SDL_GPUTextureFormatTexelBlockSize( + SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM: + return 8; + case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT: + case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT: + case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB: + return 16; + case SDL_GPU_TEXTUREFORMAT_R8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8_SNORM: + case SDL_GPU_TEXTUREFORMAT_A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8_UINT: + return 1; + case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: + case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: + case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8_UINT: + case SDL_GPU_TEXTUREFORMAT_R16_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16_SNORM: + case SDL_GPU_TEXTUREFORMAT_R16_UINT: + return 2; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_R32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: + case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM: + return 4; + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM: + case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: + return 8; + case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: + return 16; + default: + SDL_assert_release(!"Unrecognized TextureFormat!"); + return 0; + } +} + +bool SDL_GPUTextureSupportsFormat( + SDL_GPUDevice *device, + SDL_GPUTextureFormat format, + SDL_GPUTextureType type, + SDL_GPUTextureUsageFlags usage) +{ + CHECK_DEVICE_MAGIC(device, false); + + if (device->debug_mode) { + CHECK_TEXTUREFORMAT_ENUM_INVALID(format, false) + } + + return device->SupportsTextureFormat( + device->driverData, + format, + type, + usage); +} + +bool SDL_GPUTextureSupportsSampleCount( + SDL_GPUDevice *device, + SDL_GPUTextureFormat format, + SDL_GPUSampleCount sample_count) +{ + CHECK_DEVICE_MAGIC(device, 0); + + if (device->debug_mode) { + CHECK_TEXTUREFORMAT_ENUM_INVALID(format, 0) + } + + return device->SupportsSampleCount( + device->driverData, + format, + sample_count); +} + +// State Creation + +SDL_GPUComputePipeline *SDL_CreateGPUComputePipeline( + SDL_GPUDevice *device, + const SDL_GPUComputePipelineCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + if (device->debug_mode) { + if (createinfo->format == SDL_GPU_SHADERFORMAT_INVALID) { + SDL_assert_release(!"Shader format cannot be INVALID!"); + return NULL; + } + if (!(createinfo->format & device->shader_formats)) { + SDL_assert_release(!"Incompatible shader format for GPU backend"); + return NULL; + } + if (createinfo->num_readwrite_storage_textures > MAX_COMPUTE_WRITE_TEXTURES) { + SDL_assert_release(!"Compute pipeline write-only texture count cannot be higher than 8!"); + return NULL; + } + if (createinfo->num_readwrite_storage_buffers > MAX_COMPUTE_WRITE_BUFFERS) { + SDL_assert_release(!"Compute pipeline write-only buffer count cannot be higher than 8!"); + return NULL; + } + if (createinfo->threadcount_x == 0 || + createinfo->threadcount_y == 0 || + createinfo->threadcount_z == 0) { + SDL_assert_release(!"Compute pipeline threadCount dimensions must be at least 1!"); + return NULL; + } + } + + return device->CreateComputePipeline( + device->driverData, + createinfo); +} + +SDL_GPUGraphicsPipeline *SDL_CreateGPUGraphicsPipeline( + SDL_GPUDevice *device, + const SDL_GPUGraphicsPipelineCreateInfo *graphicsPipelineCreateInfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (graphicsPipelineCreateInfo == NULL) { + SDL_InvalidParamError("graphicsPipelineCreateInfo"); + return NULL; + } + + if (device->debug_mode) { + if (graphicsPipelineCreateInfo->target_info.num_color_targets > 0 && graphicsPipelineCreateInfo->target_info.color_target_descriptions == NULL) { + SDL_assert_release(!"Color target descriptions array pointer cannot be NULL if num_color_targets is greater than zero!"); + return NULL; + } + for (Uint32 i = 0; i < graphicsPipelineCreateInfo->target_info.num_color_targets; i += 1) { + CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].format, NULL); + if (IsDepthFormat(graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].format)) { + SDL_assert_release(!"Color target formats cannot be a depth format!"); + return NULL; + } + if (graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].blend_state.enable_blend) { + const SDL_GPUColorTargetBlendState *blend_state = &graphicsPipelineCreateInfo->target_info.color_target_descriptions[i].blend_state; + CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->src_color_blendfactor, NULL) + CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->dst_color_blendfactor, NULL) + CHECK_BLENDOP_ENUM_INVALID(blend_state->color_blend_op, NULL) + CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->src_alpha_blendfactor, NULL) + CHECK_BLENDFACTOR_ENUM_INVALID(blend_state->dst_alpha_blendfactor, NULL) + CHECK_BLENDOP_ENUM_INVALID(blend_state->alpha_blend_op, NULL) + } + } + if (graphicsPipelineCreateInfo->target_info.has_depth_stencil_target) { + CHECK_TEXTUREFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->target_info.depth_stencil_format, NULL); + if (!IsDepthFormat(graphicsPipelineCreateInfo->target_info.depth_stencil_format)) { + SDL_assert_release(!"Depth-stencil target format must be a depth format!"); + return NULL; + } + } + if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_buffers > 0 && graphicsPipelineCreateInfo->vertex_input_state.vertex_buffer_descriptions == NULL) { + SDL_assert_release(!"Vertex buffer descriptions array pointer cannot be NULL!"); + return NULL; + } + if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_buffers > MAX_VERTEX_BUFFERS) { + SDL_assert_release(!"The number of vertex buffer descriptions in a vertex input state must not exceed 16!"); + return NULL; + } + if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes > 0 && graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes == NULL) { + SDL_assert_release(!"Vertex attributes array pointer cannot be NULL!"); + return NULL; + } + if (graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes > MAX_VERTEX_ATTRIBUTES) { + SDL_assert_release(!"The number of vertex attributes in a vertex input state must not exceed 16!"); + return NULL; + } + Uint32 locations[MAX_VERTEX_ATTRIBUTES]; + for (Uint32 i = 0; i < graphicsPipelineCreateInfo->vertex_input_state.num_vertex_attributes; i += 1) { + CHECK_VERTEXELEMENTFORMAT_ENUM_INVALID(graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes[i].format, NULL); + + locations[i] = graphicsPipelineCreateInfo->vertex_input_state.vertex_attributes[i].location; + for (Uint32 j = 0; j < i; j += 1) { + if (locations[j] == locations[i]) { + SDL_assert_release(!"Each vertex attribute location in a vertex input state must be unique!"); + } + } + } + if (graphicsPipelineCreateInfo->depth_stencil_state.enable_depth_test) { + CHECK_COMPAREOP_ENUM_INVALID(graphicsPipelineCreateInfo->depth_stencil_state.compare_op, NULL) + } + if (graphicsPipelineCreateInfo->depth_stencil_state.enable_stencil_test) { + const SDL_GPUStencilOpState *stencil_state = &graphicsPipelineCreateInfo->depth_stencil_state.back_stencil_state; + CHECK_COMPAREOP_ENUM_INVALID(stencil_state->compare_op, NULL) + CHECK_STENCILOP_ENUM_INVALID(stencil_state->fail_op, NULL) + CHECK_STENCILOP_ENUM_INVALID(stencil_state->pass_op, NULL) + CHECK_STENCILOP_ENUM_INVALID(stencil_state->depth_fail_op, NULL) + } + } + + return device->CreateGraphicsPipeline( + device->driverData, + graphicsPipelineCreateInfo); +} + +SDL_GPUSampler *SDL_CreateGPUSampler( + SDL_GPUDevice *device, + const SDL_GPUSamplerCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + return device->CreateSampler( + device->driverData, + createinfo); +} + +SDL_GPUShader *SDL_CreateGPUShader( + SDL_GPUDevice *device, + const SDL_GPUShaderCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + if (device->debug_mode) { + if (createinfo->format == SDL_GPU_SHADERFORMAT_INVALID) { + SDL_assert_release(!"Shader format cannot be INVALID!"); + return NULL; + } + if (!(createinfo->format & device->shader_formats)) { + SDL_assert_release(!"Incompatible shader format for GPU backend"); + return NULL; + } + } + + return device->CreateShader( + device->driverData, + createinfo); +} + +SDL_GPUTexture *SDL_CreateGPUTexture( + SDL_GPUDevice *device, + const SDL_GPUTextureCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + if (device->debug_mode) { + bool failed = false; + + const Uint32 MAX_2D_DIMENSION = 16384; + const Uint32 MAX_3D_DIMENSION = 2048; + + // Common checks for all texture types + CHECK_TEXTUREFORMAT_ENUM_INVALID(createinfo->format, NULL) + + if (createinfo->width <= 0 || createinfo->height <= 0 || createinfo->layer_count_or_depth <= 0) { + SDL_assert_release(!"For any texture: width, height, and layer_count_or_depth must be >= 1"); + failed = true; + } + if (createinfo->num_levels <= 0) { + SDL_assert_release(!"For any texture: num_levels must be >= 1"); + failed = true; + } + if ((createinfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) && (createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER)) { + SDL_assert_release(!"For any texture: usage cannot contain both GRAPHICS_STORAGE_READ and SAMPLER"); + failed = true; + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && + (createinfo->usage & (SDL_GPU_TEXTUREUSAGE_SAMPLER | + SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | + SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ | + SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE))) { + SDL_assert_release(!"For multisample textures: usage cannot contain SAMPLER or STORAGE flags"); + failed = true; + } + if (IsDepthFormat(createinfo->format) && (createinfo->usage & ~(SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER))) { + SDL_assert_release(!"For depth textures: usage cannot contain any flags except for DEPTH_STENCIL_TARGET and SAMPLER"); + failed = true; + } + if (IsIntegerFormat(createinfo->format) && (createinfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER)) { + SDL_assert_release(!"For any texture: usage cannot contain SAMPLER for textures with an integer format"); + failed = true; + } + + if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE) { + // Cubemap validation + if (createinfo->width != createinfo->height) { + SDL_assert_release(!"For cube textures: width and height must be identical"); + failed = true; + } + if (createinfo->width > MAX_2D_DIMENSION || createinfo->height > MAX_2D_DIMENSION) { + SDL_assert_release(!"For cube textures: width and height must be <= 16384"); + failed = true; + } + if (createinfo->layer_count_or_depth != 6) { + SDL_assert_release(!"For cube textures: layer_count_or_depth must be 6"); + failed = true; + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"For cube textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); + failed = true; + } + if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_CUBE, createinfo->usage)) { + SDL_assert_release(!"For cube textures: the format is unsupported for the given usage"); + failed = true; + } + } else if (createinfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + // Cubemap array validation + if (createinfo->width != createinfo->height) { + SDL_assert_release(!"For cube array textures: width and height must be identical"); + failed = true; + } + if (createinfo->width > MAX_2D_DIMENSION || createinfo->height > MAX_2D_DIMENSION) { + SDL_assert_release(!"For cube array textures: width and height must be <= 16384"); + failed = true; + } + if (createinfo->layer_count_or_depth % 6 != 0) { + SDL_assert_release(!"For cube array textures: layer_count_or_depth must be a multiple of 6"); + failed = true; + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"For cube array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); + failed = true; + } + if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_CUBE_ARRAY, createinfo->usage)) { + SDL_assert_release(!"For cube array textures: the format is unsupported for the given usage"); + failed = true; + } + } else if (createinfo->type == SDL_GPU_TEXTURETYPE_3D) { + // 3D Texture Validation + if (createinfo->width > MAX_3D_DIMENSION || createinfo->height > MAX_3D_DIMENSION || createinfo->layer_count_or_depth > MAX_3D_DIMENSION) { + SDL_assert_release(!"For 3D textures: width, height, and layer_count_or_depth must be <= 2048"); + failed = true; + } + if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) { + SDL_assert_release(!"For 3D textures: usage must not contain DEPTH_STENCIL_TARGET"); + failed = true; + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"For 3D textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); + failed = true; + } + if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_3D, createinfo->usage)) { + SDL_assert_release(!"For 3D textures: the format is unsupported for the given usage"); + failed = true; + } + } else { + if (createinfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) { + // Array Texture Validation + if (createinfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) { + SDL_assert_release(!"For array textures: usage must not contain DEPTH_STENCIL_TARGET"); + failed = true; + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"For array textures: sample_count must be SDL_GPU_SAMPLECOUNT_1"); + failed = true; + } + } + if (createinfo->sample_count > SDL_GPU_SAMPLECOUNT_1 && createinfo->num_levels > 1) { + SDL_assert_release(!"For 2D multisample textures: num_levels must be 1"); + failed = true; + } + if (!SDL_GPUTextureSupportsFormat(device, createinfo->format, SDL_GPU_TEXTURETYPE_2D, createinfo->usage)) { + SDL_assert_release(!"For 2D textures: the format is unsupported for the given usage"); + failed = true; + } + } + + if (failed) { + return NULL; + } + } + + return device->CreateTexture( + device->driverData, + createinfo); +} + +SDL_GPUBuffer *SDL_CreateGPUBuffer( + SDL_GPUDevice *device, + const SDL_GPUBufferCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + return device->CreateBuffer( + device->driverData, + createinfo->usage, + createinfo->size); +} + +SDL_GPUTransferBuffer *SDL_CreateGPUTransferBuffer( + SDL_GPUDevice *device, + const SDL_GPUTransferBufferCreateInfo *createinfo) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (createinfo == NULL) { + SDL_InvalidParamError("createinfo"); + return NULL; + } + + return device->CreateTransferBuffer( + device->driverData, + createinfo->usage, + createinfo->size); +} + +// Debug Naming + +void SDL_SetGPUBufferName( + SDL_GPUDevice *device, + SDL_GPUBuffer *buffer, + const char *text) +{ + CHECK_DEVICE_MAGIC(device, ); + if (buffer == NULL) { + SDL_InvalidParamError("buffer"); + return; + } + if (text == NULL) { + SDL_InvalidParamError("text"); + } + + device->SetBufferName( + device->driverData, + buffer, + text); +} + +void SDL_SetGPUTextureName( + SDL_GPUDevice *device, + SDL_GPUTexture *texture, + const char *text) +{ + CHECK_DEVICE_MAGIC(device, ); + if (texture == NULL) { + SDL_InvalidParamError("texture"); + return; + } + if (text == NULL) { + SDL_InvalidParamError("text"); + } + + device->SetTextureName( + device->driverData, + texture, + text); +} + +void SDL_InsertGPUDebugLabel( + SDL_GPUCommandBuffer *command_buffer, + const char *text) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (text == NULL) { + SDL_InvalidParamError("text"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->InsertDebugLabel( + command_buffer, + text); +} + +void SDL_PushGPUDebugGroup( + SDL_GPUCommandBuffer *command_buffer, + const char *name) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (name == NULL) { + SDL_InvalidParamError("name"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->PushDebugGroup( + command_buffer, + name); +} + +void SDL_PopGPUDebugGroup( + SDL_GPUCommandBuffer *command_buffer) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->PopDebugGroup( + command_buffer); +} + +// Disposal + +void SDL_ReleaseGPUTexture( + SDL_GPUDevice *device, + SDL_GPUTexture *texture) +{ + CHECK_DEVICE_MAGIC(device, ); + if (texture == NULL) { + return; + } + + device->ReleaseTexture( + device->driverData, + texture); +} + +void SDL_ReleaseGPUSampler( + SDL_GPUDevice *device, + SDL_GPUSampler *sampler) +{ + CHECK_DEVICE_MAGIC(device, ); + if (sampler == NULL) { + return; + } + + device->ReleaseSampler( + device->driverData, + sampler); +} + +void SDL_ReleaseGPUBuffer( + SDL_GPUDevice *device, + SDL_GPUBuffer *buffer) +{ + CHECK_DEVICE_MAGIC(device, ); + if (buffer == NULL) { + return; + } + + device->ReleaseBuffer( + device->driverData, + buffer); +} + +void SDL_ReleaseGPUTransferBuffer( + SDL_GPUDevice *device, + SDL_GPUTransferBuffer *transfer_buffer) +{ + CHECK_DEVICE_MAGIC(device, ); + if (transfer_buffer == NULL) { + return; + } + + device->ReleaseTransferBuffer( + device->driverData, + transfer_buffer); +} + +void SDL_ReleaseGPUShader( + SDL_GPUDevice *device, + SDL_GPUShader *shader) +{ + CHECK_DEVICE_MAGIC(device, ); + if (shader == NULL) { + return; + } + + device->ReleaseShader( + device->driverData, + shader); +} + +void SDL_ReleaseGPUComputePipeline( + SDL_GPUDevice *device, + SDL_GPUComputePipeline *compute_pipeline) +{ + CHECK_DEVICE_MAGIC(device, ); + if (compute_pipeline == NULL) { + return; + } + + device->ReleaseComputePipeline( + device->driverData, + compute_pipeline); +} + +void SDL_ReleaseGPUGraphicsPipeline( + SDL_GPUDevice *device, + SDL_GPUGraphicsPipeline *graphics_pipeline) +{ + CHECK_DEVICE_MAGIC(device, ); + if (graphics_pipeline == NULL) { + return; + } + + device->ReleaseGraphicsPipeline( + device->driverData, + graphics_pipeline); +} + +// Command Buffer + +SDL_GPUCommandBuffer *SDL_AcquireGPUCommandBuffer( + SDL_GPUDevice *device) +{ + SDL_GPUCommandBuffer *command_buffer; + CommandBufferCommonHeader *commandBufferHeader; + + CHECK_DEVICE_MAGIC(device, NULL); + + command_buffer = device->AcquireCommandBuffer( + device->driverData); + + if (command_buffer == NULL) { + return NULL; + } + + commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + commandBufferHeader->device = device; + commandBufferHeader->render_pass.command_buffer = command_buffer; + commandBufferHeader->render_pass.in_progress = false; + commandBufferHeader->graphics_pipeline_bound = false; + commandBufferHeader->compute_pass.command_buffer = command_buffer; + commandBufferHeader->compute_pass.in_progress = false; + commandBufferHeader->compute_pipeline_bound = false; + commandBufferHeader->copy_pass.command_buffer = command_buffer; + commandBufferHeader->copy_pass.in_progress = false; + commandBufferHeader->submitted = false; + + return command_buffer; +} + +// Uniforms + +void SDL_PushGPUVertexUniformData( + SDL_GPUCommandBuffer *command_buffer, + Uint32 slot_index, + const void *data, + Uint32 length) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (data == NULL) { + SDL_InvalidParamError("data"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->PushVertexUniformData( + command_buffer, + slot_index, + data, + length); +} + +void SDL_PushGPUFragmentUniformData( + SDL_GPUCommandBuffer *command_buffer, + Uint32 slot_index, + const void *data, + Uint32 length) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (data == NULL) { + SDL_InvalidParamError("data"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->PushFragmentUniformData( + command_buffer, + slot_index, + data, + length); +} + +void SDL_PushGPUComputeUniformData( + SDL_GPUCommandBuffer *command_buffer, + Uint32 slot_index, + const void *data, + Uint32 length) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (data == NULL) { + SDL_InvalidParamError("data"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + } + + COMMAND_BUFFER_DEVICE->PushComputeUniformData( + command_buffer, + slot_index, + data, + length); +} + +// Render Pass + +SDL_GPURenderPass *SDL_BeginGPURenderPass( + SDL_GPUCommandBuffer *command_buffer, + const SDL_GPUColorTargetInfo *color_target_infos, + Uint32 num_color_targets, + const SDL_GPUDepthStencilTargetInfo *depth_stencil_target_info) +{ + CommandBufferCommonHeader *commandBufferHeader; + + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return NULL; + } + if (color_target_infos == NULL && num_color_targets > 0) { + SDL_InvalidParamError("color_target_infos"); + return NULL; + } + + if (num_color_targets > MAX_COLOR_TARGET_BINDINGS) { + SDL_SetError("num_color_targets exceeds MAX_COLOR_TARGET_BINDINGS"); + return NULL; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_NULL + CHECK_ANY_PASS_IN_PROGRESS("Cannot begin render pass during another pass!", NULL) + + for (Uint32 i = 0; i < num_color_targets; i += 1) { + TextureCommonHeader *textureHeader = (TextureCommonHeader *)color_target_infos[i].texture; + + if (color_target_infos[i].cycle && color_target_infos[i].load_op == SDL_GPU_LOADOP_LOAD) { + SDL_assert_release(!"Cannot cycle color target when load op is LOAD!"); + } + + if (color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE || color_target_infos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) { + if (color_target_infos[i].resolve_texture == NULL) { + SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but resolve_texture is NULL!"); + } else { + TextureCommonHeader *resolveTextureHeader = (TextureCommonHeader *)color_target_infos[i].resolve_texture; + if (textureHeader->info.sample_count == SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"Store op is RESOLVE or RESOLVE_AND_STORE but texture is not multisample!"); + } + if (resolveTextureHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"Resolve texture must have a sample count of 1!"); + } + if (resolveTextureHeader->info.format != textureHeader->info.format) { + SDL_assert_release(!"Resolve texture must have the same format as its corresponding color target!"); + } + if (resolveTextureHeader->info.type == SDL_GPU_TEXTURETYPE_3D) { + SDL_assert_release(!"Resolve texture must not be of TEXTURETYPE_3D!"); + } + if (!(resolveTextureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) { + SDL_assert_release(!"Resolve texture usage must include COLOR_TARGET!"); + } + } + } + } + + if (depth_stencil_target_info != NULL) { + + TextureCommonHeader *textureHeader = (TextureCommonHeader *)depth_stencil_target_info->texture; + if (!(textureHeader->info.usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET)) { + SDL_assert_release(!"Depth target must have been created with the DEPTH_STENCIL_TARGET usage flag!"); + } + + if (depth_stencil_target_info->cycle && (depth_stencil_target_info->load_op == SDL_GPU_LOADOP_LOAD || depth_stencil_target_info->stencil_load_op == SDL_GPU_LOADOP_LOAD)) { + SDL_assert_release(!"Cannot cycle depth target when load op or stencil load op is LOAD!"); + } + + if (depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE || + depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE || + depth_stencil_target_info->store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE || + depth_stencil_target_info->stencil_store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) { + SDL_assert_release(!"RESOLVE store ops are not supported for depth-stencil targets!"); + } + } + } + + COMMAND_BUFFER_DEVICE->BeginRenderPass( + command_buffer, + color_target_infos, + num_color_targets, + depth_stencil_target_info); + + commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + commandBufferHeader->render_pass.in_progress = true; + return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass); +} + +void SDL_BindGPUGraphicsPipeline( + SDL_GPURenderPass *render_pass, + SDL_GPUGraphicsPipeline *graphics_pipeline) +{ + CommandBufferCommonHeader *commandBufferHeader; + + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (graphics_pipeline == NULL) { + SDL_InvalidParamError("graphics_pipeline"); + return; + } + + RENDERPASS_DEVICE->BindGraphicsPipeline( + RENDERPASS_COMMAND_BUFFER, + graphics_pipeline); + + commandBufferHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER; + commandBufferHeader->graphics_pipeline_bound = true; +} + +void SDL_SetGPUViewport( + SDL_GPURenderPass *render_pass, + const SDL_GPUViewport *viewport) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (viewport == NULL) { + SDL_InvalidParamError("viewport"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->SetViewport( + RENDERPASS_COMMAND_BUFFER, + viewport); +} + +void SDL_SetGPUScissor( + SDL_GPURenderPass *render_pass, + const SDL_Rect *scissor) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (scissor == NULL) { + SDL_InvalidParamError("scissor"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->SetScissor( + RENDERPASS_COMMAND_BUFFER, + scissor); +} + +void SDL_SetGPUBlendConstants( + SDL_GPURenderPass *render_pass, + SDL_FColor blend_constants) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->SetBlendConstants( + RENDERPASS_COMMAND_BUFFER, + blend_constants); +} + +void SDL_SetGPUStencilReference( + SDL_GPURenderPass *render_pass, + Uint8 reference) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->SetStencilReference( + RENDERPASS_COMMAND_BUFFER, + reference); +} + +void SDL_BindGPUVertexBuffers( + SDL_GPURenderPass *render_pass, + Uint32 first_binding, + const SDL_GPUBufferBinding *bindings, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (bindings == NULL && num_bindings > 0) { + SDL_InvalidParamError("bindings"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindVertexBuffers( + RENDERPASS_COMMAND_BUFFER, + first_binding, + bindings, + num_bindings); +} + +void SDL_BindGPUIndexBuffer( + SDL_GPURenderPass *render_pass, + const SDL_GPUBufferBinding *binding, + SDL_GPUIndexElementSize index_element_size) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (binding == NULL) { + SDL_InvalidParamError("binding"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindIndexBuffer( + RENDERPASS_COMMAND_BUFFER, + binding, + index_element_size); +} + +void SDL_BindGPUVertexSamplers( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (texture_sampler_bindings == NULL && num_bindings > 0) { + SDL_InvalidParamError("texture_sampler_bindings"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindVertexSamplers( + RENDERPASS_COMMAND_BUFFER, + first_slot, + texture_sampler_bindings, + num_bindings); +} + +void SDL_BindGPUVertexStorageTextures( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + SDL_GPUTexture *const *storage_textures, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (storage_textures == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_textures"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindVertexStorageTextures( + RENDERPASS_COMMAND_BUFFER, + first_slot, + storage_textures, + num_bindings); +} + +void SDL_BindGPUVertexStorageBuffers( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + SDL_GPUBuffer *const *storage_buffers, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (storage_buffers == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_buffers"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindVertexStorageBuffers( + RENDERPASS_COMMAND_BUFFER, + first_slot, + storage_buffers, + num_bindings); +} + +void SDL_BindGPUFragmentSamplers( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (texture_sampler_bindings == NULL && num_bindings > 0) { + SDL_InvalidParamError("texture_sampler_bindings"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindFragmentSamplers( + RENDERPASS_COMMAND_BUFFER, + first_slot, + texture_sampler_bindings, + num_bindings); +} + +void SDL_BindGPUFragmentStorageTextures( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + SDL_GPUTexture *const *storage_textures, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (storage_textures == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_textures"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindFragmentStorageTextures( + RENDERPASS_COMMAND_BUFFER, + first_slot, + storage_textures, + num_bindings); +} + +void SDL_BindGPUFragmentStorageBuffers( + SDL_GPURenderPass *render_pass, + Uint32 first_slot, + SDL_GPUBuffer *const *storage_buffers, + Uint32 num_bindings) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (storage_buffers == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_buffers"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->BindFragmentStorageBuffers( + RENDERPASS_COMMAND_BUFFER, + first_slot, + storage_buffers, + num_bindings); +} + +void SDL_DrawGPUIndexedPrimitives( + SDL_GPURenderPass *render_pass, + Uint32 num_indices, + Uint32 num_instances, + Uint32 first_index, + Sint32 vertex_offset, + Uint32 first_instance) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + CHECK_GRAPHICS_PIPELINE_BOUND + } + + RENDERPASS_DEVICE->DrawIndexedPrimitives( + RENDERPASS_COMMAND_BUFFER, + num_indices, + num_instances, + first_index, + vertex_offset, + first_instance); +} + +void SDL_DrawGPUPrimitives( + SDL_GPURenderPass *render_pass, + Uint32 num_vertices, + Uint32 num_instances, + Uint32 first_vertex, + Uint32 first_instance) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + CHECK_GRAPHICS_PIPELINE_BOUND + } + + RENDERPASS_DEVICE->DrawPrimitives( + RENDERPASS_COMMAND_BUFFER, + num_vertices, + num_instances, + first_vertex, + first_instance); +} + +void SDL_DrawGPUPrimitivesIndirect( + SDL_GPURenderPass *render_pass, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 draw_count) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (buffer == NULL) { + SDL_InvalidParamError("buffer"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + CHECK_GRAPHICS_PIPELINE_BOUND + } + + RENDERPASS_DEVICE->DrawPrimitivesIndirect( + RENDERPASS_COMMAND_BUFFER, + buffer, + offset, + draw_count); +} + +void SDL_DrawGPUIndexedPrimitivesIndirect( + SDL_GPURenderPass *render_pass, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 draw_count) +{ + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + if (buffer == NULL) { + SDL_InvalidParamError("buffer"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + CHECK_GRAPHICS_PIPELINE_BOUND + } + + RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect( + RENDERPASS_COMMAND_BUFFER, + buffer, + offset, + draw_count); +} + +void SDL_EndGPURenderPass( + SDL_GPURenderPass *render_pass) +{ + CommandBufferCommonHeader *commandBufferCommonHeader; + + if (render_pass == NULL) { + SDL_InvalidParamError("render_pass"); + return; + } + + if (RENDERPASS_DEVICE->debug_mode) { + CHECK_RENDERPASS + } + + RENDERPASS_DEVICE->EndRenderPass( + RENDERPASS_COMMAND_BUFFER); + + commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER; + commandBufferCommonHeader->render_pass.in_progress = false; + commandBufferCommonHeader->graphics_pipeline_bound = false; +} + +// Compute Pass + +SDL_GPUComputePass *SDL_BeginGPUComputePass( + SDL_GPUCommandBuffer *command_buffer, + const SDL_GPUStorageTextureReadWriteBinding *storage_texture_bindings, + Uint32 num_storage_texture_bindings, + const SDL_GPUStorageBufferReadWriteBinding *storage_buffer_bindings, + Uint32 num_storage_buffer_bindings) +{ + CommandBufferCommonHeader *commandBufferHeader; + + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return NULL; + } + if (storage_texture_bindings == NULL && num_storage_texture_bindings > 0) { + SDL_InvalidParamError("storage_texture_bindings"); + return NULL; + } + if (storage_buffer_bindings == NULL && num_storage_buffer_bindings > 0) { + SDL_InvalidParamError("storage_buffer_bindings"); + return NULL; + } + if (num_storage_texture_bindings > MAX_COMPUTE_WRITE_TEXTURES) { + SDL_InvalidParamError("num_storage_texture_bindings"); + return NULL; + } + if (num_storage_buffer_bindings > MAX_COMPUTE_WRITE_BUFFERS) { + SDL_InvalidParamError("num_storage_buffer_bindings"); + return NULL; + } + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_NULL + CHECK_ANY_PASS_IN_PROGRESS("Cannot begin compute pass during another pass!", NULL) + + for (Uint32 i = 0; i < num_storage_texture_bindings; i += 1) { + TextureCommonHeader *header = (TextureCommonHeader *)storage_texture_bindings[i].texture; + if (!(header->info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) && !(header->info.usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE)) { + SDL_assert_release(!"Texture must be created with COMPUTE_STORAGE_WRITE or COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE flag"); + return NULL; + } + } + + // TODO: validate buffer usage? + } + + COMMAND_BUFFER_DEVICE->BeginComputePass( + command_buffer, + storage_texture_bindings, + num_storage_texture_bindings, + storage_buffer_bindings, + num_storage_buffer_bindings); + + commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + commandBufferHeader->compute_pass.in_progress = true; + return (SDL_GPUComputePass *)&(commandBufferHeader->compute_pass); +} + +void SDL_BindGPUComputePipeline( + SDL_GPUComputePass *compute_pass, + SDL_GPUComputePipeline *compute_pipeline) +{ + CommandBufferCommonHeader *commandBufferHeader; + + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + if (compute_pipeline == NULL) { + SDL_InvalidParamError("compute_pipeline"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + } + + COMPUTEPASS_DEVICE->BindComputePipeline( + COMPUTEPASS_COMMAND_BUFFER, + compute_pipeline); + + commandBufferHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER; + commandBufferHeader->compute_pipeline_bound = true; +} + +void SDL_BindGPUComputeSamplers( + SDL_GPUComputePass *compute_pass, + Uint32 first_slot, + const SDL_GPUTextureSamplerBinding *texture_sampler_bindings, + Uint32 num_bindings) +{ + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + if (texture_sampler_bindings == NULL && num_bindings > 0) { + SDL_InvalidParamError("texture_sampler_bindings"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + } + + COMPUTEPASS_DEVICE->BindComputeSamplers( + COMPUTEPASS_COMMAND_BUFFER, + first_slot, + texture_sampler_bindings, + num_bindings); +} + +void SDL_BindGPUComputeStorageTextures( + SDL_GPUComputePass *compute_pass, + Uint32 first_slot, + SDL_GPUTexture *const *storage_textures, + Uint32 num_bindings) +{ + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + if (storage_textures == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_textures"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + } + + COMPUTEPASS_DEVICE->BindComputeStorageTextures( + COMPUTEPASS_COMMAND_BUFFER, + first_slot, + storage_textures, + num_bindings); +} + +void SDL_BindGPUComputeStorageBuffers( + SDL_GPUComputePass *compute_pass, + Uint32 first_slot, + SDL_GPUBuffer *const *storage_buffers, + Uint32 num_bindings) +{ + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + if (storage_buffers == NULL && num_bindings > 0) { + SDL_InvalidParamError("storage_buffers"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + } + + COMPUTEPASS_DEVICE->BindComputeStorageBuffers( + COMPUTEPASS_COMMAND_BUFFER, + first_slot, + storage_buffers, + num_bindings); +} + +void SDL_DispatchGPUCompute( + SDL_GPUComputePass *compute_pass, + Uint32 groupcount_x, + Uint32 groupcount_y, + Uint32 groupcount_z) +{ + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + CHECK_COMPUTE_PIPELINE_BOUND + } + + COMPUTEPASS_DEVICE->DispatchCompute( + COMPUTEPASS_COMMAND_BUFFER, + groupcount_x, + groupcount_y, + groupcount_z); +} + +void SDL_DispatchGPUComputeIndirect( + SDL_GPUComputePass *compute_pass, + SDL_GPUBuffer *buffer, + Uint32 offset) +{ + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + CHECK_COMPUTE_PIPELINE_BOUND + } + + COMPUTEPASS_DEVICE->DispatchComputeIndirect( + COMPUTEPASS_COMMAND_BUFFER, + buffer, + offset); +} + +void SDL_EndGPUComputePass( + SDL_GPUComputePass *compute_pass) +{ + CommandBufferCommonHeader *commandBufferCommonHeader; + + if (compute_pass == NULL) { + SDL_InvalidParamError("compute_pass"); + return; + } + + if (COMPUTEPASS_DEVICE->debug_mode) { + CHECK_COMPUTEPASS + } + + COMPUTEPASS_DEVICE->EndComputePass( + COMPUTEPASS_COMMAND_BUFFER); + + commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER; + commandBufferCommonHeader->compute_pass.in_progress = false; + commandBufferCommonHeader->compute_pipeline_bound = false; +} + +// TransferBuffer Data + +void *SDL_MapGPUTransferBuffer( + SDL_GPUDevice *device, + SDL_GPUTransferBuffer *transfer_buffer, + bool cycle) +{ + CHECK_DEVICE_MAGIC(device, NULL); + if (transfer_buffer == NULL) { + SDL_InvalidParamError("transfer_buffer"); + return NULL; + } + + return device->MapTransferBuffer( + device->driverData, + transfer_buffer, + cycle); +} + +void SDL_UnmapGPUTransferBuffer( + SDL_GPUDevice *device, + SDL_GPUTransferBuffer *transfer_buffer) +{ + CHECK_DEVICE_MAGIC(device, ); + if (transfer_buffer == NULL) { + SDL_InvalidParamError("transfer_buffer"); + return; + } + + device->UnmapTransferBuffer( + device->driverData, + transfer_buffer); +} + +// Copy Pass + +SDL_GPUCopyPass *SDL_BeginGPUCopyPass( + SDL_GPUCommandBuffer *command_buffer) +{ + CommandBufferCommonHeader *commandBufferHeader; + + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return NULL; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_NULL + CHECK_ANY_PASS_IN_PROGRESS("Cannot begin copy pass during another pass!", NULL) + } + + COMMAND_BUFFER_DEVICE->BeginCopyPass( + command_buffer); + + commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + commandBufferHeader->copy_pass.in_progress = true; + return (SDL_GPUCopyPass *)&(commandBufferHeader->copy_pass); +} + +void SDL_UploadToGPUTexture( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUTextureTransferInfo *source, + const SDL_GPUTextureRegion *destination, + bool cycle) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->transfer_buffer == NULL) { + SDL_assert_release(!"Source transfer buffer cannot be NULL!"); + return; + } + if (destination->texture == NULL) { + SDL_assert_release(!"Destination texture cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->UploadToTexture( + COPYPASS_COMMAND_BUFFER, + source, + destination, + cycle); +} + +void SDL_UploadToGPUBuffer( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUTransferBufferLocation *source, + const SDL_GPUBufferRegion *destination, + bool cycle) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->transfer_buffer == NULL) { + SDL_assert_release(!"Source transfer buffer cannot be NULL!"); + return; + } + if (destination->buffer == NULL) { + SDL_assert_release(!"Destination buffer cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->UploadToBuffer( + COPYPASS_COMMAND_BUFFER, + source, + destination, + cycle); +} + +void SDL_CopyGPUTextureToTexture( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUTextureLocation *source, + const SDL_GPUTextureLocation *destination, + Uint32 w, + Uint32 h, + Uint32 d, + bool cycle) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->texture == NULL) { + SDL_assert_release(!"Source texture cannot be NULL!"); + return; + } + if (destination->texture == NULL) { + SDL_assert_release(!"Destination texture cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->CopyTextureToTexture( + COPYPASS_COMMAND_BUFFER, + source, + destination, + w, + h, + d, + cycle); +} + +void SDL_CopyGPUBufferToBuffer( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUBufferLocation *source, + const SDL_GPUBufferLocation *destination, + Uint32 size, + bool cycle) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->buffer == NULL) { + SDL_assert_release(!"Source buffer cannot be NULL!"); + return; + } + if (destination->buffer == NULL) { + SDL_assert_release(!"Destination buffer cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->CopyBufferToBuffer( + COPYPASS_COMMAND_BUFFER, + source, + destination, + size, + cycle); +} + +void SDL_DownloadFromGPUTexture( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUTextureRegion *source, + const SDL_GPUTextureTransferInfo *destination) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->texture == NULL) { + SDL_assert_release(!"Source texture cannot be NULL!"); + return; + } + if (destination->transfer_buffer == NULL) { + SDL_assert_release(!"Destination transfer buffer cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->DownloadFromTexture( + COPYPASS_COMMAND_BUFFER, + source, + destination); +} + +void SDL_DownloadFromGPUBuffer( + SDL_GPUCopyPass *copy_pass, + const SDL_GPUBufferRegion *source, + const SDL_GPUTransferBufferLocation *destination) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + if (source == NULL) { + SDL_InvalidParamError("source"); + return; + } + if (destination == NULL) { + SDL_InvalidParamError("destination"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + if (source->buffer == NULL) { + SDL_assert_release(!"Source buffer cannot be NULL!"); + return; + } + if (destination->transfer_buffer == NULL) { + SDL_assert_release(!"Destination transfer buffer cannot be NULL!"); + return; + } + } + + COPYPASS_DEVICE->DownloadFromBuffer( + COPYPASS_COMMAND_BUFFER, + source, + destination); +} + +void SDL_EndGPUCopyPass( + SDL_GPUCopyPass *copy_pass) +{ + if (copy_pass == NULL) { + SDL_InvalidParamError("copy_pass"); + return; + } + + if (COPYPASS_DEVICE->debug_mode) { + CHECK_COPYPASS + } + + COPYPASS_DEVICE->EndCopyPass( + COPYPASS_COMMAND_BUFFER); + + ((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false; +} + +void SDL_GenerateMipmapsForGPUTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_GPUTexture *texture) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (texture == NULL) { + SDL_InvalidParamError("texture"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + CHECK_ANY_PASS_IN_PROGRESS("Cannot generate mipmaps during a pass!", ) + + TextureCommonHeader *header = (TextureCommonHeader *)texture; + if (header->info.num_levels <= 1) { + SDL_assert_release(!"Cannot generate mipmaps for texture with num_levels <= 1!"); + return; + } + + if (!(header->info.usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) || !(header->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET)) { + SDL_assert_release(!"GenerateMipmaps texture must be created with SAMPLER and COLOR_TARGET usage flags!"); + return; + } + } + + COMMAND_BUFFER_DEVICE->GenerateMipmaps( + command_buffer, + texture); +} + +void SDL_BlitGPUTexture( + SDL_GPUCommandBuffer *command_buffer, + const SDL_GPUBlitInfo *info) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return; + } + if (info == NULL) { + SDL_InvalidParamError("info"); + return; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER + CHECK_ANY_PASS_IN_PROGRESS("Cannot blit during a pass!", ) + + // Validation + bool failed = false; + TextureCommonHeader *srcHeader = (TextureCommonHeader *)info->source.texture; + TextureCommonHeader *dstHeader = (TextureCommonHeader *)info->destination.texture; + + if (srcHeader == NULL) { + SDL_assert_release(!"Blit source texture must be non-NULL"); + return; // attempting to proceed will crash + } + if (dstHeader == NULL) { + SDL_assert_release(!"Blit destination texture must be non-NULL"); + return; // attempting to proceed will crash + } + if (srcHeader->info.sample_count != SDL_GPU_SAMPLECOUNT_1) { + SDL_assert_release(!"Blit source texture must have a sample count of 1"); + failed = true; + } + if ((srcHeader->info.usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) == 0) { + SDL_assert_release(!"Blit source texture must be created with the SAMPLER usage flag"); + failed = true; + } + if ((dstHeader->info.usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) == 0) { + SDL_assert_release(!"Blit destination texture must be created with the COLOR_TARGET usage flag"); + failed = true; + } + if (IsDepthFormat(srcHeader->info.format)) { + SDL_assert_release(!"Blit source texture cannot have a depth format"); + failed = true; + } + if (info->source.w == 0 || info->source.h == 0 || info->destination.w == 0 || info->destination.h == 0) { + SDL_assert_release(!"Blit source/destination regions must have non-zero width, height, and depth"); + failed = true; + } + + if (failed) { + return; + } + } + + COMMAND_BUFFER_DEVICE->Blit( + command_buffer, + info); +} + +// Submission/Presentation + +bool SDL_WindowSupportsGPUSwapchainComposition( + SDL_GPUDevice *device, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchain_composition) +{ + CHECK_DEVICE_MAGIC(device, false); + if (window == NULL) { + SDL_InvalidParamError("window"); + return false; + } + + if (device->debug_mode) { + CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchain_composition, false) + } + + return device->SupportsSwapchainComposition( + device->driverData, + window, + swapchain_composition); +} + +bool SDL_WindowSupportsGPUPresentMode( + SDL_GPUDevice *device, + SDL_Window *window, + SDL_GPUPresentMode present_mode) +{ + CHECK_DEVICE_MAGIC(device, false); + if (window == NULL) { + SDL_InvalidParamError("window"); + return false; + } + + if (device->debug_mode) { + CHECK_PRESENTMODE_ENUM_INVALID(present_mode, false) + } + + return device->SupportsPresentMode( + device->driverData, + window, + present_mode); +} + +bool SDL_ClaimWindowForGPUDevice( + SDL_GPUDevice *device, + SDL_Window *window) +{ + CHECK_DEVICE_MAGIC(device, false); + if (window == NULL) { + SDL_InvalidParamError("window"); + return false; + } + + return device->ClaimWindow( + device->driverData, + window); +} + +void SDL_ReleaseWindowFromGPUDevice( + SDL_GPUDevice *device, + SDL_Window *window) +{ + CHECK_DEVICE_MAGIC(device, ); + if (window == NULL) { + SDL_InvalidParamError("window"); + return; + } + + device->ReleaseWindow( + device->driverData, + window); +} + +bool SDL_SetGPUSwapchainParameters( + SDL_GPUDevice *device, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchain_composition, + SDL_GPUPresentMode present_mode) +{ + CHECK_DEVICE_MAGIC(device, false); + if (window == NULL) { + SDL_InvalidParamError("window"); + return false; + } + + if (device->debug_mode) { + CHECK_SWAPCHAINCOMPOSITION_ENUM_INVALID(swapchain_composition, false) + CHECK_PRESENTMODE_ENUM_INVALID(present_mode, false) + } + + return device->SetSwapchainParameters( + device->driverData, + window, + swapchain_composition, + present_mode); +} + +SDL_GPUTextureFormat SDL_GetGPUSwapchainTextureFormat( + SDL_GPUDevice *device, + SDL_Window *window) +{ + CHECK_DEVICE_MAGIC(device, SDL_GPU_TEXTUREFORMAT_INVALID); + if (window == NULL) { + SDL_InvalidParamError("window"); + return SDL_GPU_TEXTUREFORMAT_INVALID; + } + + return device->GetSwapchainTextureFormat( + device->driverData, + window); +} + +bool SDL_AcquireGPUSwapchainTexture( + SDL_GPUCommandBuffer *command_buffer, + SDL_Window *window, + SDL_GPUTexture **swapchain_texture, + Uint32 *swapchain_texture_width, + Uint32 *swapchain_texture_height) +{ + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return false; + } + if (window == NULL) { + SDL_InvalidParamError("window"); + return false; + } + if (swapchain_texture == NULL) { + SDL_InvalidParamError("swapchain_texture"); + return false; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_FALSE + CHECK_ANY_PASS_IN_PROGRESS("Cannot acquire a swapchain texture during a pass!", false) + } + + return COMMAND_BUFFER_DEVICE->AcquireSwapchainTexture( + command_buffer, + window, + swapchain_texture, + swapchain_texture_width, + swapchain_texture_height); +} + +bool SDL_SubmitGPUCommandBuffer( + SDL_GPUCommandBuffer *command_buffer) +{ + CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return false; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_FALSE + if ( + commandBufferHeader->render_pass.in_progress || + commandBufferHeader->compute_pass.in_progress || + commandBufferHeader->copy_pass.in_progress) { + SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!"); + return false; + } + } + + commandBufferHeader->submitted = true; + + return COMMAND_BUFFER_DEVICE->Submit( + command_buffer); +} + +SDL_GPUFence *SDL_SubmitGPUCommandBufferAndAcquireFence( + SDL_GPUCommandBuffer *command_buffer) +{ + CommandBufferCommonHeader *commandBufferHeader = (CommandBufferCommonHeader *)command_buffer; + + if (command_buffer == NULL) { + SDL_InvalidParamError("command_buffer"); + return NULL; + } + + if (COMMAND_BUFFER_DEVICE->debug_mode) { + CHECK_COMMAND_BUFFER_RETURN_NULL + if ( + commandBufferHeader->render_pass.in_progress || + commandBufferHeader->compute_pass.in_progress || + commandBufferHeader->copy_pass.in_progress) { + SDL_assert_release(!"Cannot submit command buffer while a pass is in progress!"); + return NULL; + } + } + + commandBufferHeader->submitted = true; + + return COMMAND_BUFFER_DEVICE->SubmitAndAcquireFence( + command_buffer); +} + +bool SDL_WaitForGPUIdle( + SDL_GPUDevice *device) +{ + CHECK_DEVICE_MAGIC(device, false); + + return device->Wait( + device->driverData); +} + +bool SDL_WaitForGPUFences( + SDL_GPUDevice *device, + bool wait_all, + SDL_GPUFence *const *fences, + Uint32 num_fences) +{ + CHECK_DEVICE_MAGIC(device, false); + if (fences == NULL && num_fences > 0) { + SDL_InvalidParamError("fences"); + return false; + } + + return device->WaitForFences( + device->driverData, + wait_all, + fences, + num_fences); +} + +bool SDL_QueryGPUFence( + SDL_GPUDevice *device, + SDL_GPUFence *fence) +{ + CHECK_DEVICE_MAGIC(device, false); + if (fence == NULL) { + SDL_InvalidParamError("fence"); + return false; + } + + return device->QueryFence( + device->driverData, + fence); +} + +void SDL_ReleaseGPUFence( + SDL_GPUDevice *device, + SDL_GPUFence *fence) +{ + CHECK_DEVICE_MAGIC(device, ); + if (fence == NULL) { + return; + } + + device->ReleaseFence( + device->driverData, + fence); +} diff --git a/libs/SDL3/src/gpu/SDL_sysgpu.h b/libs/SDL3/src/gpu/SDL_sysgpu.h new file mode 100644 index 000000000..ce48a5eb2 --- /dev/null +++ b/libs/SDL3/src/gpu/SDL_sysgpu.h @@ -0,0 +1,811 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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 "../video/SDL_sysvideo.h" +#include "SDL_internal.h" + +#ifndef SDL_GPU_DRIVER_H +#define SDL_GPU_DRIVER_H + +// Common Structs + +typedef struct Pass +{ + SDL_GPUCommandBuffer *command_buffer; + bool in_progress; +} Pass; + +typedef struct CommandBufferCommonHeader +{ + SDL_GPUDevice *device; + Pass render_pass; + bool graphics_pipeline_bound; + Pass compute_pass; + bool compute_pipeline_bound; + Pass copy_pass; + bool submitted; +} CommandBufferCommonHeader; + +typedef struct TextureCommonHeader +{ + SDL_GPUTextureCreateInfo info; +} TextureCommonHeader; + +typedef struct BlitFragmentUniforms +{ + // texcoord space + float left; + float top; + float width; + float height; + + Uint32 mip_level; + float layer_or_depth; +} BlitFragmentUniforms; + +typedef struct BlitPipelineCacheEntry +{ + SDL_GPUTextureType type; + SDL_GPUTextureFormat format; + SDL_GPUGraphicsPipeline *pipeline; +} BlitPipelineCacheEntry; + +// Internal Helper Utilities + +#define SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE (SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT + 1) +#define SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE (SDL_GPU_VERTEXELEMENTFORMAT_HALF4 + 1) +#define SDL_GPU_COMPAREOP_MAX_ENUM_VALUE (SDL_GPU_COMPAREOP_ALWAYS + 1) +#define SDL_GPU_STENCILOP_MAX_ENUM_VALUE (SDL_GPU_STENCILOP_DECREMENT_AND_WRAP + 1) +#define SDL_GPU_BLENDOP_MAX_ENUM_VALUE (SDL_GPU_BLENDOP_MAX + 1) +#define SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE (SDL_GPU_BLENDFACTOR_SRC_ALPHA_SATURATE + 1) +#define SDL_GPU_SWAPCHAINCOMPOSITION_MAX_ENUM_VALUE (SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2048 + 1) +#define SDL_GPU_PRESENTMODE_MAX_ENUM_VALUE (SDL_GPU_PRESENTMODE_MAILBOX + 1) + +static inline Sint32 Texture_GetBlockSize( + SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC2_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC4_R_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC5_RG_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM: + case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT: + case SDL_GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT: + case SDL_GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB: + return 4; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: + case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: + case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: + case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R16_UNORM: + case SDL_GPU_TEXTUREFORMAT_A8_UNORM: + case SDL_GPU_TEXTUREFORMAT_R8_SNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8_SNORM: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: + case SDL_GPU_TEXTUREFORMAT_R16_SNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16_SNORM: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_SNORM: + case SDL_GPU_TEXTUREFORMAT_R16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R16G16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R32G32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_R11G11B10_UFLOAT: + case SDL_GPU_TEXTUREFORMAT_R8_UINT: + case SDL_GPU_TEXTUREFORMAT_R8G8_UINT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: + case SDL_GPU_TEXTUREFORMAT_R16_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: + case SDL_GPU_TEXTUREFORMAT_R8_INT: + case SDL_GPU_TEXTUREFORMAT_R8G8_INT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT: + case SDL_GPU_TEXTUREFORMAT_R16_INT: + case SDL_GPU_TEXTUREFORMAT_R16G16_INT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: + return 1; + default: + SDL_assert_release(!"Unrecognized TextureFormat!"); + return 0; + } +} + +static inline bool IsDepthFormat( + SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_D16_UNORM: + case SDL_GPU_TEXTUREFORMAT_D24_UNORM: + case SDL_GPU_TEXTUREFORMAT_D32_FLOAT: + case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT: + case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT: + return true; + + default: + return false; + } +} + +static inline bool IsStencilFormat( + SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT: + case SDL_GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT: + return true; + + default: + return false; + } +} + +static inline bool IsIntegerFormat( + SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_R8_UINT: + case SDL_GPU_TEXTUREFORMAT_R8G8_UINT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: + case SDL_GPU_TEXTUREFORMAT_R16_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16_UINT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: + case SDL_GPU_TEXTUREFORMAT_R8_INT: + case SDL_GPU_TEXTUREFORMAT_R8G8_INT: + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_INT: + case SDL_GPU_TEXTUREFORMAT_R16_INT: + case SDL_GPU_TEXTUREFORMAT_R16G16_INT: + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_INT: + return true; + + default: + return false; + } +} + +static inline Uint32 IndexSize(SDL_GPUIndexElementSize size) +{ + return (size == SDL_GPU_INDEXELEMENTSIZE_16BIT) ? 2 : 4; +} + +static inline Uint32 BytesPerRow( + Sint32 width, + SDL_GPUTextureFormat format) +{ + Uint32 blocksPerRow = width; + Uint32 pixelRowsPerBlock = Texture_GetBlockSize(format); + + blocksPerRow = (width + pixelRowsPerBlock - 1) / pixelRowsPerBlock; + return blocksPerRow * SDL_GPUTextureFormatTexelBlockSize(format); +} + +static inline Sint32 BytesPerImage( + Uint32 width, + Uint32 height, + SDL_GPUTextureFormat format) +{ + Uint32 blocksPerRow = width; + Uint32 blocksPerColumn = height; + Uint32 pixelRowsPerBlock = Texture_GetBlockSize(format); + Uint32 pixelColumnsPerBlock = pixelRowsPerBlock; + + blocksPerRow = (width + pixelRowsPerBlock - 1) / pixelRowsPerBlock; + blocksPerColumn = (height + pixelColumnsPerBlock - 1) / pixelColumnsPerBlock; + return blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format); +} + +// GraphicsDevice Limits + +#define MAX_TEXTURE_SAMPLERS_PER_STAGE 16 +#define MAX_STORAGE_TEXTURES_PER_STAGE 8 +#define MAX_STORAGE_BUFFERS_PER_STAGE 8 +#define MAX_UNIFORM_BUFFERS_PER_STAGE 4 +#define MAX_COMPUTE_WRITE_TEXTURES 8 +#define MAX_COMPUTE_WRITE_BUFFERS 8 +#define UNIFORM_BUFFER_SIZE 32768 +#define MAX_VERTEX_BUFFERS 16 +#define MAX_VERTEX_ATTRIBUTES 16 +#define MAX_COLOR_TARGET_BINDINGS 4 +#define MAX_PRESENT_COUNT 16 +#define MAX_FRAMES_IN_FLIGHT 3 + +// Internal Macros + +#define EXPAND_ARRAY_IF_NEEDED(arr, elementType, newCount, capacity, newCapacity) \ + if (newCount >= capacity) { \ + capacity = newCapacity; \ + arr = (elementType *)SDL_realloc( \ + arr, \ + sizeof(elementType) * capacity); \ + } + +// Internal Declarations + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +SDL_GPUGraphicsPipeline *SDL_GPU_FetchBlitPipeline( + SDL_GPUDevice *device, + SDL_GPUTextureType sourceTextureType, + SDL_GPUTextureFormat destinationFormat, + SDL_GPUShader *blitVertexShader, + SDL_GPUShader *blitFrom2DShader, + SDL_GPUShader *blitFrom2DArrayShader, + SDL_GPUShader *blitFrom3DShader, + SDL_GPUShader *blitFromCubeShader, + SDL_GPUShader *blitFromCubeArrayShader, + BlitPipelineCacheEntry **blitPipelines, + Uint32 *blitPipelineCount, + Uint32 *blitPipelineCapacity); + +void SDL_GPU_BlitCommon( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBlitInfo *info, + SDL_GPUSampler *blitLinearSampler, + SDL_GPUSampler *blitNearestSampler, + SDL_GPUShader *blitVertexShader, + SDL_GPUShader *blitFrom2DShader, + SDL_GPUShader *blitFrom2DArrayShader, + SDL_GPUShader *blitFrom3DShader, + SDL_GPUShader *blitFromCubeShader, + SDL_GPUShader *blitFromCubeArrayShader, + BlitPipelineCacheEntry **blitPipelines, + Uint32 *blitPipelineCount, + Uint32 *blitPipelineCapacity); + +#ifdef __cplusplus +} +#endif // __cplusplus + +// SDL_GPUDevice Definition + +typedef struct SDL_GPURenderer SDL_GPURenderer; + +struct SDL_GPUDevice +{ + // Quit + + void (*DestroyDevice)(SDL_GPUDevice *device); + + // State Creation + + SDL_GPUComputePipeline *(*CreateComputePipeline)( + SDL_GPURenderer *driverData, + const SDL_GPUComputePipelineCreateInfo *createinfo); + + SDL_GPUGraphicsPipeline *(*CreateGraphicsPipeline)( + SDL_GPURenderer *driverData, + const SDL_GPUGraphicsPipelineCreateInfo *createinfo); + + SDL_GPUSampler *(*CreateSampler)( + SDL_GPURenderer *driverData, + const SDL_GPUSamplerCreateInfo *createinfo); + + SDL_GPUShader *(*CreateShader)( + SDL_GPURenderer *driverData, + const SDL_GPUShaderCreateInfo *createinfo); + + SDL_GPUTexture *(*CreateTexture)( + SDL_GPURenderer *driverData, + const SDL_GPUTextureCreateInfo *createinfo); + + SDL_GPUBuffer *(*CreateBuffer)( + SDL_GPURenderer *driverData, + SDL_GPUBufferUsageFlags usageFlags, + Uint32 size); + + SDL_GPUTransferBuffer *(*CreateTransferBuffer)( + SDL_GPURenderer *driverData, + SDL_GPUTransferBufferUsage usage, + Uint32 size); + + // Debug Naming + + void (*SetBufferName)( + SDL_GPURenderer *driverData, + SDL_GPUBuffer *buffer, + const char *text); + + void (*SetTextureName)( + SDL_GPURenderer *driverData, + SDL_GPUTexture *texture, + const char *text); + + void (*InsertDebugLabel)( + SDL_GPUCommandBuffer *commandBuffer, + const char *text); + + void (*PushDebugGroup)( + SDL_GPUCommandBuffer *commandBuffer, + const char *name); + + void (*PopDebugGroup)( + SDL_GPUCommandBuffer *commandBuffer); + + // Disposal + + void (*ReleaseTexture)( + SDL_GPURenderer *driverData, + SDL_GPUTexture *texture); + + void (*ReleaseSampler)( + SDL_GPURenderer *driverData, + SDL_GPUSampler *sampler); + + void (*ReleaseBuffer)( + SDL_GPURenderer *driverData, + SDL_GPUBuffer *buffer); + + void (*ReleaseTransferBuffer)( + SDL_GPURenderer *driverData, + SDL_GPUTransferBuffer *transferBuffer); + + void (*ReleaseShader)( + SDL_GPURenderer *driverData, + SDL_GPUShader *shader); + + void (*ReleaseComputePipeline)( + SDL_GPURenderer *driverData, + SDL_GPUComputePipeline *computePipeline); + + void (*ReleaseGraphicsPipeline)( + SDL_GPURenderer *driverData, + SDL_GPUGraphicsPipeline *graphicsPipeline); + + // Render Pass + + void (*BeginRenderPass)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUColorTargetInfo *colorTargetInfos, + Uint32 numColorTargets, + const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo); + + void (*BindGraphicsPipeline)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUGraphicsPipeline *graphicsPipeline); + + void (*SetViewport)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUViewport *viewport); + + void (*SetScissor)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_Rect *scissor); + + void (*SetBlendConstants)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_FColor blendConstants); + + void (*SetStencilReference)( + SDL_GPUCommandBuffer *commandBuffer, + Uint8 reference); + + void (*BindVertexBuffers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUBufferBinding *bindings, + Uint32 numBindings); + + void (*BindIndexBuffer)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferBinding *binding, + SDL_GPUIndexElementSize indexElementSize); + + void (*BindVertexSamplers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings); + + void (*BindVertexStorageTextures)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings); + + void (*BindVertexStorageBuffers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings); + + void (*BindFragmentSamplers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings); + + void (*BindFragmentStorageTextures)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings); + + void (*BindFragmentStorageBuffers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings); + + void (*PushVertexUniformData)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length); + + void (*PushFragmentUniformData)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length); + + void (*DrawIndexedPrimitives)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 numIndices, + Uint32 numInstances, + Uint32 firstIndex, + Sint32 vertexOffset, + Uint32 firstInstance); + + void (*DrawPrimitives)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 numVertices, + Uint32 numInstances, + Uint32 firstVertex, + Uint32 firstInstance); + + void (*DrawPrimitivesIndirect)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 drawCount); + + void (*DrawIndexedPrimitivesIndirect)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 drawCount); + + void (*EndRenderPass)( + SDL_GPUCommandBuffer *commandBuffer); + + // Compute Pass + + void (*BeginComputePass)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings, + Uint32 numStorageTextureBindings, + const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings, + Uint32 numStorageBufferBindings); + + void (*BindComputePipeline)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUComputePipeline *computePipeline); + + void (*BindComputeSamplers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings); + + void (*BindComputeStorageTextures)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings); + + void (*BindComputeStorageBuffers)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings); + + void (*PushComputeUniformData)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length); + + void (*DispatchCompute)( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 groupcountX, + Uint32 groupcountY, + Uint32 groupcountZ); + + void (*DispatchComputeIndirect)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset); + + void (*EndComputePass)( + SDL_GPUCommandBuffer *commandBuffer); + + // TransferBuffer Data + + void *(*MapTransferBuffer)( + SDL_GPURenderer *device, + SDL_GPUTransferBuffer *transferBuffer, + bool cycle); + + void (*UnmapTransferBuffer)( + SDL_GPURenderer *device, + SDL_GPUTransferBuffer *transferBuffer); + + // Copy Pass + + void (*BeginCopyPass)( + SDL_GPUCommandBuffer *commandBuffer); + + void (*UploadToTexture)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureTransferInfo *source, + const SDL_GPUTextureRegion *destination, + bool cycle); + + void (*UploadToBuffer)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTransferBufferLocation *source, + const SDL_GPUBufferRegion *destination, + bool cycle); + + void (*CopyTextureToTexture)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureLocation *source, + const SDL_GPUTextureLocation *destination, + Uint32 w, + Uint32 h, + Uint32 d, + bool cycle); + + void (*CopyBufferToBuffer)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferLocation *source, + const SDL_GPUBufferLocation *destination, + Uint32 size, + bool cycle); + + void (*GenerateMipmaps)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUTexture *texture); + + void (*DownloadFromTexture)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureRegion *source, + const SDL_GPUTextureTransferInfo *destination); + + void (*DownloadFromBuffer)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferRegion *source, + const SDL_GPUTransferBufferLocation *destination); + + void (*EndCopyPass)( + SDL_GPUCommandBuffer *commandBuffer); + + void (*Blit)( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBlitInfo *info); + + // Submission/Presentation + + bool (*SupportsSwapchainComposition)( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchainComposition); + + bool (*SupportsPresentMode)( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUPresentMode presentMode); + + bool (*ClaimWindow)( + SDL_GPURenderer *driverData, + SDL_Window *window); + + void (*ReleaseWindow)( + SDL_GPURenderer *driverData, + SDL_Window *window); + + bool (*SetSwapchainParameters)( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchainComposition, + SDL_GPUPresentMode presentMode); + + SDL_GPUTextureFormat (*GetSwapchainTextureFormat)( + SDL_GPURenderer *driverData, + SDL_Window *window); + + SDL_GPUCommandBuffer *(*AcquireCommandBuffer)( + SDL_GPURenderer *driverData); + + bool (*AcquireSwapchainTexture)( + SDL_GPUCommandBuffer *commandBuffer, + SDL_Window *window, + SDL_GPUTexture **swapchainTexture, + Uint32 *swapchainTextureWidth, + Uint32 *swapchainTextureHeight); + + bool (*Submit)( + SDL_GPUCommandBuffer *commandBuffer); + + SDL_GPUFence *(*SubmitAndAcquireFence)( + SDL_GPUCommandBuffer *commandBuffer); + + bool (*Wait)( + SDL_GPURenderer *driverData); + + bool (*WaitForFences)( + SDL_GPURenderer *driverData, + bool waitAll, + SDL_GPUFence *const *fences, + Uint32 numFences); + + bool (*QueryFence)( + SDL_GPURenderer *driverData, + SDL_GPUFence *fence); + + void (*ReleaseFence)( + SDL_GPURenderer *driverData, + SDL_GPUFence *fence); + + // Feature Queries + + bool (*SupportsTextureFormat)( + SDL_GPURenderer *driverData, + SDL_GPUTextureFormat format, + SDL_GPUTextureType type, + SDL_GPUTextureUsageFlags usage); + + bool (*SupportsSampleCount)( + SDL_GPURenderer *driverData, + SDL_GPUTextureFormat format, + SDL_GPUSampleCount desiredSampleCount); + + // Opaque pointer for the Driver + SDL_GPURenderer *driverData; + + // Store this for SDL_GetGPUDeviceDriver() + const char *backend; + + // Store this for SDL_GetGPUShaderFormats() + SDL_GPUShaderFormat shader_formats; + + // Store this for SDL_gpu.c's debug layer + bool debug_mode; +}; + +#define ASSIGN_DRIVER_FUNC(func, name) \ + result->func = name##_##func; +#define ASSIGN_DRIVER(name) \ + ASSIGN_DRIVER_FUNC(DestroyDevice, name) \ + ASSIGN_DRIVER_FUNC(CreateComputePipeline, name) \ + ASSIGN_DRIVER_FUNC(CreateGraphicsPipeline, name) \ + ASSIGN_DRIVER_FUNC(CreateSampler, name) \ + ASSIGN_DRIVER_FUNC(CreateShader, name) \ + ASSIGN_DRIVER_FUNC(CreateTexture, name) \ + ASSIGN_DRIVER_FUNC(CreateBuffer, name) \ + ASSIGN_DRIVER_FUNC(CreateTransferBuffer, name) \ + ASSIGN_DRIVER_FUNC(SetBufferName, name) \ + ASSIGN_DRIVER_FUNC(SetTextureName, name) \ + ASSIGN_DRIVER_FUNC(InsertDebugLabel, name) \ + ASSIGN_DRIVER_FUNC(PushDebugGroup, name) \ + ASSIGN_DRIVER_FUNC(PopDebugGroup, name) \ + ASSIGN_DRIVER_FUNC(ReleaseTexture, name) \ + ASSIGN_DRIVER_FUNC(ReleaseSampler, name) \ + ASSIGN_DRIVER_FUNC(ReleaseBuffer, name) \ + ASSIGN_DRIVER_FUNC(ReleaseTransferBuffer, name) \ + ASSIGN_DRIVER_FUNC(ReleaseShader, name) \ + ASSIGN_DRIVER_FUNC(ReleaseComputePipeline, name) \ + ASSIGN_DRIVER_FUNC(ReleaseGraphicsPipeline, name) \ + ASSIGN_DRIVER_FUNC(BeginRenderPass, name) \ + ASSIGN_DRIVER_FUNC(BindGraphicsPipeline, name) \ + ASSIGN_DRIVER_FUNC(SetViewport, name) \ + ASSIGN_DRIVER_FUNC(SetScissor, name) \ + ASSIGN_DRIVER_FUNC(SetBlendConstants, name) \ + ASSIGN_DRIVER_FUNC(SetStencilReference, name) \ + ASSIGN_DRIVER_FUNC(BindVertexBuffers, name) \ + ASSIGN_DRIVER_FUNC(BindIndexBuffer, name) \ + ASSIGN_DRIVER_FUNC(BindVertexSamplers, name) \ + ASSIGN_DRIVER_FUNC(BindVertexStorageTextures, name) \ + ASSIGN_DRIVER_FUNC(BindVertexStorageBuffers, name) \ + ASSIGN_DRIVER_FUNC(BindFragmentSamplers, name) \ + ASSIGN_DRIVER_FUNC(BindFragmentStorageTextures, name) \ + ASSIGN_DRIVER_FUNC(BindFragmentStorageBuffers, name) \ + ASSIGN_DRIVER_FUNC(PushVertexUniformData, name) \ + ASSIGN_DRIVER_FUNC(PushFragmentUniformData, name) \ + ASSIGN_DRIVER_FUNC(DrawIndexedPrimitives, name) \ + ASSIGN_DRIVER_FUNC(DrawPrimitives, name) \ + ASSIGN_DRIVER_FUNC(DrawPrimitivesIndirect, name) \ + ASSIGN_DRIVER_FUNC(DrawIndexedPrimitivesIndirect, name) \ + ASSIGN_DRIVER_FUNC(EndRenderPass, name) \ + ASSIGN_DRIVER_FUNC(BeginComputePass, name) \ + ASSIGN_DRIVER_FUNC(BindComputePipeline, name) \ + ASSIGN_DRIVER_FUNC(BindComputeSamplers, name) \ + ASSIGN_DRIVER_FUNC(BindComputeStorageTextures, name) \ + ASSIGN_DRIVER_FUNC(BindComputeStorageBuffers, name) \ + ASSIGN_DRIVER_FUNC(PushComputeUniformData, name) \ + ASSIGN_DRIVER_FUNC(DispatchCompute, name) \ + ASSIGN_DRIVER_FUNC(DispatchComputeIndirect, name) \ + ASSIGN_DRIVER_FUNC(EndComputePass, name) \ + ASSIGN_DRIVER_FUNC(MapTransferBuffer, name) \ + ASSIGN_DRIVER_FUNC(UnmapTransferBuffer, name) \ + ASSIGN_DRIVER_FUNC(BeginCopyPass, name) \ + ASSIGN_DRIVER_FUNC(UploadToTexture, name) \ + ASSIGN_DRIVER_FUNC(UploadToBuffer, name) \ + ASSIGN_DRIVER_FUNC(DownloadFromTexture, name) \ + ASSIGN_DRIVER_FUNC(DownloadFromBuffer, name) \ + ASSIGN_DRIVER_FUNC(CopyTextureToTexture, name) \ + ASSIGN_DRIVER_FUNC(CopyBufferToBuffer, name) \ + ASSIGN_DRIVER_FUNC(GenerateMipmaps, name) \ + ASSIGN_DRIVER_FUNC(EndCopyPass, name) \ + ASSIGN_DRIVER_FUNC(Blit, name) \ + ASSIGN_DRIVER_FUNC(SupportsSwapchainComposition, name) \ + ASSIGN_DRIVER_FUNC(SupportsPresentMode, name) \ + ASSIGN_DRIVER_FUNC(ClaimWindow, name) \ + ASSIGN_DRIVER_FUNC(ReleaseWindow, name) \ + ASSIGN_DRIVER_FUNC(SetSwapchainParameters, name) \ + ASSIGN_DRIVER_FUNC(GetSwapchainTextureFormat, name) \ + ASSIGN_DRIVER_FUNC(AcquireCommandBuffer, name) \ + ASSIGN_DRIVER_FUNC(AcquireSwapchainTexture, name) \ + ASSIGN_DRIVER_FUNC(Submit, name) \ + ASSIGN_DRIVER_FUNC(SubmitAndAcquireFence, name) \ + ASSIGN_DRIVER_FUNC(Wait, name) \ + ASSIGN_DRIVER_FUNC(WaitForFences, name) \ + ASSIGN_DRIVER_FUNC(QueryFence, name) \ + ASSIGN_DRIVER_FUNC(ReleaseFence, name) \ + ASSIGN_DRIVER_FUNC(SupportsTextureFormat, name) \ + ASSIGN_DRIVER_FUNC(SupportsSampleCount, name) + +typedef struct SDL_GPUBootstrap +{ + const char *name; + const SDL_GPUShaderFormat shader_formats; + bool (*PrepareDriver)(SDL_VideoDevice *_this); + SDL_GPUDevice *(*CreateDevice)(bool debug_mode, bool prefer_low_power, SDL_PropertiesID props); +} SDL_GPUBootstrap; + +#ifdef __cplusplus +extern "C" { +#endif + +extern SDL_GPUBootstrap VulkanDriver; +extern SDL_GPUBootstrap D3D11Driver; +extern SDL_GPUBootstrap D3D12Driver; +extern SDL_GPUBootstrap MetalDriver; +extern SDL_GPUBootstrap PS5Driver; + +#ifdef __cplusplus +} +#endif + +#endif // SDL_GPU_DRIVER_H diff --git a/libs/SDL3/src/gpu/d3d11/D3D11_Blit.h b/libs/SDL3/src/gpu/d3d11/D3D11_Blit.h new file mode 100644 index 000000000..58800af6d --- /dev/null +++ b/libs/SDL3/src/gpu/d3d11/D3D11_Blit.h @@ -0,0 +1,1707 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_VERTEXID 0 x 0 VERTID uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float xyzw +// +vs_5_0 +dcl_globalFlags refactoringAllowed +dcl_input_sgv v0.x, vertex_id +dcl_output o0.xy +dcl_output_siv o1.xyzw, position +dcl_temps 1 +bfi r0.x, l(1), l(1), v0.x, l(0) +and r0.z, v0.x, l(2) +utof r0.xy, r0.xzxx +mov o0.xy, r0.xyxx +mad o1.xy, r0.xyxx, l(2.000000, -2.000000, 0.000000, 0.000000), l(-1.000000, 1.000000, 0.000000, 0.000000) +mov o1.zw, l(0,0,0,1.000000) +ret +// Approximately 7 instruction slots used +#endif + +const BYTE g_FullscreenVert[] = +{ + 68, 88, 66, 67, 35, 105, + 237, 237, 146, 210, 147, 25, + 112, 64, 239, 9, 223, 111, + 229, 225, 1, 0, 0, 0, + 224, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 0, 0, 0, 212, 0, + 0, 0, 44, 1, 0, 0, + 68, 2, 0, 0, 82, 68, + 69, 70, 100, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 254, 255, 0, 1, 0, 0, + 60, 0, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 6, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 1, + 0, 0, 83, 86, 95, 86, + 69, 82, 84, 69, 88, 73, + 68, 0, 79, 83, 71, 78, + 80, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 12, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 171, 171, 171, + 83, 72, 69, 88, 16, 1, + 0, 0, 80, 0, 1, 0, + 68, 0, 0, 0, 106, 8, + 0, 1, 96, 0, 0, 4, + 18, 16, 16, 0, 0, 0, + 0, 0, 6, 0, 0, 0, + 101, 0, 0, 3, 50, 32, + 16, 0, 0, 0, 0, 0, + 103, 0, 0, 4, 242, 32, + 16, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 140, 0, 0, 11, 18, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 1, 0, 0, 0, 10, 16, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 7, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 2, 0, 0, 0, + 86, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 134, 0, 16, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 50, 32, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 50, 32, 16, 0, + 1, 0, 0, 0, 70, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 64, 0, 0, 0, 192, + 0, 0, 0, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 191, 0, 0, + 128, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 8, 194, 32, 16, 0, + 1, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 128, 63, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 7, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer SourceRegionBuffer +// { +// +// float2 UVLeftTop; // Offset: 0 Size: 8 +// float2 UVDimensions; // Offset: 8 Size: 8 +// uint MipLevel; // Offset: 16 Size: 4 +// float LayerOrDepth; // Offset: 20 Size: 4 [unused] +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// SourceSampler sampler NA NA s0 1 +// SourceTexture2D texture float4 2d t0 1 +// SourceRegionBuffer cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2d (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_output o0.xyzw +dcl_temps 1 +mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx +utof r0.z, cb0[1].x +sample_l_indexable(texture2d)(float,float,float,float) o0.xyzw, r0.xyxx, t0.xyzw, s0, r0.z +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_BlitFrom2D[] = +{ + 68, 88, 66, 67, 202, 121, + 86, 209, 195, 28, 22, 216, + 35, 118, 37, 69, 114, 188, + 248, 164, 1, 0, 0, 0, + 160, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 156, 2, 0, 0, 244, 2, + 0, 0, 40, 3, 0, 0, + 4, 4, 0, 0, 82, 68, + 69, 70, 96, 2, 0, 0, + 1, 0, 0, 0, 208, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 56, 2, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 4, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 186, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 83, 111, 117, 114, 99, 101, + 83, 97, 109, 112, 108, 101, + 114, 0, 83, 111, 117, 114, + 99, 101, 84, 101, 120, 116, + 117, 114, 101, 50, 68, 0, + 83, 111, 117, 114, 99, 101, + 82, 101, 103, 105, 111, 110, + 66, 117, 102, 102, 101, 114, + 0, 171, 171, 171, 186, 0, + 0, 0, 4, 0, 0, 0, + 232, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 156, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 192, 1, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 156, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 205, 1, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 220, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 2, + 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 0, 0, + 0, 0, 20, 2, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 85, 86, 76, 101, + 102, 116, 84, 111, 112, 0, + 102, 108, 111, 97, 116, 50, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 1, 0, 0, 85, 86, + 68, 105, 109, 101, 110, 115, + 105, 111, 110, 115, 0, 77, + 105, 112, 76, 101, 118, 101, + 108, 0, 100, 119, 111, 114, + 100, 0, 0, 0, 19, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 1, + 0, 0, 76, 97, 121, 101, + 114, 79, 114, 68, 101, 112, + 116, 104, 0, 102, 108, 111, + 97, 116, 0, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 2, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 80, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 171, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 212, 0, 0, 0, + 80, 0, 0, 0, 53, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 24, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 50, 0, + 0, 11, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 70, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 86, 0, 0, 6, 66, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 72, 0, 0, 141, 194, 0, + 0, 128, 67, 85, 21, 0, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 0, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer SourceRegionBuffer +// { +// +// float2 UVLeftTop; // Offset: 0 Size: 8 +// float2 UVDimensions; // Offset: 8 Size: 8 +// uint MipLevel; // Offset: 16 Size: 4 +// float LayerOrDepth; // Offset: 20 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// SourceSampler sampler NA NA s0 1 +// SourceTexture2DArray texture float4 2darray t0 1 +// SourceRegionBuffer cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture2darray (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_output o0.xyzw +dcl_temps 1 +ftou r0.x, cb0[1].y +utof r0.z, r0.x +mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx +utof r0.w, cb0[1].x +sample_l_indexable(texture2darray)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w +ret +// Approximately 6 instruction slots used +#endif + +const BYTE g_BlitFrom2DArray[] = +{ + 68, 88, 66, 67, 228, 235, + 27, 223, 254, 144, 184, 34, + 12, 203, 116, 115, 17, 233, + 159, 157, 1, 0, 0, 0, + 208, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 2, 0, 0, 248, 2, + 0, 0, 44, 3, 0, 0, + 52, 4, 0, 0, 82, 68, + 69, 70, 100, 2, 0, 0, + 1, 0, 0, 0, 212, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 60, 2, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 5, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 191, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 83, 111, 117, 114, 99, 101, + 83, 97, 109, 112, 108, 101, + 114, 0, 83, 111, 117, 114, + 99, 101, 84, 101, 120, 116, + 117, 114, 101, 50, 68, 65, + 114, 114, 97, 121, 0, 83, + 111, 117, 114, 99, 101, 82, + 101, 103, 105, 111, 110, 66, + 117, 102, 102, 101, 114, 0, + 171, 171, 191, 0, 0, 0, + 4, 0, 0, 0, 236, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 160, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 196, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 160, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 209, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 224, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 4, 2, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 24, 2, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 85, 86, 76, 101, 102, 116, + 84, 111, 112, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 171, 171, 1, 0, 3, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 1, + 0, 0, 85, 86, 68, 105, + 109, 101, 110, 115, 105, 111, + 110, 115, 0, 77, 105, 112, + 76, 101, 118, 101, 108, 0, + 100, 119, 111, 114, 100, 0, + 0, 0, 19, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 1, 0, 0, + 76, 97, 121, 101, 114, 79, + 114, 68, 101, 112, 116, 104, + 0, 102, 108, 111, 97, 116, + 0, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 2, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 79, + 83, 73, 84, 73, 79, 78, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 0, 1, 0, 0, 80, 0, + 0, 0, 64, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 64, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 1, 0, + 0, 0, 28, 0, 0, 6, + 18, 0, 16, 0, 0, 0, + 0, 0, 26, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 86, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 10, 0, 16, 0, + 0, 0, 0, 0, 50, 0, + 0, 11, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 70, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 86, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 72, 0, 0, 141, 2, 2, + 0, 128, 67, 85, 21, 0, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 6, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer SourceRegionBuffer +// { +// +// float2 UVLeftTop; // Offset: 0 Size: 8 +// float2 UVDimensions; // Offset: 8 Size: 8 +// uint MipLevel; // Offset: 16 Size: 4 +// float LayerOrDepth; // Offset: 20 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// SourceSampler sampler NA NA s0 1 +// SourceTexture3D texture float4 3d t0 1 +// SourceRegionBuffer cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texture3d (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_output o0.xyzw +dcl_temps 1 +mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx +utof r0.w, cb0[1].x +mov r0.z, cb0[1].y +sample_l_indexable(texture3d)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w +ret +// Approximately 5 instruction slots used +#endif + +const BYTE g_BlitFrom3D[] = +{ + 68, 88, 66, 67, 147, 168, + 4, 231, 209, 46, 121, 4, + 107, 179, 12, 172, 196, 130, + 224, 85, 1, 0, 0, 0, + 184, 4, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 156, 2, 0, 0, 244, 2, + 0, 0, 40, 3, 0, 0, + 28, 4, 0, 0, 82, 68, + 69, 70, 96, 2, 0, 0, + 1, 0, 0, 0, 208, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 56, 2, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 8, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 186, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 83, 111, 117, 114, 99, 101, + 83, 97, 109, 112, 108, 101, + 114, 0, 83, 111, 117, 114, + 99, 101, 84, 101, 120, 116, + 117, 114, 101, 51, 68, 0, + 83, 111, 117, 114, 99, 101, + 82, 101, 103, 105, 111, 110, + 66, 117, 102, 102, 101, 114, + 0, 171, 171, 171, 186, 0, + 0, 0, 4, 0, 0, 0, + 232, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 156, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 192, 1, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 156, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 205, 1, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 220, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 2, + 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 20, 2, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 85, 86, 76, 101, + 102, 116, 84, 111, 112, 0, + 102, 108, 111, 97, 116, 50, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 1, 0, 0, 85, 86, + 68, 105, 109, 101, 110, 115, + 105, 111, 110, 115, 0, 77, + 105, 112, 76, 101, 118, 101, + 108, 0, 100, 119, 111, 114, + 100, 0, 0, 0, 19, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 1, + 0, 0, 76, 97, 121, 101, + 114, 79, 114, 68, 101, 112, + 116, 104, 0, 102, 108, 111, + 97, 116, 0, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 2, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 80, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 171, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 236, 0, 0, 0, + 80, 0, 0, 0, 59, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 40, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 1, 0, 0, 0, 50, 0, + 0, 11, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 70, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 86, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 6, 66, 0, + 16, 0, 0, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 72, 0, 0, 141, 66, 1, + 0, 128, 67, 85, 21, 0, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 5, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer SourceRegionBuffer +// { +// +// float2 UVLeftTop; // Offset: 0 Size: 8 +// float2 UVDimensions; // Offset: 8 Size: 8 +// uint MipLevel; // Offset: 16 Size: 4 +// float LayerOrDepth; // Offset: 20 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// SourceSampler sampler NA NA s0 1 +// SourceTextureCube texture float4 cube t0 1 +// SourceRegionBuffer cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texturecube (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_output o0.xyzw +dcl_temps 2 +mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx +mad r0.xz, r0.xxyx, l(2.000000, 0.000000, 2.000000, 0.000000), l(-1.000000, 0.000000, -1.000000, 0.000000) +ftou r1.x, cb0[1].y +switch r1.x + case l(0) + mov r0.yz, -r0.zzxz + mov r0.x, l(1.000000) + break + case l(1) + mov r0.y, l(-1.000000) + mov r0.w, -r0.z + mov r0.xyz, r0.ywxy + break + case l(2) + mul r0.xz, r0.xxzx, l(1.000000, 0.000000, -1.000000, 0.000000) + mov r0.y, l(1.000000) + break + case l(3) + mov r0.y, l(-1.000000) + break + case l(4) + mul r0.xy, r0.xzxx, l(1.000000, -1.000000, 0.000000, 0.000000) + mov r0.z, l(1.000000) + break + case l(5) + mov r0.xy, -r0.xzxx + mov r0.z, l(-1.000000) + break + default + mov r0.xyz, l(0,0,0,0) + break +endswitch +utof r0.w, cb0[1].x +sample_l_indexable(texturecube)(float,float,float,float) o0.xyzw, r0.xyzx, t0.xyzw, s0, r0.w +ret +// Approximately 35 instruction slots used +#endif + +const BYTE g_BlitFromCube[] = +{ + 68, 88, 66, 67, 10, 119, + 223, 12, 113, 233, 111, 65, + 57, 156, 6, 26, 212, 111, + 79, 35, 1, 0, 0, 0, + 176, 6, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 156, 2, 0, 0, 244, 2, + 0, 0, 40, 3, 0, 0, + 20, 6, 0, 0, 82, 68, + 69, 70, 96, 2, 0, 0, + 1, 0, 0, 0, 208, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 56, 2, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 9, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 188, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 83, 111, 117, 114, 99, 101, + 83, 97, 109, 112, 108, 101, + 114, 0, 83, 111, 117, 114, + 99, 101, 84, 101, 120, 116, + 117, 114, 101, 67, 117, 98, + 101, 0, 83, 111, 117, 114, + 99, 101, 82, 101, 103, 105, + 111, 110, 66, 117, 102, 102, + 101, 114, 0, 171, 188, 0, + 0, 0, 4, 0, 0, 0, + 232, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 136, 1, + 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 2, 0, + 0, 0, 156, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 192, 1, 0, 0, + 8, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 156, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 205, 1, 0, 0, 16, 0, + 0, 0, 4, 0, 0, 0, + 2, 0, 0, 0, 220, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 2, + 0, 0, 20, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 20, 2, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 85, 86, 76, 101, + 102, 116, 84, 111, 112, 0, + 102, 108, 111, 97, 116, 50, + 0, 171, 171, 171, 1, 0, + 3, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 146, 1, 0, 0, 85, 86, + 68, 105, 109, 101, 110, 115, + 105, 111, 110, 115, 0, 77, + 105, 112, 76, 101, 118, 101, + 108, 0, 100, 119, 111, 114, + 100, 0, 0, 0, 19, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 214, 1, + 0, 0, 76, 97, 121, 101, + 114, 79, 114, 68, 101, 112, + 116, 104, 0, 102, 108, 111, + 97, 116, 0, 171, 0, 0, + 3, 0, 1, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 13, 2, 0, 0, 77, 105, + 99, 114, 111, 115, 111, 102, + 116, 32, 40, 82, 41, 32, + 72, 76, 83, 76, 32, 83, + 104, 97, 100, 101, 114, 32, + 67, 111, 109, 112, 105, 108, + 101, 114, 32, 49, 48, 46, + 49, 0, 73, 83, 71, 78, + 80, 0, 0, 0, 2, 0, + 0, 0, 8, 0, 0, 0, + 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 3, 3, 0, 0, + 65, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 3, 0, 0, 0, 1, 0, + 0, 0, 15, 0, 0, 0, + 84, 69, 88, 67, 79, 79, + 82, 68, 0, 83, 86, 95, + 80, 79, 83, 73, 84, 73, + 79, 78, 0, 171, 171, 171, + 79, 83, 71, 78, 44, 0, + 0, 0, 1, 0, 0, 0, + 8, 0, 0, 0, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 83, 86, + 95, 84, 97, 114, 103, 101, + 116, 0, 171, 171, 83, 72, + 69, 88, 228, 2, 0, 0, + 80, 0, 0, 0, 185, 0, + 0, 0, 106, 8, 0, 1, + 89, 0, 0, 4, 70, 142, + 32, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 90, 0, + 0, 3, 0, 96, 16, 0, + 0, 0, 0, 0, 88, 48, + 0, 4, 0, 112, 16, 0, + 0, 0, 0, 0, 85, 85, + 0, 0, 98, 16, 0, 3, + 50, 16, 16, 0, 0, 0, + 0, 0, 101, 0, 0, 3, + 242, 32, 16, 0, 0, 0, + 0, 0, 104, 0, 0, 2, + 2, 0, 0, 0, 50, 0, + 0, 11, 50, 0, 16, 0, + 0, 0, 0, 0, 230, 138, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 70, 16, + 16, 0, 0, 0, 0, 0, + 70, 128, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 50, 0, 0, 15, 82, 0, + 16, 0, 0, 0, 0, 0, + 6, 1, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 191, + 0, 0, 0, 0, 0, 0, + 128, 191, 0, 0, 0, 0, + 28, 0, 0, 6, 18, 0, + 16, 0, 1, 0, 0, 0, + 26, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 76, 0, 0, 3, 10, 0, + 16, 0, 1, 0, 0, 0, + 6, 0, 0, 3, 1, 64, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 6, 98, 0, + 16, 0, 0, 0, 0, 0, + 166, 8, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 18, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 2, 0, 0, 1, + 6, 0, 0, 3, 1, 64, + 0, 0, 1, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 54, 0, 0, 6, + 130, 0, 16, 0, 0, 0, + 0, 0, 42, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 114, 0, 16, 0, 0, 0, + 0, 0, 214, 4, 16, 0, + 0, 0, 0, 0, 2, 0, + 0, 1, 6, 0, 0, 3, + 1, 64, 0, 0, 2, 0, + 0, 0, 56, 0, 0, 10, + 82, 0, 16, 0, 0, 0, + 0, 0, 6, 2, 16, 0, + 0, 0, 0, 0, 2, 64, + 0, 0, 0, 0, 128, 63, + 0, 0, 0, 0, 0, 0, + 128, 191, 0, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 63, 2, 0, 0, 1, + 6, 0, 0, 3, 1, 64, + 0, 0, 3, 0, 0, 0, + 54, 0, 0, 5, 34, 0, + 16, 0, 0, 0, 0, 0, + 1, 64, 0, 0, 0, 0, + 128, 191, 2, 0, 0, 1, + 6, 0, 0, 3, 1, 64, + 0, 0, 4, 0, 0, 0, + 56, 0, 0, 10, 50, 0, + 16, 0, 0, 0, 0, 0, + 134, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 128, 191, 0, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 2, 0, 0, 1, 6, 0, + 0, 3, 1, 64, 0, 0, + 5, 0, 0, 0, 54, 0, + 0, 6, 50, 0, 16, 0, + 0, 0, 0, 0, 134, 0, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 66, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 2, 0, 0, 1, 10, 0, + 0, 1, 54, 0, 0, 8, + 114, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 1, 23, 0, 0, 1, + 86, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 128, 32, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 72, 0, 0, 141, 130, 1, + 0, 128, 67, 85, 21, 0, + 242, 32, 16, 0, 0, 0, + 0, 0, 70, 2, 16, 0, + 0, 0, 0, 0, 70, 126, + 16, 0, 0, 0, 0, 0, + 0, 96, 16, 0, 0, 0, + 0, 0, 58, 0, 16, 0, + 0, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 148, 0, 0, 0, 35, 0, + 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0 +}; +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Buffer Definitions: +// +// cbuffer SourceRegionBuffer +// { +// +// float2 UVLeftTop; // Offset: 0 Size: 8 +// float2 UVDimensions; // Offset: 8 Size: 8 +// uint MipLevel; // Offset: 16 Size: 4 +// float LayerOrDepth; // Offset: 20 Size: 4 +// +// } +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// SourceSampler sampler NA NA s0 1 +// SourceTextureCubeArray texture float4 cubearray t0 1 +// SourceRegionBuffer cbuffer NA NA cb0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// TEXCOORD 0 xy 0 NONE float xy +// SV_POSITION 0 xyzw 1 POS float +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_Target 0 xyzw 0 TARGET float xyzw +// +ps_5_0 +dcl_globalFlags refactoringAllowed +dcl_constantbuffer CB0[2], immediateIndexed +dcl_sampler s0, mode_default +dcl_resource_texturecubearray (float,float,float,float) t0 +dcl_input_ps linear v0.xy +dcl_output o0.xyzw +dcl_temps 3 +mad r0.xy, cb0[0].zwzz, v0.xyxx, cb0[0].xyxx +mad r0.xz, r0.xxyx, l(2.000000, 0.000000, 2.000000, 0.000000), l(-1.000000, 0.000000, -1.000000, 0.000000) +ftou r1.x, cb0[1].y +udiv r1.x, r2.x, r1.x, l(6) +switch r2.x + case l(0) + mov r0.yz, -r0.zzxz + mov r0.x, l(1.000000) + break + case l(1) + mov r0.y, l(-1.000000) + mov r0.w, -r0.z + mov r0.xyz, r0.ywxy + break + case l(2) + mul r0.xz, r0.xxzx, l(1.000000, 0.000000, -1.000000, 0.000000) + mov r0.y, l(1.000000) + break + case l(3) + mov r0.y, l(-1.000000) + break + case l(4) + mul r0.xy, r0.xzxx, l(1.000000, -1.000000, 0.000000, 0.000000) + mov r0.z, l(1.000000) + break + case l(5) + mov r0.xy, -r0.xzxx + mov r0.z, l(-1.000000) + break +endswitch +utof r0.w, r1.x +utof r1.x, cb0[1].x +sample_l_indexable(texturecubearray)(float,float,float,float) o0.xyzw, r0.xyzw, t0.xyzw, s0, r1.x +ret +// Approximately 34 instruction slots used +#endif + +const BYTE g_BlitFromCubeArray[] = +{ + 68, 88, 66, 67, 59, 147, + 203, 21, 33, 208, 116, 167, + 11, 254, 103, 46, 206, 206, + 176, 66, 1, 0, 0, 0, + 196, 6, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 160, 2, 0, 0, 248, 2, + 0, 0, 44, 3, 0, 0, + 40, 6, 0, 0, 82, 68, + 69, 70, 100, 2, 0, 0, + 1, 0, 0, 0, 212, 0, + 0, 0, 3, 0, 0, 0, + 60, 0, 0, 0, 0, 5, + 255, 255, 0, 1, 0, 0, + 60, 2, 0, 0, 82, 68, + 49, 49, 60, 0, 0, 0, + 24, 0, 0, 0, 32, 0, + 0, 0, 40, 0, 0, 0, + 36, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 0, 0, + 156, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, + 0, 0, 170, 0, 0, 0, + 2, 0, 0, 0, 5, 0, + 0, 0, 10, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 1, 0, 0, 0, + 13, 0, 0, 0, 193, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, + 83, 111, 117, 114, 99, 101, + 83, 97, 109, 112, 108, 101, + 114, 0, 83, 111, 117, 114, + 99, 101, 84, 101, 120, 116, + 117, 114, 101, 67, 117, 98, + 101, 65, 114, 114, 97, 121, + 0, 83, 111, 117, 114, 99, + 101, 82, 101, 103, 105, 111, + 110, 66, 117, 102, 102, 101, + 114, 0, 193, 0, 0, 0, + 4, 0, 0, 0, 236, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 140, 1, 0, 0, + 0, 0, 0, 0, 8, 0, + 0, 0, 2, 0, 0, 0, + 160, 1, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 196, 1, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, + 2, 0, 0, 0, 160, 1, + 0, 0, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 209, 1, + 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, + 0, 0, 224, 1, 0, 0, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 255, 255, 255, 255, 0, 0, + 0, 0, 4, 2, 0, 0, + 20, 0, 0, 0, 4, 0, + 0, 0, 2, 0, 0, 0, + 24, 2, 0, 0, 0, 0, + 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 255, 255, + 255, 255, 0, 0, 0, 0, + 85, 86, 76, 101, 102, 116, + 84, 111, 112, 0, 102, 108, + 111, 97, 116, 50, 0, 171, + 171, 171, 1, 0, 3, 0, + 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 1, + 0, 0, 85, 86, 68, 105, + 109, 101, 110, 115, 105, 111, + 110, 115, 0, 77, 105, 112, + 76, 101, 118, 101, 108, 0, + 100, 119, 111, 114, 100, 0, + 0, 0, 19, 0, 1, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 218, 1, 0, 0, + 76, 97, 121, 101, 114, 79, + 114, 68, 101, 112, 116, 104, + 0, 102, 108, 111, 97, 116, + 0, 171, 0, 0, 3, 0, + 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17, 2, + 0, 0, 77, 105, 99, 114, + 111, 115, 111, 102, 116, 32, + 40, 82, 41, 32, 72, 76, + 83, 76, 32, 83, 104, 97, + 100, 101, 114, 32, 67, 111, + 109, 112, 105, 108, 101, 114, + 32, 49, 48, 46, 49, 0, + 73, 83, 71, 78, 80, 0, + 0, 0, 2, 0, 0, 0, + 8, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 3, 3, 0, 0, 65, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 3, 0, + 0, 0, 1, 0, 0, 0, + 15, 0, 0, 0, 84, 69, + 88, 67, 79, 79, 82, 68, + 0, 83, 86, 95, 80, 79, + 83, 73, 84, 73, 79, 78, + 0, 171, 171, 171, 79, 83, + 71, 78, 44, 0, 0, 0, + 1, 0, 0, 0, 8, 0, + 0, 0, 32, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, + 171, 171, 83, 72, 69, 88, + 244, 2, 0, 0, 80, 0, + 0, 0, 189, 0, 0, 0, + 106, 8, 0, 1, 89, 0, + 0, 4, 70, 142, 32, 0, + 0, 0, 0, 0, 2, 0, + 0, 0, 90, 0, 0, 3, + 0, 96, 16, 0, 0, 0, + 0, 0, 88, 80, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 0, 0, 0, 0, + 101, 0, 0, 3, 242, 32, + 16, 0, 0, 0, 0, 0, + 104, 0, 0, 2, 3, 0, + 0, 0, 50, 0, 0, 11, + 50, 0, 16, 0, 0, 0, + 0, 0, 230, 138, 32, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 70, 16, 16, 0, + 0, 0, 0, 0, 70, 128, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 50, 0, + 0, 15, 82, 0, 16, 0, + 0, 0, 0, 0, 6, 1, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 0, 64, 0, 0, 0, 0, + 0, 0, 0, 64, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 191, 0, 0, + 0, 0, 0, 0, 128, 191, + 0, 0, 0, 0, 28, 0, + 0, 6, 18, 0, 16, 0, + 1, 0, 0, 0, 26, 128, + 32, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 78, 0, + 0, 9, 18, 0, 16, 0, + 1, 0, 0, 0, 18, 0, + 16, 0, 2, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 1, 64, 0, 0, + 6, 0, 0, 0, 76, 0, + 0, 3, 10, 0, 16, 0, + 2, 0, 0, 0, 6, 0, + 0, 3, 1, 64, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 6, 98, 0, 16, 0, + 0, 0, 0, 0, 166, 8, + 16, 128, 65, 0, 0, 0, + 0, 0, 0, 0, 54, 0, + 0, 5, 18, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 2, 0, 0, 1, 6, 0, + 0, 3, 1, 64, 0, 0, + 1, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 54, 0, 0, 6, 130, 0, + 16, 0, 0, 0, 0, 0, + 42, 0, 16, 128, 65, 0, + 0, 0, 0, 0, 0, 0, + 54, 0, 0, 5, 114, 0, + 16, 0, 0, 0, 0, 0, + 214, 4, 16, 0, 0, 0, + 0, 0, 2, 0, 0, 1, + 6, 0, 0, 3, 1, 64, + 0, 0, 2, 0, 0, 0, + 56, 0, 0, 10, 82, 0, + 16, 0, 0, 0, 0, 0, + 6, 2, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 128, 63, 0, 0, + 0, 0, 0, 0, 128, 191, + 0, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 63, + 2, 0, 0, 1, 6, 0, + 0, 3, 1, 64, 0, 0, + 3, 0, 0, 0, 54, 0, + 0, 5, 34, 0, 16, 0, + 0, 0, 0, 0, 1, 64, + 0, 0, 0, 0, 128, 191, + 2, 0, 0, 1, 6, 0, + 0, 3, 1, 64, 0, 0, + 4, 0, 0, 0, 56, 0, + 0, 10, 50, 0, 16, 0, + 0, 0, 0, 0, 134, 0, + 16, 0, 0, 0, 0, 0, + 2, 64, 0, 0, 0, 0, + 128, 63, 0, 0, 128, 191, + 0, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 63, 2, 0, + 0, 1, 6, 0, 0, 3, + 1, 64, 0, 0, 5, 0, + 0, 0, 54, 0, 0, 6, + 50, 0, 16, 0, 0, 0, + 0, 0, 134, 0, 16, 128, + 65, 0, 0, 0, 0, 0, + 0, 0, 54, 0, 0, 5, + 66, 0, 16, 0, 0, 0, + 0, 0, 1, 64, 0, 0, + 0, 0, 128, 191, 2, 0, + 0, 1, 23, 0, 0, 1, + 86, 0, 0, 5, 130, 0, + 16, 0, 0, 0, 0, 0, + 10, 0, 16, 0, 1, 0, + 0, 0, 86, 0, 0, 6, + 18, 0, 16, 0, 1, 0, + 0, 0, 10, 128, 32, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 72, 0, 0, 141, + 130, 2, 0, 128, 67, 85, + 21, 0, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 0, 96, 16, 0, + 0, 0, 0, 0, 10, 0, + 16, 0, 1, 0, 0, 0, + 62, 0, 0, 1, 83, 84, + 65, 84, 148, 0, 0, 0, + 34, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0 +}; diff --git a/libs/SDL3/src/gpu/d3d11/SDL_gpu_d3d11.c b/libs/SDL3/src/gpu/d3d11/SDL_gpu_d3d11.c new file mode 100644 index 000000000..ff3b9370b --- /dev/null +++ b/libs/SDL3/src/gpu/d3d11/SDL_gpu_d3d11.c @@ -0,0 +1,6469 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2024 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_GPU_D3D11 + +#define D3D11_NO_HELPERS +#define CINTERFACE +#define COBJMACROS + +#include +#include +#include +#include +#include + +#include "../SDL_sysgpu.h" + +#ifdef __IDXGIInfoQueue_INTERFACE_DEFINED__ +#define HAVE_IDXGIINFOQUEUE +#endif + +// Function Pointer Signatures +typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY1)(const GUID *riid, void **ppFactory); +typedef HRESULT(WINAPI *PFN_DXGI_GET_DEBUG_INTERFACE)(const GUID *riid, void **ppDebug); + +// IIDs (from https://www.magnumdb.com/) +static const IID D3D_IID_IDXGIFactory1 = { 0x770aae78, 0xf26f, 0x4dba, { 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3, 0x87 } }; +static const IID D3D_IID_IDXGIFactory4 = { 0x1bc6ea02, 0xef36, 0x464f, { 0xbf, 0x0c, 0x21, 0xca, 0x39, 0xe5, 0x16, 0x8a } }; +static const IID D3D_IID_IDXGIFactory5 = { 0x7632e1f5, 0xee65, 0x4dca, { 0x87, 0xfd, 0x84, 0xcd, 0x75, 0xf8, 0x83, 0x8d } }; +static const IID D3D_IID_IDXGIFactory6 = { 0xc1b6694f, 0xff09, 0x44a9, { 0xb0, 0x3c, 0x77, 0x90, 0x0a, 0x0a, 0x1d, 0x17 } }; +static const IID D3D_IID_IDXGIAdapter1 = { 0x29038f61, 0x3839, 0x4626, { 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a, 0x05 } }; +static const IID D3D_IID_IDXGISwapChain3 = { 0x94d99bdb, 0xf1f8, 0x4ab0, { 0xb2, 0x36, 0x7d, 0xa0, 0x17, 0x0e, 0xda, 0xb1 } }; +static const IID D3D_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } }; +static const IID D3D_IID_ID3DUserDefinedAnnotation = { 0xb2daad8b, 0x03d4, 0x4dbf, { 0x95, 0xeb, 0x32, 0xab, 0x4b, 0x63, 0xd0, 0xab } }; +static const IID D3D_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } }; +static const IID D3D_IID_IDXGIDebug = { 0x119e7452, 0xde9e, 0x40fe, { 0x88, 0x06, 0x88, 0xf9, 0x0c, 0x12, 0xb4, 0x41 } }; +#ifdef HAVE_IDXGIINFOQUEUE +static const IID D3D_IID_IDXGIInfoQueue = { 0xd67441c7, 0x672a, 0x476f, { 0x9e, 0x82, 0xcd, 0x55, 0xb4, 0x49, 0x49, 0xce } }; +#endif + +static const GUID D3D_IID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, { 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 } }; +static const GUID D3D_IID_DXGI_DEBUG_ALL = { 0xe48ae283, 0xda80, 0x490b, { 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x08 } }; + +// Defines + +#if defined(_WIN32) +#define D3D11_DLL "d3d11.dll" +#define DXGI_DLL "dxgi.dll" +#define DXGIDEBUG_DLL "dxgidebug.dll" +#elif defined(__APPLE__) +#define D3D11_DLL "libdxvk_d3d11.0.dylib" +#define DXGI_DLL "libdxvk_dxgi.0.dylib" +#define DXGIDEBUG_DLL "libdxvk_dxgidebug.0.dylib" +#else +#define D3D11_DLL "libdxvk_d3d11.so.0" +#define DXGI_DLL "libdxvk_dxgi.so.0" +#define DXGIDEBUG_DLL "libdxvk_dxgidebug.so.0" +#endif + +#define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice" +#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" +#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" +#define WINDOW_PROPERTY_DATA "SDL_GPUD3D11WindowPropertyData" + +#define SDL_GPU_SHADERSTAGE_COMPUTE 2 + +#ifdef _WIN32 +#define HRESULT_FMT "(0x%08lX)" +#else +#define HRESULT_FMT "(0x%08X)" +#endif + +// Built-in shaders, compiled with compile_shaders.bat + +#define g_FullscreenVert D3D11_FullscreenVert +#define g_BlitFrom2D D3D11_BlitFrom2D +#define g_BlitFrom2DArray D3D11_BlitFrom2DArray +#define g_BlitFrom3D D3D11_BlitFrom3D +#define g_BlitFromCube D3D11_BlitFromCube +#define g_BlitFromCubeArray D3D11_BlitFromCubeArray +#include "D3D11_Blit.h" +#undef g_FullscreenVert +#undef g_BlitFrom2D +#undef g_BlitFrom2DArray +#undef g_BlitFrom3D +#undef g_BlitFromCube +#undef g_BlitFromCubeArray + +// Macros + +#define SET_ERROR_AND_RETURN(fmt, msg, ret) \ + if (renderer->debugMode) { \ + SDL_LogError(SDL_LOG_CATEGORY_GPU, fmt, msg); \ + } \ + SDL_SetError(fmt, msg); \ + return ret; \ + +#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret) + +#define CHECK_D3D11_ERROR_AND_RETURN(msg, ret) \ + if (FAILED(res)) { \ + D3D11_INTERNAL_SetError(renderer, msg, res); \ + return ret; \ + } + +#define TRACK_RESOURCE(resource, type, array, count, capacity) \ + Uint32 i; \ + \ + for (i = 0; i < commandBuffer->count; i += 1) { \ + if (commandBuffer->array[i] == resource) { \ + return; \ + } \ + } \ + \ + if (commandBuffer->count == commandBuffer->capacity) { \ + commandBuffer->capacity += 1; \ + commandBuffer->array = SDL_realloc( \ + commandBuffer->array, \ + commandBuffer->capacity * sizeof(type)); \ + } \ + commandBuffer->array[commandBuffer->count] = resource; \ + commandBuffer->count += 1; \ + SDL_AtomicIncRef(&resource->referenceCount); + +// Forward Declarations + +static bool D3D11_Wait(SDL_GPURenderer *driverData); +static void D3D11_ReleaseWindow( + SDL_GPURenderer *driverData, + SDL_Window *window); +static void D3D11_INTERNAL_DestroyBlitPipelines(SDL_GPURenderer *driverData); + +// Conversions + +static SDL_GPUTextureFormat SwapchainCompositionToSDLTextureFormat[] = { + SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, // SDR + SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, // SDR_SRGB + SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, // HDR + SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED +}; + +static DXGI_FORMAT SwapchainCompositionToTextureFormat[] = { + DXGI_FORMAT_B8G8R8A8_UNORM, // SDR + DXGI_FORMAT_B8G8R8A8_UNORM, /* SDR_SRGB */ // NOTE: The RTV uses the sRGB format + DXGI_FORMAT_R16G16B16A16_FLOAT, // HDR + DXGI_FORMAT_R10G10B10A2_UNORM, // HDR_ADVANCED +}; + +static DXGI_COLOR_SPACE_TYPE SwapchainCompositionToColorSpace[] = { + DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR + DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, // SDR_SRGB + DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709, // HDR + DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 // HDR_ADVANCED +}; + +static DXGI_FORMAT SDLToD3D11_TextureFormat[] = { + DXGI_FORMAT_UNKNOWN, // INVALID + DXGI_FORMAT_A8_UNORM, // A8_UNORM + DXGI_FORMAT_R8_UNORM, // R8_UNORM + DXGI_FORMAT_R8G8_UNORM, // R8G8_UNORM + DXGI_FORMAT_R8G8B8A8_UNORM, // R8G8B8A8_UNORM + DXGI_FORMAT_R16_UNORM, // R16_UNORM + DXGI_FORMAT_R16G16_UNORM, // R16G16_UNORM + DXGI_FORMAT_R16G16B16A16_UNORM, // R16G16B16A16_UNORM + DXGI_FORMAT_R10G10B10A2_UNORM, // R10G10B10A2_UNORM + DXGI_FORMAT_B5G6R5_UNORM, // B5G6R5_UNORM + DXGI_FORMAT_B5G5R5A1_UNORM, // B5G5R5A1_UNORM + DXGI_FORMAT_B4G4R4A4_UNORM, // B4G4R4A4_UNORM + DXGI_FORMAT_B8G8R8A8_UNORM, // B8G8R8A8_UNORM + DXGI_FORMAT_BC1_UNORM, // BC1_UNORM + DXGI_FORMAT_BC2_UNORM, // BC2_UNORM + DXGI_FORMAT_BC3_UNORM, // BC3_UNORM + DXGI_FORMAT_BC4_UNORM, // BC4_UNORM + DXGI_FORMAT_BC5_UNORM, // BC5_UNORM + DXGI_FORMAT_BC7_UNORM, // BC7_UNORM + DXGI_FORMAT_BC6H_SF16, // BC6H_FLOAT + DXGI_FORMAT_BC6H_UF16, // BC6H_UFLOAT + DXGI_FORMAT_R8_SNORM, // R8_SNORM + DXGI_FORMAT_R8G8_SNORM, // R8G8_SNORM + DXGI_FORMAT_R8G8B8A8_SNORM, // R8G8B8A8_SNORM + DXGI_FORMAT_R16_SNORM, // R16_SNORM + DXGI_FORMAT_R16G16_SNORM, // R16G16_SNORM + DXGI_FORMAT_R16G16B16A16_SNORM, // R16G16B16A16_SNORM + DXGI_FORMAT_R16_FLOAT, // R16_FLOAT + DXGI_FORMAT_R16G16_FLOAT, // R16G16_FLOAT + DXGI_FORMAT_R16G16B16A16_FLOAT, // R16G16B16A16_FLOAT + DXGI_FORMAT_R32_FLOAT, // R32_FLOAT + DXGI_FORMAT_R32G32_FLOAT, // R32G32_FLOAT + DXGI_FORMAT_R32G32B32A32_FLOAT, // R32G32B32A32_FLOAT + DXGI_FORMAT_R11G11B10_FLOAT, // R11G11B10_UFLOAT + DXGI_FORMAT_R8_UINT, // R8_UINT + DXGI_FORMAT_R8G8_UINT, // R8G8_UINT + DXGI_FORMAT_R8G8B8A8_UINT, // R8G8B8A8_UINT + DXGI_FORMAT_R16_UINT, // R16_UINT + DXGI_FORMAT_R16G16_UINT, // R16G16_UINT + DXGI_FORMAT_R16G16B16A16_UINT, // R16G16B16A16_UINT + DXGI_FORMAT_R32_UINT, // R32_UINT + DXGI_FORMAT_R32G32_UINT, // R32G32_UINT + DXGI_FORMAT_R32G32B32A32_UINT, // R32G32B32A32_UINT + DXGI_FORMAT_R8_SINT, // R8_INT + DXGI_FORMAT_R8G8_SINT, // R8G8_INT + DXGI_FORMAT_R8G8B8A8_SINT, // R8G8B8A8_INT + DXGI_FORMAT_R16_SINT, // R16_INT + DXGI_FORMAT_R16G16_SINT, // R16G16_INT + DXGI_FORMAT_R16G16B16A16_SINT, // R16G16B16A16_INT + DXGI_FORMAT_R32_SINT, // R32_INT + DXGI_FORMAT_R32G32_SINT, // R32G32_INT + DXGI_FORMAT_R32G32B32A32_SINT, // R32G32B32A32_INT + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, // R8G8B8A8_UNORM_SRGB + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, // B8G8R8A8_UNORM_SRGB + DXGI_FORMAT_BC1_UNORM_SRGB, // BC1_UNORM_SRGB + DXGI_FORMAT_BC2_UNORM_SRGB, // BC2_UNORM_SRGB + DXGI_FORMAT_BC3_UNORM_SRGB, // BC3_UNORM_SRGB + DXGI_FORMAT_BC7_UNORM_SRGB, // BC7_UNORM_SRGB + DXGI_FORMAT_D16_UNORM, // D16_UNORM + DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM + DXGI_FORMAT_D32_FLOAT, // D32_FLOAT + DXGI_FORMAT_D24_UNORM_S8_UINT, // D24_UNORM_S8_UINT + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, // D32_FLOAT_S8_UINT +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_TextureFormat, SDL_arraysize(SDLToD3D11_TextureFormat) == SDL_GPU_TEXTUREFORMAT_MAX_ENUM_VALUE); + +static DXGI_FORMAT SDLToD3D11_VertexFormat[] = { + DXGI_FORMAT_UNKNOWN, // INVALID + DXGI_FORMAT_R32_SINT, // INT + DXGI_FORMAT_R32G32_SINT, // INT2 + DXGI_FORMAT_R32G32B32_SINT, // INT3 + DXGI_FORMAT_R32G32B32A32_SINT, // INT4 + DXGI_FORMAT_R32_UINT, // UINT + DXGI_FORMAT_R32G32_UINT, // UINT2 + DXGI_FORMAT_R32G32B32_UINT, // UINT3 + DXGI_FORMAT_R32G32B32A32_UINT, // UINT4 + DXGI_FORMAT_R32_FLOAT, // FLOAT + DXGI_FORMAT_R32G32_FLOAT, // FLOAT2 + DXGI_FORMAT_R32G32B32_FLOAT, // FLOAT3 + DXGI_FORMAT_R32G32B32A32_FLOAT, // FLOAT4 + DXGI_FORMAT_R8G8_SINT, // BYTE2 + DXGI_FORMAT_R8G8B8A8_SINT, // BYTE4 + DXGI_FORMAT_R8G8_UINT, // UBYTE2 + DXGI_FORMAT_R8G8B8A8_UINT, // UBYTE4 + DXGI_FORMAT_R8G8_SNORM, // BYTE2_NORM + DXGI_FORMAT_R8G8B8A8_SNORM, // BYTE4_NORM + DXGI_FORMAT_R8G8_UNORM, // UBYTE2_NORM + DXGI_FORMAT_R8G8B8A8_UNORM, // UBYTE4_NORM + DXGI_FORMAT_R16G16_SINT, // SHORT2 + DXGI_FORMAT_R16G16B16A16_SINT, // SHORT4 + DXGI_FORMAT_R16G16_UINT, // USHORT2 + DXGI_FORMAT_R16G16B16A16_UINT, // USHORT4 + DXGI_FORMAT_R16G16_SNORM, // SHORT2_NORM + DXGI_FORMAT_R16G16B16A16_SNORM, // SHORT4_NORM + DXGI_FORMAT_R16G16_UNORM, // USHORT2_NORM + DXGI_FORMAT_R16G16B16A16_UNORM, // USHORT4_NORM + DXGI_FORMAT_R16G16_FLOAT, // HALF2 + DXGI_FORMAT_R16G16B16A16_FLOAT // HALF4 +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_VertexFormat, SDL_arraysize(SDLToD3D11_VertexFormat) == SDL_GPU_VERTEXELEMENTFORMAT_MAX_ENUM_VALUE); + +static Uint32 SDLToD3D11_SampleCount[] = { + 1, // SDL_GPU_SAMPLECOUNT_1 + 2, // SDL_GPU_SAMPLECOUNT_2 + 4, // SDL_GPU_SAMPLECOUNT_4 + 8 // SDL_GPU_SAMPLECOUNT_8 +}; + +static DXGI_FORMAT SDLToD3D11_IndexType[] = { + DXGI_FORMAT_R16_UINT, // 16BIT + DXGI_FORMAT_R32_UINT // 32BIT +}; + +static D3D11_PRIMITIVE_TOPOLOGY SDLToD3D11_PrimitiveType[] = { + D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST, // TRIANGLELIST + D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // TRIANGLESTRIP + D3D_PRIMITIVE_TOPOLOGY_LINELIST, // LINELIST + D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, // LINESTRIP + D3D_PRIMITIVE_TOPOLOGY_POINTLIST // POINTLIST +}; + +static D3D11_CULL_MODE SDLToD3D11_CullMode[] = { + D3D11_CULL_NONE, // NONE + D3D11_CULL_FRONT, // FRONT + D3D11_CULL_BACK // BACK +}; + +static D3D11_BLEND SDLToD3D11_BlendFactor[] = { + D3D11_BLEND_ZERO, // INVALID + D3D11_BLEND_ZERO, // ZERO + D3D11_BLEND_ONE, // ONE + D3D11_BLEND_SRC_COLOR, // SRC_COLOR + D3D11_BLEND_INV_SRC_COLOR, // ONE_MINUS_SRC_COLOR + D3D11_BLEND_DEST_COLOR, // DST_COLOR + D3D11_BLEND_INV_DEST_COLOR, // ONE_MINUS_DST_COLOR + D3D11_BLEND_SRC_ALPHA, // SRC_ALPHA + D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA + D3D11_BLEND_DEST_ALPHA, // DST_ALPHA + D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA + D3D11_BLEND_BLEND_FACTOR, // CONSTANT_COLOR + D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR + D3D11_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendFactor, SDL_arraysize(SDLToD3D11_BlendFactor) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE); + +static D3D11_BLEND SDLToD3D11_BlendFactorAlpha[] = { + D3D11_BLEND_ZERO, // ALPHA + D3D11_BLEND_ZERO, // ZERO + D3D11_BLEND_ONE, // ONE + D3D11_BLEND_SRC_ALPHA, // SRC_COLOR + D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_COLOR + D3D11_BLEND_DEST_ALPHA, // DST_COLOR + D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_COLOR + D3D11_BLEND_SRC_ALPHA, // SRC_ALPHA + D3D11_BLEND_INV_SRC_ALPHA, // ONE_MINUS_SRC_ALPHA + D3D11_BLEND_DEST_ALPHA, // DST_ALPHA + D3D11_BLEND_INV_DEST_ALPHA, // ONE_MINUS_DST_ALPHA + D3D11_BLEND_BLEND_FACTOR, // CONSTANT_COLOR + D3D11_BLEND_INV_BLEND_FACTOR, // ONE_MINUS_CONSTANT_COLOR + D3D11_BLEND_SRC_ALPHA_SAT, // SRC_ALPHA_SATURATE +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendFactorAlpha, SDL_arraysize(SDLToD3D11_BlendFactorAlpha) == SDL_GPU_BLENDFACTOR_MAX_ENUM_VALUE); + +static D3D11_BLEND_OP SDLToD3D11_BlendOp[] = { + D3D11_BLEND_OP_ADD, // INVALID + D3D11_BLEND_OP_ADD, // ADD + D3D11_BLEND_OP_SUBTRACT, // SUBTRACT + D3D11_BLEND_OP_REV_SUBTRACT, // REVERSE_SUBTRACT + D3D11_BLEND_OP_MIN, // MIN + D3D11_BLEND_OP_MAX // MAX +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_BlendOp, SDL_arraysize(SDLToD3D11_BlendOp) == SDL_GPU_BLENDOP_MAX_ENUM_VALUE); + +static D3D11_COMPARISON_FUNC SDLToD3D11_CompareOp[] = { + D3D11_COMPARISON_NEVER, // INVALID + D3D11_COMPARISON_NEVER, // NEVER + D3D11_COMPARISON_LESS, // LESS + D3D11_COMPARISON_EQUAL, // EQUAL + D3D11_COMPARISON_LESS_EQUAL, // LESS_OR_EQUAL + D3D11_COMPARISON_GREATER, // GREATER + D3D11_COMPARISON_NOT_EQUAL, // NOT_EQUAL + D3D11_COMPARISON_GREATER_EQUAL, // GREATER_OR_EQUAL + D3D11_COMPARISON_ALWAYS // ALWAYS +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_CompareOp, SDL_arraysize(SDLToD3D11_CompareOp) == SDL_GPU_COMPAREOP_MAX_ENUM_VALUE); + +static D3D11_STENCIL_OP SDLToD3D11_StencilOp[] = { + D3D11_STENCIL_OP_KEEP, // INVALID + D3D11_STENCIL_OP_KEEP, // KEEP + D3D11_STENCIL_OP_ZERO, // ZERO + D3D11_STENCIL_OP_REPLACE, // REPLACE + D3D11_STENCIL_OP_INCR_SAT, // INCREMENT_AND_CLAMP + D3D11_STENCIL_OP_DECR_SAT, // DECREMENT_AND_CLAMP + D3D11_STENCIL_OP_INVERT, // INVERT + D3D11_STENCIL_OP_INCR, // INCREMENT_AND_WRAP + D3D11_STENCIL_OP_DECR // DECREMENT_AND_WRAP +}; +SDL_COMPILE_TIME_ASSERT(SDLToD3D11_StencilOp, SDL_arraysize(SDLToD3D11_StencilOp) == SDL_GPU_STENCILOP_MAX_ENUM_VALUE); + +static D3D11_INPUT_CLASSIFICATION SDLToD3D11_VertexInputRate[] = { + D3D11_INPUT_PER_VERTEX_DATA, // VERTEX + D3D11_INPUT_PER_INSTANCE_DATA // INSTANCE +}; + +static D3D11_TEXTURE_ADDRESS_MODE SDLToD3D11_SamplerAddressMode[] = { + D3D11_TEXTURE_ADDRESS_WRAP, // REPEAT + D3D11_TEXTURE_ADDRESS_MIRROR, // MIRRORED_REPEAT + D3D11_TEXTURE_ADDRESS_CLAMP // CLAMP_TO_EDGE +}; + +static D3D11_FILTER SDLToD3D11_Filter(const SDL_GPUSamplerCreateInfo *createInfo) +{ + if (createInfo->min_filter == SDL_GPU_FILTER_LINEAR) { + if (createInfo->mag_filter == SDL_GPU_FILTER_LINEAR) { + if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) { + return D3D11_FILTER_MIN_MAG_MIP_LINEAR; + } else { + return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + } + } else { + if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) { + return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + } else { + return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + } + } + } else { + if (createInfo->mag_filter == SDL_GPU_FILTER_LINEAR) { + if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) { + return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; + } else { + return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + } + } else { + if (createInfo->mipmap_mode == SDL_GPU_SAMPLERMIPMAPMODE_LINEAR) { + return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + } else { + return D3D11_FILTER_MIN_MAG_MIP_POINT; + } + } + } +} + +// Structs + +typedef struct D3D11Texture D3D11Texture; + +typedef struct D3D11TextureContainer +{ + TextureCommonHeader header; + + D3D11Texture *activeTexture; + + Uint32 textureCapacity; + Uint32 textureCount; + D3D11Texture **textures; + + char *debugName; + bool canBeCycled; +} D3D11TextureContainer; + +typedef struct D3D11TextureSubresource +{ + D3D11Texture *parent; + Uint32 layer; + Uint32 level; + Uint32 depth; // total depth + Uint32 index; + + // One RTV per depth slice + ID3D11RenderTargetView **colorTargetViews; // NULL if not a color target + + ID3D11UnorderedAccessView *uav; // NULL if not a storage texture + ID3D11DepthStencilView *depthStencilTargetView; // NULL if not a depth stencil target +} D3D11TextureSubresource; + +struct D3D11Texture +{ + D3D11TextureContainer *container; + Uint32 containerIndex; + + ID3D11Resource *handle; /* ID3D11Texture2D* or ID3D11Texture3D* */ + ID3D11ShaderResourceView *shaderView; + + D3D11TextureSubresource *subresources; + Uint32 subresourceCount; /* layerCount * num_levels */ + + SDL_AtomicInt referenceCount; +}; + +typedef struct D3D11Fence +{ + ID3D11Query *handle; + SDL_AtomicInt referenceCount; +} D3D11Fence; + +typedef struct D3D11WindowData +{ + SDL_Window *window; + IDXGISwapChain *swapchain; + D3D11Texture texture; + D3D11TextureContainer textureContainer; + SDL_GPUPresentMode presentMode; + SDL_GPUSwapchainComposition swapchainComposition; + DXGI_FORMAT swapchainFormat; + DXGI_COLOR_SPACE_TYPE swapchainColorSpace; + Uint32 width; + Uint32 height; + SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT]; + Uint32 frameCounter; + bool needsSwapchainRecreate; +} D3D11WindowData; + +typedef struct D3D11Shader +{ + ID3D11DeviceChild *handle; // ID3D11VertexShader, ID3D11PixelShader, ID3D11ComputeShader + void *bytecode; + size_t bytecodeSize; + + Uint32 numSamplers; + Uint32 numUniformBuffers; + Uint32 numStorageBuffers; + Uint32 numStorageTextures; +} D3D11Shader; + +typedef struct D3D11GraphicsPipeline +{ + Sint32 numColorTargets; + DXGI_FORMAT colorTargetFormats[MAX_COLOR_TARGET_BINDINGS]; + ID3D11BlendState *colorTargetBlendState; + Uint32 sampleMask; + + SDL_GPUMultisampleState multisampleState; + + Uint8 hasDepthStencilTarget; + DXGI_FORMAT depthStencilTargetFormat; + ID3D11DepthStencilState *depthStencilState; + + SDL_GPUPrimitiveType primitiveType; + ID3D11RasterizerState *rasterizerState; + + ID3D11VertexShader *vertexShader; + ID3D11PixelShader *fragmentShader; + + ID3D11InputLayout *inputLayout; + Uint32 vertexStrides[MAX_VERTEX_BUFFERS]; + + Uint32 vertexSamplerCount; + Uint32 vertexUniformBufferCount; + Uint32 vertexStorageBufferCount; + Uint32 vertexStorageTextureCount; + + Uint32 fragmentSamplerCount; + Uint32 fragmentUniformBufferCount; + Uint32 fragmentStorageBufferCount; + Uint32 fragmentStorageTextureCount; +} D3D11GraphicsPipeline; + +typedef struct D3D11ComputePipeline +{ + ID3D11ComputeShader *computeShader; + + Uint32 numSamplers; + Uint32 numReadonlyStorageTextures; + Uint32 numReadWriteStorageTextures; + Uint32 numReadonlyStorageBuffers; + Uint32 numReadWriteStorageBuffers; + Uint32 numUniformBuffers; +} D3D11ComputePipeline; + +typedef struct D3D11Buffer +{ + ID3D11Buffer *handle; + ID3D11UnorderedAccessView *uav; + ID3D11ShaderResourceView *srv; + Uint32 size; + SDL_AtomicInt referenceCount; +} D3D11Buffer; + +typedef struct D3D11BufferContainer +{ + D3D11Buffer *activeBuffer; + + Uint32 bufferCapacity; + Uint32 bufferCount; + D3D11Buffer **buffers; + + D3D11_BUFFER_DESC bufferDesc; + + char *debugName; +} D3D11BufferContainer; + +typedef struct D3D11BufferDownload +{ + ID3D11Buffer *stagingBuffer; + Uint32 dstOffset; + Uint32 size; +} D3D11BufferDownload; + +typedef struct D3D11TextureDownload +{ + ID3D11Resource *stagingTexture; + Uint32 width; + Uint32 height; + Uint32 depth; + Uint32 bufferOffset; + Uint32 bytesPerRow; + Uint32 bytesPerDepthSlice; +} D3D11TextureDownload; + +typedef struct D3D11TransferBuffer +{ + Uint8 *data; + Uint32 size; + SDL_AtomicInt referenceCount; + + D3D11BufferDownload *bufferDownloads; + Uint32 bufferDownloadCount; + Uint32 bufferDownloadCapacity; + + D3D11TextureDownload *textureDownloads; + Uint32 textureDownloadCount; + Uint32 textureDownloadCapacity; +} D3D11TransferBuffer; + +typedef struct D3D11TransferBufferContainer +{ + D3D11TransferBuffer *activeBuffer; + + /* These are all the buffers that have been used by this container. + * If the resource is bound and then updated with DISCARD, a new resource + * will be added to this list. + * These can be reused after they are submitted and command processing is complete. + */ + Uint32 bufferCapacity; + Uint32 bufferCount; + D3D11TransferBuffer **buffers; +} D3D11TransferBufferContainer; + +typedef struct D3D11UniformBuffer +{ + ID3D11Buffer *buffer; + void *mappedData; + + Uint32 drawOffset; + Uint32 writeOffset; + Uint32 currentBlockSize; +} D3D11UniformBuffer; + +typedef struct D3D11Sampler +{ + ID3D11SamplerState *handle; +} D3D11Sampler; + +typedef struct D3D11Renderer D3D11Renderer; + +typedef struct D3D11CommandBuffer +{ + CommandBufferCommonHeader common; + D3D11Renderer *renderer; + + // Deferred Context + ID3D11DeviceContext1 *context; + + // Presentation + D3D11WindowData **windowDatas; + Uint32 windowDataCount; + Uint32 windowDataCapacity; + + // Render Pass + D3D11GraphicsPipeline *graphicsPipeline; + Uint8 stencilRef; + SDL_FColor blendConstants; + D3D11TextureSubresource *colorTargetSubresources[MAX_COLOR_TARGET_BINDINGS]; + D3D11TextureSubresource *colorResolveSubresources[MAX_COLOR_TARGET_BINDINGS]; + + // Compute Pass + D3D11ComputePipeline *computePipeline; + + // Debug Annotation + ID3DUserDefinedAnnotation *annotation; + + // Resource slot state + + bool needVertexBufferBind; + + bool needVertexSamplerBind; + bool needVertexStorageTextureBind; + bool needVertexStorageBufferBind; + bool needVertexUniformBufferBind; + + bool needFragmentSamplerBind; + bool needFragmentStorageTextureBind; + bool needFragmentStorageBufferBind; + bool needFragmentUniformBufferBind; + + bool needComputeSamplerBind; + bool needComputeReadOnlyTextureBind; + bool needComputeReadOnlyBufferBind; + bool needComputeUniformBufferBind; + + // defer OMSetBlendState because it combines three different states + bool needBlendStateSet; + + ID3D11Buffer *vertexBuffers[MAX_VERTEX_BUFFERS]; + Uint32 vertexBufferOffsets[MAX_VERTEX_BUFFERS]; + Uint32 vertexBufferCount; + + D3D11Texture *vertexSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Sampler *vertexSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Texture *vertexStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE]; + D3D11Buffer *vertexStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE]; + + D3D11Texture *fragmentSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Sampler *fragmentSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Texture *fragmentStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE]; + D3D11Buffer *fragmentStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE]; + + D3D11Texture *computeSamplerTextures[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Sampler *computeSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + D3D11Texture *computeReadOnlyStorageTextures[MAX_STORAGE_TEXTURES_PER_STAGE]; + D3D11Buffer *computeReadOnlyStorageBuffers[MAX_STORAGE_BUFFERS_PER_STAGE]; + D3D11TextureSubresource *computeReadWriteStorageTextureSubresources[MAX_COMPUTE_WRITE_TEXTURES]; + D3D11Buffer *computeReadWriteStorageBuffers[MAX_COMPUTE_WRITE_BUFFERS]; + + // Uniform buffers + D3D11UniformBuffer *vertexUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE]; + D3D11UniformBuffer *fragmentUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE]; + D3D11UniformBuffer *computeUniformBuffers[MAX_UNIFORM_BUFFERS_PER_STAGE]; + + // Fences + D3D11Fence *fence; + Uint8 autoReleaseFence; + + // Reference Counting + D3D11Buffer **usedBuffers; + Uint32 usedBufferCount; + Uint32 usedBufferCapacity; + + D3D11TransferBuffer **usedTransferBuffers; + Uint32 usedTransferBufferCount; + Uint32 usedTransferBufferCapacity; + + D3D11Texture **usedTextures; + Uint32 usedTextureCount; + Uint32 usedTextureCapacity; + + D3D11UniformBuffer **usedUniformBuffers; + Uint32 usedUniformBufferCount; + Uint32 usedUniformBufferCapacity; +} D3D11CommandBuffer; + +struct D3D11Renderer +{ + ID3D11Device1 *device; + ID3D11DeviceContext *immediateContext; + IDXGIFactory1 *factory; + IDXGIAdapter1 *adapter; + IDXGIDebug *dxgiDebug; +#ifdef HAVE_IDXGIINFOQUEUE + IDXGIInfoQueue *dxgiInfoQueue; +#endif + + SDL_SharedObject *d3d11_dll; + SDL_SharedObject *dxgi_dll; + SDL_SharedObject *dxgidebug_dll; + + Uint8 debugMode; + BOOL supportsTearing; + Uint8 supportsFlipDiscard; + + SDL_iconv_t iconv; + + // Blit + BlitPipelineCacheEntry blitPipelines[5]; + SDL_GPUSampler *blitNearestSampler; + SDL_GPUSampler *blitLinearSampler; + + // Resource Tracking + D3D11WindowData **claimedWindows; + Uint32 claimedWindowCount; + Uint32 claimedWindowCapacity; + + D3D11CommandBuffer **availableCommandBuffers; + Uint32 availableCommandBufferCount; + Uint32 availableCommandBufferCapacity; + + D3D11CommandBuffer **submittedCommandBuffers; + Uint32 submittedCommandBufferCount; + Uint32 submittedCommandBufferCapacity; + + D3D11Fence **availableFences; + Uint32 availableFenceCount; + Uint32 availableFenceCapacity; + + D3D11UniformBuffer **uniformBufferPool; + Uint32 uniformBufferPoolCount; + Uint32 uniformBufferPoolCapacity; + + D3D11TransferBufferContainer **transferBufferContainersToDestroy; + Uint32 transferBufferContainersToDestroyCount; + Uint32 transferBufferContainersToDestroyCapacity; + + D3D11BufferContainer **bufferContainersToDestroy; + Uint32 bufferContainersToDestroyCount; + Uint32 bufferContainersToDestroyCapacity; + + D3D11TextureContainer **textureContainersToDestroy; + Uint32 textureContainersToDestroyCount; + Uint32 textureContainersToDestroyCapacity; + + SDL_Mutex *contextLock; + SDL_Mutex *acquireCommandBufferLock; + SDL_Mutex *acquireUniformBufferLock; + SDL_Mutex *fenceLock; + SDL_Mutex *windowLock; + + // Null arrays for resetting resource slots + ID3D11RenderTargetView *nullRTVs[MAX_COLOR_TARGET_BINDINGS]; + + ID3D11ShaderResourceView *nullSRVs[MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 + + MAX_STORAGE_TEXTURES_PER_STAGE + + MAX_STORAGE_BUFFERS_PER_STAGE]; + + ID3D11SamplerState *nullSamplers[MAX_TEXTURE_SAMPLERS_PER_STAGE * 2]; + + ID3D11UnorderedAccessView *nullUAVs[MAX_COMPUTE_WRITE_TEXTURES + + MAX_COMPUTE_WRITE_BUFFERS]; +}; + +// Logging + +static void D3D11_INTERNAL_SetError( + D3D11Renderer *renderer, + const char *msg, + HRESULT res) +{ +#define MAX_ERROR_LEN 1024 // FIXME: Arbitrary! + + // Buffer for text, ensure space for \0 terminator after buffer + char wszMsgBuff[MAX_ERROR_LEN + 1]; + DWORD dwChars; // Number of chars returned. + + if (res == DXGI_ERROR_DEVICE_REMOVED) { + res = ID3D11Device_GetDeviceRemovedReason(renderer->device); + } + + // Try to get the message from the system errors. +#ifdef _WIN32 + dwChars = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + res, + 0, + wszMsgBuff, + MAX_ERROR_LEN, + NULL); +#else + // FIXME: Do we have error strings in dxvk-native? -flibit + dwChars = 0; +#endif + + // No message? Screw it, just post the code. + if (dwChars == 0) { + if (renderer->debugMode) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: " HRESULT_FMT, msg, res); + } + SDL_SetError("%s! Error Code: " HRESULT_FMT, msg, res); + return; + } + + // Ensure valid range + dwChars = SDL_min(dwChars, MAX_ERROR_LEN); + + // Trim whitespace from tail of message + while (dwChars > 0) { + if (wszMsgBuff[dwChars - 1] <= ' ') { + dwChars--; + } else { + break; + } + } + + // Ensure null-terminated string + wszMsgBuff[dwChars] = '\0'; + + if (renderer->debugMode) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res); + } + SDL_SetError("%s! Error Code: %s " HRESULT_FMT, msg, wszMsgBuff, res); +} + +// Helper Functions + +static inline Uint32 D3D11_INTERNAL_CalcSubresource( + Uint32 mipLevel, + Uint32 layer, + Uint32 numLevels) +{ + return mipLevel + (layer * numLevels); +} + +static inline Uint32 D3D11_INTERNAL_NextHighestAlignment( + Uint32 n, + Uint32 align) +{ + return align * ((n + align - 1) / align); +} + +static DXGI_FORMAT D3D11_INTERNAL_GetTypelessFormat( + DXGI_FORMAT typedFormat) +{ + switch (typedFormat) { + case DXGI_FORMAT_D16_UNORM: + return DXGI_FORMAT_R16_TYPELESS; + case DXGI_FORMAT_D32_FLOAT: + return DXGI_FORMAT_R32_TYPELESS; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return DXGI_FORMAT_R24G8_TYPELESS; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return DXGI_FORMAT_R32G8X24_TYPELESS; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +static DXGI_FORMAT D3D11_INTERNAL_GetSampleableFormat( + DXGI_FORMAT format) +{ + switch (format) { + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_R16_UNORM; + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_R32_FLOAT; + case DXGI_FORMAT_R24G8_TYPELESS: + return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; + default: + return format; + } +} + +// Quit + +static void D3D11_INTERNAL_DestroyBufferContainer( + D3D11BufferContainer *container) +{ + for (Uint32 i = 0; i < container->bufferCount; i += 1) { + D3D11Buffer *d3d11Buffer = container->buffers[i]; + + if (d3d11Buffer->uav != NULL) { + ID3D11UnorderedAccessView_Release(d3d11Buffer->uav); + } + + if (d3d11Buffer->srv != NULL) { + ID3D11ShaderResourceView_Release(d3d11Buffer->srv); + } + + ID3D11Buffer_Release(d3d11Buffer->handle); + + SDL_free(d3d11Buffer); + } + + SDL_free(container->buffers); + SDL_free(container); +} + +static void D3D11_DestroyDevice( + SDL_GPUDevice *device) +{ + D3D11Renderer *renderer = (D3D11Renderer *)device->driverData; + + // Flush any remaining GPU work... + D3D11_Wait(device->driverData); + + // Release the window data + for (Sint32 i = renderer->claimedWindowCount - 1; i >= 0; i -= 1) { + D3D11_ReleaseWindow(device->driverData, renderer->claimedWindows[i]->window); + } + SDL_free(renderer->claimedWindows); + + // Release the blit resources + D3D11_INTERNAL_DestroyBlitPipelines(device->driverData); + + // Release UBOs + for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) { + ID3D11Buffer_Release(renderer->uniformBufferPool[i]->buffer); + SDL_free(renderer->uniformBufferPool[i]); + } + SDL_free(renderer->uniformBufferPool); + + // Release command buffer infrastructure + for (Uint32 i = 0; i < renderer->availableCommandBufferCount; i += 1) { + D3D11CommandBuffer *commandBuffer = renderer->availableCommandBuffers[i]; + if (commandBuffer->annotation) { + ID3DUserDefinedAnnotation_Release(commandBuffer->annotation); + } + ID3D11DeviceContext_Release(commandBuffer->context); + SDL_free(commandBuffer->usedBuffers); + SDL_free(commandBuffer->usedTransferBuffers); + SDL_free(commandBuffer); + } + SDL_free(renderer->availableCommandBuffers); + SDL_free(renderer->submittedCommandBuffers); + + // Release fence infrastructure + for (Uint32 i = 0; i < renderer->availableFenceCount; i += 1) { + D3D11Fence *fence = renderer->availableFences[i]; + ID3D11Query_Release(fence->handle); + SDL_free(fence); + } + SDL_free(renderer->availableFences); + + // Release the iconv, if applicable + if (renderer->iconv != NULL) { + SDL_iconv_close(renderer->iconv); + } + + // Release the mutexes + SDL_DestroyMutex(renderer->acquireCommandBufferLock); + SDL_DestroyMutex(renderer->acquireUniformBufferLock); + SDL_DestroyMutex(renderer->contextLock); + SDL_DestroyMutex(renderer->fenceLock); + SDL_DestroyMutex(renderer->windowLock); + + // Release the device and associated objects + ID3D11DeviceContext_Release(renderer->immediateContext); + ID3D11Device_Release(renderer->device); + IDXGIAdapter_Release(renderer->adapter); + IDXGIFactory_Release(renderer->factory); + + // Report leaks and clean up debug objects + if (renderer->dxgiDebug) { + IDXGIDebug_ReportLiveObjects( + renderer->dxgiDebug, + D3D_IID_DXGI_DEBUG_ALL, + DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_DETAIL); + IDXGIDebug_Release(renderer->dxgiDebug); + } + +#ifdef HAVE_IDXGIINFOQUEUE + if (renderer->dxgiInfoQueue) { + IDXGIInfoQueue_Release(renderer->dxgiInfoQueue); + } +#endif + + // Release the DLLs + SDL_UnloadObject(renderer->d3d11_dll); + SDL_UnloadObject(renderer->dxgi_dll); + if (renderer->dxgidebug_dll) { + SDL_UnloadObject(renderer->dxgidebug_dll); + } + + // Free the primary structures + SDL_free(renderer); + SDL_free(device); +} + +// Resource tracking + +static void D3D11_INTERNAL_TrackBuffer( + D3D11CommandBuffer *commandBuffer, + D3D11Buffer *buffer) +{ + TRACK_RESOURCE( + buffer, + D3D11Buffer *, + usedBuffers, + usedBufferCount, + usedBufferCapacity); +} + +static void D3D11_INTERNAL_TrackTransferBuffer( + D3D11CommandBuffer *commandBuffer, + D3D11TransferBuffer *buffer) +{ + TRACK_RESOURCE( + buffer, + D3D11TransferBuffer *, + usedTransferBuffers, + usedTransferBufferCount, + usedTransferBufferCapacity); +} + +static void D3D11_INTERNAL_TrackTexture( + D3D11CommandBuffer *commandBuffer, + D3D11Texture *texture) +{ + TRACK_RESOURCE( + texture, + D3D11Texture *, + usedTextures, + usedTextureCount, + usedTextureCapacity); +} + +static void D3D11_INTERNAL_TrackUniformBuffer( + D3D11CommandBuffer *commandBuffer, + D3D11UniformBuffer *uniformBuffer) +{ + Uint32 i; + for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) { + if (commandBuffer->usedUniformBuffers[i] == uniformBuffer) { + return; + } + } + + if (commandBuffer->usedUniformBufferCount == commandBuffer->usedUniformBufferCapacity) { + commandBuffer->usedUniformBufferCapacity += 1; + commandBuffer->usedUniformBuffers = SDL_realloc( + commandBuffer->usedUniformBuffers, + commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *)); + } + + commandBuffer->usedUniformBuffers[commandBuffer->usedUniformBufferCount] = uniformBuffer; + commandBuffer->usedUniformBufferCount += 1; +} + +// Disposal + +static void D3D11_INTERNAL_DestroyTexture(D3D11Texture *d3d11Texture) +{ + if (d3d11Texture->shaderView) { + ID3D11ShaderResourceView_Release(d3d11Texture->shaderView); + } + + for (Uint32 subresourceIndex = 0; subresourceIndex < d3d11Texture->subresourceCount; subresourceIndex += 1) { + if (d3d11Texture->subresources[subresourceIndex].colorTargetViews != NULL) { + for (Uint32 depthIndex = 0; depthIndex < d3d11Texture->subresources[subresourceIndex].depth; depthIndex += 1) { + ID3D11RenderTargetView_Release(d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]); + } + SDL_free(d3d11Texture->subresources[subresourceIndex].colorTargetViews); + } + + if (d3d11Texture->subresources[subresourceIndex].depthStencilTargetView != NULL) { + ID3D11DepthStencilView_Release(d3d11Texture->subresources[subresourceIndex].depthStencilTargetView); + } + + if (d3d11Texture->subresources[subresourceIndex].uav != NULL) { + ID3D11UnorderedAccessView_Release(d3d11Texture->subresources[subresourceIndex].uav); + } + } + SDL_free(d3d11Texture->subresources); + + ID3D11Resource_Release(d3d11Texture->handle); +} + +static void D3D11_INTERNAL_DestroyTextureContainer( + D3D11TextureContainer *container) +{ + for (Uint32 i = 0; i < container->textureCount; i += 1) { + D3D11_INTERNAL_DestroyTexture(container->textures[i]); + } + + SDL_free(container->textures); + SDL_free(container); +} + +static void D3D11_ReleaseTexture( + SDL_GPURenderer *driverData, + SDL_GPUTexture *texture) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11TextureContainer *container = (D3D11TextureContainer *)texture; + + SDL_LockMutex(renderer->contextLock); + + EXPAND_ARRAY_IF_NEEDED( + renderer->textureContainersToDestroy, + D3D11TextureContainer *, + renderer->textureContainersToDestroyCount + 1, + renderer->textureContainersToDestroyCapacity, + renderer->textureContainersToDestroyCapacity + 1); + + renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount] = container; + renderer->textureContainersToDestroyCount += 1; + + SDL_UnlockMutex(renderer->contextLock); +} + +static void D3D11_ReleaseSampler( + SDL_GPURenderer *driverData, + SDL_GPUSampler *sampler) +{ + (void)driverData; // used by other backends + D3D11Sampler *d3d11Sampler = (D3D11Sampler *)sampler; + ID3D11SamplerState_Release(d3d11Sampler->handle); + SDL_free(d3d11Sampler); +} + +static void D3D11_ReleaseBuffer( + SDL_GPURenderer *driverData, + SDL_GPUBuffer *buffer) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11BufferContainer *container = (D3D11BufferContainer *)buffer; + + SDL_LockMutex(renderer->contextLock); + + EXPAND_ARRAY_IF_NEEDED( + renderer->bufferContainersToDestroy, + D3D11BufferContainer *, + renderer->bufferContainersToDestroyCount + 1, + renderer->bufferContainersToDestroyCapacity, + renderer->bufferContainersToDestroyCapacity + 1); + + renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount] = container; + renderer->bufferContainersToDestroyCount += 1; + + SDL_UnlockMutex(renderer->contextLock); +} + +static void D3D11_ReleaseTransferBuffer( + SDL_GPURenderer *driverData, + SDL_GPUTransferBuffer *transferBuffer) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + + SDL_LockMutex(renderer->contextLock); + + EXPAND_ARRAY_IF_NEEDED( + renderer->transferBufferContainersToDestroy, + D3D11TransferBufferContainer *, + renderer->transferBufferContainersToDestroyCount + 1, + renderer->transferBufferContainersToDestroyCapacity, + renderer->transferBufferContainersToDestroyCapacity + 1); + + renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount] = (D3D11TransferBufferContainer *)transferBuffer; + renderer->transferBufferContainersToDestroyCount += 1; + + SDL_UnlockMutex(renderer->contextLock); +} + +static void D3D11_INTERNAL_DestroyTransferBufferContainer( + D3D11TransferBufferContainer *transferBufferContainer) +{ + for (Uint32 i = 0; i < transferBufferContainer->bufferCount; i += 1) { + if (transferBufferContainer->buffers[i]->bufferDownloadCount > 0) { + SDL_free(transferBufferContainer->buffers[i]->bufferDownloads); + } + if (transferBufferContainer->buffers[i]->textureDownloadCount > 0) { + SDL_free(transferBufferContainer->buffers[i]->textureDownloads); + } + SDL_free(transferBufferContainer->buffers[i]->data); + SDL_free(transferBufferContainer->buffers[i]); + } + SDL_free(transferBufferContainer->buffers); +} + +static void D3D11_ReleaseShader( + SDL_GPURenderer *driverData, + SDL_GPUShader *shader) +{ + (void)driverData; // used by other backends + D3D11Shader *d3dShader = (D3D11Shader *)shader; + ID3D11DeviceChild_Release(d3dShader->handle); + if (d3dShader->bytecode) { + SDL_free(d3dShader->bytecode); + } + SDL_free(d3dShader); +} + +static void D3D11_ReleaseComputePipeline( + SDL_GPURenderer *driverData, + SDL_GPUComputePipeline *computePipeline) +{ + D3D11ComputePipeline *d3d11ComputePipeline = (D3D11ComputePipeline *)computePipeline; + + ID3D11ComputeShader_Release(d3d11ComputePipeline->computeShader); + + SDL_free(d3d11ComputePipeline); +} + +static void D3D11_ReleaseGraphicsPipeline( + SDL_GPURenderer *driverData, + SDL_GPUGraphicsPipeline *graphicsPipeline) +{ + (void)driverData; // used by other backends + D3D11GraphicsPipeline *d3d11GraphicsPipeline = (D3D11GraphicsPipeline *)graphicsPipeline; + + ID3D11BlendState_Release(d3d11GraphicsPipeline->colorTargetBlendState); + ID3D11DepthStencilState_Release(d3d11GraphicsPipeline->depthStencilState); + ID3D11RasterizerState_Release(d3d11GraphicsPipeline->rasterizerState); + + if (d3d11GraphicsPipeline->inputLayout) { + ID3D11InputLayout_Release(d3d11GraphicsPipeline->inputLayout); + } + + ID3D11VertexShader_Release(d3d11GraphicsPipeline->vertexShader); + ID3D11PixelShader_Release(d3d11GraphicsPipeline->fragmentShader); + + SDL_free(d3d11GraphicsPipeline); +} + +// State Creation + +static ID3D11BlendState *D3D11_INTERNAL_FetchBlendState( + D3D11Renderer *renderer, + Uint32 numColorTargets, + const SDL_GPUColorTargetDescription *colorTargets) +{ + ID3D11BlendState *result; + D3D11_BLEND_DESC blendDesc; + HRESULT res; + + /* Create a new blend state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + SDL_zero(blendDesc); // needed for any unused RT entries + + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = TRUE; + + for (Uint32 i = 0; i < numColorTargets; i += 1) { + SDL_GPUColorComponentFlags colorWriteMask = colorTargets[i].blend_state.enable_color_write_mask ? + colorTargets[i].blend_state.color_write_mask : + 0xF; + + blendDesc.RenderTarget[i].BlendEnable = colorTargets[i].blend_state.enable_blend; + blendDesc.RenderTarget[i].BlendOp = SDLToD3D11_BlendOp[colorTargets[i].blend_state.color_blend_op]; + blendDesc.RenderTarget[i].BlendOpAlpha = SDLToD3D11_BlendOp[colorTargets[i].blend_state.alpha_blend_op]; + blendDesc.RenderTarget[i].DestBlend = SDLToD3D11_BlendFactor[colorTargets[i].blend_state.dst_color_blendfactor]; + blendDesc.RenderTarget[i].DestBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorTargets[i].blend_state.dst_alpha_blendfactor]; + blendDesc.RenderTarget[i].RenderTargetWriteMask = colorWriteMask; + blendDesc.RenderTarget[i].SrcBlend = SDLToD3D11_BlendFactor[colorTargets[i].blend_state.src_color_blendfactor]; + blendDesc.RenderTarget[i].SrcBlendAlpha = SDLToD3D11_BlendFactorAlpha[colorTargets[i].blend_state.src_alpha_blendfactor]; + } + + res = ID3D11Device_CreateBlendState( + renderer->device, + &blendDesc, + &result); + CHECK_D3D11_ERROR_AND_RETURN("Could not create blend state", NULL); + + return result; +} + +static ID3D11DepthStencilState *D3D11_INTERNAL_FetchDepthStencilState( + D3D11Renderer *renderer, + SDL_GPUDepthStencilState depthStencilState) +{ + ID3D11DepthStencilState *result; + D3D11_DEPTH_STENCIL_DESC dsDesc; + HRESULT res; + + /* Create a new depth-stencil state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + dsDesc.DepthEnable = depthStencilState.enable_depth_test; + dsDesc.StencilEnable = depthStencilState.enable_stencil_test; + dsDesc.DepthFunc = SDLToD3D11_CompareOp[depthStencilState.compare_op]; + dsDesc.DepthWriteMask = (depthStencilState.enable_depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO); + + dsDesc.BackFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.back_stencil_state.compare_op]; + dsDesc.BackFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.depth_fail_op]; + dsDesc.BackFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.fail_op]; + dsDesc.BackFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.back_stencil_state.pass_op]; + + dsDesc.FrontFace.StencilFunc = SDLToD3D11_CompareOp[depthStencilState.front_stencil_state.compare_op]; + dsDesc.FrontFace.StencilDepthFailOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.depth_fail_op]; + dsDesc.FrontFace.StencilFailOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.fail_op]; + dsDesc.FrontFace.StencilPassOp = SDLToD3D11_StencilOp[depthStencilState.front_stencil_state.pass_op]; + + dsDesc.StencilReadMask = depthStencilState.compare_mask; + dsDesc.StencilWriteMask = depthStencilState.write_mask; + + res = ID3D11Device_CreateDepthStencilState( + renderer->device, + &dsDesc, + &result); + CHECK_D3D11_ERROR_AND_RETURN("Could not create depth-stencil state", NULL); + + return result; +} + +static ID3D11RasterizerState *D3D11_INTERNAL_FetchRasterizerState( + D3D11Renderer *renderer, + SDL_GPURasterizerState rasterizerState) +{ + ID3D11RasterizerState *result; + D3D11_RASTERIZER_DESC rasterizerDesc; + HRESULT res; + + /* Create a new rasterizer state. + * The spec says the driver will not create duplicate states, so there's no need to cache. + */ + rasterizerDesc.AntialiasedLineEnable = FALSE; + rasterizerDesc.CullMode = SDLToD3D11_CullMode[rasterizerState.cull_mode]; + rasterizerDesc.DepthBias = SDL_lroundf(rasterizerState.depth_bias_constant_factor); + rasterizerDesc.DepthBiasClamp = rasterizerState.depth_bias_clamp; + rasterizerDesc.DepthClipEnable = rasterizerState.enable_depth_clip; + rasterizerDesc.FillMode = (rasterizerState.fill_mode == SDL_GPU_FILLMODE_FILL) ? D3D11_FILL_SOLID : D3D11_FILL_WIREFRAME; + rasterizerDesc.FrontCounterClockwise = (rasterizerState.front_face == SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE); + rasterizerDesc.MultisampleEnable = TRUE; // only applies to MSAA render targets + rasterizerDesc.ScissorEnable = TRUE; + rasterizerDesc.SlopeScaledDepthBias = rasterizerState.depth_bias_slope_factor; + + res = ID3D11Device_CreateRasterizerState( + renderer->device, + &rasterizerDesc, + &result); + CHECK_D3D11_ERROR_AND_RETURN("Could not create rasterizer state", NULL); + + return result; +} + +static Uint32 D3D11_INTERNAL_FindIndexOfVertexSlot( + Uint32 targetSlot, + const SDL_GPUVertexBufferDescription *bufferDescriptions, + Uint32 numDescriptions) +{ + for (Uint32 i = 0; i < numDescriptions; i += 1) { + if (bufferDescriptions[i].slot == targetSlot) { + return i; + } + } + + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not find vertex buffer slot %u!", targetSlot); + return 0; +} + +static ID3D11InputLayout *D3D11_INTERNAL_FetchInputLayout( + D3D11Renderer *renderer, + SDL_GPUVertexInputState inputState, + void *shaderBytes, + size_t shaderByteLength) +{ + ID3D11InputLayout *result = NULL; + D3D11_INPUT_ELEMENT_DESC *elementDescs; + Uint32 bindingIndex; + HRESULT res; + + // Don't bother creating/fetching an input layout if there are no attributes. + if (inputState.num_vertex_attributes == 0) { + return NULL; + } + + // Allocate an array of vertex elements + elementDescs = SDL_stack_alloc( + D3D11_INPUT_ELEMENT_DESC, + inputState.num_vertex_attributes); + + // Create the array of input elements + for (Uint32 i = 0; i < inputState.num_vertex_attributes; i += 1) { + elementDescs[i].AlignedByteOffset = inputState.vertex_attributes[i].offset; + elementDescs[i].Format = SDLToD3D11_VertexFormat[inputState.vertex_attributes[i].format]; + elementDescs[i].InputSlot = inputState.vertex_attributes[i].buffer_slot; + + bindingIndex = D3D11_INTERNAL_FindIndexOfVertexSlot( + elementDescs[i].InputSlot, + inputState.vertex_buffer_descriptions, + inputState.num_vertex_buffers); + elementDescs[i].InputSlotClass = SDLToD3D11_VertexInputRate[inputState.vertex_buffer_descriptions[bindingIndex].input_rate]; + // The spec requires this to be 0 for per-vertex data + elementDescs[i].InstanceDataStepRate = (inputState.vertex_buffer_descriptions[bindingIndex].input_rate == SDL_GPU_VERTEXINPUTRATE_INSTANCE) + ? inputState.vertex_buffer_descriptions[bindingIndex].instance_step_rate + : 0; + + elementDescs[i].SemanticIndex = inputState.vertex_attributes[i].location; + elementDescs[i].SemanticName = "TEXCOORD"; + } + + res = ID3D11Device_CreateInputLayout( + renderer->device, + elementDescs, + inputState.num_vertex_attributes, + shaderBytes, + shaderByteLength, + &result); + if (FAILED(res)) { + SDL_stack_free(elementDescs); + CHECK_D3D11_ERROR_AND_RETURN("Could not create input layout!", NULL) + return NULL; + } + + /* FIXME: + * These are not cached by the driver! Should we cache them, or allow duplicates? + * If we have one input layout per graphics pipeline maybe that wouldn't be so bad...? + */ + + SDL_stack_free(elementDescs); + return result; +} + +// Pipeline Creation + +static ID3D11DeviceChild *D3D11_INTERNAL_CreateID3D11Shader( + D3D11Renderer *renderer, + Uint32 stage, + const Uint8 *code, + size_t codeSize, + const char *entrypointName, + void **pBytecode, + size_t *pBytecodeSize) +{ + ID3D11DeviceChild *handle = NULL; + HRESULT res; + + // Create the shader from the byte blob + if (stage == SDL_GPU_SHADERSTAGE_VERTEX) { + res = ID3D11Device_CreateVertexShader( + renderer->device, + code, + codeSize, + NULL, + (ID3D11VertexShader **)&handle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create vertex shader", NULL) + } else if (stage == SDL_GPU_SHADERSTAGE_FRAGMENT) { + res = ID3D11Device_CreatePixelShader( + renderer->device, + code, + codeSize, + NULL, + (ID3D11PixelShader **)&handle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create pixel shader", NULL) + } else if (stage == SDL_GPU_SHADERSTAGE_COMPUTE) { + res = ID3D11Device_CreateComputeShader( + renderer->device, + code, + codeSize, + NULL, + (ID3D11ComputeShader **)&handle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create compute shader", NULL) + } + + if (pBytecode != NULL) { + *pBytecode = SDL_malloc(codeSize); + SDL_memcpy(*pBytecode, code, codeSize); + *pBytecodeSize = codeSize; + } + + return handle; +} + +static SDL_GPUComputePipeline *D3D11_CreateComputePipeline( + SDL_GPURenderer *driverData, + const SDL_GPUComputePipelineCreateInfo *createinfo) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + ID3D11ComputeShader *shader; + D3D11ComputePipeline *pipeline; + + shader = (ID3D11ComputeShader *)D3D11_INTERNAL_CreateID3D11Shader( + renderer, + SDL_GPU_SHADERSTAGE_COMPUTE, + createinfo->code, + createinfo->code_size, + createinfo->entrypoint, + NULL, + NULL); + if (shader == NULL) { + return NULL; + } + + pipeline = SDL_malloc(sizeof(D3D11ComputePipeline)); + pipeline->computeShader = shader; + pipeline->numSamplers = createinfo->num_samplers; + pipeline->numReadonlyStorageTextures = createinfo->num_readonly_storage_textures; + pipeline->numReadWriteStorageTextures = createinfo->num_readwrite_storage_textures; + pipeline->numReadonlyStorageBuffers = createinfo->num_readonly_storage_buffers; + pipeline->numReadWriteStorageBuffers = createinfo->num_readwrite_storage_buffers; + pipeline->numUniformBuffers = createinfo->num_uniform_buffers; + // thread counts are ignored in d3d11 + + return (SDL_GPUComputePipeline *)pipeline; +} + +static SDL_GPUGraphicsPipeline *D3D11_CreateGraphicsPipeline( + SDL_GPURenderer *driverData, + const SDL_GPUGraphicsPipelineCreateInfo *createinfo) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11Shader *vertShader = (D3D11Shader *)createinfo->vertex_shader; + D3D11Shader *fragShader = (D3D11Shader *)createinfo->fragment_shader; + D3D11GraphicsPipeline *pipeline = SDL_malloc(sizeof(D3D11GraphicsPipeline)); + + // Blend + + pipeline->colorTargetBlendState = D3D11_INTERNAL_FetchBlendState( + renderer, + createinfo->target_info.num_color_targets, + createinfo->target_info.color_target_descriptions); + + if (pipeline->colorTargetBlendState == NULL) { + return NULL; + } + + pipeline->numColorTargets = createinfo->target_info.num_color_targets; + for (Sint32 i = 0; i < pipeline->numColorTargets; i += 1) { + pipeline->colorTargetFormats[i] = SDLToD3D11_TextureFormat[createinfo->target_info.color_target_descriptions[i].format]; + } + + // Multisample + + pipeline->multisampleState = createinfo->multisample_state; + pipeline->sampleMask = createinfo->multisample_state.enable_mask ? + createinfo->multisample_state.sample_mask : + 0xFFFFFFFF; + + // Depth-Stencil + + pipeline->depthStencilState = D3D11_INTERNAL_FetchDepthStencilState( + renderer, + createinfo->depth_stencil_state); + + if (pipeline->depthStencilState == NULL) { + return NULL; + } + + pipeline->hasDepthStencilTarget = createinfo->target_info.has_depth_stencil_target; + pipeline->depthStencilTargetFormat = SDLToD3D11_TextureFormat[createinfo->target_info.depth_stencil_format]; + + // Rasterizer + + pipeline->primitiveType = createinfo->primitive_type; + pipeline->rasterizerState = D3D11_INTERNAL_FetchRasterizerState( + renderer, + createinfo->rasterizer_state); + + if (pipeline->rasterizerState == NULL) { + return NULL; + } + + // Shaders + + pipeline->vertexShader = (ID3D11VertexShader *)vertShader->handle; + ID3D11VertexShader_AddRef(pipeline->vertexShader); + + pipeline->fragmentShader = (ID3D11PixelShader *)fragShader->handle; + ID3D11PixelShader_AddRef(pipeline->fragmentShader); + + // Input Layout + + pipeline->inputLayout = D3D11_INTERNAL_FetchInputLayout( + renderer, + createinfo->vertex_input_state, + vertShader->bytecode, + vertShader->bytecodeSize); + + SDL_zeroa(pipeline->vertexStrides); + if (createinfo->vertex_input_state.num_vertex_buffers > 0) { + for (Uint32 i = 0; i < createinfo->vertex_input_state.num_vertex_buffers; i += 1) { + pipeline->vertexStrides[createinfo->vertex_input_state.vertex_buffer_descriptions[i].slot] = + createinfo->vertex_input_state.vertex_buffer_descriptions[i].pitch; + } + } + + // Resource layout + + pipeline->vertexSamplerCount = vertShader->numSamplers; + pipeline->vertexStorageTextureCount = vertShader->numStorageTextures; + pipeline->vertexStorageBufferCount = vertShader->numStorageBuffers; + pipeline->vertexUniformBufferCount = vertShader->numUniformBuffers; + + pipeline->fragmentSamplerCount = fragShader->numSamplers; + pipeline->fragmentStorageTextureCount = fragShader->numStorageTextures; + pipeline->fragmentStorageBufferCount = fragShader->numStorageBuffers; + pipeline->fragmentUniformBufferCount = fragShader->numUniformBuffers; + + return (SDL_GPUGraphicsPipeline *)pipeline; +} + +// Debug Naming + +static void D3D11_INTERNAL_SetBufferName( + D3D11Renderer *renderer, + D3D11Buffer *buffer, + const char *text) +{ + if (renderer->debugMode) { + ID3D11DeviceChild_SetPrivateData( + buffer->handle, + &D3D_IID_D3DDebugObjectName, + (UINT)SDL_strlen(text), + text); + } +} + +static void D3D11_SetBufferName( + SDL_GPURenderer *driverData, + SDL_GPUBuffer *buffer, + const char *text) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11BufferContainer *container = (D3D11BufferContainer *)buffer; + size_t textLength = SDL_strlen(text) + 1; + + if (renderer->debugMode) { + container->debugName = SDL_realloc( + container->debugName, + textLength); + + SDL_utf8strlcpy( + container->debugName, + text, + textLength); + + for (Uint32 i = 0; i < container->bufferCount; i += 1) { + D3D11_INTERNAL_SetBufferName( + renderer, + container->buffers[i], + text); + } + } +} + +static void D3D11_INTERNAL_SetTextureName( + D3D11Renderer *renderer, + D3D11Texture *texture, + const char *text) +{ + if (renderer->debugMode) { + ID3D11DeviceChild_SetPrivateData( + texture->handle, + &D3D_IID_D3DDebugObjectName, + (UINT)SDL_strlen(text), + text); + } +} + +static void D3D11_SetTextureName( + SDL_GPURenderer *driverData, + SDL_GPUTexture *texture, + const char *text) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11TextureContainer *container = (D3D11TextureContainer *)texture; + size_t textLength = SDL_strlen(text) + 1; + + if (renderer->debugMode) { + container->debugName = SDL_realloc( + container->debugName, + textLength); + + SDL_utf8strlcpy( + container->debugName, + text, + textLength); + + for (Uint32 i = 0; i < container->textureCount; i += 1) { + D3D11_INTERNAL_SetTextureName( + renderer, + container->textures[i], + text); + } + } +} + +static bool D3D11_INTERNAL_StrToWStr( + D3D11Renderer *renderer, + const char *str, + wchar_t *wstr, + size_t wstrSize) +{ + size_t inlen, result; + size_t outlen = wstrSize; + + if (renderer->iconv == NULL) { + renderer->iconv = SDL_iconv_open("WCHAR_T", "UTF-8"); + SDL_assert(renderer->iconv); + } + + // Convert... + inlen = SDL_strlen(str) + 1; + result = SDL_iconv( + renderer->iconv, + &str, + &inlen, + (char **)&wstr, + &outlen); + + // Check... + switch (result) { + case SDL_ICONV_ERROR: + case SDL_ICONV_E2BIG: + case SDL_ICONV_EILSEQ: + case SDL_ICONV_EINVAL: + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Failed to convert string to wchar_t!"); + return false; + default: + break; + } + + return true; +} + +static void D3D11_InsertDebugLabel( + SDL_GPUCommandBuffer *commandBuffer, + const char *text) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + + if (d3d11CommandBuffer->annotation == NULL) { + return; + } + + wchar_t wstr[256]; + if (!D3D11_INTERNAL_StrToWStr(renderer, text, wstr, sizeof(wstr))) { + return; + } + + ID3DUserDefinedAnnotation_SetMarker(d3d11CommandBuffer->annotation, wstr); +} + +static void D3D11_PushDebugGroup( + SDL_GPUCommandBuffer *commandBuffer, + const char *name) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + + if (d3d11CommandBuffer->annotation == NULL) { + return; + } + + wchar_t wstr[256]; + if (!D3D11_INTERNAL_StrToWStr(renderer, name, wstr, sizeof(wstr))) { + return; + } + + ID3DUserDefinedAnnotation_BeginEvent(d3d11CommandBuffer->annotation, wstr); +} + +static void D3D11_PopDebugGroup( + SDL_GPUCommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + if (d3d11CommandBuffer->annotation == NULL) { + return; + } + ID3DUserDefinedAnnotation_EndEvent(d3d11CommandBuffer->annotation); +} + +// Resource Creation + +static SDL_GPUSampler *D3D11_CreateSampler( + SDL_GPURenderer *driverData, + const SDL_GPUSamplerCreateInfo *createinfo) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11_SAMPLER_DESC samplerDesc; + ID3D11SamplerState *samplerStateHandle; + D3D11Sampler *d3d11Sampler; + HRESULT res; + + samplerDesc.AddressU = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_u]; + samplerDesc.AddressV = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_v]; + samplerDesc.AddressW = SDLToD3D11_SamplerAddressMode[createinfo->address_mode_w]; + samplerDesc.ComparisonFunc = (createinfo->enable_compare ? SDLToD3D11_CompareOp[createinfo->compare_op] : SDLToD3D11_CompareOp[SDL_GPU_COMPAREOP_ALWAYS]); + samplerDesc.MaxAnisotropy = (createinfo->enable_anisotropy ? (UINT)createinfo->max_anisotropy : 0); + samplerDesc.Filter = SDLToD3D11_Filter(createinfo); + samplerDesc.MaxLOD = createinfo->max_lod; + samplerDesc.MinLOD = createinfo->min_lod; + samplerDesc.MipLODBias = createinfo->mip_lod_bias; + SDL_zeroa(samplerDesc.BorderColor); // arbitrary, unused + + res = ID3D11Device_CreateSamplerState( + renderer->device, + &samplerDesc, + &samplerStateHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create sampler state", NULL); + + d3d11Sampler = (D3D11Sampler *)SDL_malloc(sizeof(D3D11Sampler)); + d3d11Sampler->handle = samplerStateHandle; + + return (SDL_GPUSampler *)d3d11Sampler; +} + +SDL_GPUShader *D3D11_CreateShader( + SDL_GPURenderer *driverData, + const SDL_GPUShaderCreateInfo *createinfo) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + ID3D11DeviceChild *handle; + void *bytecode = NULL; + size_t bytecodeSize = 0; + D3D11Shader *shader; + + handle = D3D11_INTERNAL_CreateID3D11Shader( + renderer, + createinfo->stage, + createinfo->code, + createinfo->code_size, + createinfo->entrypoint, + createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecode : NULL, + createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX ? &bytecodeSize : NULL); + if (handle == NULL) { + return NULL; + } + + shader = (D3D11Shader *)SDL_calloc(1, sizeof(D3D11Shader)); + shader->handle = handle; + shader->numSamplers = createinfo->num_samplers; + shader->numStorageBuffers = createinfo->num_storage_buffers; + shader->numStorageTextures = createinfo->num_storage_textures; + shader->numUniformBuffers = createinfo->num_uniform_buffers; + if (createinfo->stage == SDL_GPU_SHADERSTAGE_VERTEX) { + // Store the raw bytecode and its length for creating InputLayouts + shader->bytecode = bytecode; + shader->bytecodeSize = bytecodeSize; + } + + return (SDL_GPUShader *)shader; +} + +static D3D11Texture *D3D11_INTERNAL_CreateTexture( + D3D11Renderer *renderer, + const SDL_GPUTextureCreateInfo *createInfo, + D3D11_SUBRESOURCE_DATA *initialData) +{ + Uint8 needsSRV, isColorTarget, isDepthStencil, isMultisample, isStaging, needSubresourceUAV, isMippable; + DXGI_FORMAT format; + ID3D11Resource *textureHandle; + ID3D11ShaderResourceView *srv = NULL; + D3D11Texture *d3d11Texture; + HRESULT res; + + isColorTarget = createInfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; + isDepthStencil = createInfo->usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET; + needsSRV = + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) || + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ) || + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ); + needSubresourceUAV = + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) || + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE); + isMultisample = createInfo->sample_count > SDL_GPU_SAMPLECOUNT_1; + isStaging = createInfo->usage == 0; + isMippable = + createInfo->num_levels > 1 && + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) && + (createInfo->usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET); + format = SDLToD3D11_TextureFormat[createInfo->format]; + if (isDepthStencil) { + format = D3D11_INTERNAL_GetTypelessFormat(format); + } + + Uint32 layerCount = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? 1 : createInfo->layer_count_or_depth; + Uint32 depth = createInfo->type == SDL_GPU_TEXTURETYPE_3D ? createInfo->layer_count_or_depth : 1; + + if (createInfo->type != SDL_GPU_TEXTURETYPE_3D) { + D3D11_TEXTURE2D_DESC desc2D; + + desc2D.BindFlags = 0; + if (needsSRV) { + desc2D.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (needSubresourceUAV) { + desc2D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + if (isColorTarget) { + desc2D.BindFlags |= D3D11_BIND_RENDER_TARGET; + } + if (isDepthStencil) { + desc2D.BindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + + desc2D.Width = createInfo->width; + desc2D.Height = createInfo->height; + desc2D.ArraySize = layerCount; + desc2D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0; + desc2D.Format = format; + desc2D.MipLevels = createInfo->num_levels; + desc2D.MiscFlags = 0; + desc2D.SampleDesc.Count = SDLToD3D11_SampleCount[createInfo->sample_count]; + desc2D.SampleDesc.Quality = isMultisample ? D3D11_STANDARD_MULTISAMPLE_PATTERN : 0; + desc2D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT; + + if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + desc2D.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; + } + if (isMippable) { + desc2D.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + } + + res = ID3D11Device_CreateTexture2D( + renderer->device, + &desc2D, + initialData, + (ID3D11Texture2D **)&textureHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture2D", NULL); + + // Create the SRV, if applicable + if (needsSRV) { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = D3D11_INTERNAL_GetSampleableFormat(format); + + if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE) { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = desc2D.MipLevels; + srvDesc.TextureCube.MostDetailedMip = 0; + } else if (createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; + srvDesc.TextureCubeArray.MipLevels = desc2D.MipLevels; + srvDesc.TextureCubeArray.MostDetailedMip = 0; + srvDesc.TextureCubeArray.First2DArrayFace = 0; + srvDesc.TextureCubeArray.NumCubes = layerCount / 6; + } else if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY) { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MipLevels = desc2D.MipLevels; + srvDesc.Texture2DArray.MostDetailedMip = 0; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = layerCount; + } else { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = desc2D.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + } + + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + textureHandle, + &srvDesc, + &srv); + if (FAILED(res)) { + ID3D11Resource_Release(textureHandle); + D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 2D texture", res); + return NULL; + } + } + } else { + D3D11_TEXTURE3D_DESC desc3D; + + desc3D.BindFlags = 0; + if (needsSRV) { + desc3D.BindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (needSubresourceUAV) { + desc3D.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + if (isColorTarget) { + desc3D.BindFlags |= D3D11_BIND_RENDER_TARGET; + } + + desc3D.Width = createInfo->width; + desc3D.Height = createInfo->height; + desc3D.Depth = depth; + desc3D.CPUAccessFlags = isStaging ? D3D11_CPU_ACCESS_WRITE : 0; + desc3D.Format = format; + desc3D.MipLevels = createInfo->num_levels; + desc3D.MiscFlags = isMippable ? D3D11_RESOURCE_MISC_GENERATE_MIPS : 0; + desc3D.Usage = isStaging ? D3D11_USAGE_STAGING : D3D11_USAGE_DEFAULT; + + res = ID3D11Device_CreateTexture3D( + renderer->device, + &desc3D, + initialData, + (ID3D11Texture3D **)&textureHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create Texture3D", NULL); + + // Create the SRV, if applicable + if (needsSRV) { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MipLevels = desc3D.MipLevels; + srvDesc.Texture3D.MostDetailedMip = 0; + + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + textureHandle, + &srvDesc, + &srv); + if (FAILED(res)) { + ID3D11Resource_Release(textureHandle); + D3D11_INTERNAL_SetError(renderer, "Could not create SRV for 3D texture", res); + return NULL; + } + } + } + + d3d11Texture = (D3D11Texture *)SDL_malloc(sizeof(D3D11Texture)); + d3d11Texture->handle = textureHandle; + d3d11Texture->shaderView = srv; + SDL_SetAtomicInt(&d3d11Texture->referenceCount, 0); + d3d11Texture->container = NULL; + d3d11Texture->containerIndex = 0; + + d3d11Texture->subresourceCount = createInfo->num_levels * layerCount; + d3d11Texture->subresources = SDL_malloc( + d3d11Texture->subresourceCount * sizeof(D3D11TextureSubresource)); + + for (Uint32 layerIndex = 0; layerIndex < layerCount; layerIndex += 1) { + for (Uint32 levelIndex = 0; levelIndex < createInfo->num_levels; levelIndex += 1) { + Uint32 subresourceIndex = D3D11_INTERNAL_CalcSubresource( + levelIndex, + layerIndex, + createInfo->num_levels); + + d3d11Texture->subresources[subresourceIndex].parent = d3d11Texture; + d3d11Texture->subresources[subresourceIndex].layer = layerIndex; + d3d11Texture->subresources[subresourceIndex].level = levelIndex; + d3d11Texture->subresources[subresourceIndex].depth = depth; + d3d11Texture->subresources[subresourceIndex].index = subresourceIndex; + + d3d11Texture->subresources[subresourceIndex].colorTargetViews = NULL; + d3d11Texture->subresources[subresourceIndex].uav = NULL; + d3d11Texture->subresources[subresourceIndex].depthStencilTargetView = NULL; + + if (isDepthStencil) { + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format]; + dsvDesc.Flags = 0; + + if (isMultisample) { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } else { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateDepthStencilView( + renderer->device, + d3d11Texture->handle, + &dsvDesc, + &d3d11Texture->subresources[subresourceIndex].depthStencilTargetView); + CHECK_D3D11_ERROR_AND_RETURN("Could not create DSV!", NULL); + + } else if (isColorTarget) { + + d3d11Texture->subresources[subresourceIndex].colorTargetViews = SDL_calloc(depth, sizeof(ID3D11RenderTargetView *)); + + for (Uint32 depthIndex = 0; depthIndex < depth; depthIndex += 1) { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = SDLToD3D11_TextureFormat[createInfo->format]; + + if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = levelIndex; + rtvDesc.Texture2DArray.FirstArraySlice = layerIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = levelIndex; + rtvDesc.Texture3D.FirstWSlice = depthIndex; + rtvDesc.Texture3D.WSize = 1; + } else if (isMultisample) { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + } else { + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + d3d11Texture->handle, + &rtvDesc, + &d3d11Texture->subresources[subresourceIndex].colorTargetViews[depthIndex]); + CHECK_D3D11_ERROR_AND_RETURN("Could not create RTV!", NULL); + } + } + + if (needSubresourceUAV) { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = format; + + if (createInfo->type == SDL_GPU_TEXTURETYPE_2D_ARRAY || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE || createInfo->type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY) { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; + uavDesc.Texture2DArray.MipSlice = levelIndex; + uavDesc.Texture2DArray.FirstArraySlice = layerIndex; + uavDesc.Texture2DArray.ArraySize = 1; + } else if (createInfo->type == SDL_GPU_TEXTURETYPE_3D) { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; + uavDesc.Texture3D.MipSlice = levelIndex; + uavDesc.Texture3D.FirstWSlice = 0; + uavDesc.Texture3D.WSize = depth; + } else { + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.MipSlice = levelIndex; + } + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + d3d11Texture->handle, + &uavDesc, + &d3d11Texture->subresources[subresourceIndex].uav); + CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV!", NULL); + } + } + } + + return d3d11Texture; +} + +static bool D3D11_SupportsSampleCount( + SDL_GPURenderer *driverData, + SDL_GPUTextureFormat format, + SDL_GPUSampleCount sampleCount) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + Uint32 levels; + + HRESULT res = ID3D11Device_CheckMultisampleQualityLevels( + renderer->device, + SDLToD3D11_TextureFormat[format], + SDLToD3D11_SampleCount[sampleCount], + &levels); + + return SUCCEEDED(res) && levels > 0; +} + +static SDL_GPUTexture *D3D11_CreateTexture( + SDL_GPURenderer *driverData, + const SDL_GPUTextureCreateInfo *createinfo) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11TextureContainer *container; + D3D11Texture *texture; + + texture = D3D11_INTERNAL_CreateTexture( + renderer, + createinfo, + NULL); + + if (texture == NULL) { + return NULL; + } + + container = SDL_malloc(sizeof(D3D11TextureContainer)); + container->header.info = *createinfo; + container->canBeCycled = 1; + container->activeTexture = texture; + container->textureCapacity = 1; + container->textureCount = 1; + container->textures = SDL_malloc( + container->textureCapacity * sizeof(D3D11Texture *)); + container->textures[0] = texture; + container->debugName = NULL; + + texture->container = container; + texture->containerIndex = 0; + + return (SDL_GPUTexture *)container; +} + +static void D3D11_INTERNAL_CycleActiveTexture( + D3D11Renderer *renderer, + D3D11TextureContainer *container) +{ + for (Uint32 i = 0; i < container->textureCount; i += 1) { + if (SDL_GetAtomicInt(&container->textures[i]->referenceCount) == 0) { + container->activeTexture = container->textures[i]; + return; + } + } + + D3D11Texture *texture = D3D11_INTERNAL_CreateTexture( + renderer, + &container->header.info, + NULL); + if (texture == NULL) { + return; + } + + // No texture is available, generate a new one. + + EXPAND_ARRAY_IF_NEEDED( + container->textures, + D3D11Texture *, + container->textureCount + 1, + container->textureCapacity, + container->textureCapacity + 1); + + container->textures[container->textureCount] = texture; + texture->container = container; + texture->containerIndex = container->textureCount; + container->textureCount += 1; + + container->activeTexture = container->textures[container->textureCount - 1]; + + if (renderer->debugMode && container->debugName != NULL) { + D3D11_INTERNAL_SetTextureName( + renderer, + container->activeTexture, + container->debugName); + } +} + +static D3D11TextureSubresource *D3D11_INTERNAL_FetchTextureSubresource( + D3D11TextureContainer *container, + Uint32 layer, + Uint32 level) +{ + Uint32 index = D3D11_INTERNAL_CalcSubresource( + level, + layer, + container->header.info.num_levels); + return &container->activeTexture->subresources[index]; +} + +static D3D11TextureSubresource *D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + D3D11Renderer *renderer, + D3D11TextureContainer *container, + Uint32 layer, + Uint32 level, + bool cycle) +{ + D3D11TextureSubresource *subresource = D3D11_INTERNAL_FetchTextureSubresource( + container, + layer, + level); + + if ( + container->canBeCycled && + cycle && + SDL_GetAtomicInt(&subresource->parent->referenceCount) > 0) { + D3D11_INTERNAL_CycleActiveTexture( + renderer, + container); + + subresource = D3D11_INTERNAL_FetchTextureSubresource( + container, + layer, + level); + } + + return subresource; +} + +static D3D11Buffer *D3D11_INTERNAL_CreateBuffer( + D3D11Renderer *renderer, + D3D11_BUFFER_DESC *bufferDesc, + Uint32 size) +{ + ID3D11Buffer *bufferHandle; + ID3D11UnorderedAccessView *uav = NULL; + ID3D11ShaderResourceView *srv = NULL; + D3D11Buffer *d3d11Buffer; + HRESULT res; + + // Storage buffers have to be 4-aligned, so might as well align them all + size = D3D11_INTERNAL_NextHighestAlignment(size, 4); + + res = ID3D11Device_CreateBuffer( + renderer->device, + bufferDesc, + NULL, + &bufferHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create buffer", NULL); + + // Storage buffer + if (bufferDesc->MiscFlags & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) { + // Create a UAV for the buffer + + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uavDesc.Format = DXGI_FORMAT_R32_TYPELESS; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + uavDesc.Buffer.FirstElement = 0; + uavDesc.Buffer.NumElements = size / sizeof(Uint32); + uavDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; + + res = ID3D11Device_CreateUnorderedAccessView( + renderer->device, + (ID3D11Resource *)bufferHandle, + &uavDesc, + &uav); + if (FAILED(res)) { + ID3D11Buffer_Release(bufferHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create UAV for buffer!", NULL); + } + + // Create a SRV for the buffer + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = DXGI_FORMAT_R32_TYPELESS; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; + srvDesc.BufferEx.FirstElement = 0; + srvDesc.BufferEx.NumElements = size / sizeof(Uint32); + srvDesc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; + + res = ID3D11Device_CreateShaderResourceView( + renderer->device, + (ID3D11Resource *)bufferHandle, + &srvDesc, + &srv); + if (FAILED(res)) { + ID3D11Buffer_Release(bufferHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create SRV for buffer!", NULL); + } + } + + d3d11Buffer = SDL_malloc(sizeof(D3D11Buffer)); + d3d11Buffer->handle = bufferHandle; + d3d11Buffer->size = size; + d3d11Buffer->uav = uav; + d3d11Buffer->srv = srv; + SDL_SetAtomicInt(&d3d11Buffer->referenceCount, 0); + + return d3d11Buffer; +} + +static SDL_GPUBuffer *D3D11_CreateBuffer( + SDL_GPURenderer *driverData, + SDL_GPUBufferUsageFlags usageFlags, + Uint32 size) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11BufferContainer *container; + D3D11Buffer *buffer; + D3D11_BUFFER_DESC bufferDesc; + + bufferDesc.BindFlags = 0; + if (usageFlags & SDL_GPU_BUFFERUSAGE_VERTEX) { + bufferDesc.BindFlags |= D3D11_BIND_VERTEX_BUFFER; + } + if (usageFlags & SDL_GPU_BUFFERUSAGE_INDEX) { + bufferDesc.BindFlags |= D3D11_BIND_INDEX_BUFFER; + } + if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) { + bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS; + } + + if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ | + SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ | + SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) { + bufferDesc.BindFlags |= D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE; + } + + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.MiscFlags = 0; + + if (usageFlags & SDL_GPU_BUFFERUSAGE_INDIRECT) { + bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + } + if (usageFlags & (SDL_GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ | + SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ | + SDL_GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE)) { + bufferDesc.MiscFlags |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + } + + buffer = D3D11_INTERNAL_CreateBuffer( + renderer, + &bufferDesc, + size); + + if (buffer == NULL) { + return NULL; + } + + container = SDL_malloc(sizeof(D3D11BufferContainer)); + container->activeBuffer = buffer; + container->bufferCapacity = 1; + container->bufferCount = 1; + container->buffers = SDL_malloc( + container->bufferCapacity * sizeof(D3D11Buffer *)); + container->buffers[0] = container->activeBuffer; + container->bufferDesc = bufferDesc; + container->debugName = NULL; + + return (SDL_GPUBuffer *)container; +} + +static D3D11UniformBuffer *D3D11_INTERNAL_CreateUniformBuffer( + D3D11Renderer *renderer, + Uint32 size) +{ + D3D11UniformBuffer *uniformBuffer; + ID3D11Buffer *buffer; + D3D11_BUFFER_DESC bufferDesc; + HRESULT res; + + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.ByteWidth = size; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &bufferDesc, + NULL, + &buffer); + CHECK_D3D11_ERROR_AND_RETURN("Could not create uniform buffer", NULL) + + uniformBuffer = SDL_malloc(sizeof(D3D11UniformBuffer)); + uniformBuffer->buffer = buffer; + uniformBuffer->writeOffset = 0; + uniformBuffer->drawOffset = 0; + uniformBuffer->currentBlockSize = 0; + + return uniformBuffer; +} + +static void D3D11_INTERNAL_CycleActiveBuffer( + D3D11Renderer *renderer, + D3D11BufferContainer *container) +{ + Uint32 size = container->activeBuffer->size; + + for (Uint32 i = 0; i < container->bufferCount; i += 1) { + if (SDL_GetAtomicInt(&container->buffers[i]->referenceCount) == 0) { + container->activeBuffer = container->buffers[i]; + return; + } + } + + EXPAND_ARRAY_IF_NEEDED( + container->buffers, + D3D11Buffer *, + container->bufferCount + 1, + container->bufferCapacity, + container->bufferCapacity + 1); + + container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateBuffer( + renderer, + &container->bufferDesc, + size); + container->bufferCount += 1; + + container->activeBuffer = container->buffers[container->bufferCount - 1]; + + if (renderer->debugMode && container->debugName != NULL) { + D3D11_INTERNAL_SetBufferName( + renderer, + container->activeBuffer, + container->debugName); + } +} + +static D3D11Buffer *D3D11_INTERNAL_PrepareBufferForWrite( + D3D11Renderer *renderer, + D3D11BufferContainer *container, + bool cycle) +{ + if ( + cycle && + SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) { + D3D11_INTERNAL_CycleActiveBuffer( + renderer, + container); + } + + return container->activeBuffer; +} + +static D3D11TransferBuffer *D3D11_INTERNAL_CreateTransferBuffer( + D3D11Renderer *renderer, + Uint32 size) +{ + D3D11TransferBuffer *transferBuffer = SDL_malloc(sizeof(D3D11TransferBuffer)); + + transferBuffer->data = (Uint8 *)SDL_malloc(size); + transferBuffer->size = size; + SDL_SetAtomicInt(&transferBuffer->referenceCount, 0); + + transferBuffer->bufferDownloads = NULL; + transferBuffer->bufferDownloadCount = 0; + transferBuffer->bufferDownloadCapacity = 0; + + transferBuffer->textureDownloads = NULL; + transferBuffer->textureDownloadCount = 0; + transferBuffer->textureDownloadCapacity = 0; + + return transferBuffer; +} + +// This actually returns a container handle so we can rotate buffers on Cycle. +static SDL_GPUTransferBuffer *D3D11_CreateTransferBuffer( + SDL_GPURenderer *driverData, + SDL_GPUTransferBufferUsage usage, // ignored on D3D11 + Uint32 size) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)SDL_malloc(sizeof(D3D11TransferBufferContainer)); + + container->bufferCapacity = 1; + container->bufferCount = 1; + container->buffers = SDL_malloc( + container->bufferCapacity * sizeof(D3D11TransferBuffer *)); + + container->buffers[0] = D3D11_INTERNAL_CreateTransferBuffer( + renderer, + size); + + container->activeBuffer = container->buffers[0]; + + return (SDL_GPUTransferBuffer *)container; +} + +// TransferBuffer Data + +static void D3D11_INTERNAL_CycleActiveTransferBuffer( + D3D11Renderer *renderer, + D3D11TransferBufferContainer *container) +{ + Uint32 size = container->activeBuffer->size; + + for (Uint32 i = 0; i < container->bufferCount; i += 1) { + if (SDL_GetAtomicInt(&container->buffers[i]->referenceCount) == 0) { + container->activeBuffer = container->buffers[i]; + return; + } + } + + EXPAND_ARRAY_IF_NEEDED( + container->buffers, + D3D11TransferBuffer *, + container->bufferCount + 1, + container->bufferCapacity, + container->bufferCapacity + 1); + + container->buffers[container->bufferCount] = D3D11_INTERNAL_CreateTransferBuffer( + renderer, + size); + container->bufferCount += 1; + + container->activeBuffer = container->buffers[container->bufferCount - 1]; +} + +static void *D3D11_MapTransferBuffer( + SDL_GPURenderer *driverData, + SDL_GPUTransferBuffer *transferBuffer, + bool cycle) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11TransferBufferContainer *container = (D3D11TransferBufferContainer *)transferBuffer; + D3D11TransferBuffer *buffer = container->activeBuffer; + + // Rotate the transfer buffer if necessary + if ( + cycle && + SDL_GetAtomicInt(&container->activeBuffer->referenceCount) > 0) { + D3D11_INTERNAL_CycleActiveTransferBuffer( + renderer, + container); + buffer = container->activeBuffer; + } + + return buffer->data; +} + +static void D3D11_UnmapTransferBuffer( + SDL_GPURenderer *driverData, + SDL_GPUTransferBuffer *transferBuffer) +{ + // no-op + (void)driverData; + (void)transferBuffer; +} + +// Copy Pass + +static void D3D11_BeginCopyPass( + SDL_GPUCommandBuffer *commandBuffer) +{ + // no-op +} + +static void D3D11_UploadToTexture( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureTransferInfo *source, + const SDL_GPUTextureRegion *destination, + bool cycle) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11TransferBufferContainer *srcTransferContainer = (D3D11TransferBufferContainer *)source->transfer_buffer; + D3D11TransferBuffer *srcTransferBuffer = srcTransferContainer->activeBuffer; + D3D11TextureContainer *dstTextureContainer = (D3D11TextureContainer *)destination->texture; + SDL_GPUTextureFormat dstFormat = dstTextureContainer->header.info.format; + Uint32 bufferStride = source->pixels_per_row; + Uint32 bufferImageHeight = source->rows_per_layer; + Sint32 w = destination->w; + Sint32 h = destination->h; + D3D11Texture *stagingTexture; + SDL_GPUTextureCreateInfo stagingTextureCreateInfo; + D3D11_SUBRESOURCE_DATA initialData; + + D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + renderer, + dstTextureContainer, + destination->layer, + destination->mip_level, + cycle); + + Sint32 blockSize = Texture_GetBlockSize(dstFormat); + if (blockSize > 1) { + w = (w + blockSize - 1) & ~(blockSize - 1); + h = (h + blockSize - 1) & ~(blockSize - 1); + } + + if (bufferStride == 0) { + bufferStride = w; + } + + if (bufferImageHeight == 0) { + bufferImageHeight = h; + } + + Uint32 bytesPerRow = BytesPerRow(bufferStride, dstFormat); + Uint32 bytesPerDepthSlice = bytesPerRow * bufferImageHeight; + + /* UpdateSubresource1 is completely busted on AMD, it truncates after X bytes. + * So we get to do this Fun (Tm) workaround where we create a staging texture + * with initial data before issuing a copy command. + */ + + stagingTextureCreateInfo.width = w; + stagingTextureCreateInfo.height = h; + stagingTextureCreateInfo.layer_count_or_depth = 1; + stagingTextureCreateInfo.num_levels = 1; + stagingTextureCreateInfo.type = SDL_GPU_TEXTURETYPE_2D; + stagingTextureCreateInfo.usage = 0; + stagingTextureCreateInfo.sample_count = SDL_GPU_SAMPLECOUNT_1; + stagingTextureCreateInfo.format = dstFormat; + + initialData.pSysMem = srcTransferBuffer->data + source->offset; + initialData.SysMemPitch = bytesPerRow; + initialData.SysMemSlicePitch = bytesPerDepthSlice; + + stagingTexture = D3D11_INTERNAL_CreateTexture( + renderer, + &stagingTextureCreateInfo, + &initialData); + + if (stagingTexture == NULL) { + return; + } + + ID3D11DeviceContext_CopySubresourceRegion( + d3d11CommandBuffer->context, + textureSubresource->parent->handle, + textureSubresource->index, + destination->x, + destination->y, + destination->z, + stagingTexture->handle, + 0, + NULL); + + // Clean up the staging texture + D3D11_INTERNAL_DestroyTexture(stagingTexture); + + D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent); + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, srcTransferBuffer); +} + +static void D3D11_UploadToBuffer( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTransferBufferLocation *source, + const SDL_GPUBufferRegion *destination, + bool cycle) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11TransferBufferContainer *transferContainer = (D3D11TransferBufferContainer *)source->transfer_buffer; + D3D11TransferBuffer *d3d11TransferBuffer = transferContainer->activeBuffer; + D3D11BufferContainer *bufferContainer = (D3D11BufferContainer *)destination->buffer; + D3D11Buffer *d3d11Buffer = D3D11_INTERNAL_PrepareBufferForWrite( + renderer, + bufferContainer, + cycle); + ID3D11Buffer *stagingBuffer; + D3D11_BUFFER_DESC stagingBufferDesc; + D3D11_SUBRESOURCE_DATA stagingBufferData; + HRESULT res; + + // Upload to staging buffer immediately + stagingBufferDesc.ByteWidth = destination->size; + stagingBufferDesc.Usage = D3D11_USAGE_STAGING; + stagingBufferDesc.BindFlags = 0; + stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + stagingBufferDesc.MiscFlags = 0; + stagingBufferDesc.StructureByteStride = 0; + + stagingBufferData.pSysMem = d3d11TransferBuffer->data + source->offset; + stagingBufferData.SysMemPitch = 0; + stagingBufferData.SysMemSlicePitch = 0; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &stagingBufferDesc, + &stagingBufferData, + &stagingBuffer); + CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", ) + + // Copy from staging buffer to buffer + ID3D11DeviceContext1_CopySubresourceRegion( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11Buffer->handle, + 0, + destination->offset, + 0, + 0, + (ID3D11Resource *)stagingBuffer, + 0, + NULL); + + ID3D11Buffer_Release(stagingBuffer); + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer); + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); +} + +static void D3D11_DownloadFromTexture( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureRegion *source, + const SDL_GPUTextureTransferInfo *destination) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = d3d11CommandBuffer->renderer; + D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transfer_buffer; + D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer; + D3D11TextureContainer *srcTextureContainer = (D3D11TextureContainer *)source->texture; + SDL_GPUTextureFormat srcFormat = srcTextureContainer->header.info.format; + D3D11_TEXTURE2D_DESC stagingDesc2D; + D3D11_TEXTURE3D_DESC stagingDesc3D; + D3D11TextureSubresource *textureSubresource = D3D11_INTERNAL_FetchTextureSubresource( + srcTextureContainer, + source->layer, + source->mip_level); + D3D11TextureDownload *textureDownload; + Uint32 bufferStride = destination->pixels_per_row; + Uint32 bufferImageHeight = destination->rows_per_layer; + Uint32 bytesPerRow, bytesPerDepthSlice; + D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + source->w, source->y + source->h, source->z + source->d }; + HRESULT res; + + if (d3d11TransferBuffer->textureDownloadCount >= d3d11TransferBuffer->textureDownloadCapacity) { + d3d11TransferBuffer->textureDownloadCapacity += 1; + d3d11TransferBuffer->textureDownloads = SDL_realloc( + d3d11TransferBuffer->textureDownloads, + d3d11TransferBuffer->textureDownloadCapacity * sizeof(D3D11TextureDownload)); + } + + textureDownload = &d3d11TransferBuffer->textureDownloads[d3d11TransferBuffer->textureDownloadCount]; + d3d11TransferBuffer->textureDownloadCount += 1; + + if (bufferStride == 0) { + bufferStride = source->w; + } + + if (bufferImageHeight == 0) { + bufferImageHeight = source->h; + } + + bytesPerRow = BytesPerRow(bufferStride, srcFormat); + bytesPerDepthSlice = bytesPerRow * bufferImageHeight; + + if (source->d == 1) { + stagingDesc2D.Width = source->w; + stagingDesc2D.Height = source->h; + stagingDesc2D.MipLevels = 1; + stagingDesc2D.ArraySize = 1; + stagingDesc2D.Format = SDLToD3D11_TextureFormat[srcFormat]; + stagingDesc2D.SampleDesc.Count = 1; + stagingDesc2D.SampleDesc.Quality = 0; + stagingDesc2D.Usage = D3D11_USAGE_STAGING; + stagingDesc2D.BindFlags = 0; + stagingDesc2D.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc2D.MiscFlags = 0; + + res = ID3D11Device_CreateTexture2D( + renderer->device, + &stagingDesc2D, + NULL, + (ID3D11Texture2D **)&textureDownload->stagingTexture); + CHECK_D3D11_ERROR_AND_RETURN("Staging texture creation failed", ) + } else { + stagingDesc3D.Width = source->w; + stagingDesc3D.Height = source->h; + stagingDesc3D.Depth = source->d; + stagingDesc3D.MipLevels = 1; + stagingDesc3D.Format = SDLToD3D11_TextureFormat[srcFormat]; + stagingDesc3D.Usage = D3D11_USAGE_STAGING; + stagingDesc3D.BindFlags = 0; + stagingDesc3D.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc3D.MiscFlags = 0; + + res = ID3D11Device_CreateTexture3D( + renderer->device, + &stagingDesc3D, + NULL, + (ID3D11Texture3D **)&textureDownload->stagingTexture); + } + + textureDownload->width = source->w; + textureDownload->height = source->h; + textureDownload->depth = source->d; + textureDownload->bufferOffset = destination->offset; + textureDownload->bytesPerRow = bytesPerRow; + textureDownload->bytesPerDepthSlice = bytesPerDepthSlice; + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + textureDownload->stagingTexture, + 0, + 0, + 0, + 0, + textureSubresource->parent->handle, + textureSubresource->index, + &srcBox, + D3D11_COPY_NO_OVERWRITE); + + D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, textureSubresource->parent); + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); +} + +static void D3D11_DownloadFromBuffer( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferRegion *source, + const SDL_GPUTransferBufferLocation *destination) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = d3d11CommandBuffer->renderer; + D3D11TransferBufferContainer *dstTransferContainer = (D3D11TransferBufferContainer *)destination->transfer_buffer; + D3D11TransferBuffer *d3d11TransferBuffer = dstTransferContainer->activeBuffer; + D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer; + D3D11BufferDownload *bufferDownload; + D3D11_BOX srcBox = { source->offset, 0, 0, source->size, 1, 1 }; + D3D11_BUFFER_DESC stagingBufferDesc; + HRESULT res; + + if (d3d11TransferBuffer->bufferDownloadCount >= d3d11TransferBuffer->bufferDownloadCapacity) { + d3d11TransferBuffer->bufferDownloadCapacity += 1; + d3d11TransferBuffer->bufferDownloads = SDL_realloc( + d3d11TransferBuffer->bufferDownloads, + d3d11TransferBuffer->bufferDownloadCapacity * sizeof(D3D11BufferDownload)); + } + + bufferDownload = &d3d11TransferBuffer->bufferDownloads[d3d11TransferBuffer->bufferDownloadCount]; + d3d11TransferBuffer->bufferDownloadCount += 1; + + stagingBufferDesc.ByteWidth = source->size; + stagingBufferDesc.Usage = D3D11_USAGE_STAGING; + stagingBufferDesc.BindFlags = 0; + stagingBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingBufferDesc.MiscFlags = 0; + stagingBufferDesc.StructureByteStride = 0; + + res = ID3D11Device_CreateBuffer( + renderer->device, + &stagingBufferDesc, + NULL, + &bufferDownload->stagingBuffer); + CHECK_D3D11_ERROR_AND_RETURN("Could not create staging buffer", ) + + ID3D11DeviceContext1_CopySubresourceRegion1( + d3d11CommandBuffer->context, + (ID3D11Resource *)bufferDownload->stagingBuffer, + 0, + 0, + 0, + 0, + (ID3D11Resource *)srcBufferContainer->activeBuffer->handle, + 0, + &srcBox, + D3D11_COPY_NO_OVERWRITE); + + bufferDownload->dstOffset = destination->offset; + bufferDownload->size = source->size; + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBufferContainer->activeBuffer); + D3D11_INTERNAL_TrackTransferBuffer(d3d11CommandBuffer, d3d11TransferBuffer); +} + +static void D3D11_CopyTextureToTexture( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUTextureLocation *source, + const SDL_GPUTextureLocation *destination, + Uint32 w, + Uint32 h, + Uint32 d, + bool cycle) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11TextureContainer *srcContainer = (D3D11TextureContainer *)source->texture; + D3D11TextureContainer *dstContainer = (D3D11TextureContainer *)destination->texture; + + D3D11_BOX srcBox = { source->x, source->y, source->z, source->x + w, source->y + h, source->z + d }; + + D3D11TextureSubresource *srcSubresource = D3D11_INTERNAL_FetchTextureSubresource( + srcContainer, + source->layer, + source->mip_level); + + D3D11TextureSubresource *dstSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + renderer, + dstContainer, + destination->layer, + destination->mip_level, + cycle); + + ID3D11DeviceContext1_CopySubresourceRegion( + d3d11CommandBuffer->context, + dstSubresource->parent->handle, + dstSubresource->index, + destination->x, + destination->y, + destination->z, + srcSubresource->parent->handle, + srcSubresource->index, + &srcBox); + + D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, srcSubresource->parent); + D3D11_INTERNAL_TrackTexture(d3d11CommandBuffer, dstSubresource->parent); +} + +static void D3D11_CopyBufferToBuffer( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferLocation *source, + const SDL_GPUBufferLocation *destination, + Uint32 size, + bool cycle) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11BufferContainer *srcBufferContainer = (D3D11BufferContainer *)source->buffer; + D3D11BufferContainer *dstBufferContainer = (D3D11BufferContainer *)destination->buffer; + D3D11_BOX srcBox = { source->offset, 0, 0, source->offset + size, 1, 1 }; + + D3D11Buffer *srcBuffer = srcBufferContainer->activeBuffer; + D3D11Buffer *dstBuffer = D3D11_INTERNAL_PrepareBufferForWrite( + renderer, + dstBufferContainer, + cycle); + + ID3D11DeviceContext1_CopySubresourceRegion( + d3d11CommandBuffer->context, + (ID3D11Resource *)dstBuffer->handle, + 0, + destination->offset, + 0, + 0, + (ID3D11Resource *)srcBuffer->handle, + 0, + &srcBox); + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, srcBuffer); + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, dstBuffer); +} + +static void D3D11_GenerateMipmaps( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUTexture *texture) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11TextureContainer *d3d11TextureContainer = (D3D11TextureContainer *)texture; + + ID3D11DeviceContext1_GenerateMips( + d3d11CommandBuffer->context, + d3d11TextureContainer->activeTexture->shaderView); + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + d3d11TextureContainer->activeTexture); +} + +static void D3D11_EndCopyPass( + SDL_GPUCommandBuffer *commandBuffer) +{ + // no-op +} + +// Graphics State + +static void D3D11_INTERNAL_AllocateCommandBuffers( + D3D11Renderer *renderer, + Uint32 allocateCount) +{ + D3D11CommandBuffer *commandBuffer; + HRESULT res; + + renderer->availableCommandBufferCapacity += allocateCount; + + renderer->availableCommandBuffers = SDL_realloc( + renderer->availableCommandBuffers, + sizeof(D3D11CommandBuffer *) * renderer->availableCommandBufferCapacity); + + for (Uint32 i = 0; i < allocateCount; i += 1) { + commandBuffer = SDL_calloc(1, sizeof(D3D11CommandBuffer)); + commandBuffer->renderer = renderer; + + // Deferred Device Context + res = ID3D11Device1_CreateDeferredContext1( + renderer->device, + 0, + &commandBuffer->context); + CHECK_D3D11_ERROR_AND_RETURN("Could not create deferred context", ); + + // Initialize debug annotation support, if available + ID3D11DeviceContext_QueryInterface( + commandBuffer->context, + &D3D_IID_ID3DUserDefinedAnnotation, + (void **)&commandBuffer->annotation); + + // Window handling + commandBuffer->windowDataCapacity = 1; + commandBuffer->windowDataCount = 0; + commandBuffer->windowDatas = SDL_malloc( + commandBuffer->windowDataCapacity * sizeof(D3D11WindowData *)); + + // Reference Counting + commandBuffer->usedBufferCapacity = 4; + commandBuffer->usedBufferCount = 0; + commandBuffer->usedBuffers = SDL_malloc( + commandBuffer->usedBufferCapacity * sizeof(D3D11Buffer *)); + + commandBuffer->usedTransferBufferCapacity = 4; + commandBuffer->usedTransferBufferCount = 0; + commandBuffer->usedTransferBuffers = SDL_malloc( + commandBuffer->usedTransferBufferCapacity * sizeof(D3D11TransferBuffer *)); + + commandBuffer->usedTextureCapacity = 4; + commandBuffer->usedTextureCount = 0; + commandBuffer->usedTextures = SDL_malloc( + commandBuffer->usedTextureCapacity * sizeof(D3D11Texture *)); + + commandBuffer->usedUniformBufferCapacity = 4; + commandBuffer->usedUniformBufferCount = 0; + commandBuffer->usedUniformBuffers = SDL_malloc( + commandBuffer->usedUniformBufferCapacity * sizeof(D3D11UniformBuffer *)); + + renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; + renderer->availableCommandBufferCount += 1; + } +} + +static D3D11CommandBuffer *D3D11_INTERNAL_GetInactiveCommandBufferFromPool( + D3D11Renderer *renderer) +{ + D3D11CommandBuffer *commandBuffer; + + if (renderer->availableCommandBufferCount == 0) { + D3D11_INTERNAL_AllocateCommandBuffers( + renderer, + renderer->availableCommandBufferCapacity); + } + + commandBuffer = renderer->availableCommandBuffers[renderer->availableCommandBufferCount - 1]; + renderer->availableCommandBufferCount -= 1; + + return commandBuffer; +} + +static bool D3D11_INTERNAL_CreateFence( + D3D11Renderer *renderer) +{ + D3D11_QUERY_DESC queryDesc; + ID3D11Query *queryHandle; + D3D11Fence *fence; + HRESULT res; + + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + res = ID3D11Device_CreateQuery( + renderer->device, + &queryDesc, + &queryHandle); + CHECK_D3D11_ERROR_AND_RETURN("Could not create query", false); + + fence = SDL_malloc(sizeof(D3D11Fence)); + fence->handle = queryHandle; + SDL_SetAtomicInt(&fence->referenceCount, 0); + + // Add it to the available pool + if (renderer->availableFenceCount >= renderer->availableFenceCapacity) { + renderer->availableFenceCapacity *= 2; + renderer->availableFences = SDL_realloc( + renderer->availableFences, + sizeof(D3D11Fence *) * renderer->availableFenceCapacity); + } + + renderer->availableFences[renderer->availableFenceCount] = fence; + renderer->availableFenceCount += 1; + + return true; +} + +static bool D3D11_INTERNAL_AcquireFence( + D3D11CommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11Fence *fence; + + // Acquire a fence from the pool + SDL_LockMutex(renderer->fenceLock); + + if (renderer->availableFenceCount == 0) { + if (!D3D11_INTERNAL_CreateFence(renderer)) { + SDL_UnlockMutex(renderer->fenceLock); + return false; + } + } + + fence = renderer->availableFences[renderer->availableFenceCount - 1]; + renderer->availableFenceCount -= 1; + + SDL_UnlockMutex(renderer->fenceLock); + + // Associate the fence with the command buffer + commandBuffer->fence = fence; + (void)SDL_AtomicIncRef(&commandBuffer->fence->referenceCount); + + return true; +} + +static SDL_GPUCommandBuffer *D3D11_AcquireCommandBuffer( + SDL_GPURenderer *driverData) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11CommandBuffer *commandBuffer; + Uint32 i; + + SDL_LockMutex(renderer->acquireCommandBufferLock); + + commandBuffer = D3D11_INTERNAL_GetInactiveCommandBufferFromPool(renderer); + commandBuffer->graphicsPipeline = NULL; + commandBuffer->stencilRef = 0; + commandBuffer->blendConstants.r = 1.0f; + commandBuffer->blendConstants.g = 1.0f; + commandBuffer->blendConstants.b = 1.0f; + commandBuffer->blendConstants.a = 1.0f; + commandBuffer->computePipeline = NULL; + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { + commandBuffer->colorTargetSubresources[i] = NULL; + commandBuffer->colorResolveSubresources[i] = NULL; + } + + for (i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) { + commandBuffer->vertexUniformBuffers[i] = NULL; + commandBuffer->fragmentUniformBuffers[i] = NULL; + commandBuffer->computeUniformBuffers[i] = NULL; + } + + commandBuffer->needVertexSamplerBind = true; + commandBuffer->needVertexStorageTextureBind = true; + commandBuffer->needVertexStorageBufferBind = true; + commandBuffer->needVertexUniformBufferBind = true; + commandBuffer->needFragmentSamplerBind = true; + commandBuffer->needFragmentStorageTextureBind = true; + commandBuffer->needFragmentStorageBufferBind = true; + commandBuffer->needFragmentUniformBufferBind = true; + commandBuffer->needComputeUniformBufferBind = true; + commandBuffer->needBlendStateSet = true; + + SDL_zeroa(commandBuffer->vertexSamplers); + SDL_zeroa(commandBuffer->vertexSamplerTextures); + SDL_zeroa(commandBuffer->vertexStorageTextures); + SDL_zeroa(commandBuffer->vertexStorageBuffers); + + SDL_zeroa(commandBuffer->fragmentSamplers); + SDL_zeroa(commandBuffer->fragmentSamplerTextures); + SDL_zeroa(commandBuffer->fragmentStorageTextures); + SDL_zeroa(commandBuffer->fragmentStorageBuffers); + + SDL_zeroa(commandBuffer->computeSamplers); + SDL_zeroa(commandBuffer->computeSamplerTextures); + SDL_zeroa(commandBuffer->computeReadOnlyStorageTextures); + SDL_zeroa(commandBuffer->computeReadOnlyStorageBuffers); + SDL_zeroa(commandBuffer->computeReadWriteStorageTextureSubresources); + SDL_zeroa(commandBuffer->computeReadWriteStorageBuffers); + + bool acquireFenceResult = D3D11_INTERNAL_AcquireFence(commandBuffer); + commandBuffer->autoReleaseFence = 1; + + SDL_UnlockMutex(renderer->acquireCommandBufferLock); + + if (!acquireFenceResult) { + return NULL; + } + + return (SDL_GPUCommandBuffer *)commandBuffer; +} + +static D3D11UniformBuffer *D3D11_INTERNAL_AcquireUniformBufferFromPool( + D3D11CommandBuffer *commandBuffer) +{ + D3D11Renderer *renderer = commandBuffer->renderer; + D3D11UniformBuffer *uniformBuffer; + + SDL_LockMutex(renderer->acquireUniformBufferLock); + + if (renderer->uniformBufferPoolCount > 0) { + uniformBuffer = renderer->uniformBufferPool[renderer->uniformBufferPoolCount - 1]; + renderer->uniformBufferPoolCount -= 1; + } else { + uniformBuffer = D3D11_INTERNAL_CreateUniformBuffer( + renderer, + UNIFORM_BUFFER_SIZE); + } + + SDL_UnlockMutex(renderer->acquireUniformBufferLock); + + D3D11_INTERNAL_TrackUniformBuffer(commandBuffer, uniformBuffer); + + return uniformBuffer; +} + +static void D3D11_INTERNAL_ReturnUniformBufferToPool( + D3D11Renderer *renderer, + D3D11UniformBuffer *uniformBuffer) +{ + if (renderer->uniformBufferPoolCount >= renderer->uniformBufferPoolCapacity) { + renderer->uniformBufferPoolCapacity *= 2; + renderer->uniformBufferPool = SDL_realloc( + renderer->uniformBufferPool, + renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *)); + } + + renderer->uniformBufferPool[renderer->uniformBufferPoolCount] = uniformBuffer; + renderer->uniformBufferPoolCount += 1; + + uniformBuffer->writeOffset = 0; + uniformBuffer->drawOffset = 0; + uniformBuffer->mappedData = NULL; +} + +static void D3D11_INTERNAL_PushUniformData( + D3D11CommandBuffer *d3d11CommandBuffer, + SDL_GPUShaderStage shaderStage, + Uint32 slotIndex, + const void *data, + Uint32 length) +{ + D3D11Renderer *renderer = d3d11CommandBuffer->renderer; + D3D11UniformBuffer *d3d11UniformBuffer; + D3D11_MAPPED_SUBRESOURCE subres; + HRESULT res; + + if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) { + if (d3d11CommandBuffer->vertexUniformBuffers[slotIndex] == NULL) { + d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + d3d11UniformBuffer = d3d11CommandBuffer->vertexUniformBuffers[slotIndex]; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) { + if (d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] == NULL) { + d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + d3d11UniformBuffer = d3d11CommandBuffer->fragmentUniformBuffers[slotIndex]; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) { + if (d3d11CommandBuffer->computeUniformBuffers[slotIndex] == NULL) { + d3d11CommandBuffer->computeUniformBuffers[slotIndex] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + d3d11UniformBuffer = d3d11CommandBuffer->computeUniformBuffers[slotIndex]; + } else { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!"); + return; + } + + d3d11UniformBuffer->currentBlockSize = + D3D11_INTERNAL_NextHighestAlignment( + length, + 256); + + // If there is no more room, acquire a new uniform buffer + if (d3d11UniformBuffer->writeOffset + d3d11UniformBuffer->currentBlockSize >= UNIFORM_BUFFER_SIZE) { + ID3D11DeviceContext_Unmap( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11UniformBuffer->buffer, + 0); + d3d11UniformBuffer->mappedData = NULL; + + d3d11UniformBuffer = D3D11_INTERNAL_AcquireUniformBufferFromPool(d3d11CommandBuffer); + + d3d11UniformBuffer->drawOffset = 0; + d3d11UniformBuffer->writeOffset = 0; + + if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) { + d3d11CommandBuffer->vertexUniformBuffers[slotIndex] = d3d11UniformBuffer; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) { + d3d11CommandBuffer->fragmentUniformBuffers[slotIndex] = d3d11UniformBuffer; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) { + d3d11CommandBuffer->computeUniformBuffers[slotIndex] = d3d11UniformBuffer; + } else { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!"); + } + } + + // Map the uniform data on first push + if (d3d11UniformBuffer->writeOffset == 0) { + res = ID3D11DeviceContext_Map( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11UniformBuffer->buffer, + 0, + D3D11_MAP_WRITE_DISCARD, + 0, + &subres); + CHECK_D3D11_ERROR_AND_RETURN("Failed to map uniform buffer", ) + + d3d11UniformBuffer->mappedData = subres.pData; + } + + d3d11UniformBuffer->drawOffset = d3d11UniformBuffer->writeOffset; + + SDL_memcpy( + (Uint8 *)d3d11UniformBuffer->mappedData + d3d11UniformBuffer->writeOffset, + data, + length); + + d3d11UniformBuffer->writeOffset += d3d11UniformBuffer->currentBlockSize; + + if (shaderStage == SDL_GPU_SHADERSTAGE_VERTEX) { + d3d11CommandBuffer->needVertexUniformBufferBind = true; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_FRAGMENT) { + d3d11CommandBuffer->needFragmentUniformBufferBind = true; + } else if (shaderStage == SDL_GPU_SHADERSTAGE_COMPUTE) { + d3d11CommandBuffer->needComputeUniformBufferBind = true; + } else { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Unrecognized shader stage!"); + } +} + +static void D3D11_SetViewport( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUViewport *viewport) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_VIEWPORT vp = { + viewport->x, + viewport->y, + viewport->w, + viewport->h, + viewport->min_depth, + viewport->max_depth + }; + + ID3D11DeviceContext_RSSetViewports( + d3d11CommandBuffer->context, + 1, + &vp); +} + +static void D3D11_SetScissor( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_Rect *scissor) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_RECT rect = { + scissor->x, + scissor->y, + scissor->x + scissor->w, + scissor->y + scissor->h + }; + + ID3D11DeviceContext_RSSetScissorRects( + d3d11CommandBuffer->context, + 1, + &rect); +} + +static void D3D11_SetBlendConstants( + SDL_GPUCommandBuffer *commandBuffer, + SDL_FColor blendConstants) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + d3d11CommandBuffer->blendConstants = blendConstants; + d3d11CommandBuffer->needBlendStateSet = true; +} + +static void D3D11_SetStencilReference( + SDL_GPUCommandBuffer *commandBuffer, + Uint8 reference) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + d3d11CommandBuffer->stencilRef = reference; + + if (d3d11CommandBuffer->graphicsPipeline != NULL) { + ID3D11DeviceContext_OMSetDepthStencilState( + d3d11CommandBuffer->context, + d3d11CommandBuffer->graphicsPipeline->depthStencilState, + reference); + } +} + +static void D3D11_BeginRenderPass( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUColorTargetInfo *colorTargetInfos, + Uint32 numColorTargets, + const SDL_GPUDepthStencilTargetInfo *depthStencilTargetInfo) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + ID3D11RenderTargetView *rtvs[MAX_COLOR_TARGET_BINDINGS]; + ID3D11DepthStencilView *dsv = NULL; + Uint32 vpWidth = SDL_MAX_UINT32; + Uint32 vpHeight = SDL_MAX_UINT32; + SDL_GPUViewport viewport; + SDL_Rect scissorRect; + + // Clear the bound targets for the current command buffer + for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { + d3d11CommandBuffer->colorTargetSubresources[i] = NULL; + d3d11CommandBuffer->colorResolveSubresources[i] = NULL; + } + + // Set up the new color target bindings + for (Uint32 i = 0; i < numColorTargets; i += 1) { + D3D11TextureContainer *container = (D3D11TextureContainer *)colorTargetInfos[i].texture; + D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + renderer, + container, + container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? 0 : colorTargetInfos[i].layer_or_depth_plane, + colorTargetInfos[i].mip_level, + colorTargetInfos[i].cycle); + + Uint32 rtvIndex = container->header.info.type == SDL_GPU_TEXTURETYPE_3D ? colorTargetInfos[i].layer_or_depth_plane : 0; + rtvs[i] = subresource->colorTargetViews[rtvIndex]; + d3d11CommandBuffer->colorTargetSubresources[i] = subresource; + + if (colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE || colorTargetInfos[i].store_op == SDL_GPU_STOREOP_RESOLVE_AND_STORE) { + D3D11TextureContainer *resolveContainer = (D3D11TextureContainer *)colorTargetInfos[i].resolve_texture; + D3D11TextureSubresource *resolveSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + renderer, + resolveContainer, + colorTargetInfos[i].resolve_layer, + colorTargetInfos[i].resolve_mip_level, + colorTargetInfos[i].cycle_resolve_texture); + + d3d11CommandBuffer->colorResolveSubresources[i] = resolveSubresource; + } + + if (colorTargetInfos[i].load_op == SDL_GPU_LOADOP_CLEAR) { + float clearColor[] = { + colorTargetInfos[i].clear_color.r, + colorTargetInfos[i].clear_color.g, + colorTargetInfos[i].clear_color.b, + colorTargetInfos[i].clear_color.a + }; + ID3D11DeviceContext_ClearRenderTargetView( + d3d11CommandBuffer->context, + rtvs[i], + clearColor); + } + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + subresource->parent); + } + + // Get the DSV for the depth stencil target, if applicable + if (depthStencilTargetInfo != NULL) { + D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilTargetInfo->texture; + D3D11TextureSubresource *subresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + renderer, + container, + 0, + 0, + depthStencilTargetInfo->cycle); + + dsv = subresource->depthStencilTargetView; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + subresource->parent); + } + + // Actually set the RTs + ID3D11DeviceContext_OMSetRenderTargets( + d3d11CommandBuffer->context, + numColorTargets, + numColorTargets > 0 ? rtvs : NULL, + dsv); + + if (depthStencilTargetInfo != NULL) { + D3D11_CLEAR_FLAG dsClearFlags = 0; + if (depthStencilTargetInfo->load_op == SDL_GPU_LOADOP_CLEAR) { + dsClearFlags |= D3D11_CLEAR_DEPTH; + } + if (depthStencilTargetInfo->stencil_load_op == SDL_GPU_LOADOP_CLEAR) { + dsClearFlags |= D3D11_CLEAR_STENCIL; + } + + if (dsClearFlags != 0) { + ID3D11DeviceContext_ClearDepthStencilView( + d3d11CommandBuffer->context, + dsv, + dsClearFlags, + depthStencilTargetInfo->clear_depth, + depthStencilTargetInfo->clear_stencil); + } + } + + // The viewport cannot be larger than the smallest target. + for (Uint32 i = 0; i < numColorTargets; i += 1) { + D3D11TextureContainer *container = (D3D11TextureContainer *)colorTargetInfos[i].texture; + Uint32 w = container->header.info.width >> colorTargetInfos[i].mip_level; + Uint32 h = container->header.info.height >> colorTargetInfos[i].mip_level; + + if (w < vpWidth) { + vpWidth = w; + } + + if (h < vpHeight) { + vpHeight = h; + } + } + + if (depthStencilTargetInfo != NULL) { + D3D11TextureContainer *container = (D3D11TextureContainer *)depthStencilTargetInfo->texture; + Uint32 w = container->header.info.width; + Uint32 h = container->header.info.height; + + if (w < vpWidth) { + vpWidth = w; + } + + if (h < vpHeight) { + vpHeight = h; + } + } + + // Set sensible default states + viewport.x = 0; + viewport.y = 0; + viewport.w = (float)vpWidth; + viewport.h = (float)vpHeight; + viewport.min_depth = 0; + viewport.max_depth = 1; + + D3D11_SetViewport( + commandBuffer, + &viewport); + + scissorRect.x = 0; + scissorRect.y = 0; + scissorRect.w = (int)vpWidth; + scissorRect.h = (int)vpHeight; + + D3D11_SetScissor( + commandBuffer, + &scissorRect); + + D3D11_SetStencilReference( + commandBuffer, + 0); + + SDL_FColor blendConstants; + blendConstants.r = 1.0f; + blendConstants.g = 1.0f; + blendConstants.b = 1.0f; + blendConstants.a = 1.0f; + + D3D11_SetBlendConstants( + commandBuffer, + blendConstants); +} + +static void D3D11_BindGraphicsPipeline( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUGraphicsPipeline *graphicsPipeline) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11GraphicsPipeline *pipeline = (D3D11GraphicsPipeline *)graphicsPipeline; + d3d11CommandBuffer->graphicsPipeline = pipeline; + + ID3D11DeviceContext_OMSetDepthStencilState( + d3d11CommandBuffer->context, + pipeline->depthStencilState, + d3d11CommandBuffer->stencilRef); + + ID3D11DeviceContext_IASetPrimitiveTopology( + d3d11CommandBuffer->context, + SDLToD3D11_PrimitiveType[pipeline->primitiveType]); + + ID3D11DeviceContext_IASetInputLayout( + d3d11CommandBuffer->context, + pipeline->inputLayout); + + ID3D11DeviceContext_RSSetState( + d3d11CommandBuffer->context, + pipeline->rasterizerState); + + ID3D11DeviceContext_VSSetShader( + d3d11CommandBuffer->context, + pipeline->vertexShader, + NULL, + 0); + + ID3D11DeviceContext_PSSetShader( + d3d11CommandBuffer->context, + pipeline->fragmentShader, + NULL, + 0); + + // Acquire uniform buffers if necessary + for (Uint32 i = 0; i < pipeline->vertexUniformBufferCount; i += 1) { + if (d3d11CommandBuffer->vertexUniformBuffers[i] == NULL) { + d3d11CommandBuffer->vertexUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + } + + for (Uint32 i = 0; i < pipeline->fragmentUniformBufferCount; i += 1) { + if (d3d11CommandBuffer->fragmentUniformBuffers[i] == NULL) { + d3d11CommandBuffer->fragmentUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + } + + // Mark that bindings are needed + d3d11CommandBuffer->needVertexSamplerBind = true; + d3d11CommandBuffer->needVertexStorageTextureBind = true; + d3d11CommandBuffer->needVertexStorageBufferBind = true; + d3d11CommandBuffer->needVertexUniformBufferBind = true; + d3d11CommandBuffer->needFragmentSamplerBind = true; + d3d11CommandBuffer->needFragmentStorageTextureBind = true; + d3d11CommandBuffer->needFragmentStorageBufferBind = true; + d3d11CommandBuffer->needFragmentUniformBufferBind = true; + d3d11CommandBuffer->needBlendStateSet = true; +} + +static void D3D11_BindVertexBuffers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUBufferBinding *bindings, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11Buffer *currentBuffer = ((D3D11BufferContainer *)bindings[i].buffer)->activeBuffer; + d3d11CommandBuffer->vertexBuffers[firstSlot + i] = currentBuffer->handle; + d3d11CommandBuffer->vertexBufferOffsets[firstSlot + i] = bindings[i].offset; + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, currentBuffer); + } + + d3d11CommandBuffer->vertexBufferCount = + SDL_max(d3d11CommandBuffer->vertexBufferCount, firstSlot + numBindings); + + d3d11CommandBuffer->needVertexBufferBind = true; +} + +static void D3D11_BindIndexBuffer( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBufferBinding *binding, + SDL_GPUIndexElementSize indexElementSize) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)binding->buffer)->activeBuffer; + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer); + + ID3D11DeviceContext_IASetIndexBuffer( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + SDLToD3D11_IndexType[indexElementSize], + (UINT)binding->offset); +} + +static void D3D11_BindVertexSamplers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->vertexSamplers[firstSlot + i] = + (D3D11Sampler *)textureSamplerBindings[i].sampler; + + d3d11CommandBuffer->vertexSamplerTextures[firstSlot + i] = + textureContainer->activeTexture; + } + + d3d11CommandBuffer->needVertexSamplerBind = true; +} + +static void D3D11_BindVertexStorageTextures( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i]; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->vertexStorageTextures[firstSlot + i] = + textureContainer->activeTexture; + } + + d3d11CommandBuffer->needVertexStorageTextureBind = true; +} + +static void D3D11_BindVertexStorageBuffers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11BufferContainer *bufferContainer; + Uint32 i; + + for (i = 0; i < numBindings; i += 1) { + bufferContainer = (D3D11BufferContainer *)storageBuffers[i]; + + D3D11_INTERNAL_TrackBuffer( + d3d11CommandBuffer, + bufferContainer->activeBuffer); + + d3d11CommandBuffer->vertexStorageBuffers[firstSlot + i] = + bufferContainer->activeBuffer; + } + + d3d11CommandBuffer->needVertexStorageBufferBind = true; +} + +static void D3D11_BindFragmentSamplers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->fragmentSamplers[firstSlot + i] = + (D3D11Sampler *)textureSamplerBindings[i].sampler; + + d3d11CommandBuffer->fragmentSamplerTextures[firstSlot + i] = + (D3D11Texture *)textureContainer->activeTexture; + } + + d3d11CommandBuffer->needFragmentSamplerBind = true; +} + +static void D3D11_BindFragmentStorageTextures( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i]; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->fragmentStorageTextures[firstSlot + i] = + textureContainer->activeTexture; + } + + d3d11CommandBuffer->needFragmentStorageTextureBind = true; +} + +static void D3D11_BindFragmentStorageBuffers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11BufferContainer *bufferContainer; + Uint32 i; + + for (i = 0; i < numBindings; i += 1) { + bufferContainer = (D3D11BufferContainer *)storageBuffers[i]; + + D3D11_INTERNAL_TrackBuffer( + d3d11CommandBuffer, + bufferContainer->activeBuffer); + + d3d11CommandBuffer->fragmentStorageBuffers[firstSlot + i] = + bufferContainer->activeBuffer; + } + + d3d11CommandBuffer->needFragmentStorageBufferBind = true; +} + +static void D3D11_INTERNAL_BindGraphicsResources( + D3D11CommandBuffer *commandBuffer) +{ + D3D11GraphicsPipeline *graphicsPipeline = commandBuffer->graphicsPipeline; + + ID3D11Buffer *nullBuf = NULL; + Uint32 offsetInConstants, blockSizeInConstants; + + if (commandBuffer->needVertexBufferBind) { + ID3D11DeviceContext_IASetVertexBuffers( + commandBuffer->context, + 0, + commandBuffer->vertexBufferCount, + commandBuffer->vertexBuffers, + graphicsPipeline->vertexStrides, + commandBuffer->vertexBufferOffsets); + } + + if (commandBuffer->needVertexSamplerBind) { + if (graphicsPipeline->vertexSamplerCount > 0) { + ID3D11SamplerState *samplerStates[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->vertexSamplerCount; i += 1) { + samplerStates[i] = commandBuffer->vertexSamplers[i]->handle; + srvs[i] = commandBuffer->vertexSamplerTextures[i]->shaderView; + } + + ID3D11DeviceContext_VSSetSamplers( + commandBuffer->context, + 0, + graphicsPipeline->vertexSamplerCount, + samplerStates); + + ID3D11DeviceContext_VSSetShaderResources( + commandBuffer->context, + 0, + graphicsPipeline->vertexSamplerCount, + srvs); + } + + commandBuffer->needVertexSamplerBind = false; + } + + if (commandBuffer->needVertexStorageTextureBind) { + if (graphicsPipeline->vertexStorageTextureCount > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->vertexStorageTextureCount; i += 1) { + srvs[i] = commandBuffer->vertexStorageTextures[i]->shaderView; + } + + ID3D11DeviceContext_VSSetShaderResources( + commandBuffer->context, + graphicsPipeline->vertexSamplerCount, + graphicsPipeline->vertexStorageTextureCount, + srvs); + } + + commandBuffer->needVertexStorageTextureBind = false; + } + + if (commandBuffer->needVertexStorageBufferBind) { + if (graphicsPipeline->vertexStorageBufferCount > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_BUFFERS_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->vertexStorageBufferCount; i += 1) { + srvs[i] = commandBuffer->vertexStorageBuffers[i]->srv; + } + + ID3D11DeviceContext_VSSetShaderResources( + commandBuffer->context, + graphicsPipeline->vertexSamplerCount + graphicsPipeline->vertexStorageTextureCount, + graphicsPipeline->vertexStorageBufferCount, + srvs); + } + + commandBuffer->needVertexStorageBufferBind = false; + } + + if (commandBuffer->needVertexUniformBufferBind) { + for (Uint32 i = 0; i < graphicsPipeline->vertexUniformBufferCount; i += 1) { + /* stupid workaround for god awful D3D11 drivers + * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation + */ + ID3D11DeviceContext1_VSSetConstantBuffers( + commandBuffer->context, + i, + 1, + &nullBuf); + + offsetInConstants = commandBuffer->vertexUniformBuffers[i]->drawOffset / 16; + blockSizeInConstants = commandBuffer->vertexUniformBuffers[i]->currentBlockSize / 16; + + ID3D11DeviceContext1_VSSetConstantBuffers1( + commandBuffer->context, + i, + 1, + &commandBuffer->vertexUniformBuffers[i]->buffer, + &offsetInConstants, + &blockSizeInConstants); + } + + commandBuffer->needVertexUniformBufferBind = false; + } + + if (commandBuffer->needFragmentSamplerBind) { + if (graphicsPipeline->fragmentSamplerCount > 0) { + ID3D11SamplerState *samplerStates[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->fragmentSamplerCount; i += 1) { + samplerStates[i] = commandBuffer->fragmentSamplers[i]->handle; + srvs[i] = commandBuffer->fragmentSamplerTextures[i]->shaderView; + } + + ID3D11DeviceContext_PSSetSamplers( + commandBuffer->context, + 0, + graphicsPipeline->fragmentSamplerCount, + samplerStates); + + ID3D11DeviceContext_PSSetShaderResources( + commandBuffer->context, + 0, + graphicsPipeline->fragmentSamplerCount, + srvs); + } + + commandBuffer->needFragmentSamplerBind = false; + } + + if (commandBuffer->needFragmentStorageTextureBind) { + if (graphicsPipeline->fragmentStorageTextureCount > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageTextureCount; i += 1) { + srvs[i] = commandBuffer->fragmentStorageTextures[i]->shaderView; + } + + ID3D11DeviceContext_PSSetShaderResources( + commandBuffer->context, + graphicsPipeline->fragmentSamplerCount, + graphicsPipeline->fragmentStorageTextureCount, + srvs); + } + + commandBuffer->needFragmentStorageTextureBind = false; + } + + if (commandBuffer->needFragmentStorageBufferBind) { + if (graphicsPipeline->fragmentStorageBufferCount > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_BUFFERS_PER_STAGE]; + + for (Uint32 i = 0; i < graphicsPipeline->fragmentStorageBufferCount; i += 1) { + srvs[i] = commandBuffer->fragmentStorageBuffers[i]->srv; + } + + ID3D11DeviceContext_PSSetShaderResources( + commandBuffer->context, + graphicsPipeline->fragmentSamplerCount + graphicsPipeline->fragmentStorageTextureCount, + graphicsPipeline->fragmentStorageBufferCount, + srvs); + } + + commandBuffer->needFragmentStorageBufferBind = false; + } + + if (commandBuffer->needFragmentUniformBufferBind) { + for (Uint32 i = 0; i < graphicsPipeline->fragmentUniformBufferCount; i += 1) { + /* stupid workaround for god awful D3D11 drivers + * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-pssetconstantbuffers1#calling-pssetconstantbuffers1-with-command-list-emulation + */ + ID3D11DeviceContext1_PSSetConstantBuffers( + commandBuffer->context, + i, + 1, + &nullBuf); + + offsetInConstants = commandBuffer->fragmentUniformBuffers[i]->drawOffset / 16; + blockSizeInConstants = commandBuffer->fragmentUniformBuffers[i]->currentBlockSize / 16; + + ID3D11DeviceContext1_PSSetConstantBuffers1( + commandBuffer->context, + i, + 1, + &commandBuffer->fragmentUniformBuffers[i]->buffer, + &offsetInConstants, + &blockSizeInConstants); + } + + commandBuffer->needFragmentUniformBufferBind = false; + } + + if (commandBuffer->needBlendStateSet) { + FLOAT blendFactor[4] = { + commandBuffer->blendConstants.r, + commandBuffer->blendConstants.g, + commandBuffer->blendConstants.b, + commandBuffer->blendConstants.a + }; + + ID3D11DeviceContext_OMSetBlendState( + commandBuffer->context, + graphicsPipeline->colorTargetBlendState, + blendFactor, + graphicsPipeline->sampleMask); + + commandBuffer->needBlendStateSet = false; + } +} + +static void D3D11_DrawIndexedPrimitives( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 numIndices, + Uint32 numInstances, + Uint32 firstIndex, + Sint32 vertexOffset, + Uint32 firstInstance) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer); + + ID3D11DeviceContext_DrawIndexedInstanced( + d3d11CommandBuffer->context, + numIndices, + numInstances, + firstIndex, + vertexOffset, + firstInstance); +} + +static void D3D11_DrawPrimitives( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 numVertices, + Uint32 numInstances, + Uint32 firstVertex, + Uint32 firstInstance) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer); + + ID3D11DeviceContext_DrawInstanced( + d3d11CommandBuffer->context, + numVertices, + numInstances, + firstVertex, + firstInstance); +} + +static void D3D11_DrawPrimitivesIndirect( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 drawCount) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer); + + D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer; + + /* D3D11: "We have multi-draw at home!" + * Multi-draw at home: + */ + for (Uint32 i = 0; i < drawCount; i += 1) { + ID3D11DeviceContext_DrawInstancedIndirect( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + offset + (sizeof(SDL_GPUIndirectDrawCommand) * i)); + } + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer); +} + +static void D3D11_DrawIndexedPrimitivesIndirect( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset, + Uint32 drawCount) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_INTERNAL_BindGraphicsResources(d3d11CommandBuffer); + + D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer; + + /* D3D11: "We have multi-draw at home!" + * Multi-draw at home: + */ + for (Uint32 i = 0; i < drawCount; i += 1) { + ID3D11DeviceContext_DrawIndexedInstancedIndirect( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + offset + (sizeof(SDL_GPUIndexedIndirectDrawCommand) * i)); + } + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer); +} + +static void D3D11_EndRenderPass( + SDL_GPUCommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = d3d11CommandBuffer->renderer; + Uint32 i; + + // Set render target slots to NULL to avoid NULL set behavior + // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-pssetshaderresources + ID3D11DeviceContext_OMSetRenderTargets( + d3d11CommandBuffer->context, + MAX_COLOR_TARGET_BINDINGS, + renderer->nullRTVs, + NULL); + + // Resolve MSAA color render targets + for (i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1) { + if (d3d11CommandBuffer->colorResolveSubresources[i] != NULL) { + ID3D11DeviceContext_ResolveSubresource( + d3d11CommandBuffer->context, + d3d11CommandBuffer->colorResolveSubresources[i]->parent->handle, + d3d11CommandBuffer->colorResolveSubresources[i]->index, + d3d11CommandBuffer->colorTargetSubresources[i]->parent->handle, + d3d11CommandBuffer->colorTargetSubresources[i]->index, + SDLToD3D11_TextureFormat[d3d11CommandBuffer->colorTargetSubresources[i]->parent->container->header.info.format]); + } + } + + ID3D11DeviceContext_VSSetSamplers( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE, + renderer->nullSamplers); + + ID3D11DeviceContext_VSSetShaderResources( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE, + renderer->nullSRVs); + + ID3D11DeviceContext_PSSetSamplers( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE, + renderer->nullSamplers); + + ID3D11DeviceContext_PSSetShaderResources( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE * 2 + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE, + renderer->nullSRVs); + + // Reset bind state + SDL_zeroa(d3d11CommandBuffer->vertexBuffers); + SDL_zeroa(d3d11CommandBuffer->vertexBufferOffsets); + d3d11CommandBuffer->vertexBufferCount = 0; + + SDL_zeroa(d3d11CommandBuffer->vertexSamplers); + SDL_zeroa(d3d11CommandBuffer->vertexSamplerTextures); + SDL_zeroa(d3d11CommandBuffer->vertexStorageTextures); + SDL_zeroa(d3d11CommandBuffer->vertexStorageBuffers); + + SDL_zeroa(d3d11CommandBuffer->fragmentSamplers); + SDL_zeroa(d3d11CommandBuffer->fragmentSamplerTextures); + SDL_zeroa(d3d11CommandBuffer->fragmentStorageTextures); + SDL_zeroa(d3d11CommandBuffer->fragmentStorageBuffers); +} + +static void D3D11_PushVertexUniformData( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length) +{ + D3D11_INTERNAL_PushUniformData( + (D3D11CommandBuffer *)commandBuffer, + SDL_GPU_SHADERSTAGE_VERTEX, + slotIndex, + data, + length); +} + +static void D3D11_PushFragmentUniformData( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length) +{ + D3D11_INTERNAL_PushUniformData( + (D3D11CommandBuffer *)commandBuffer, + SDL_GPU_SHADERSTAGE_FRAGMENT, + slotIndex, + data, + length); +} + +// Blit + +static void D3D11_Blit( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUBlitInfo *info) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + BlitPipelineCacheEntry *blitPipelines = &renderer->blitPipelines[0]; + + SDL_GPU_BlitCommon( + commandBuffer, + info, + renderer->blitLinearSampler, + renderer->blitNearestSampler, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &blitPipelines, + NULL, + NULL); +} + +// Compute State + +static void D3D11_BeginComputePass( + SDL_GPUCommandBuffer *commandBuffer, + const SDL_GPUStorageTextureReadWriteBinding *storageTextureBindings, + Uint32 numStorageTextureBindings, + const SDL_GPUStorageBufferReadWriteBinding *storageBufferBindings, + Uint32 numStorageBufferBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11TextureContainer *textureContainer; + D3D11TextureSubresource *textureSubresource; + D3D11BufferContainer *bufferContainer; + D3D11Buffer *buffer; + ID3D11UnorderedAccessView *uavs[MAX_COMPUTE_WRITE_TEXTURES + MAX_COMPUTE_WRITE_BUFFERS]; + + for (Uint32 i = 0; i < numStorageTextureBindings; i += 1) { + textureContainer = (D3D11TextureContainer *)storageTextureBindings[i].texture; + + textureSubresource = D3D11_INTERNAL_PrepareTextureSubresourceForWrite( + d3d11CommandBuffer->renderer, + textureContainer, + storageTextureBindings[i].layer, + storageTextureBindings[i].mip_level, + storageTextureBindings[i].cycle); + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureSubresource->parent); + + d3d11CommandBuffer->computeReadWriteStorageTextureSubresources[i] = textureSubresource; + } + + for (Uint32 i = 0; i < numStorageBufferBindings; i += 1) { + bufferContainer = (D3D11BufferContainer *)storageBufferBindings[i].buffer; + + buffer = D3D11_INTERNAL_PrepareBufferForWrite( + d3d11CommandBuffer->renderer, + bufferContainer, + storageBufferBindings[i].cycle); + + D3D11_INTERNAL_TrackBuffer( + d3d11CommandBuffer, + buffer); + + d3d11CommandBuffer->computeReadWriteStorageBuffers[i] = buffer; + } + + for (Uint32 i = 0; i < numStorageTextureBindings; i += 1) { + uavs[i] = d3d11CommandBuffer->computeReadWriteStorageTextureSubresources[i]->uav; + } + + for (Uint32 i = 0; i < numStorageBufferBindings; i += 1) { + uavs[numStorageTextureBindings + i] = d3d11CommandBuffer->computeReadWriteStorageBuffers[i]->uav; + } + + ID3D11DeviceContext_CSSetUnorderedAccessViews( + d3d11CommandBuffer->context, + 0, + numStorageTextureBindings + numStorageBufferBindings, + uavs, + NULL); +} + +static void D3D11_BindComputePipeline( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUComputePipeline *computePipeline) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11ComputePipeline *pipeline = (D3D11ComputePipeline *)computePipeline; + + d3d11CommandBuffer->computePipeline = pipeline; + + ID3D11DeviceContext_CSSetShader( + d3d11CommandBuffer->context, + pipeline->computeShader, + NULL, + 0); + + // Acquire uniform buffers if necessary + for (Uint32 i = 0; i < pipeline->numUniformBuffers; i += 1) { + if (d3d11CommandBuffer->computeUniformBuffers[i] == NULL) { + d3d11CommandBuffer->computeUniformBuffers[i] = D3D11_INTERNAL_AcquireUniformBufferFromPool( + d3d11CommandBuffer); + } + } + + d3d11CommandBuffer->needComputeSamplerBind = true; + d3d11CommandBuffer->needComputeReadOnlyTextureBind = true; + d3d11CommandBuffer->needComputeReadOnlyBufferBind = true; + d3d11CommandBuffer->needComputeUniformBufferBind = true; +} + +static void D3D11_BindComputeSamplers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + const SDL_GPUTextureSamplerBinding *textureSamplerBindings, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)textureSamplerBindings[i].texture; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->computeSamplers[firstSlot + i] = + (D3D11Sampler *)textureSamplerBindings[i].sampler; + + d3d11CommandBuffer->computeSamplerTextures[firstSlot + i] = + textureContainer->activeTexture; + } + + d3d11CommandBuffer->needComputeSamplerBind = true; +} + +static void D3D11_BindComputeStorageTextures( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUTexture *const *storageTextures, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + + for (Uint32 i = 0; i < numBindings; i += 1) { + D3D11TextureContainer *textureContainer = (D3D11TextureContainer *)storageTextures[i]; + + D3D11_INTERNAL_TrackTexture( + d3d11CommandBuffer, + textureContainer->activeTexture); + + d3d11CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = + textureContainer->activeTexture; + } + + d3d11CommandBuffer->needComputeReadOnlyTextureBind = true; +} + +static void D3D11_BindComputeStorageBuffers( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 firstSlot, + SDL_GPUBuffer *const *storageBuffers, + Uint32 numBindings) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11BufferContainer *bufferContainer; + Uint32 i; + + for (i = 0; i < numBindings; i += 1) { + bufferContainer = (D3D11BufferContainer *)storageBuffers[i]; + + D3D11_INTERNAL_TrackBuffer( + d3d11CommandBuffer, + bufferContainer->activeBuffer); + + d3d11CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = + bufferContainer->activeBuffer; + } + + d3d11CommandBuffer->needComputeReadOnlyBufferBind = true; +} + +static void D3D11_PushComputeUniformData( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 slotIndex, + const void *data, + Uint32 length) +{ + D3D11_INTERNAL_PushUniformData( + (D3D11CommandBuffer *)commandBuffer, + SDL_GPU_SHADERSTAGE_COMPUTE, + slotIndex, + data, + length); +} + +static void D3D11_INTERNAL_BindComputeResources( + D3D11CommandBuffer *commandBuffer) +{ + D3D11ComputePipeline *computePipeline = commandBuffer->computePipeline; + + ID3D11Buffer *nullBuf = NULL; + Uint32 offsetInConstants, blockSizeInConstants; + + if (commandBuffer->needComputeSamplerBind) { + if (computePipeline->numSamplers > 0) { + ID3D11SamplerState *samplers[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + ID3D11ShaderResourceView *srvs[MAX_TEXTURE_SAMPLERS_PER_STAGE]; + + for (Uint32 i = 0; i < computePipeline->numSamplers; i += 1) { + samplers[i] = commandBuffer->computeSamplers[i]->handle; + srvs[i] = commandBuffer->computeSamplerTextures[i]->shaderView; + } + + ID3D11DeviceContext_CSSetSamplers( + commandBuffer->context, + 0, + computePipeline->numSamplers, + samplers); + + ID3D11DeviceContext_CSSetShaderResources( + commandBuffer->context, + 0, + computePipeline->numSamplers, + srvs); + } + + commandBuffer->needComputeSamplerBind = false; + } + + if (commandBuffer->needComputeReadOnlyTextureBind) { + if (computePipeline->numReadonlyStorageTextures > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE]; + + for (Uint32 i = 0; i < computePipeline->numReadonlyStorageTextures; i += 1) { + srvs[i] = commandBuffer->computeReadOnlyStorageTextures[i]->shaderView; + } + + ID3D11DeviceContext_CSSetShaderResources( + commandBuffer->context, + computePipeline->numSamplers, + computePipeline->numReadonlyStorageTextures, + srvs); + } + + commandBuffer->needComputeReadOnlyTextureBind = false; + } + + if (commandBuffer->needComputeReadOnlyBufferBind) { + if (computePipeline->numReadonlyStorageBuffers > 0) { + ID3D11ShaderResourceView *srvs[MAX_STORAGE_TEXTURES_PER_STAGE]; + + for (Uint32 i = 0; i < computePipeline->numReadonlyStorageBuffers; i += 1) { + srvs[i] = commandBuffer->computeReadOnlyStorageBuffers[i]->srv; + } + + ID3D11DeviceContext_CSSetShaderResources( + commandBuffer->context, + computePipeline->numSamplers + computePipeline->numReadonlyStorageTextures, + computePipeline->numReadonlyStorageBuffers, + srvs); + } + + commandBuffer->needComputeReadOnlyBufferBind = false; + } + + if (commandBuffer->needComputeUniformBufferBind) { + for (Uint32 i = 0; i < computePipeline->numUniformBuffers; i += 1) { + /* stupid workaround for god awful D3D11 drivers + * see: https://learn.microsoft.com/en-us/windows/win32/api/d3d11_1/nf-d3d11_1-id3d11devicecontext1-vssetconstantbuffers1#calling-vssetconstantbuffers1-with-command-list-emulation + */ + ID3D11DeviceContext1_CSSetConstantBuffers( + commandBuffer->context, + i, + 1, + &nullBuf); + + offsetInConstants = commandBuffer->computeUniformBuffers[i]->drawOffset / 16; + blockSizeInConstants = commandBuffer->computeUniformBuffers[i]->currentBlockSize / 16; + + ID3D11DeviceContext1_CSSetConstantBuffers1( + commandBuffer->context, + i, + 1, + &commandBuffer->computeUniformBuffers[i]->buffer, + &offsetInConstants, + &blockSizeInConstants); + } + commandBuffer->needComputeUniformBufferBind = false; + } +} + +static void D3D11_DispatchCompute( + SDL_GPUCommandBuffer *commandBuffer, + Uint32 groupcountX, + Uint32 groupcountY, + Uint32 groupcountZ) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer); + + ID3D11DeviceContext_Dispatch( + d3d11CommandBuffer->context, + groupcountX, + groupcountY, + groupcountZ); +} + +static void D3D11_DispatchComputeIndirect( + SDL_GPUCommandBuffer *commandBuffer, + SDL_GPUBuffer *buffer, + Uint32 offset) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Buffer *d3d11Buffer = ((D3D11BufferContainer *)buffer)->activeBuffer; + + D3D11_INTERNAL_BindComputeResources(d3d11CommandBuffer); + + ID3D11DeviceContext_DispatchIndirect( + d3d11CommandBuffer->context, + d3d11Buffer->handle, + offset); + + D3D11_INTERNAL_TrackBuffer(d3d11CommandBuffer, d3d11Buffer); +} + +static void D3D11_EndComputePass( + SDL_GPUCommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = d3d11CommandBuffer->renderer; + + // reset UAV slots to avoid NULL set behavior + // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-id3d11devicecontext-cssetshaderresources + ID3D11DeviceContext_CSSetUnorderedAccessViews( + d3d11CommandBuffer->context, + 0, + MAX_COMPUTE_WRITE_TEXTURES + MAX_COMPUTE_WRITE_BUFFERS, + renderer->nullUAVs, + NULL); + + ID3D11DeviceContext_CSSetSamplers( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE, + renderer->nullSamplers); + + ID3D11DeviceContext_CSSetShaderResources( + d3d11CommandBuffer->context, + 0, + MAX_TEXTURE_SAMPLERS_PER_STAGE + MAX_STORAGE_TEXTURES_PER_STAGE + MAX_STORAGE_BUFFERS_PER_STAGE, + renderer->nullSRVs); + + d3d11CommandBuffer->computePipeline = NULL; + + // Reset bind state + SDL_zeroa(d3d11CommandBuffer->computeSamplers); + SDL_zeroa(d3d11CommandBuffer->computeSamplerTextures); + SDL_zeroa(d3d11CommandBuffer->computeReadOnlyStorageTextures); + SDL_zeroa(d3d11CommandBuffer->computeReadOnlyStorageBuffers); + SDL_zeroa(d3d11CommandBuffer->computeReadWriteStorageTextureSubresources); + SDL_zeroa(d3d11CommandBuffer->computeReadWriteStorageBuffers); +} + +// Fence Cleanup + +static void D3D11_INTERNAL_ReleaseFenceToPool( + D3D11Renderer *renderer, + D3D11Fence *fence) +{ + SDL_LockMutex(renderer->fenceLock); + + if (renderer->availableFenceCount == renderer->availableFenceCapacity) { + renderer->availableFenceCapacity *= 2; + renderer->availableFences = SDL_realloc( + renderer->availableFences, + renderer->availableFenceCapacity * sizeof(D3D11Fence *)); + } + renderer->availableFences[renderer->availableFenceCount] = fence; + renderer->availableFenceCount += 1; + + SDL_UnlockMutex(renderer->fenceLock); +} + +static void D3D11_ReleaseFence( + SDL_GPURenderer *driverData, + SDL_GPUFence *fence) +{ + D3D11Fence *d3d11Fence = (D3D11Fence *)fence; + + if (SDL_AtomicDecRef(&d3d11Fence->referenceCount)) { + D3D11_INTERNAL_ReleaseFenceToPool( + (D3D11Renderer *)driverData, + d3d11Fence); + } +} + +// Cleanup + +/* D3D11 does not provide a deferred texture-to-buffer copy operation, + * so instead of the transfer buffer containing an actual D3D11 buffer, + * the transfer buffer data is just a malloc'd pointer. + * In the download operation we copy data to a staging resource, and + * wait until the command buffer has finished executing to map the staging resource. + */ + +static bool D3D11_INTERNAL_MapAndCopyBufferDownload( + D3D11Renderer *renderer, + D3D11TransferBuffer *transferBuffer, + D3D11BufferDownload *bufferDownload) +{ + D3D11_MAPPED_SUBRESOURCE subres; + HRESULT res; + + SDL_LockMutex(renderer->contextLock); + res = ID3D11DeviceContext_Map( + renderer->immediateContext, + (ID3D11Resource *)bufferDownload->stagingBuffer, + 0, + D3D11_MAP_READ, + 0, + &subres); + SDL_UnlockMutex(renderer->contextLock); + + CHECK_D3D11_ERROR_AND_RETURN("Failed to map staging buffer", false) + + SDL_memcpy( + ((Uint8 *)transferBuffer->data) + bufferDownload->dstOffset, + ((Uint8 *)subres.pData), + bufferDownload->size); + + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_Unmap( + renderer->immediateContext, + (ID3D11Resource *)bufferDownload->stagingBuffer, + 0); + SDL_UnlockMutex(renderer->contextLock); + + ID3D11Buffer_Release(bufferDownload->stagingBuffer); + + return true; +} + +static bool D3D11_INTERNAL_MapAndCopyTextureDownload( + D3D11Renderer *renderer, + D3D11TransferBuffer *transferBuffer, + D3D11TextureDownload *textureDownload) +{ + D3D11_MAPPED_SUBRESOURCE subres; + HRESULT res; + Uint32 dataPtrOffset; + Uint32 depth, row; + + SDL_LockMutex(renderer->contextLock); + res = ID3D11DeviceContext_Map( + renderer->immediateContext, + (ID3D11Resource *)textureDownload->stagingTexture, + 0, + D3D11_MAP_READ, + 0, + &subres); + SDL_UnlockMutex(renderer->contextLock); + + CHECK_D3D11_ERROR_AND_RETURN("Could not map staging texture", false) + + for (depth = 0; depth < textureDownload->depth; depth += 1) { + dataPtrOffset = textureDownload->bufferOffset + (depth * textureDownload->bytesPerDepthSlice); + + for (row = 0; row < textureDownload->height; row += 1) { + SDL_memcpy( + transferBuffer->data + dataPtrOffset, + (Uint8 *)subres.pData + (depth * subres.DepthPitch) + (row * subres.RowPitch), + textureDownload->bytesPerRow); + dataPtrOffset += textureDownload->bytesPerRow; + } + } + + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_Unmap( + renderer->immediateContext, + textureDownload->stagingTexture, + 0); + SDL_UnlockMutex(renderer->contextLock); + + ID3D11Resource_Release(textureDownload->stagingTexture); + + return true; +} + +static bool D3D11_INTERNAL_CleanCommandBuffer( + D3D11Renderer *renderer, + D3D11CommandBuffer *commandBuffer) +{ + Uint32 i, j; + bool result = true; + + // Perform deferred download map and copy + + for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) { + D3D11TransferBuffer *transferBuffer = commandBuffer->usedTransferBuffers[i]; + + for (j = 0; j < transferBuffer->bufferDownloadCount; j += 1) { + result &= D3D11_INTERNAL_MapAndCopyBufferDownload( + renderer, + transferBuffer, + &transferBuffer->bufferDownloads[j]); + } + + for (j = 0; j < transferBuffer->textureDownloadCount; j += 1) { + result &= D3D11_INTERNAL_MapAndCopyTextureDownload( + renderer, + transferBuffer, + &transferBuffer->textureDownloads[j]); + } + + transferBuffer->bufferDownloadCount = 0; + transferBuffer->textureDownloadCount = 0; + } + + // Uniform buffers are now available + + SDL_LockMutex(renderer->acquireUniformBufferLock); + + for (i = 0; i < commandBuffer->usedUniformBufferCount; i += 1) { + D3D11_INTERNAL_ReturnUniformBufferToPool( + renderer, + commandBuffer->usedUniformBuffers[i]); + } + commandBuffer->usedUniformBufferCount = 0; + + SDL_UnlockMutex(renderer->acquireUniformBufferLock); + + // Reference Counting + + for (i = 0; i < commandBuffer->usedBufferCount; i += 1) { + (void)SDL_AtomicDecRef(&commandBuffer->usedBuffers[i]->referenceCount); + } + commandBuffer->usedBufferCount = 0; + + for (i = 0; i < commandBuffer->usedTransferBufferCount; i += 1) { + (void)SDL_AtomicDecRef(&commandBuffer->usedTransferBuffers[i]->referenceCount); + } + commandBuffer->usedTransferBufferCount = 0; + + for (i = 0; i < commandBuffer->usedTextureCount; i += 1) { + (void)SDL_AtomicDecRef(&commandBuffer->usedTextures[i]->referenceCount); + } + commandBuffer->usedTextureCount = 0; + + // Reset presentation + commandBuffer->windowDataCount = 0; + + // The fence is now available (unless SubmitAndAcquireFence was called) + if (commandBuffer->autoReleaseFence) { + D3D11_ReleaseFence( + (SDL_GPURenderer *)renderer, + (SDL_GPUFence *)commandBuffer->fence); + } + + // Return command buffer to pool + SDL_LockMutex(renderer->acquireCommandBufferLock); + if (renderer->availableCommandBufferCount == renderer->availableCommandBufferCapacity) { + renderer->availableCommandBufferCapacity += 1; + renderer->availableCommandBuffers = SDL_realloc( + renderer->availableCommandBuffers, + renderer->availableCommandBufferCapacity * sizeof(D3D11CommandBuffer *)); + } + renderer->availableCommandBuffers[renderer->availableCommandBufferCount] = commandBuffer; + renderer->availableCommandBufferCount += 1; + SDL_UnlockMutex(renderer->acquireCommandBufferLock); + + // Remove this command buffer from the submitted list + for (i = 0; i < renderer->submittedCommandBufferCount; i += 1) { + if (renderer->submittedCommandBuffers[i] == commandBuffer) { + renderer->submittedCommandBuffers[i] = renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount - 1]; + renderer->submittedCommandBufferCount -= 1; + } + } + + return result; +} + +static void D3D11_INTERNAL_PerformPendingDestroys( + D3D11Renderer *renderer) +{ + Sint32 referenceCount = 0; + Sint32 i; + Uint32 j; + + for (i = renderer->transferBufferContainersToDestroyCount - 1; i >= 0; i -= 1) { + referenceCount = 0; + for (j = 0; j < renderer->transferBufferContainersToDestroy[i]->bufferCount; j += 1) { + referenceCount += SDL_GetAtomicInt(&renderer->transferBufferContainersToDestroy[i]->buffers[j]->referenceCount); + } + + if (referenceCount == 0) { + D3D11_INTERNAL_DestroyTransferBufferContainer( + renderer->transferBufferContainersToDestroy[i]); + + renderer->transferBufferContainersToDestroy[i] = renderer->transferBufferContainersToDestroy[renderer->transferBufferContainersToDestroyCount - 1]; + renderer->transferBufferContainersToDestroyCount -= 1; + } + } + + for (i = renderer->bufferContainersToDestroyCount - 1; i >= 0; i -= 1) { + referenceCount = 0; + for (j = 0; j < renderer->bufferContainersToDestroy[i]->bufferCount; j += 1) { + referenceCount += SDL_GetAtomicInt(&renderer->bufferContainersToDestroy[i]->buffers[j]->referenceCount); + } + + if (referenceCount == 0) { + D3D11_INTERNAL_DestroyBufferContainer( + renderer->bufferContainersToDestroy[i]); + + renderer->bufferContainersToDestroy[i] = renderer->bufferContainersToDestroy[renderer->bufferContainersToDestroyCount - 1]; + renderer->bufferContainersToDestroyCount -= 1; + } + } + + for (i = renderer->textureContainersToDestroyCount - 1; i >= 0; i -= 1) { + referenceCount = 0; + for (j = 0; j < renderer->textureContainersToDestroy[i]->textureCount; j += 1) { + referenceCount += SDL_GetAtomicInt(&renderer->textureContainersToDestroy[i]->textures[j]->referenceCount); + } + + if (referenceCount == 0) { + D3D11_INTERNAL_DestroyTextureContainer( + renderer->textureContainersToDestroy[i]); + + renderer->textureContainersToDestroy[i] = renderer->textureContainersToDestroy[renderer->textureContainersToDestroyCount - 1]; + renderer->textureContainersToDestroyCount -= 1; + } + } +} + +// Fences + +static void D3D11_INTERNAL_WaitForFence( + D3D11Renderer *renderer, + D3D11Fence *fence) +{ + BOOL queryData; + HRESULT res; + + SDL_LockMutex(renderer->contextLock); + + do { + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous *)fence->handle, + &queryData, + sizeof(queryData), + 0); + } while (res != S_OK); // Spin until we get a result back... + + SDL_UnlockMutex(renderer->contextLock); +} + +static bool D3D11_WaitForFences( + SDL_GPURenderer *driverData, + bool waitAll, + SDL_GPUFence *const *fences, + Uint32 numFences) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11Fence *fence; + BOOL queryData; + HRESULT res = S_FALSE; + + if (waitAll) { + for (Uint32 i = 0; i < numFences; i += 1) { + fence = (D3D11Fence *)fences[i]; + D3D11_INTERNAL_WaitForFence(renderer, fence); + } + } else { + SDL_LockMutex(renderer->contextLock); + + while (res != S_OK) { + for (Uint32 i = 0; i < numFences; i += 1) { + fence = (D3D11Fence *)fences[i]; + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous *)fence->handle, + &queryData, + sizeof(queryData), + 0); + if (res == S_OK) { + break; + } + } + } + + SDL_UnlockMutex(renderer->contextLock); + } + + SDL_LockMutex(renderer->contextLock); + + bool result = true; + // Check if we can perform any cleanups + for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) { + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle, + &queryData, + sizeof(queryData), + 0); + if (res == S_OK) { + result &= D3D11_INTERNAL_CleanCommandBuffer( + renderer, + renderer->submittedCommandBuffers[i]); + } + } + + D3D11_INTERNAL_PerformPendingDestroys(renderer); + + SDL_UnlockMutex(renderer->contextLock); + + return result; +} + +static bool D3D11_QueryFence( + SDL_GPURenderer *driverData, + SDL_GPUFence *fence) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11Fence *d3d11Fence = (D3D11Fence *)fence; + BOOL queryData; + HRESULT res; + + SDL_LockMutex(renderer->contextLock); + + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous *)d3d11Fence->handle, + &queryData, + sizeof(queryData), + 0); + + SDL_UnlockMutex(renderer->contextLock); + + return res == S_OK; +} + +// Window and Swapchain Management + +static D3D11WindowData *D3D11_INTERNAL_FetchWindowData( + SDL_Window *window) +{ + SDL_PropertiesID properties = SDL_GetWindowProperties(window); + return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL); +} + +static bool D3D11_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e) +{ + SDL_Window *w = (SDL_Window *)userdata; + D3D11WindowData *data; + if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) { + data = D3D11_INTERNAL_FetchWindowData(w); + data->needsSwapchainRecreate = true; + } + + return true; +} + +static bool D3D11_INTERNAL_InitializeSwapchainTexture( + D3D11Renderer *renderer, + IDXGISwapChain *swapchain, + DXGI_FORMAT swapchainFormat, + DXGI_FORMAT rtvFormat, + D3D11Texture *pTexture) +{ + ID3D11Texture2D *swapchainTexture; + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + ID3D11RenderTargetView *rtv; + HRESULT res; + + // Clear all the texture data + SDL_zerop(pTexture); + + // Grab the buffer from the swapchain + res = IDXGISwapChain_GetBuffer( + swapchain, + 0, + &D3D_IID_ID3D11Texture2D, + (void **)&swapchainTexture); + CHECK_D3D11_ERROR_AND_RETURN("Could not get buffer from swapchain!", false); + + // Create the RTV for the swapchain + rtvDesc.Format = rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = 0; + + res = ID3D11Device_CreateRenderTargetView( + renderer->device, + (ID3D11Resource *)swapchainTexture, + &rtvDesc, + &rtv); + if (FAILED(res)) { + ID3D11Texture2D_Release(swapchainTexture); + D3D11_INTERNAL_SetError(renderer, "Swapchain RTV creation failed", res); + return false; + } + + // Fill out the texture struct + pTexture->handle = NULL; // This will be set in AcquireSwapchainTexture. + pTexture->shaderView = NULL; // We don't allow swapchain texture to be sampled + SDL_SetAtomicInt(&pTexture->referenceCount, 0); + pTexture->subresourceCount = 1; + pTexture->subresources = SDL_malloc(sizeof(D3D11TextureSubresource)); + pTexture->subresources[0].colorTargetViews = SDL_calloc(1, sizeof(ID3D11RenderTargetView *)); + pTexture->subresources[0].colorTargetViews[0] = rtv; + pTexture->subresources[0].uav = NULL; + pTexture->subresources[0].depthStencilTargetView = NULL; + pTexture->subresources[0].layer = 0; + pTexture->subresources[0].level = 0; + pTexture->subresources[0].depth = 1; + pTexture->subresources[0].index = 0; + pTexture->subresources[0].parent = pTexture; + + // Cleanup + ID3D11Texture2D_Release(swapchainTexture); + + return true; +} + +static bool D3D11_INTERNAL_CreateSwapchain( + D3D11Renderer *renderer, + D3D11WindowData *windowData, + SDL_GPUSwapchainComposition swapchainComposition, + SDL_GPUPresentMode presentMode) +{ + HWND dxgiHandle; + Uint32 i; + DXGI_SWAP_CHAIN_DESC swapchainDesc; + DXGI_FORMAT swapchainFormat; + IDXGIFactory1 *pParent; + IDXGISwapChain *swapchain; + IDXGISwapChain3 *swapchain3; + HRESULT res; + + // Get the DXGI handle +#ifdef _WIN32 + dxgiHandle = (HWND)SDL_GetPointerProperty(SDL_GetWindowProperties(windowData->window), SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL); +#else + dxgiHandle = (HWND)windowData->window; +#endif + + swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition]; + + // Initialize the swapchain buffer descriptor + swapchainDesc.BufferDesc.Width = 0; + swapchainDesc.BufferDesc.Height = 0; + swapchainDesc.BufferDesc.RefreshRate.Numerator = 0; + swapchainDesc.BufferDesc.RefreshRate.Denominator = 0; + swapchainDesc.BufferDesc.Format = swapchainFormat; + swapchainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapchainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + + // Initialize the rest of the swapchain descriptor + swapchainDesc.SampleDesc.Count = 1; + swapchainDesc.SampleDesc.Quality = 0; + swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchainDesc.BufferCount = 2; + swapchainDesc.OutputWindow = dxgiHandle; + swapchainDesc.Windowed = 1; + + if (renderer->supportsTearing) { + swapchainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + // We know this is supported because tearing support implies DXGI 1.5+ + swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + } else { + swapchainDesc.Flags = 0; + swapchainDesc.SwapEffect = (renderer->supportsFlipDiscard ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD); + } + + // Create the swapchain! + res = IDXGIFactory1_CreateSwapChain( + (IDXGIFactory1 *)renderer->factory, + (IUnknown *)renderer->device, + &swapchainDesc, + &swapchain); + CHECK_D3D11_ERROR_AND_RETURN("Could not create swapchain", false); + + /* + * The swapchain's parent is a separate factory from the factory that + * we used to create the swapchain, and only that parent can be used to + * set the window association. Trying to set an association on our factory + * will silently fail and doesn't even verify arguments or return errors. + * See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/ + */ + res = IDXGISwapChain_GetParent( + swapchain, + &D3D_IID_IDXGIFactory1, + (void **)&pParent); + if (FAILED(res)) { + SDL_LogWarn( + SDL_LOG_CATEGORY_GPU, + "Could not get swapchain parent! Error Code: " HRESULT_FMT, + res); + } else { + // Disable DXGI window crap + res = IDXGIFactory1_MakeWindowAssociation( + pParent, + dxgiHandle, + DXGI_MWA_NO_WINDOW_CHANGES); + if (FAILED(res)) { + SDL_LogWarn( + SDL_LOG_CATEGORY_GPU, + "MakeWindowAssociation failed! Error Code: " HRESULT_FMT, + res); + } + + // We're done with the parent now + IDXGIFactory1_Release(pParent); + } + + if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) { + // Set the color space, support already verified if we hit this block + IDXGISwapChain3_QueryInterface( + swapchain, + &D3D_IID_IDXGISwapChain3, + (void **)&swapchain3); + + IDXGISwapChain3_SetColorSpace1( + swapchain3, + SwapchainCompositionToColorSpace[swapchainComposition]); + + IDXGISwapChain3_Release(swapchain3); + } + + // Initialize the swapchain data + windowData->swapchain = swapchain; + windowData->presentMode = presentMode; + windowData->swapchainComposition = swapchainComposition; + windowData->swapchainFormat = swapchainFormat; + windowData->swapchainColorSpace = SwapchainCompositionToColorSpace[swapchainComposition]; + windowData->frameCounter = 0; + + for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) { + windowData->inFlightFences[i] = NULL; + } + + /* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB. + * You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB + */ + if (!D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + swapchain, + swapchainFormat, + (swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat, + &windowData->texture)) { + IDXGISwapChain_Release(swapchain); + return false; + } + + int w, h; + SDL_SyncWindow(windowData->window); + SDL_GetWindowSizeInPixels(windowData->window, &w, &h); + + // Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture + SDL_zerop(&windowData->textureContainer); + windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *)); + windowData->textureContainer.activeTexture = &windowData->texture; + windowData->textureContainer.textures[0] = &windowData->texture; + windowData->textureContainer.canBeCycled = false; + windowData->textureContainer.textureCount = 1; + windowData->textureContainer.textureCapacity = 1; + + windowData->textureContainer.header.info.layer_count_or_depth = 1; + windowData->textureContainer.header.info.format = SwapchainCompositionToSDLTextureFormat[windowData->swapchainComposition]; + windowData->textureContainer.header.info.type = SDL_GPU_TEXTURETYPE_2D; + windowData->textureContainer.header.info.num_levels = 1; + windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1; + windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET; + windowData->textureContainer.header.info.width = w; + windowData->textureContainer.header.info.height = h; + + windowData->texture.container = &windowData->textureContainer; + windowData->texture.containerIndex = 0; + + windowData->width = w; + windowData->height = h; + return true; +} + +static bool D3D11_INTERNAL_ResizeSwapchain( + D3D11Renderer *renderer, + D3D11WindowData *windowData) +{ + D3D11_Wait((SDL_GPURenderer *)renderer); + + // Release the old RTV + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]); + SDL_free(windowData->texture.subresources[0].colorTargetViews); + SDL_free(windowData->texture.subresources); + + int w, h; + SDL_SyncWindow(windowData->window); + SDL_GetWindowSizeInPixels(windowData->window, &w, &h); + + // Resize the swapchain + HRESULT res = IDXGISwapChain_ResizeBuffers( + windowData->swapchain, + 0, // Keep buffer count the same + w, + h, + DXGI_FORMAT_UNKNOWN, // Keep the old format + renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0); + CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false); + + // Create the texture object for the swapchain + bool result = D3D11_INTERNAL_InitializeSwapchainTexture( + renderer, + windowData->swapchain, + windowData->swapchainFormat, + (windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat, + &windowData->texture); + + windowData->textureContainer.header.info.width = w; + windowData->textureContainer.header.info.height = h; + windowData->width = w; + windowData->height = h; + windowData->needsSwapchainRecreate = !result; + return result; +} + +static bool D3D11_SupportsSwapchainComposition( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchainComposition) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + DXGI_FORMAT format; + Uint32 formatSupport = 0; + IDXGISwapChain3 *swapchain3; + Uint32 colorSpaceSupport; + HRESULT res; + + format = SwapchainCompositionToTextureFormat[swapchainComposition]; + + res = ID3D11Device_CheckFormatSupport( + renderer->device, + format, + &formatSupport); + if (FAILED(res)) { + // Format is apparently unknown + return false; + } + + if (!(formatSupport & D3D11_FORMAT_SUPPORT_DISPLAY)) { + return false; + } + + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window); + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Must claim window before querying swapchain composition support!", false) + } + + // Check the color space support if necessary + if (swapchainComposition != SDL_GPU_SWAPCHAINCOMPOSITION_SDR) { + if (SUCCEEDED(IDXGISwapChain3_QueryInterface( + windowData->swapchain, + &D3D_IID_IDXGISwapChain3, + (void **)&swapchain3))) { + IDXGISwapChain3_CheckColorSpaceSupport( + swapchain3, + SwapchainCompositionToColorSpace[swapchainComposition], + &colorSpaceSupport); + + IDXGISwapChain3_Release(swapchain3); + + if (!(colorSpaceSupport & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) { + return false; + } + } else { + SET_STRING_ERROR_AND_RETURN("DXGI 1.4 not supported, cannot use composition other than SDL_GPU_SWAPCHAINCOMPOSITION_SDR!", false) + } + } + + return true; +} + +static bool D3D11_SupportsPresentMode( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUPresentMode presentMode) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + (void)window; // used by other backends + switch (presentMode) { + case SDL_GPU_PRESENTMODE_IMMEDIATE: + case SDL_GPU_PRESENTMODE_VSYNC: + return true; + case SDL_GPU_PRESENTMODE_MAILBOX: + return renderer->supportsFlipDiscard; + } + SDL_assert(!"Unrecognized present mode"); + return false; +} + +static bool D3D11_ClaimWindow( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + windowData = (D3D11WindowData *)SDL_calloc(1, sizeof(D3D11WindowData)); + windowData->window = window; + + if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) { + SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData); + + SDL_LockMutex(renderer->windowLock); + if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) { + renderer->claimedWindowCapacity *= 2; + renderer->claimedWindows = SDL_realloc( + renderer->claimedWindows, + renderer->claimedWindowCapacity * sizeof(D3D11WindowData *)); + } + renderer->claimedWindows[renderer->claimedWindowCount] = windowData; + renderer->claimedWindowCount += 1; + SDL_UnlockMutex(renderer->windowLock); + + SDL_AddEventWatch(D3D11_INTERNAL_OnWindowResize, window); + + return true; + } else { + SDL_free(windowData); + SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", false) + } + } else { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Window already claimed!"); + return false; + } +} + +static void D3D11_INTERNAL_DestroySwapchain( + D3D11Renderer *renderer, + D3D11WindowData *windowData) +{ + Uint32 i; + + D3D11_Wait((SDL_GPURenderer *)renderer); + + ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]); + SDL_free(windowData->texture.subresources[0].colorTargetViews); + SDL_free(windowData->texture.subresources); + SDL_free(windowData->textureContainer.textures); + IDXGISwapChain_Release(windowData->swapchain); + + // DXGI will crash if we don't flush deferred swapchain destruction + SDL_LockMutex(renderer->contextLock); + ID3D11DeviceContext_ClearState(renderer->immediateContext); + ID3D11DeviceContext_Flush(renderer->immediateContext); + SDL_UnlockMutex(renderer->contextLock); + + windowData->swapchain = NULL; + + for (i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) { + if (windowData->inFlightFences[i] != NULL) { + D3D11_ReleaseFence( + (SDL_GPURenderer *)renderer, + windowData->inFlightFences[i]); + } + } +} + +static void D3D11_ReleaseWindow( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + return; + } + + D3D11_INTERNAL_DestroySwapchain( + renderer, + windowData); + + SDL_LockMutex(renderer->windowLock); + for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) { + if (renderer->claimedWindows[i]->window == window) { + renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1]; + renderer->claimedWindowCount -= 1; + break; + } + } + SDL_UnlockMutex(renderer->windowLock); + + SDL_free(windowData); + + SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA); + SDL_RemoveEventWatch(D3D11_INTERNAL_OnWindowResize, window); +} + +static bool D3D11_AcquireSwapchainTexture( + SDL_GPUCommandBuffer *commandBuffer, + SDL_Window *window, + SDL_GPUTexture **swapchainTexture, + Uint32 *swapchainTextureWidth, + Uint32 *swapchainTextureHeight) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + D3D11WindowData *windowData; + HRESULT res; + + *swapchainTexture = NULL; + if (swapchainTextureWidth) { + *swapchainTextureWidth = 0; + } + if (swapchainTextureHeight) { + *swapchainTextureHeight = 0; + } + + windowData = D3D11_INTERNAL_FetchWindowData(window); + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false) + } + + if (windowData->needsSwapchainRecreate) { + if (!D3D11_INTERNAL_ResizeSwapchain(renderer, windowData)) { + return false; + } + } + + if (swapchainTextureWidth) { + *swapchainTextureWidth = windowData->width; + } + if (swapchainTextureHeight) { + *swapchainTextureHeight = windowData->height; + } + + if (windowData->inFlightFences[windowData->frameCounter] != NULL) { + if (windowData->presentMode == SDL_GPU_PRESENTMODE_VSYNC) { + // In VSYNC mode, block until the least recent presented frame is done + if (!D3D11_WaitForFences( + (SDL_GPURenderer *)renderer, + true, + &windowData->inFlightFences[windowData->frameCounter], + 1)) { + return false; + } + } else { + if (!D3D11_QueryFence( + (SDL_GPURenderer *)d3d11CommandBuffer->renderer, + windowData->inFlightFences[windowData->frameCounter])) { + /* + * In MAILBOX or IMMEDIATE mode, if the least recent fence is not signaled, + * return true to indicate that there is no error but rendering should be skipped + */ + return true; + } + } + + D3D11_ReleaseFence( + (SDL_GPURenderer *)d3d11CommandBuffer->renderer, + windowData->inFlightFences[windowData->frameCounter]); + + windowData->inFlightFences[windowData->frameCounter] = NULL; + } + + // Set the handle on the windowData texture data. + res = IDXGISwapChain_GetBuffer( + windowData->swapchain, + 0, + &D3D_IID_ID3D11Texture2D, + (void **)&windowData->texture.handle); + CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false); + + // Set up presentation + if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) { + d3d11CommandBuffer->windowDataCapacity += 1; + d3d11CommandBuffer->windowDatas = SDL_realloc( + d3d11CommandBuffer->windowDatas, + d3d11CommandBuffer->windowDataCapacity * sizeof(D3D11WindowData *)); + } + d3d11CommandBuffer->windowDatas[d3d11CommandBuffer->windowDataCount] = windowData; + d3d11CommandBuffer->windowDataCount += 1; + + // Return the swapchain texture + *swapchainTexture = (SDL_GPUTexture*) &windowData->textureContainer; + return true; +} + +static SDL_GPUTextureFormat D3D11_GetSwapchainTextureFormat( + SDL_GPURenderer *driverData, + SDL_Window *window) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot get swapchain format, window has not been claimed!", SDL_GPU_TEXTUREFORMAT_INVALID) + } + + return windowData->textureContainer.header.info.format; +} + +static bool D3D11_SetSwapchainParameters( + SDL_GPURenderer *driverData, + SDL_Window *window, + SDL_GPUSwapchainComposition swapchainComposition, + SDL_GPUPresentMode presentMode) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window); + + if (windowData == NULL) { + SET_STRING_ERROR_AND_RETURN("Cannot set swapchain parameters on unclaimed window!", false) + } + + if (!D3D11_SupportsSwapchainComposition(driverData, window, swapchainComposition)) { + SET_STRING_ERROR_AND_RETURN("Swapchain composition not supported!", false) + } + + if (!D3D11_SupportsPresentMode(driverData, window, presentMode)) { + SET_STRING_ERROR_AND_RETURN("Present mode not supported!", false) + } + + if ( + swapchainComposition != windowData->swapchainComposition || + presentMode != windowData->presentMode) { + D3D11_Wait(driverData); + + // Recreate the swapchain + D3D11_INTERNAL_DestroySwapchain( + renderer, + windowData); + + return D3D11_INTERNAL_CreateSwapchain( + renderer, + windowData, + swapchainComposition, + presentMode); + } + + return true; +} + +// Submission + +static bool D3D11_Submit( + SDL_GPUCommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer; + ID3D11CommandList *commandList; + HRESULT res; + + // Unmap uniform buffers + + for (Uint32 i = 0; i < MAX_UNIFORM_BUFFERS_PER_STAGE; i += 1) { + if (d3d11CommandBuffer->vertexUniformBuffers[i] != NULL) { + ID3D11DeviceContext_Unmap( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11CommandBuffer->vertexUniformBuffers[i]->buffer, + 0); + } + + if (d3d11CommandBuffer->fragmentUniformBuffers[i] != NULL) { + ID3D11DeviceContext_Unmap( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11CommandBuffer->fragmentUniformBuffers[i]->buffer, + 0); + } + + if (d3d11CommandBuffer->computeUniformBuffers[i] != NULL) { + ID3D11DeviceContext_Unmap( + d3d11CommandBuffer->context, + (ID3D11Resource *)d3d11CommandBuffer->computeUniformBuffers[i]->buffer, + 0); + } + } + + SDL_LockMutex(renderer->contextLock); + + // Notify the command buffer completion query that we have completed recording + ID3D11DeviceContext_End( + renderer->immediateContext, + (ID3D11Asynchronous *)d3d11CommandBuffer->fence->handle); + + // Serialize the commands into the command list + res = ID3D11DeviceContext_FinishCommandList( + d3d11CommandBuffer->context, + 0, + &commandList); + if (FAILED(res)) { + SDL_UnlockMutex(renderer->contextLock); + CHECK_D3D11_ERROR_AND_RETURN("Could not finish command list recording!", false) + } + + // Submit the command list to the immediate context + ID3D11DeviceContext_ExecuteCommandList( + renderer->immediateContext, + commandList, + 0); + ID3D11CommandList_Release(commandList); + + // Mark the command buffer as submitted + if (renderer->submittedCommandBufferCount >= renderer->submittedCommandBufferCapacity) { + renderer->submittedCommandBufferCapacity = renderer->submittedCommandBufferCount + 1; + + renderer->submittedCommandBuffers = SDL_realloc( + renderer->submittedCommandBuffers, + sizeof(D3D11CommandBuffer *) * renderer->submittedCommandBufferCapacity); + } + + renderer->submittedCommandBuffers[renderer->submittedCommandBufferCount] = d3d11CommandBuffer; + renderer->submittedCommandBufferCount += 1; + + bool result = true; + + // Present, if applicable + for (Uint32 i = 0; i < d3d11CommandBuffer->windowDataCount; i += 1) { + D3D11WindowData *windowData = d3d11CommandBuffer->windowDatas[i]; + + Uint32 syncInterval = 1; + if (windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE || + (renderer->supportsFlipDiscard && windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX)) { + syncInterval = 0; + } + + Uint32 presentFlags = 0; + if (renderer->supportsTearing && + windowData->presentMode == SDL_GPU_PRESENTMODE_IMMEDIATE) { + presentFlags = DXGI_PRESENT_ALLOW_TEARING; + } + + res = IDXGISwapChain_Present( + windowData->swapchain, + syncInterval, + presentFlags); + + if (FAILED(res)) { + result = false; + } + + ID3D11Texture2D_Release(windowData->texture.handle); + + windowData->inFlightFences[windowData->frameCounter] = (SDL_GPUFence*)d3d11CommandBuffer->fence; + + (void)SDL_AtomicIncRef(&d3d11CommandBuffer->fence->referenceCount); + + windowData->frameCounter = (windowData->frameCounter + 1) % MAX_FRAMES_IN_FLIGHT; + } + + // Check if we can perform any cleanups + for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) { + BOOL queryData; + res = ID3D11DeviceContext_GetData( + renderer->immediateContext, + (ID3D11Asynchronous *)renderer->submittedCommandBuffers[i]->fence->handle, + &queryData, + sizeof(queryData), + 0); + if (res == S_OK) { + result &= D3D11_INTERNAL_CleanCommandBuffer( + renderer, + renderer->submittedCommandBuffers[i]); + } + } + + D3D11_INTERNAL_PerformPendingDestroys(renderer); + + SDL_UnlockMutex(renderer->contextLock); + + return result; +} + +static SDL_GPUFence *D3D11_SubmitAndAcquireFence( + SDL_GPUCommandBuffer *commandBuffer) +{ + D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer; + D3D11Fence *fence = d3d11CommandBuffer->fence; + + d3d11CommandBuffer->autoReleaseFence = 0; + D3D11_Submit(commandBuffer); + + return (SDL_GPUFence *)fence; +} + +static bool D3D11_Wait( + SDL_GPURenderer *driverData) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11CommandBuffer *commandBuffer; + bool result = true; + + /* + * Wait for all submitted command buffers to complete. + * Sort of equivalent to vkDeviceWaitIdle. + */ + for (Uint32 i = 0; i < renderer->submittedCommandBufferCount; i += 1) { + D3D11_INTERNAL_WaitForFence( + renderer, + renderer->submittedCommandBuffers[i]->fence); + } + + SDL_LockMutex(renderer->contextLock); // This effectively acts as a lock around submittedCommandBuffers + + for (Sint32 i = renderer->submittedCommandBufferCount - 1; i >= 0; i -= 1) { + commandBuffer = renderer->submittedCommandBuffers[i]; + result &= D3D11_INTERNAL_CleanCommandBuffer(renderer, commandBuffer); + } + + D3D11_INTERNAL_PerformPendingDestroys(renderer); + + SDL_UnlockMutex(renderer->contextLock); + + return result; +} + +// Format Info + +static bool D3D11_SupportsTextureFormat( + SDL_GPURenderer *driverData, + SDL_GPUTextureFormat format, + SDL_GPUTextureType type, + SDL_GPUTextureUsageFlags usage) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + DXGI_FORMAT dxgiFormat = SDLToD3D11_TextureFormat[format]; + DXGI_FORMAT typelessFormat = D3D11_INTERNAL_GetTypelessFormat(dxgiFormat); + UINT formatSupport, sampleableFormatSupport; + D3D11_FEATURE_DATA_FORMAT_SUPPORT2 formatSupport2 = { dxgiFormat, 0 }; + HRESULT res; + + res = ID3D11Device_CheckFormatSupport( + renderer->device, + dxgiFormat, + &formatSupport); + if (FAILED(res)) { + // Format is apparently unknown + return false; + } + + /* Depth textures are stored as typeless textures, but interpreted as color textures for sampling. + * In order to get supported usages for both interpretations, we have to do this. + */ + if (typelessFormat != DXGI_FORMAT_UNKNOWN) { + res = ID3D11Device_CheckFormatSupport( + renderer->device, + D3D11_INTERNAL_GetSampleableFormat(typelessFormat), + &sampleableFormatSupport); + if (SUCCEEDED(res)) { + formatSupport |= sampleableFormatSupport; + } + } + + // Checks for SIMULTANEOUS_READ_WRITE support + if (usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) { + res = ID3D11Device_CheckFeatureSupport( + renderer->device, + D3D11_FEATURE_FORMAT_SUPPORT2, + &formatSupport2, + sizeof(formatSupport2)); + if (FAILED(res)) { + // Format is apparently unknown + return false; + } + } + + // Is the texture type supported? + if (type == SDL_GPU_TEXTURETYPE_2D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) { + return false; + } + if (type == SDL_GPU_TEXTURETYPE_2D_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)) { + return false; + } + if (type == SDL_GPU_TEXTURETYPE_3D && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D)) { + return false; + } + if (type == SDL_GPU_TEXTURETYPE_CUBE && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) { + return false; + } + if (type == SDL_GPU_TEXTURETYPE_CUBE_ARRAY && !(formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE)) { + return false; + } + + // Are the usage flags supported? + if ((usage & SDL_GPU_TEXTUREUSAGE_SAMPLER) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) { + return false; + } + if ((usage & (SDL_GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ)) && !(formatSupport & D3D11_FORMAT_SUPPORT_SHADER_LOAD)) { + return false; + } + if ((usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE) && !(formatSupport & D3D11_FORMAT_SUPPORT_TYPED_UNORDERED_ACCESS_VIEW))) { + // TYPED_UNORDERED_ACCESS_VIEW implies support for typed UAV stores + return false; + } + #define D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD 0x40 /* for old toolchains */ + if ((usage & (SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE) && !(formatSupport2.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD))) { + return false; + } + if ((usage & SDL_GPU_TEXTUREUSAGE_COLOR_TARGET) && !(formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) { + return false; + } + if ((usage & SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET) && !(formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)) { + return false; + } + + return true; +} + +// Device Creation + +static bool D3D11_PrepareDriver(SDL_VideoDevice *this) +{ + SDL_SharedObject *d3d11_dll; + SDL_SharedObject *dxgi_dll; + PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; + D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; + PFN_CREATE_DXGI_FACTORY1 CreateDxgiFactoryFunc; + HRESULT res; + + // Can we load D3D11? + + d3d11_dll = SDL_LoadObject(D3D11_DLL); + if (d3d11_dll == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " D3D11_DLL); + return false; + } + + D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction( + d3d11_dll, + D3D11_CREATE_DEVICE_FUNC); + if (D3D11CreateDeviceFunc == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " D3D11_CREATE_DEVICE_FUNC " in " D3D11_DLL); + SDL_UnloadObject(d3d11_dll); + return false; + } + + // Can we create a device? + + res = D3D11CreateDeviceFunc( + NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, + levels, + SDL_arraysize(levels), + D3D11_SDK_VERSION, + NULL, + NULL, + NULL); + + SDL_UnloadObject(d3d11_dll); + + if (FAILED(res)) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not create D3D11Device with feature level 11_1"); + return false; + } + + // Can we load DXGI? + + dxgi_dll = SDL_LoadObject(DXGI_DLL); + if (dxgi_dll == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find " DXGI_DLL); + return false; + } + + CreateDxgiFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction( + dxgi_dll, + CREATE_DXGI_FACTORY1_FUNC); + SDL_UnloadObject(dxgi_dll); // We're not going to call this function, so we can just unload now. + if (CreateDxgiFactoryFunc == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "D3D11: Could not find function " CREATE_DXGI_FACTORY1_FUNC " in " DXGI_DLL); + return false; + } + + return true; +} + +static void D3D11_INTERNAL_TryInitializeDXGIDebug(D3D11Renderer *renderer) +{ + PFN_DXGI_GET_DEBUG_INTERFACE DXGIGetDebugInterfaceFunc; + HRESULT res; + + renderer->dxgidebug_dll = SDL_LoadObject(DXGIDEBUG_DLL); + if (renderer->dxgidebug_dll == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not find " DXGIDEBUG_DLL); + return; + } + + DXGIGetDebugInterfaceFunc = (PFN_DXGI_GET_DEBUG_INTERFACE)SDL_LoadFunction( + renderer->dxgidebug_dll, + DXGI_GET_DEBUG_INTERFACE_FUNC); + if (DXGIGetDebugInterfaceFunc == NULL) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not load function: " DXGI_GET_DEBUG_INTERFACE_FUNC); + return; + } + + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIDebug, (void **)&renderer->dxgiDebug); + if (FAILED(res)) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIDebug interface"); + } + +#ifdef HAVE_IDXGIINFOQUEUE + res = DXGIGetDebugInterfaceFunc(&D3D_IID_IDXGIInfoQueue, (void **)&renderer->dxgiInfoQueue); + if (FAILED(res)) { + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Could not get IDXGIInfoQueue interface"); + } +#endif +} + +static void D3D11_INTERNAL_InitBlitPipelines( + D3D11Renderer *renderer) +{ + SDL_GPUShaderCreateInfo shaderCreateInfo; + SDL_GPUShader *fullscreenVertexShader; + SDL_GPUShader *blitFrom2DPixelShader; + SDL_GPUShader *blitFrom2DArrayPixelShader; + SDL_GPUShader *blitFrom3DPixelShader; + SDL_GPUShader *blitFromCubePixelShader; + SDL_GPUShader *blitFromCubeArrayPixelShader; + SDL_GPUGraphicsPipelineCreateInfo blitPipelineCreateInfo; + SDL_GPUGraphicsPipeline *blitPipeline; + SDL_GPUSamplerCreateInfo samplerCreateInfo; + SDL_GPUColorTargetDescription colorTargetDesc; + + // Fullscreen vertex shader + SDL_zero(shaderCreateInfo); + shaderCreateInfo.code = (Uint8 *)D3D11_FullscreenVert; + shaderCreateInfo.code_size = sizeof(D3D11_FullscreenVert); + shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_VERTEX; + shaderCreateInfo.format = SDL_GPU_SHADERFORMAT_DXBC; + shaderCreateInfo.entrypoint = "main"; + + fullscreenVertexShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (fullscreenVertexShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile vertex shader for blit!"); + } + + // BlitFrom2D pixel shader + shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2D; + shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom2D); + shaderCreateInfo.stage = SDL_GPU_SHADERSTAGE_FRAGMENT; + shaderCreateInfo.num_samplers = 1; + shaderCreateInfo.num_uniform_buffers = 1; + + blitFrom2DPixelShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (blitFrom2DPixelShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2D pixel shader!"); + } + + // BlitFrom2DArray pixel shader + shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom2DArray; + shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom2DArray); + + blitFrom2DArrayPixelShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (blitFrom2DArrayPixelShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom2DArray pixel shader!"); + } + + // BlitFrom3D pixel shader + shaderCreateInfo.code = (Uint8 *)D3D11_BlitFrom3D; + shaderCreateInfo.code_size = sizeof(D3D11_BlitFrom3D); + + blitFrom3DPixelShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (blitFrom3DPixelShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFrom3D pixel shader!"); + } + + // BlitFromCube pixel shader + shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCube; + shaderCreateInfo.code_size = sizeof(D3D11_BlitFromCube); + + blitFromCubePixelShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (blitFromCubePixelShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCube pixel shader!"); + } + + // BlitFromCubeArray pixel shader + shaderCreateInfo.code = (Uint8 *)D3D11_BlitFromCubeArray; + shaderCreateInfo.code_size = sizeof(D3D11_BlitFromCubeArray); + + blitFromCubeArrayPixelShader = D3D11_CreateShader( + (SDL_GPURenderer *)renderer, + &shaderCreateInfo); + + if (blitFromCubeArrayPixelShader == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to compile BlitFromCubeArray pixel shader!"); + } + + // BlitFrom2D pipeline + SDL_zero(blitPipelineCreateInfo); + + SDL_zero(colorTargetDesc); + colorTargetDesc.blend_state.color_write_mask = 0xF; + colorTargetDesc.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; // format doesn't matter in d3d11 + + blitPipelineCreateInfo.target_info.color_target_descriptions = &colorTargetDesc; + blitPipelineCreateInfo.target_info.num_color_targets = 1; + blitPipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM; // arbitrary + blitPipelineCreateInfo.target_info.has_depth_stencil_target = false; + + blitPipelineCreateInfo.vertex_shader = fullscreenVertexShader; + blitPipelineCreateInfo.fragment_shader = blitFrom2DPixelShader; + + blitPipelineCreateInfo.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1; + blitPipelineCreateInfo.multisample_state.enable_mask = false; + + blitPipelineCreateInfo.primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST; + + blitPipeline = D3D11_CreateGraphicsPipeline( + (SDL_GPURenderer *)renderer, + &blitPipelineCreateInfo); + + if (blitPipeline == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2D pipeline!"); + } + + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].pipeline = blitPipeline; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].type = SDL_GPU_TEXTURETYPE_2D; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D].format = SDL_GPU_TEXTUREFORMAT_INVALID; + + // BlitFrom2DArrayPipeline + blitPipelineCreateInfo.fragment_shader = blitFrom2DArrayPixelShader; + blitPipeline = D3D11_CreateGraphicsPipeline( + (SDL_GPURenderer *)renderer, + &blitPipelineCreateInfo); + + if (blitPipeline == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom2DArray pipeline!"); + } + + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].pipeline = blitPipeline; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].type = SDL_GPU_TEXTURETYPE_2D_ARRAY; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_2D_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID; + + // BlitFrom3DPipeline + blitPipelineCreateInfo.fragment_shader = blitFrom3DPixelShader; + blitPipeline = D3D11_CreateGraphicsPipeline( + (SDL_GPURenderer *)renderer, + &blitPipelineCreateInfo); + + if (blitPipeline == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFrom3D pipeline!"); + } + + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].pipeline = blitPipeline; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].type = SDL_GPU_TEXTURETYPE_3D; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_3D].format = SDL_GPU_TEXTUREFORMAT_INVALID; + + // BlitFromCubePipeline + blitPipelineCreateInfo.fragment_shader = blitFromCubePixelShader; + blitPipeline = D3D11_CreateGraphicsPipeline( + (SDL_GPURenderer *)renderer, + &blitPipelineCreateInfo); + + if (blitPipeline == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCube pipeline!"); + } + + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].pipeline = blitPipeline; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].type = SDL_GPU_TEXTURETYPE_CUBE; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE].format = SDL_GPU_TEXTUREFORMAT_INVALID; + + // BlitFromCubeArrayPipeline + blitPipelineCreateInfo.fragment_shader = blitFromCubeArrayPixelShader; + blitPipeline = D3D11_CreateGraphicsPipeline( + (SDL_GPURenderer *)renderer, + &blitPipelineCreateInfo); + + if (blitPipeline == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create BlitFromCubeArray pipeline!"); + } + + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].pipeline = blitPipeline; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].type = SDL_GPU_TEXTURETYPE_CUBE_ARRAY; + renderer->blitPipelines[SDL_GPU_TEXTURETYPE_CUBE_ARRAY].format = SDL_GPU_TEXTUREFORMAT_INVALID; + + // Create samplers + samplerCreateInfo.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samplerCreateInfo.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samplerCreateInfo.address_mode_w = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE; + samplerCreateInfo.enable_anisotropy = 0; + samplerCreateInfo.enable_compare = 0; + samplerCreateInfo.mag_filter = SDL_GPU_FILTER_NEAREST; + samplerCreateInfo.min_filter = SDL_GPU_FILTER_NEAREST; + samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_NEAREST; + samplerCreateInfo.mip_lod_bias = 0.0f; + samplerCreateInfo.min_lod = 0; + samplerCreateInfo.max_lod = 1000; + + renderer->blitNearestSampler = D3D11_CreateSampler( + (SDL_GPURenderer *)renderer, + &samplerCreateInfo); + + if (renderer->blitNearestSampler == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit nearest sampler!"); + } + + samplerCreateInfo.mag_filter = SDL_GPU_FILTER_LINEAR; + samplerCreateInfo.min_filter = SDL_GPU_FILTER_LINEAR; + samplerCreateInfo.mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR; + + renderer->blitLinearSampler = D3D11_CreateSampler( + (SDL_GPURenderer *)renderer, + &samplerCreateInfo); + + if (renderer->blitLinearSampler == NULL) { + SDL_LogError(SDL_LOG_CATEGORY_GPU, "Failed to create blit linear sampler!"); + } + + // Clean up + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, fullscreenVertexShader); + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom2DPixelShader); + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom2DArrayPixelShader); + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFrom3DPixelShader); + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubePixelShader); + D3D11_ReleaseShader((SDL_GPURenderer *)renderer, blitFromCubeArrayPixelShader); +} + +static void D3D11_INTERNAL_DestroyBlitPipelines( + SDL_GPURenderer *driverData) +{ + D3D11Renderer *renderer = (D3D11Renderer *)driverData; + D3D11_ReleaseSampler(driverData, renderer->blitLinearSampler); + D3D11_ReleaseSampler(driverData, renderer->blitNearestSampler); + for (int i = 0; i < SDL_arraysize(renderer->blitPipelines); i += 1) { + D3D11_ReleaseGraphicsPipeline(driverData, renderer->blitPipelines[i].pipeline); + } +} + +static SDL_GPUDevice *D3D11_CreateDevice(bool debugMode, bool preferLowPower, SDL_PropertiesID props) +{ + D3D11Renderer *renderer; + PFN_CREATE_DXGI_FACTORY1 CreateDxgiFactoryFunc; + PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc; + D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_1 }; + IDXGIFactory4 *factory4; + IDXGIFactory5 *factory5; + IDXGIFactory6 *factory6; + Uint32 flags; + DXGI_ADAPTER_DESC1 adapterDesc; + HRESULT res; + SDL_GPUDevice *result; + + // Allocate and zero out the renderer + renderer = (D3D11Renderer *)SDL_calloc(1, sizeof(D3D11Renderer)); + + // Load the DXGI library + renderer->dxgi_dll = SDL_LoadObject(DXGI_DLL); + if (renderer->dxgi_dll == NULL) { + SET_STRING_ERROR_AND_RETURN("Could not find " DXGI_DLL, NULL) + } + + // Load the CreateDXGIFactory1 function + CreateDxgiFactoryFunc = (PFN_CREATE_DXGI_FACTORY1)SDL_LoadFunction( + renderer->dxgi_dll, + CREATE_DXGI_FACTORY1_FUNC); + if (CreateDxgiFactoryFunc == NULL) { + SET_STRING_ERROR_AND_RETURN("Could not load function: " CREATE_DXGI_FACTORY1_FUNC, NULL) + } + + // Create the DXGI factory + res = CreateDxgiFactoryFunc( + &D3D_IID_IDXGIFactory1, + (void **)&renderer->factory); + CHECK_D3D11_ERROR_AND_RETURN("Could not create DXGIFactory", NULL); + + // Check for flip-model discard support (supported on Windows 10+) + res = IDXGIFactory1_QueryInterface( + renderer->factory, + &D3D_IID_IDXGIFactory4, + (void **)&factory4); + if (SUCCEEDED(res)) { + renderer->supportsFlipDiscard = 1; + IDXGIFactory4_Release(factory4); + } + + // Check for explicit tearing support + res = IDXGIFactory1_QueryInterface( + renderer->factory, + &D3D_IID_IDXGIFactory5, + (void **)&factory5); + if (SUCCEEDED(res)) { + res = IDXGIFactory5_CheckFeatureSupport( + factory5, + DXGI_FEATURE_PRESENT_ALLOW_TEARING, + &renderer->supportsTearing, + sizeof(renderer->supportsTearing)); + if (FAILED(res)) { + renderer->supportsTearing = FALSE; + } + IDXGIFactory5_Release(factory5); + } + + // Select the appropriate device for rendering + res = IDXGIAdapter1_QueryInterface( + renderer->factory, + &D3D_IID_IDXGIFactory6, + (void **)&factory6); + if (SUCCEEDED(res)) { + IDXGIFactory6_EnumAdapterByGpuPreference( + factory6, + 0, + preferLowPower ? DXGI_GPU_PREFERENCE_MINIMUM_POWER : DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE, + &D3D_IID_IDXGIAdapter1, + (void **)&renderer->adapter); + IDXGIFactory6_Release(factory6); + } else { + IDXGIFactory1_EnumAdapters1( + renderer->factory, + 0, + &renderer->adapter); + } + + // Get information about the selected adapter. Used for logging info. + IDXGIAdapter1_GetDesc1(renderer->adapter, &adapterDesc); + + // Initialize the DXGI debug layer, if applicable + if (debugMode) { + D3D11_INTERNAL_TryInitializeDXGIDebug(renderer); + } + + // Load the D3D library + renderer->d3d11_dll = SDL_LoadObject(D3D11_DLL); + if (renderer->d3d11_dll == NULL) { + SET_STRING_ERROR_AND_RETURN("Could not find " D3D11_DLL, NULL) + } + + // Load the CreateDevice function + D3D11CreateDeviceFunc = (PFN_D3D11_CREATE_DEVICE)SDL_LoadFunction( + renderer->d3d11_dll, + D3D11_CREATE_DEVICE_FUNC); + if (D3D11CreateDeviceFunc == NULL) { + SET_STRING_ERROR_AND_RETURN("Could not load function: " D3D11_CREATE_DEVICE_FUNC, NULL) + } + + // Set up device flags + flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; + if (debugMode) { + flags |= D3D11_CREATE_DEVICE_DEBUG; + } + + // Create the device + ID3D11Device *d3d11Device; +tryCreateDevice: + res = D3D11CreateDeviceFunc( + (IDXGIAdapter *)renderer->adapter, + D3D_DRIVER_TYPE_UNKNOWN, // Must be UNKNOWN if adapter is non-null according to spec + NULL, + flags, + levels, + SDL_arraysize(levels), + D3D11_SDK_VERSION, + &d3d11Device, + NULL, + &renderer->immediateContext); + if (FAILED(res) && debugMode) { + // If device creation failed, and we're in debug mode, remove the debug flag and try again. + SDL_LogWarn(SDL_LOG_CATEGORY_GPU, "Creating device in debug mode failed with error " HRESULT_FMT ". Trying non-debug.", res); + flags &= ~D3D11_CREATE_DEVICE_DEBUG; + debugMode = 0; + goto tryCreateDevice; + } + + CHECK_D3D11_ERROR_AND_RETURN("Could not create D3D11 device", NULL); + + // The actual device we want is the ID3D11Device1 interface... + res = ID3D11Device_QueryInterface( + d3d11Device, + &D3D_IID_ID3D11Device1, + (void **)&renderer->device); + CHECK_D3D11_ERROR_AND_RETURN("Could not get ID3D11Device1 interface", NULL); + + // Release the old device interface, we don't need it anymore + ID3D11Device_Release(d3d11Device); + +#ifdef HAVE_IDXGIINFOQUEUE + // Set up the info queue + if (renderer->dxgiInfoQueue) { + DXGI_INFO_QUEUE_MESSAGE_SEVERITY sevList[] = { + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING, + // DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO, // This can be a bit much, so toggle as needed for debugging. + DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE + }; + DXGI_INFO_QUEUE_FILTER filter = { 0 }; + filter.AllowList.NumSeverities = SDL_arraysize(sevList); + filter.AllowList.pSeverityList = sevList; + + IDXGIInfoQueue_PushStorageFilter( + renderer->dxgiInfoQueue, + D3D_IID_DXGI_DEBUG_ALL, + &filter); + } +#endif + + // Print driver info + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "SDL GPU Driver: D3D11"); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "D3D11 Adapter: %S", adapterDesc.Description); + + // Create mutexes + renderer->contextLock = SDL_CreateMutex(); + renderer->acquireCommandBufferLock = SDL_CreateMutex(); + renderer->acquireUniformBufferLock = SDL_CreateMutex(); + renderer->fenceLock = SDL_CreateMutex(); + renderer->windowLock = SDL_CreateMutex(); + + // Initialize miscellaneous renderer members + renderer->debugMode = (flags & D3D11_CREATE_DEVICE_DEBUG); + + // Create command buffer pool + D3D11_INTERNAL_AllocateCommandBuffers(renderer, 2); + + // Create fence pool + renderer->availableFenceCapacity = 2; + renderer->availableFences = SDL_malloc( + sizeof(D3D11Fence *) * renderer->availableFenceCapacity); + + // Create uniform buffer pool + + renderer->uniformBufferPoolCapacity = 32; + renderer->uniformBufferPoolCount = 32; + renderer->uniformBufferPool = SDL_malloc( + renderer->uniformBufferPoolCapacity * sizeof(D3D11UniformBuffer *)); + + for (Uint32 i = 0; i < renderer->uniformBufferPoolCount; i += 1) { + renderer->uniformBufferPool[i] = D3D11_INTERNAL_CreateUniformBuffer( + renderer, + UNIFORM_BUFFER_SIZE); + } + + // Create deferred destroy arrays + renderer->transferBufferContainersToDestroyCapacity = 2; + renderer->transferBufferContainersToDestroyCount = 0; + renderer->transferBufferContainersToDestroy = SDL_malloc( + renderer->transferBufferContainersToDestroyCapacity * sizeof(D3D11TransferBufferContainer *)); + + renderer->bufferContainersToDestroyCapacity = 2; + renderer->bufferContainersToDestroyCount = 0; + renderer->bufferContainersToDestroy = SDL_malloc( + renderer->bufferContainersToDestroyCapacity * sizeof(D3D11BufferContainer *)); + + renderer->textureContainersToDestroyCapacity = 2; + renderer->textureContainersToDestroyCount = 0; + renderer->textureContainersToDestroy = SDL_malloc( + renderer->textureContainersToDestroyCapacity * sizeof(D3D11TextureContainer *)); + + // Create claimed window list + renderer->claimedWindowCapacity = 1; + renderer->claimedWindows = SDL_malloc( + sizeof(D3D11WindowData *) * renderer->claimedWindowCapacity); + + // Initialize null states + + SDL_zeroa(renderer->nullRTVs); + SDL_zeroa(renderer->nullSRVs); + SDL_zeroa(renderer->nullSamplers); + SDL_zeroa(renderer->nullUAVs); + + // Initialize built-in pipelines + D3D11_INTERNAL_InitBlitPipelines(renderer); + + // Create the SDL_GPU Device + result = (SDL_GPUDevice *)SDL_malloc(sizeof(SDL_GPUDevice)); + ASSIGN_DRIVER(D3D11) + result->driverData = (SDL_GPURenderer *)renderer; + + return result; +} + +SDL_GPUBootstrap D3D11Driver = { + "direct3d11", + SDL_GPU_SHADERFORMAT_DXBC, + D3D11_PrepareDriver, + D3D11_CreateDevice +}; + +#endif // SDL_GPU_D3D11 diff --git a/libs/SDL3/src/gpu/d3d11/compile_shaders.bat b/libs/SDL3/src/gpu/d3d11/compile_shaders.bat new file mode 100644 index 000000000..56eadcc25 --- /dev/null +++ b/libs/SDL3/src/gpu/d3d11/compile_shaders.bat @@ -0,0 +1,8 @@ +fxc /T vs_5_0 /E FullscreenVert /Fh D3D11_FullscreenVert.h ..\d3dcommon\D3D_Blit.hlsl +fxc /T ps_5_0 /E BlitFrom2D /Fh D3D11_BlitFrom2D.h ..\d3dcommon\D3D_Blit.hlsl +fxc /T ps_5_0 /E BlitFrom2DArray /Fh D3D11_BlitFrom2DArray.h ..\d3dcommon\D3D_Blit.hlsl +fxc /T ps_5_0 /E BlitFrom3D /Fh D3D11_BlitFrom3D.h ..\d3dcommon\D3D_Blit.hlsl +fxc /T ps_5_0 /E BlitFromCube /Fh D3D11_BlitFromCube.h ..\d3dcommon\D3D_Blit.hlsl +fxc /T ps_5_0 /E BlitFromCubeArray /Fh D3D11_BlitFromCubeArray.h ..\d3dcommon\D3D_Blit.hlsl +copy /b D3D11_FullscreenVert.h+D3D11_BlitFrom2D.h+D3D11_BlitFrom2DArray.h+D3D11_BlitFrom3D.h+D3D11_BlitFromCube.h+D3D11_BlitFromCubeArray.h D3D11_Blit.h +del D3D11_FullscreenVert.h D3D11_BlitFrom2D.h D3D11_BlitFrom2DArray.h D3D11_BlitFrom3D.h D3D11_BlitFromCube.h D3D11_BlitFromCubeArray.h diff --git a/libs/SDL3/src/gpu/d3d12/D3D12_Blit.h b/libs/SDL3/src/gpu/d3d12/D3D12_Blit.h new file mode 100644 index 000000000..d8cfbaf6c --- /dev/null +++ b/libs/SDL3/src/gpu/d3d12/D3D12_Blit.h @@ -0,0 +1,3349 @@ +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_VertexID 0 x 0 VERTID uint x +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; TEXCOORD 0 xy 0 NONE float xy +; SV_Position 0 xyzw 1 POS float xyzw +; +; shader hash: 347572259f9a9ea84d2f90bafbd0e1ae +; +; Pipeline Runtime Information: +; +; Vertex Shader +; OutputPositionPresent=1 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_VertexID 0 +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; TEXCOORD 0 linear +; SV_Position 0 noperspective +; +; Buffer Definitions: +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; +; +; ViewId state: +; +; Number of inputs: 1, outputs: 8 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0 } +; output 1 depends on inputs: { 0 } +; output 4 depends on inputs: { 0 } +; output 5 depends on inputs: { 0 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +define void @FullscreenVert() { + %1 = call i32 @dx.op.loadInput.i32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %2 = shl i32 %1, 1 + %3 = and i32 %2, 2 + %4 = uitofp i32 %3 to float + %5 = and i32 %1, 2 + %6 = uitofp i32 %5 to float + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %4) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %6) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + %7 = fmul fast float %4, 2.000000e+00 + %8 = fmul fast float %6, 2.000000e+00 + %9 = fadd fast float %7, -1.000000e+00 + %10 = fsub fast float 1.000000e+00, %8 + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 0, float %9) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 1, float %10) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 2, float 0.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 1, i32 0, i8 3, float 1.000000e+00) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare i32 @dx.op.loadInput.i32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.viewIdState = !{!4} +!dx.entryPoints = !{!5} + +!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 6} +!3 = !{!"vs", i32 6, i32 0} +!4 = !{[3 x i32] [i32 1, i32 8, i32 51]} +!5 = !{void ()* @FullscreenVert, !"FullscreenVert", !6, null, null} +!6 = !{!7, !11, null} +!7 = !{!8} +!8 = !{i32 0, !"SV_VertexID", i8 5, i8 1, !9, i8 0, i32 1, i8 1, i32 0, i8 0, !10} +!9 = !{i32 0} +!10 = !{i32 3, i32 1} +!11 = !{!12, !14} +!12 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !9, i8 2, i32 1, i8 2, i32 0, i8 0, !13} +!13 = !{i32 3, i32 3} +!14 = !{i32 1, !"SV_Position", i8 9, i8 3, !9, i8 4, i32 1, i8 4, i32 1, i8 0, !15} +!15 = !{i32 3, i32 15} + +#endif + +const unsigned char g_FullscreenVert[] = { + 0x44, 0x58, 0x42, 0x43, 0x81, 0xc4, 0x09, 0xbf, 0x6d, 0xef, 0xac, 0x67, + 0x8f, 0x1d, 0x64, 0xb4, 0xf2, 0x1e, 0x4b, 0xca, 0x01, 0x00, 0x00, 0x00, + 0x4d, 0x0d, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, + 0x8d, 0x01, 0x00, 0x00, 0x1d, 0x02, 0x00, 0x00, 0xa9, 0x07, 0x00, 0x00, + 0xc5, 0x07, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, + 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x56, + 0x65, 0x72, 0x74, 0x65, 0x78, 0x49, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x31, + 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, + 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x00, 0x50, 0x53, 0x56, 0x30, 0x94, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, + 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, + 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x33, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x52, 0x54, 0x53, 0x30, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x53, 0x54, 0x41, 0x54, 0x84, 0x05, 0x00, 0x00, 0x60, 0x00, 0x01, + 0x00, 0x61, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x6c, 0x05, 0x00, 0x00, 0x42, 0x43, 0xc0, + 0xde, 0x21, 0x0c, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, + 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, + 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, + 0x02, 0x42, 0x92, 0x0b, 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, + 0x4b, 0x0a, 0x32, 0x42, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, + 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, + 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, + 0x06, 0x51, 0x18, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, + 0xff, 0xff, 0xff, 0x03, 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, + 0x00, 0x89, 0x20, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, + 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, + 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, + 0x4c, 0x10, 0x3c, 0x23, 0x00, 0x25, 0x00, 0x8a, 0x39, 0x02, 0x30, 0x98, + 0x23, 0x40, 0x8a, 0x31, 0x33, 0x43, 0x43, 0x35, 0x03, 0x50, 0x0c, 0x98, + 0x19, 0x3a, 0xc2, 0x81, 0x80, 0x61, 0x04, 0xe1, 0x18, 0x46, 0x20, 0x8e, + 0xa3, 0xa4, 0x29, 0xa2, 0x84, 0xc9, 0x7f, 0x89, 0x68, 0x22, 0xae, 0xd6, + 0x49, 0x91, 0x8b, 0x58, 0x90, 0xb0, 0x9c, 0x03, 0x03, 0x13, 0x14, 0x72, + 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, + 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, + 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, + 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, + 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, + 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, + 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, + 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x05, 0x10, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0e, 0x00, 0x00, + 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, + 0x47, 0xc6, 0x04, 0x43, 0x9a, 0x12, 0x18, 0x01, 0x28, 0x86, 0x02, 0x2a, + 0x83, 0x42, 0x28, 0x87, 0x92, 0x28, 0x90, 0xf2, 0x28, 0x97, 0xc2, 0x20, + 0x2a, 0x85, 0x12, 0x18, 0x01, 0x28, 0x89, 0x22, 0x28, 0x83, 0x42, 0xa0, + 0x9e, 0x01, 0x20, 0x1f, 0x6b, 0x08, 0x90, 0x39, 0x00, 0x79, 0x18, 0x00, + 0x00, 0x84, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, + 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, + 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, + 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, + 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, + 0x84, 0x61, 0x98, 0x20, 0x0c, 0xc4, 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, + 0x41, 0xc1, 0x6e, 0x6e, 0x82, 0x30, 0x14, 0x1b, 0x86, 0x03, 0x21, 0x26, + 0x08, 0x8d, 0x35, 0x41, 0x18, 0x0c, 0x0e, 0x74, 0x65, 0x78, 0x13, 0x84, + 0xe1, 0x98, 0x20, 0x0c, 0x08, 0x13, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, + 0x29, 0x22, 0x98, 0x09, 0xc2, 0x90, 0x4c, 0x10, 0x06, 0x65, 0x03, 0x82, + 0x30, 0x0d, 0xe1, 0x3c, 0x50, 0xc4, 0x01, 0xee, 0x6d, 0x6e, 0x82, 0x30, + 0x2c, 0x5c, 0xa6, 0xac, 0xbe, 0xa0, 0x9e, 0xa6, 0x92, 0xa8, 0x92, 0x9e, + 0x9c, 0x36, 0x20, 0xc8, 0xd4, 0x50, 0x4e, 0x05, 0x45, 0x1b, 0x86, 0x45, + 0xb2, 0x36, 0x0c, 0x84, 0x72, 0x4d, 0x10, 0x04, 0x60, 0x03, 0xb0, 0x61, + 0x20, 0x34, 0x6d, 0x43, 0xb0, 0x6d, 0x18, 0x86, 0x8c, 0x9b, 0x20, 0x38, + 0xd7, 0x86, 0xc0, 0xa3, 0x63, 0x54, 0xc7, 0xc6, 0x36, 0x37, 0x26, 0x57, + 0x56, 0xe6, 0x66, 0x55, 0x26, 0x47, 0xc7, 0x65, 0xca, 0xea, 0xcb, 0xaa, + 0x4c, 0x8e, 0xae, 0x0c, 0x2f, 0x89, 0x68, 0x82, 0x40, 0x3c, 0x13, 0x04, + 0x02, 0xda, 0x10, 0x10, 0x13, 0x04, 0x22, 0xda, 0x20, 0x34, 0xc3, 0x86, + 0x85, 0x08, 0x03, 0x31, 0x18, 0x03, 0x32, 0x28, 0x83, 0x61, 0x0c, 0x88, + 0x32, 0x30, 0x83, 0x0d, 0xc1, 0x19, 0x10, 0xa1, 0x2a, 0xc2, 0x1a, 0x7a, + 0x7a, 0x92, 0x22, 0x9a, 0x20, 0x10, 0xd2, 0x04, 0x81, 0x98, 0x36, 0x08, + 0x4d, 0xb3, 0x61, 0x21, 0xd2, 0x40, 0x0d, 0xca, 0x80, 0x0c, 0xd6, 0x60, + 0x58, 0x03, 0xa2, 0x0c, 0xd8, 0x80, 0xcb, 0x94, 0xd5, 0x17, 0xd4, 0xdb, + 0x5c, 0x1a, 0x5d, 0xda, 0x9b, 0xdb, 0x04, 0x81, 0xa0, 0x26, 0x08, 0x44, + 0x35, 0x41, 0x18, 0x98, 0x0d, 0x42, 0x13, 0x07, 0x1b, 0x96, 0xc1, 0x0d, + 0xd4, 0xe0, 0x0d, 0xc8, 0x00, 0x0e, 0x06, 0x38, 0x18, 0xca, 0x40, 0x0e, + 0x36, 0x08, 0x6d, 0x30, 0x07, 0x1b, 0x06, 0x34, 0xa0, 0x03, 0x60, 0x43, + 0x91, 0x81, 0x41, 0x1d, 0x00, 0x00, 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0xba, + 0x39, 0x16, 0x69, 0x6e, 0x73, 0x74, 0x73, 0x13, 0x84, 0xa1, 0xa1, 0x31, + 0x97, 0x76, 0xf6, 0xc5, 0x46, 0x46, 0x63, 0x2e, 0xed, 0xec, 0x6b, 0x8e, + 0x6e, 0x82, 0x30, 0x38, 0x2c, 0xea, 0xd2, 0xdc, 0xe8, 0xe6, 0x36, 0x28, + 0x77, 0x80, 0xe0, 0x41, 0x1e, 0xe8, 0xc1, 0xb0, 0x07, 0x7c, 0xd0, 0x07, + 0x4d, 0x15, 0x36, 0x36, 0xbb, 0x36, 0x97, 0x34, 0xb2, 0x32, 0x37, 0xba, + 0x29, 0x41, 0x50, 0x85, 0x0c, 0xcf, 0xc5, 0xae, 0x4c, 0x6e, 0x2e, 0xed, + 0xcd, 0x6d, 0x4a, 0x40, 0x34, 0x21, 0xc3, 0x73, 0xb1, 0x0b, 0x63, 0xb3, + 0x2b, 0x93, 0x9b, 0x12, 0x14, 0x75, 0xc8, 0xf0, 0x5c, 0xe6, 0xd0, 0xc2, + 0xc8, 0xca, 0xe4, 0x9a, 0xde, 0xc8, 0xca, 0xd8, 0xa6, 0x04, 0x48, 0x25, + 0x32, 0x3c, 0x17, 0xba, 0x3c, 0xb8, 0xb2, 0x20, 0x37, 0xb7, 0x37, 0xba, + 0x30, 0xba, 0xb4, 0x37, 0xb7, 0xb9, 0x29, 0xc2, 0xc5, 0xd5, 0x21, 0xc3, + 0x73, 0xb1, 0x4b, 0x2b, 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, 0xa3, 0x2b, + 0x9b, 0x12, 0x78, 0x75, 0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, 0xe4, 0xf2, + 0xa0, 0xde, 0xd2, 0xdc, 0xe8, 0xe6, 0xa6, 0x04, 0x75, 0xd0, 0x85, 0x0c, + 0xcf, 0x65, 0xec, 0xad, 0xce, 0x8d, 0xae, 0x4c, 0x6e, 0x6e, 0x4a, 0xd0, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, + 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, + 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, + 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, + 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, + 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, + 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, + 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, + 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, + 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, + 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, + 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, + 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, + 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, + 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, + 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, + 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, + 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, + 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, + 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, + 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, + 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, + 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, + 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, + 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, + 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, + 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x06, 0xe0, 0x7c, 0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd, 0x4b, + 0x44, 0x93, 0x05, 0x4c, 0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, + 0x36, 0x0f, 0x35, 0xf9, 0xc8, 0x6d, 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, + 0xf8, 0xd2, 0xe4, 0x44, 0x04, 0x4a, 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x75, 0x72, 0x25, 0x9f, 0x9a, 0x9e, + 0xa8, 0x4d, 0x2f, 0x90, 0xba, 0xfb, 0xd0, 0xe1, 0xae, 0x44, 0x58, 0x49, + 0x4c, 0x80, 0x05, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x60, 0x01, 0x00, + 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x68, 0x05, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, + 0x00, 0x57, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, + 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, + 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x10, 0x45, 0x02, 0x42, 0x92, 0x0b, + 0x42, 0x84, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x42, + 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, + 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x22, 0xc4, 0x50, 0x41, 0x51, 0x81, + 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x21, 0x46, 0x06, 0x51, 0x18, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, + 0x20, 0x01, 0x00, 0x00, 0x00, 0x49, 0x18, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x32, 0x22, 0x08, 0x09, 0x20, 0x64, 0x85, + 0x04, 0x13, 0x22, 0xa4, 0x84, 0x04, 0x13, 0x22, 0xe3, 0x84, 0xa1, 0x90, + 0x14, 0x12, 0x4c, 0x88, 0x8c, 0x0b, 0x84, 0x84, 0x4c, 0x10, 0x30, 0x23, + 0x00, 0x25, 0x00, 0x8a, 0x39, 0x02, 0x30, 0x98, 0x23, 0x40, 0x8a, 0x31, + 0x33, 0x43, 0x43, 0x35, 0x03, 0x50, 0x0c, 0x98, 0x19, 0x3a, 0xc2, 0x81, + 0x80, 0x1c, 0x18, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, + 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, + 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, + 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, + 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, + 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, + 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, + 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, + 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, + 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, + 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, + 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, + 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x86, 0x3c, 0x05, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc8, 0x02, 0x01, 0x0b, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, + 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, + 0x9a, 0x12, 0x18, 0x01, 0x28, 0x86, 0x32, 0x28, 0x0f, 0xa2, 0x52, 0x28, + 0x81, 0x11, 0x80, 0x92, 0x28, 0x82, 0x32, 0x28, 0x04, 0xda, 0xb1, 0x86, + 0x00, 0x99, 0x03, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x51, 0x00, 0x00, + 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, + 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, + 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, + 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, + 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x84, 0x61, 0x98, 0x20, + 0x0c, 0xc4, 0x06, 0x61, 0x20, 0x26, 0x08, 0x43, 0xb1, 0x41, 0x18, 0x0c, + 0x0a, 0x76, 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0xcb, 0xb3, 0x21, + 0x50, 0x26, 0x08, 0x02, 0x40, 0xc7, 0xa8, 0x8e, 0x8d, 0x6d, 0x6e, 0x4c, + 0xae, 0xac, 0xcc, 0xcd, 0xaa, 0x4c, 0x8e, 0x8e, 0xcb, 0x94, 0xd5, 0x97, + 0x55, 0x99, 0x1c, 0x5d, 0x19, 0x5e, 0x12, 0xd1, 0x04, 0x81, 0x40, 0x26, + 0x08, 0x44, 0xb2, 0x21, 0x20, 0x26, 0x08, 0x84, 0x32, 0x41, 0x18, 0x8c, + 0x0d, 0xc2, 0x34, 0x6c, 0x58, 0x08, 0xe7, 0x81, 0x22, 0x69, 0x80, 0x08, + 0x89, 0xda, 0x10, 0x54, 0x44, 0xa8, 0x8a, 0xb0, 0x86, 0x9e, 0x9e, 0xa4, + 0x88, 0x26, 0x08, 0xc4, 0x32, 0x41, 0x20, 0x98, 0x0d, 0xc2, 0x34, 0x6d, + 0x58, 0x88, 0x0b, 0x93, 0xa2, 0x6c, 0xc8, 0x08, 0x49, 0xe3, 0x32, 0x65, + 0xf5, 0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x20, + 0x9a, 0x09, 0x02, 0xe1, 0x4c, 0x10, 0x86, 0x63, 0x83, 0x30, 0x7d, 0x1b, + 0x96, 0x81, 0xc3, 0xba, 0xc8, 0x1b, 0xbc, 0x41, 0x02, 0x83, 0x0d, 0xc2, + 0x16, 0x06, 0x1b, 0x06, 0x4b, 0x0c, 0x80, 0x0d, 0x05, 0xd3, 0x8c, 0x01, + 0x00, 0x54, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, + 0x9b, 0x12, 0x04, 0x55, 0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, + 0xde, 0xdc, 0xa6, 0x04, 0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, 0x36, + 0xbb, 0x32, 0xb9, 0x29, 0x81, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, 0x2d, + 0x8c, 0xac, 0x4c, 0xae, 0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, 0xd4, + 0x21, 0xc3, 0x73, 0xb1, 0x4b, 0x2b, 0xbb, 0x4b, 0x22, 0x9b, 0xa2, 0x0b, + 0xa3, 0x2b, 0x9b, 0x12, 0x28, 0x75, 0xc8, 0xf0, 0x5c, 0xca, 0xdc, 0xe8, + 0xe4, 0xf2, 0xa0, 0xde, 0xd2, 0xdc, 0xe8, 0xe6, 0xa6, 0x04, 0x63, 0x00, + 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, + 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, + 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, + 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, + 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, + 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, + 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, + 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, + 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, + 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, + 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, + 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, + 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, + 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, + 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, + 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, + 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, + 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, + 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, + 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, + 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, + 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, + 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, + 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, + 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, + 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, + 0x00, 0x71, 0x20, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x06, 0xe0, 0x7c, + 0xd4, 0xb2, 0x48, 0x42, 0x44, 0x10, 0xcd, 0x4b, 0x44, 0x93, 0x05, 0x4c, + 0xc3, 0xe5, 0x3b, 0x8f, 0xbf, 0x38, 0xc0, 0x20, 0x36, 0x0f, 0x35, 0xf9, + 0xc8, 0x6d, 0x9b, 0x40, 0x35, 0x5c, 0xbe, 0xf3, 0xf8, 0xd2, 0xe4, 0x44, + 0x04, 0x4a, 0x4d, 0x0f, 0x35, 0xf9, 0xc5, 0x6d, 0x03, 0x61, 0x20, 0x00, + 0x00, 0x39, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x34, 0xa5, 0x50, 0x04, 0x85, 0x30, 0x03, + 0x40, 0x37, 0x02, 0x30, 0x46, 0x00, 0x82, 0x20, 0x08, 0x82, 0xc1, 0x18, + 0x01, 0x08, 0x82, 0x20, 0xfe, 0x8d, 0x11, 0x80, 0x20, 0x08, 0xe2, 0xbf, + 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x50, 0x5c, 0x06, 0x45, 0x39, + 0x45, 0x05, 0xd6, 0x55, 0x90, 0xe8, 0x05, 0x57, 0x45, 0x2c, 0x7a, 0xc1, + 0xd5, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x9c, 0xa3, 0x69, 0x94, + 0x32, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0xe7, 0x68, 0x5a, 0xa5, + 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xc2, 0x39, 0x9b, 0x46, 0x29, + 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0x70, 0xce, 0xa6, 0x55, 0xca, + 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x9c, 0xb3, 0x69, 0x92, 0x32, + 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0xe7, 0x6c, 0x5a, 0xa4, 0x8c, + 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0xc2, 0x39, 0x9a, 0x46, 0x0d, 0x23, + 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0x70, 0x8e, 0xa6, 0x55, 0x81, 0x0d, + 0x89, 0x7c, 0x4c, 0x50, 0xe4, 0x63, 0x42, 0x02, 0x1f, 0x5b, 0x84, 0xf8, + 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x02, 0x06, 0xd2, 0xe7, 0x61, + 0xc2, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x60, 0x20, 0x7d, 0x5e, + 0x16, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, 0x01, 0x02, 0x06, 0xd2, 0xe7, + 0x59, 0xce, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x60, 0x20, 0x7d, + 0x5e, 0xc5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; TEXCOORD 0 xy 0 NONE float xy +; SV_Position 0 xyzw 1 POS float +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: 964a7513a7ff5558ed84391b53971f63 +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; TEXCOORD 0 linear +; SV_Position 0 noperspective +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; cbuffer SourceRegionBuffer +; { +; +; struct SourceRegionBuffer +; { +; +; float2 UVLeftTop; ; Offset: 0 +; float2 UVDimensions; ; Offset: 8 +; uint MipLevel; ; Offset: 16 +; float LayerOrDepth; ; Offset: 20 +; +; } SourceRegionBuffer; ; Offset: 0 Size: 24 +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; SourceRegionBuffer cbuffer NA NA CB0 cb0,space3 1 +; SourceSampler sampler NA NA S0 s0,space2 1 +; SourceTexture2D texture f32 2d T0 t0,space2 1 +; +; +; ViewId state: +; +; Number of inputs: 8, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0, 1 } +; output 1 depends on inputs: { 0, 1 } +; output 2 depends on inputs: { 0, 1 } +; output 3 depends on inputs: { 0, 1 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.CBufRet.f32 = type { float, float, float, float } +%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 } +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } +%"class.Texture2D >" = type { <4 x float>, %"class.Texture2D >::mips_type" } +%"class.Texture2D >::mips_type" = type { i32 } +%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float } +%struct.SamplerState = type { i32 } + +define void @BlitFrom2D() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0) ; CBufferLoadLegacy(handle,regIndex) + %7 = extractvalue %dx.types.CBufRet.f32 %6, 0 + %8 = extractvalue %dx.types.CBufRet.f32 %6, 1 + %9 = extractvalue %dx.types.CBufRet.f32 %6, 2 + %10 = extractvalue %dx.types.CBufRet.f32 %6, 3 + %11 = fmul fast float %9, %4 + %12 = fmul fast float %10, %5 + %13 = fadd fast float %11, %7 + %14 = fadd fast float %12, %8 + %15 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %16 = extractvalue %dx.types.CBufRet.i32 %15, 0 + %17 = uitofp i32 %16 to float + %18 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float undef, float undef, i32 0, i32 0, i32 undef, float %17) ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD) + %19 = extractvalue %dx.types.ResRet.f32 %18, 0 + %20 = extractvalue %dx.types.ResRet.f32 %18, 1 + %21 = extractvalue %dx.types.ResRet.f32 %18, 2 + %22 = extractvalue %dx.types.ResRet.f32 %18, 3 + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %19) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %20) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %21) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %22) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +; Function Attrs: nounwind readonly +declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } +attributes #2 = { nounwind readonly } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.resources = !{!4} +!dx.viewIdState = !{!12} +!dx.entryPoints = !{!13} + +!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 6} +!3 = !{!"ps", i32 6, i32 0} +!4 = !{!5, null, !8, !10} +!5 = !{!6} +!6 = !{i32 0, %"class.Texture2D >"* undef, !"", i32 2, i32 0, i32 1, i32 2, i32 0, !7} +!7 = !{i32 0, i32 9} +!8 = !{!9} +!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null} +!10 = !{!11} +!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null} +!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]} +!13 = !{void ()* @BlitFrom2D, !"BlitFrom2D", !14, !4, null} +!14 = !{!15, !20, null} +!15 = !{!16, !19} +!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18} +!17 = !{i32 0} +!18 = !{i32 3, i32 3} +!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null} +!20 = !{!21} +!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22} +!22 = !{i32 3, i32 15} + +#endif + +const unsigned char g_BlitFrom2D[] = { + 0x44, 0x58, 0x42, 0x43, 0x18, 0x05, 0x35, 0x74, 0x86, 0x3d, 0x7b, 0xa8, + 0x8e, 0x1e, 0xae, 0xc3, 0xeb, 0x7f, 0x9a, 0xd9, 0x01, 0x00, 0x00, 0x00, + 0x2b, 0x12, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, + 0xe7, 0x01, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00, 0x5b, 0x0a, 0x00, 0x00, + 0x77, 0x0a, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, + 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, + 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x00, 0x4f, 0x53, 0x47, 0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, + 0x53, 0x56, 0x30, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x53, 0x30, 0x88, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xdc, + 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xf7, 0x01, 0x00, 0x00, 0x44, + 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc4, + 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xee, + 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, + 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, + 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, + 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, + 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, + 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, + 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, + 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, + 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, + 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, + 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, + 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, + 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, + 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, + 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, + 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, + 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, + 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, + 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, + 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, + 0xc5, 0x4a, 0x4c, 0x3e, 0x72, 0xdb, 0x88, 0x20, 0x08, 0x82, 0x28, 0xc4, + 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, + 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc5, 0x6d, 0x23, 0x62, 0x18, 0x86, + 0xa1, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, + 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, + 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, + 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x05, 0x3e, + 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, + 0x60, 0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, + 0x00, 0x03, 0x3f, 0xd0, 0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, + 0xf8, 0x05, 0x7a, 0xc8, 0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, + 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, + 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, 0xf0, + 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, + 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, + 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, + 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, + 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, + 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, + 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, + 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, + 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, + 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, + 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, + 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, + 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, + 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, + 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, + 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, + 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, + 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, + 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14, + 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c, + 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, + 0x8a, 0xa0, 0x24, 0xca, 0xa0, 0x60, 0xca, 0xa1, 0x20, 0x0a, 0xa4, 0x14, + 0x0a, 0xa5, 0x3c, 0xca, 0xa6, 0x10, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, + 0x28, 0x83, 0x42, 0x28, 0x10, 0xaa, 0x6a, 0x80, 0xb8, 0x19, 0x00, 0xf2, + 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14, + 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0xae, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, + 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, + 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, + 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, + 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, + 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36, + 0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03, + 0x21, 0x26, 0x08, 0x5c, 0xc7, 0x67, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c, + 0xaa, 0x0c, 0x8f, 0xae, 0x4e, 0xae, 0x4c, 0x86, 0x68, 0x82, 0x40, 0x28, + 0x13, 0x04, 0x62, 0xd9, 0x20, 0x10, 0xcd, 0x86, 0x84, 0x50, 0x16, 0x86, + 0x18, 0x18, 0xc2, 0xd9, 0x10, 0x3c, 0x13, 0x84, 0xef, 0xa3, 0x34, 0xf5, + 0x56, 0x27, 0x37, 0x56, 0x26, 0x55, 0x76, 0x96, 0xf6, 0xe6, 0x26, 0x54, + 0x67, 0x66, 0x56, 0x26, 0x37, 0x41, 0x20, 0x98, 0x09, 0x02, 0xd1, 0x6c, + 0x40, 0x88, 0x48, 0x9a, 0x88, 0x81, 0x02, 0x36, 0x04, 0xd5, 0x04, 0x21, + 0x0c, 0xc0, 0x80, 0xcd, 0xd4, 0x5b, 0x9d, 0xdc, 0x58, 0xd9, 0x54, 0x58, + 0x1b, 0x1c, 0x5b, 0x99, 0xdc, 0x06, 0x84, 0xb8, 0x30, 0x86, 0x18, 0x08, + 0x60, 0x43, 0x90, 0x6d, 0x20, 0x20, 0xc0, 0xd2, 0x26, 0x08, 0x9e, 0xc7, + 0xa4, 0xca, 0x8a, 0xa9, 0xcc, 0x8c, 0x8e, 0xea, 0x0d, 0x6e, 0x82, 0x40, + 0x38, 0x13, 0x84, 0x8a, 0xdb, 0x80, 0x20, 0xdd, 0x44, 0x78, 0x4d, 0xf3, + 0x91, 0xa9, 0xb2, 0x22, 0x4a, 0x6b, 0x2b, 0x73, 0x9b, 0x4b, 0x7b, 0x73, + 0x9b, 0x9b, 0x20, 0x10, 0xcf, 0x06, 0x04, 0x09, 0x83, 0x49, 0x0c, 0xbc, + 0xa6, 0xf9, 0x88, 0x34, 0xa5, 0xc1, 0x31, 0x95, 0xd9, 0x95, 0xb1, 0x4d, + 0x10, 0x08, 0x68, 0x82, 0x40, 0x44, 0x1b, 0x10, 0x84, 0x0c, 0xa6, 0x32, + 0xf0, 0xcc, 0xa0, 0xf9, 0xc8, 0x30, 0x85, 0xe5, 0x95, 0xc9, 0x3d, 0xc9, + 0x11, 0x95, 0xc1, 0xd1, 0xa1, 0x4d, 0x10, 0x08, 0x69, 0x83, 0x81, 0xa0, + 0xc1, 0x94, 0x06, 0x5e, 0xb3, 0xa1, 0xa0, 0xc0, 0x60, 0x0c, 0xce, 0x40, + 0x0d, 0x36, 0x0c, 0x04, 0xb7, 0x06, 0x13, 0x04, 0x01, 0xd8, 0x00, 0x6c, + 0x18, 0x08, 0x37, 0x70, 0x83, 0x0d, 0xc1, 0x1b, 0x6c, 0x18, 0x86, 0x36, + 0x80, 0x83, 0x09, 0x82, 0x18, 0x84, 0xc1, 0x86, 0x40, 0x0e, 0xa8, 0x08, + 0xb1, 0xa5, 0xd1, 0x19, 0xc9, 0xbd, 0xb5, 0xc9, 0x10, 0x11, 0xa1, 0x2a, + 0xc2, 0x1a, 0x7a, 0x7a, 0x92, 0x22, 0x9a, 0x20, 0x14, 0xd6, 0x04, 0xa1, + 0xb8, 0x36, 0x04, 0xc4, 0x04, 0xa1, 0xc0, 0x36, 0x08, 0xd3, 0xb4, 0x61, + 0x21, 0xea, 0xc0, 0x0e, 0xee, 0x00, 0x0f, 0xf2, 0x60, 0xc8, 0x03, 0xe2, + 0x0e, 0xf4, 0x80, 0xcb, 0x94, 0xd5, 0x17, 0xd4, 0xdb, 0x5c, 0x1a, 0x5d, + 0xda, 0x9b, 0xdb, 0x04, 0xa1, 0xc8, 0x26, 0x08, 0x85, 0xb6, 0x61, 0x19, + 0xf8, 0xc0, 0x0e, 0xfa, 0x00, 0x0f, 0xfc, 0x60, 0xf0, 0x83, 0xe1, 0x0e, + 0x80, 0x0d, 0xc2, 0x1e, 0xfc, 0x01, 0x93, 0x29, 0xab, 0x2f, 0xaa, 0x30, + 0xb9, 0xb3, 0x32, 0xba, 0x09, 0x42, 0xb1, 0x4d, 0x10, 0x88, 0x69, 0x83, + 0x30, 0x8d, 0xc2, 0x86, 0x85, 0x08, 0x05, 0x3b, 0x10, 0x05, 0x3c, 0xb8, + 0x83, 0xc1, 0x0f, 0x88, 0x3b, 0x20, 0x85, 0x0d, 0x41, 0x29, 0x6c, 0x18, + 0x40, 0xc1, 0x14, 0x80, 0x0d, 0x45, 0x1b, 0xd0, 0xc1, 0x29, 0x6c, 0x00, + 0x0d, 0x33, 0xb6, 0xb7, 0x30, 0xba, 0x39, 0x16, 0x69, 0x6e, 0x73, 0x74, + 0x73, 0x13, 0x04, 0x82, 0xa2, 0x31, 0x97, 0x76, 0xf6, 0xc5, 0x46, 0x46, + 0x63, 0x2e, 0xed, 0xec, 0x6b, 0x8e, 0x6e, 0x82, 0x40, 0x54, 0x44, 0xe8, + 0xca, 0xf0, 0xbe, 0xdc, 0xde, 0xe4, 0xda, 0x36, 0x28, 0xa9, 0x60, 0x06, + 0xaa, 0xb0, 0x0a, 0xac, 0xc0, 0xb4, 0x82, 0x2b, 0xbc, 0xc2, 0x50, 0x85, + 0x8d, 0xcd, 0xae, 0xcd, 0x25, 0x8d, 0xac, 0xcc, 0x8d, 0x6e, 0x4a, 0x10, + 0x54, 0x21, 0xc3, 0x73, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, + 0x12, 0x10, 0x4d, 0xc8, 0xf0, 0x5c, 0xec, 0xc2, 0xd8, 0xec, 0xca, 0xe4, + 0xa6, 0x04, 0x45, 0x1d, 0x32, 0x3c, 0x97, 0x39, 0xb4, 0x30, 0xb2, 0x32, + 0xb9, 0xa6, 0x37, 0xb2, 0x32, 0xb6, 0x29, 0x01, 0x52, 0x86, 0x0c, 0xcf, + 0x45, 0xae, 0x6c, 0xee, 0xad, 0x4e, 0x6e, 0xac, 0x6c, 0x6e, 0x4a, 0xa0, + 0x55, 0x22, 0xc3, 0x73, 0xa1, 0xcb, 0x83, 0x2b, 0x0b, 0x72, 0x73, 0x7b, + 0xa3, 0x0b, 0xa3, 0x4b, 0x7b, 0x73, 0x9b, 0x9b, 0x22, 0xac, 0x01, 0x1c, + 0xd4, 0x21, 0xc3, 0x73, 0xb1, 0x4b, 0x2b, 0xbb, 0x4b, 0x22, 0x9b, 0xa2, + 0x0b, 0xa3, 0x2b, 0x9b, 0x12, 0xc8, 0x41, 0x1d, 0x32, 0x3c, 0x97, 0x32, + 0x37, 0x3a, 0xb9, 0x3c, 0xa8, 0xb7, 0x34, 0x37, 0xba, 0xb9, 0x29, 0xc1, + 0x29, 0x74, 0x21, 0xc3, 0x73, 0x19, 0x7b, 0xab, 0x73, 0xa3, 0x2b, 0x93, + 0x9b, 0x9b, 0x12, 0xbc, 0x02, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, + 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, + 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, + 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, + 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, + 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, + 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, + 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, + 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, + 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, + 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, + 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, + 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, + 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, + 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, + 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, + 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, + 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, + 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, + 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, + 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, + 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, + 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, + 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, + 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, + 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xd8, + 0x9d, 0x15, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, + 0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x1b, + 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, + 0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48, + 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c, + 0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88, + 0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c, + 0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb, + 0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52, + 0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, + 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, + 0x4a, 0x75, 0x13, 0xa7, 0xff, 0x55, 0x58, 0xed, 0x84, 0x39, 0x1b, 0x53, + 0x97, 0x1f, 0x63, 0x44, 0x58, 0x49, 0x4c, 0xac, 0x07, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xeb, 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, + 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x94, 0x07, 0x00, 0x00, 0x42, + 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xe2, 0x01, 0x00, 0x00, 0x0b, + 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, + 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, + 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, + 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, + 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, + 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, + 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, + 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b, + 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, + 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, + 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x32, + 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04, + 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b, + 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66, + 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44, + 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1, + 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2, + 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13, + 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3, + 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3, + 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x3e, + 0x72, 0xdb, 0x88, 0x20, 0x08, 0x82, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41, + 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b, + 0x31, 0xf9, 0xc5, 0x6d, 0x23, 0x62, 0x18, 0x86, 0xa1, 0x10, 0x12, 0xc1, + 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2, + 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, 0x18, 0x07, 0x76, 0x08, + 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8, + 0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x05, 0x3e, 0xb0, 0x87, 0x72, 0x18, + 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, 0x60, 0x87, 0x77, 0x08, + 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, 0x00, 0x03, 0x3f, 0xd0, + 0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, 0xf8, 0x05, 0x7a, 0xc8, + 0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, 0xc1, 0x38, 0xb0, 0x43, + 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, 0x03, 0x3e, 0xd0, 0x43, + 0x3d, 0xc8, 0x43, 0x39, 0xc8, 0x01, 0x29, 0xf0, 0x81, 0x3d, 0x94, 0xc3, + 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, + 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, + 0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48, + 0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1, + 0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, + 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15, + 0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, + 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, + 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, + 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, + 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, + 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, + 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, + 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, + 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x32, + 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, + 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x24, 0xca, + 0xa0, 0x60, 0xca, 0x83, 0x8a, 0x92, 0x18, 0x01, 0x28, 0x82, 0x32, 0x28, + 0x84, 0x02, 0x21, 0x6e, 0x06, 0x80, 0xbe, 0x19, 0x00, 0x0a, 0x67, 0x00, + 0x48, 0x1c, 0x4b, 0x41, 0x88, 0xe7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x1a, + 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, + 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, + 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, + 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, + 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, + 0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x70, + 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x5c, 0x45, 0x60, 0x82, 0x40, + 0x28, 0x13, 0x04, 0x62, 0xd9, 0x20, 0x10, 0xcd, 0x86, 0x84, 0x50, 0x16, + 0x86, 0x18, 0x18, 0xc2, 0xd9, 0x10, 0x3c, 0x13, 0x84, 0xcf, 0x9a, 0x20, + 0x10, 0xcc, 0x04, 0x81, 0x68, 0x36, 0x20, 0x44, 0xb4, 0x48, 0xc4, 0x30, + 0x01, 0x1b, 0x02, 0x6a, 0x82, 0x10, 0x06, 0xd7, 0x06, 0x84, 0xb0, 0x16, + 0x86, 0x18, 0x08, 0x60, 0x43, 0x70, 0x6d, 0x20, 0x20, 0xa0, 0xc2, 0x26, + 0x08, 0x62, 0x80, 0x6d, 0x08, 0xb4, 0x09, 0x82, 0x00, 0x50, 0x11, 0x62, + 0x4b, 0xa3, 0x33, 0x92, 0x7b, 0x6b, 0x93, 0x21, 0x22, 0x42, 0x55, 0x84, + 0x35, 0xf4, 0xf4, 0x24, 0x45, 0x34, 0x41, 0x28, 0x9e, 0x09, 0x42, 0x01, + 0x6d, 0x08, 0x88, 0x09, 0x42, 0x11, 0x6d, 0x10, 0x24, 0x69, 0xc3, 0x42, + 0x78, 0x1f, 0x18, 0x84, 0x81, 0x18, 0x0c, 0x62, 0x40, 0x80, 0xc1, 0x18, + 0x70, 0x99, 0xb2, 0xfa, 0x82, 0x7a, 0x9b, 0x4b, 0xa3, 0x4b, 0x7b, 0x73, + 0x9b, 0x20, 0x14, 0xd2, 0x04, 0xa1, 0x98, 0x36, 0x2c, 0x43, 0x19, 0x7c, + 0x66, 0x10, 0x06, 0x67, 0x30, 0x9c, 0xc1, 0x00, 0x06, 0xc0, 0x06, 0x81, + 0x0c, 0xd0, 0x80, 0xc9, 0x94, 0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, + 0xdd, 0x04, 0xa1, 0xa0, 0x26, 0x08, 0x84, 0xb3, 0x41, 0x90, 0xd8, 0x60, + 0xc3, 0x42, 0xa8, 0xc1, 0xb7, 0x06, 0x61, 0x00, 0x06, 0xc3, 0x19, 0x10, + 0x60, 0xd0, 0x06, 0x1b, 0x02, 0x37, 0xd8, 0x30, 0xa4, 0xc1, 0x1b, 0x00, + 0x1b, 0x0a, 0xae, 0x83, 0x83, 0x0c, 0xa8, 0xc2, 0xc6, 0x66, 0xd7, 0xe6, + 0x92, 0x46, 0x56, 0xe6, 0x46, 0x37, 0x25, 0x08, 0xaa, 0x90, 0xe1, 0xb9, + 0xd8, 0x95, 0xc9, 0xcd, 0xa5, 0xbd, 0xb9, 0x4d, 0x09, 0x88, 0x26, 0x64, + 0x78, 0x2e, 0x76, 0x61, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x02, 0xa3, 0x0e, + 0x19, 0x9e, 0xcb, 0x1c, 0x5a, 0x18, 0x59, 0x99, 0x5c, 0xd3, 0x1b, 0x59, + 0x19, 0xdb, 0x94, 0x00, 0x29, 0x43, 0x86, 0xe7, 0x22, 0x57, 0x36, 0xf7, + 0x56, 0x27, 0x37, 0x56, 0x36, 0x37, 0x25, 0xc0, 0xea, 0x90, 0xe1, 0xb9, + 0xd8, 0xa5, 0x95, 0xdd, 0x25, 0x91, 0x4d, 0xd1, 0x85, 0xd1, 0x95, 0x4d, + 0x09, 0xb4, 0x3a, 0x64, 0x78, 0x2e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x53, 0x02, 0x38, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, + 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, + 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, + 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, + 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, + 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, + 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, + 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, + 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, + 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, + 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, + 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, + 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, + 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, + 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, + 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, + 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, + 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, + 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, + 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, + 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, + 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, + 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, + 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, + 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, + 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, + 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, + 0x7d, 0x91, 0xc3, 0xd8, 0x9d, 0x15, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, + 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, + 0xf9, 0xc5, 0x6d, 0x1b, 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, + 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, + 0xdc, 0xb6, 0x19, 0x48, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, + 0x11, 0x21, 0xd0, 0x0c, 0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, + 0x2f, 0x0e, 0x30, 0x88, 0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, + 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, + 0x2c, 0x7e, 0x71, 0xdb, 0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, + 0x39, 0x11, 0x81, 0x52, 0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x61, + 0x20, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, 0x8d, 0x00, 0x10, 0x51, + 0x0a, 0x25, 0x37, 0x03, 0x50, 0x08, 0x65, 0x57, 0x7c, 0x54, 0x94, 0x00, + 0x0d, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x06, 0x09, 0x00, 0x82, + 0x60, 0x60, 0x71, 0x87, 0xa4, 0x69, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20, + 0x18, 0x58, 0x1d, 0x12, 0x6d, 0x9b, 0x32, 0x62, 0x90, 0x00, 0x20, 0x08, + 0x06, 0x96, 0x97, 0x4c, 0x1c, 0xb7, 0x8c, 0x18, 0x24, 0x00, 0x08, 0x82, + 0x81, 0x41, 0x06, 0x48, 0xd7, 0x55, 0xc9, 0x88, 0x41, 0x02, 0x80, 0x20, + 0x18, 0x18, 0x65, 0x90, 0x78, 0x9e, 0xa1, 0x8c, 0x18, 0x1c, 0x00, 0x08, + 0x82, 0xc1, 0x24, 0x06, 0xc9, 0xf0, 0x8d, 0x26, 0x04, 0xc0, 0x68, 0x82, + 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, 0x98, 0x70, 0xc8, 0xc7, + 0x84, 0x43, 0x3e, 0x26, 0x18, 0xf0, 0x31, 0xc1, 0x80, 0xcf, 0x88, 0xc1, + 0x01, 0x80, 0x20, 0x18, 0x40, 0x6c, 0x20, 0x31, 0x69, 0x30, 0x9a, 0x10, + 0x00, 0x17, 0x0c, 0x35, 0x62, 0xf0, 0x00, 0x20, 0x08, 0x06, 0x0d, 0x1c, + 0x50, 0x11, 0x54, 0x10, 0x92, 0xb4, 0x06, 0x6b, 0x70, 0x05, 0xa3, 0x09, + 0x01, 0x30, 0x9a, 0x20, 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, + 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0xd8, 0x81, 0x07, 0x07, 0x70, + 0x80, 0x06, 0xc4, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x76, 0xe0, + 0xc1, 0x01, 0x1c, 0x60, 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, + 0x76, 0xe0, 0xc1, 0x01, 0x1c, 0x9c, 0x81, 0x30, 0x62, 0x90, 0x00, 0x20, + 0x08, 0x06, 0x88, 0x1d, 0x78, 0x70, 0x00, 0x07, 0x66, 0x10, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; TEXCOORD 0 xy 0 NONE float xy +; SV_Position 0 xyzw 1 POS float +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: 2e13f04e8780c355f36dba74b811bc6f +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; TEXCOORD 0 linear +; SV_Position 0 noperspective +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; cbuffer SourceRegionBuffer +; { +; +; struct SourceRegionBuffer +; { +; +; float2 UVLeftTop; ; Offset: 0 +; float2 UVDimensions; ; Offset: 8 +; uint MipLevel; ; Offset: 16 +; float LayerOrDepth; ; Offset: 20 +; +; } SourceRegionBuffer; ; Offset: 0 Size: 24 +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; SourceRegionBuffer cbuffer NA NA CB0 cb0,space3 1 +; SourceSampler sampler NA NA S0 s0,space2 1 +; SourceTexture2DArray texture f32 2darray T0 t0,space2 1 +; +; +; ViewId state: +; +; Number of inputs: 8, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0, 1 } +; output 1 depends on inputs: { 0, 1 } +; output 2 depends on inputs: { 0, 1 } +; output 3 depends on inputs: { 0, 1 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.CBufRet.f32 = type { float, float, float, float } +%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 } +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } +%"class.Texture2DArray >" = type { <4 x float>, %"class.Texture2DArray >::mips_type" } +%"class.Texture2DArray >::mips_type" = type { i32 } +%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float } +%struct.SamplerState = type { i32 } + +define void @BlitFrom2DArray() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0) ; CBufferLoadLegacy(handle,regIndex) + %7 = extractvalue %dx.types.CBufRet.f32 %6, 0 + %8 = extractvalue %dx.types.CBufRet.f32 %6, 1 + %9 = extractvalue %dx.types.CBufRet.f32 %6, 2 + %10 = extractvalue %dx.types.CBufRet.f32 %6, 3 + %11 = fmul fast float %9, %4 + %12 = fmul fast float %10, %5 + %13 = fadd fast float %11, %7 + %14 = fadd fast float %12, %8 + %15 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %16 = extractvalue %dx.types.CBufRet.f32 %15, 1 + %17 = fptoui float %16 to i32 + %18 = uitofp i32 %17 to float + %19 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %20 = extractvalue %dx.types.CBufRet.i32 %19, 0 + %21 = uitofp i32 %20 to float + %22 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float %18, float undef, i32 0, i32 0, i32 undef, float %21) ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD) + %23 = extractvalue %dx.types.ResRet.f32 %22, 0 + %24 = extractvalue %dx.types.ResRet.f32 %22, 1 + %25 = extractvalue %dx.types.ResRet.f32 %22, 2 + %26 = extractvalue %dx.types.ResRet.f32 %22, 3 + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %23) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %24) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %25) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %26) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +; Function Attrs: nounwind readonly +declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } +attributes #2 = { nounwind readonly } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.resources = !{!4} +!dx.viewIdState = !{!12} +!dx.entryPoints = !{!13} + +!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 6} +!3 = !{!"ps", i32 6, i32 0} +!4 = !{!5, null, !8, !10} +!5 = !{!6} +!6 = !{i32 0, %"class.Texture2DArray >"* undef, !"", i32 2, i32 0, i32 1, i32 7, i32 0, !7} +!7 = !{i32 0, i32 9} +!8 = !{!9} +!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null} +!10 = !{!11} +!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null} +!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]} +!13 = !{void ()* @BlitFrom2DArray, !"BlitFrom2DArray", !14, !4, null} +!14 = !{!15, !20, null} +!15 = !{!16, !19} +!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18} +!17 = !{i32 0} +!18 = !{i32 3, i32 3} +!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null} +!20 = !{!21} +!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22} +!22 = !{i32 3, i32 15} + +#endif + +const unsigned char g_BlitFrom2DArray[] = { + 0x44, 0x58, 0x42, 0x43, 0xdf, 0xde, 0xbd, 0x23, 0xe2, 0x83, 0x0e, 0x5d, + 0xfb, 0xe3, 0x84, 0xf0, 0x8c, 0x87, 0xbb, 0x3c, 0x01, 0x00, 0x00, 0x00, + 0x83, 0x12, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, + 0xe7, 0x01, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00, 0x7b, 0x0a, 0x00, 0x00, + 0x97, 0x0a, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, + 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, + 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x00, 0x4f, 0x53, 0x47, 0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, + 0x53, 0x56, 0x30, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x53, 0x30, 0x88, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xfc, + 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x44, + 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xe4, + 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xf6, + 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, + 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, + 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, + 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, + 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, + 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, + 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, + 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, + 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, + 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, + 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, + 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, + 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, + 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, + 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, + 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, + 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, + 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, + 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, + 0xc5, 0x4a, 0x4c, 0x7e, 0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, + 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, + 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, + 0xa2, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, + 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0x26, 0x39, + 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, + 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07, 0x39, 0x20, 0x85, 0x50, + 0x90, 0x07, 0x79, 0x08, 0x87, 0x7c, 0xe0, 0x03, 0x7b, 0x28, 0x87, 0x71, + 0xa0, 0x87, 0x77, 0x90, 0x07, 0x3e, 0x30, 0x07, 0x76, 0x78, 0x87, 0x70, + 0xa0, 0x07, 0x36, 0x00, 0x03, 0x3a, 0xf0, 0x03, 0x30, 0xf0, 0x03, 0x3d, + 0xd0, 0x83, 0x76, 0x48, 0x07, 0x78, 0x98, 0x87, 0x5f, 0xa0, 0x87, 0x7c, + 0x80, 0x87, 0x72, 0x40, 0x01, 0x31, 0xd3, 0x19, 0x8c, 0x03, 0x3b, 0x84, + 0xc3, 0x3c, 0xcc, 0x83, 0x1b, 0xd0, 0x42, 0x39, 0xe0, 0x03, 0x3d, 0xd4, + 0x83, 0x3c, 0x94, 0x83, 0x1c, 0x90, 0x42, 0x28, 0xc8, 0x83, 0x3c, 0x84, + 0x43, 0x3e, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, + 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, + 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61, + 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c, + 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d, + 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, + 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x00, 0x13, + 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, + 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, + 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, + 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, + 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, + 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, + 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, + 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, + 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, + 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, + 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, + 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, + 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, + 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, + 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x2c, 0x10, 0x14, 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18, 0x19, + 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, + 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x1c, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, + 0x20, 0x0a, 0xa4, 0x14, 0x0a, 0xa5, 0x3c, 0xca, 0xa7, 0x10, 0xa8, 0x28, + 0x89, 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x10, 0xaa, 0x6a, 0x80, + 0xb8, 0x19, 0x00, 0xf2, 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, 0x06, + 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x1a, + 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, + 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, + 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, + 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, + 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, + 0x06, 0x61, 0x20, 0x36, 0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, + 0x24, 0x1b, 0x86, 0x03, 0x21, 0x26, 0x08, 0x5c, 0x47, 0x6a, 0xea, 0xad, + 0x4e, 0x6e, 0xac, 0x8c, 0xaa, 0x0c, 0x8f, 0xae, 0x4e, 0xae, 0x4c, 0x86, + 0x28, 0x48, 0x4e, 0x2e, 0x2c, 0x6f, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, + 0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30, + 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20, 0x7c, 0x1f, 0xa5, 0xa9, + 0xb7, 0x3a, 0xb9, 0xb1, 0x32, 0xa9, 0xb2, 0xb3, 0xb4, 0x37, 0x37, 0xa1, + 0x3a, 0x33, 0xb3, 0x32, 0xb9, 0x09, 0x02, 0xd1, 0x4c, 0x10, 0x08, 0x67, + 0x03, 0x42, 0x48, 0x13, 0x45, 0x0c, 0x15, 0xb0, 0x21, 0xb0, 0x26, 0x08, + 0x61, 0x00, 0x06, 0x6c, 0xa6, 0xde, 0xea, 0xe4, 0xc6, 0xca, 0xa6, 0xc2, + 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x36, 0x20, 0x04, 0x96, 0x31, 0xc4, 0x40, + 0x00, 0x1b, 0x02, 0x6d, 0x03, 0x11, 0x01, 0xd7, 0x36, 0x41, 0xf0, 0x3c, + 0x26, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f, 0x70, 0x13, 0x84, + 0x8a, 0xdb, 0x80, 0x20, 0x1e, 0x45, 0x34, 0x8e, 0xf3, 0x91, 0xa9, 0xb2, + 0x22, 0x4a, 0x6b, 0x2b, 0x73, 0x9b, 0x4b, 0x7b, 0x73, 0x9b, 0x9b, 0x20, + 0x10, 0xcf, 0x06, 0x04, 0x09, 0x03, 0x4a, 0x0c, 0x1a, 0xc7, 0xf9, 0x88, + 0x34, 0xa5, 0xc1, 0x31, 0x95, 0xd9, 0x95, 0xb1, 0x4d, 0x10, 0x08, 0x68, + 0x82, 0x40, 0x44, 0x1b, 0x10, 0x84, 0x0c, 0xa8, 0x32, 0x68, 0xcc, 0xc0, + 0xf9, 0xc8, 0x30, 0x85, 0xe5, 0x95, 0xc9, 0x3d, 0xc9, 0x11, 0x95, 0xc1, + 0xd1, 0xa1, 0x4d, 0x10, 0x08, 0x69, 0x03, 0x82, 0xa0, 0x01, 0x95, 0x06, + 0x8d, 0xe3, 0x7c, 0x1b, 0x8a, 0x0a, 0x0c, 0xc6, 0xe0, 0x0c, 0xd4, 0x60, + 0xc3, 0x40, 0x74, 0x6b, 0x30, 0x41, 0x10, 0x80, 0x0d, 0xc0, 0x86, 0x81, + 0x70, 0x03, 0x37, 0xd8, 0x10, 0xbc, 0xc1, 0x86, 0x61, 0x68, 0x03, 0x38, + 0x98, 0x20, 0x88, 0x41, 0x18, 0x6c, 0x08, 0xe4, 0x80, 0x8f, 0x10, 0x5b, + 0x1a, 0x9d, 0x91, 0xdc, 0x5b, 0x9b, 0x0c, 0x51, 0x90, 0x9c, 0x5c, 0x58, + 0x1e, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, 0x29, 0xa2, 0x09, 0x42, + 0x61, 0x4d, 0x10, 0x8a, 0x6b, 0x43, 0x40, 0x4c, 0x10, 0x0a, 0x6c, 0x83, + 0x40, 0x51, 0x1b, 0x16, 0xa2, 0x0e, 0xec, 0xe0, 0x0e, 0xf0, 0x20, 0x0f, + 0x86, 0x3c, 0x20, 0xee, 0x40, 0x0f, 0xb8, 0x4c, 0x59, 0x7d, 0x41, 0xbd, + 0xcd, 0xa5, 0xd1, 0xa5, 0xbd, 0xb9, 0x4d, 0x10, 0x8a, 0x6c, 0x82, 0x50, + 0x68, 0x1b, 0x96, 0x81, 0x0f, 0xec, 0xa0, 0x0f, 0xf0, 0xc0, 0x0f, 0x06, + 0x3f, 0x18, 0xee, 0x00, 0xd8, 0x20, 0xec, 0xc1, 0x1f, 0x30, 0x99, 0xb2, + 0xfa, 0xa2, 0x0a, 0x93, 0x3b, 0x2b, 0xa3, 0x9b, 0x20, 0x14, 0xdb, 0x04, + 0x81, 0x98, 0x36, 0x08, 0xd4, 0x28, 0x6c, 0x58, 0x88, 0x50, 0xb0, 0x03, + 0x51, 0xc0, 0x83, 0x3b, 0x18, 0xfc, 0x80, 0xb8, 0x03, 0x52, 0xd8, 0x10, + 0x94, 0xc2, 0x86, 0x01, 0x14, 0x4c, 0x01, 0xd8, 0x50, 0xb4, 0x01, 0x1d, + 0x9c, 0x02, 0x07, 0xd0, 0x30, 0x63, 0x7b, 0x0b, 0xa3, 0x9b, 0x63, 0x91, + 0xe6, 0x36, 0x47, 0x37, 0x37, 0x41, 0x20, 0x28, 0x1a, 0x73, 0x69, 0x67, + 0x5f, 0x6c, 0x64, 0x34, 0xe6, 0xd2, 0xce, 0xbe, 0xe6, 0xe8, 0x26, 0x08, + 0x44, 0x45, 0x84, 0xae, 0x0c, 0xef, 0xcb, 0xed, 0x4d, 0xae, 0x6d, 0x83, + 0x92, 0x0a, 0x8d, 0x2a, 0xac, 0x02, 0x2b, 0x30, 0xad, 0xe0, 0x0a, 0xaf, + 0x30, 0x54, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, 0xa3, + 0x9b, 0x12, 0x04, 0x55, 0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, 0xd2, + 0xde, 0xdc, 0xa6, 0x04, 0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, 0x36, + 0xbb, 0x32, 0xb9, 0x29, 0x41, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, 0x2d, + 0x8c, 0xac, 0x4c, 0xae, 0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, 0x94, + 0x21, 0xc3, 0x73, 0x91, 0x2b, 0x9b, 0x7b, 0xab, 0x93, 0x1b, 0x2b, 0x9b, + 0x9b, 0x12, 0x6c, 0x95, 0xc8, 0xf0, 0x5c, 0xe8, 0xf2, 0xe0, 0xca, 0x82, + 0xdc, 0xdc, 0xde, 0xe8, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xe6, 0xa6, 0x08, + 0x6b, 0x00, 0x07, 0x75, 0xc8, 0xf0, 0x5c, 0xec, 0xd2, 0xca, 0xee, 0x92, + 0xc8, 0xa6, 0xe8, 0xc2, 0xe8, 0xca, 0xa6, 0x04, 0x72, 0x50, 0x87, 0x0c, + 0xcf, 0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, 0x6e, + 0x6e, 0x4a, 0x70, 0x0a, 0x5d, 0xc8, 0xf0, 0x5c, 0xc6, 0xde, 0xea, 0xdc, + 0xe8, 0xca, 0xe4, 0xe6, 0xa6, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, + 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, + 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, + 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, + 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, + 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, + 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, + 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, + 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, + 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, + 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, + 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, + 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, + 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, + 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, + 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, + 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, + 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, + 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, + 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, + 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, + 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, + 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, + 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, + 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, + 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0xf0, 0x6c, 0x0b, 0x32, + 0x7d, 0x91, 0xc3, 0xd8, 0x9d, 0x16, 0x45, 0x00, 0x66, 0x04, 0xdb, 0x70, + 0xf9, 0xce, 0xe3, 0x0b, 0x01, 0x55, 0x14, 0x44, 0x54, 0x3a, 0xc0, 0x50, + 0x12, 0x06, 0x20, 0x60, 0x7e, 0x71, 0xdb, 0x56, 0xb0, 0x0d, 0x97, 0xef, + 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, + 0x00, 0x02, 0xe6, 0x23, 0xb7, 0x6d, 0x06, 0xd2, 0x70, 0xf9, 0xce, 0xe3, + 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0, 0x34, + 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93, 0x5f, + 0xdc, 0xb6, 0x0d, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x01, 0xcc, 0xb3, + 0x10, 0x25, 0x51, 0x11, 0x8b, 0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, + 0x3b, 0x8f, 0x2f, 0x4d, 0x4e, 0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, + 0xdc, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x13, 0xf0, 0x4e, 0x87, + 0x80, 0xc3, 0x55, 0xf3, 0x6d, 0xba, 0x74, 0xb8, 0x11, 0xbc, 0x6f, 0x44, + 0x58, 0x49, 0x4c, 0xe4, 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xf9, + 0x01, 0x00, 0x00, 0x44, 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0xcc, 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, + 0x0c, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, + 0xc8, 0x04, 0x49, 0x06, 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, + 0x05, 0x08, 0x19, 0x1e, 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, + 0x92, 0x0b, 0x42, 0xc4, 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, + 0x32, 0x62, 0x88, 0x48, 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, + 0x19, 0x32, 0x42, 0xe4, 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, + 0x51, 0x81, 0x8c, 0xe1, 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, + 0x18, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x40, 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, + 0xff, 0x03, 0x20, 0x6d, 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x09, 0xa8, 0x00, 0x49, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, + 0x82, 0x60, 0x42, 0x20, 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, + 0x20, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, + 0x64, 0x85, 0x04, 0x13, 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, + 0xa1, 0x90, 0x14, 0x12, 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, + 0x8c, 0xc1, 0x08, 0x40, 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, + 0x60, 0x8e, 0x00, 0x29, 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, + 0x80, 0x20, 0x88, 0x62, 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, + 0x24, 0x7f, 0x25, 0xa4, 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, + 0xc3, 0x40, 0x50, 0x71, 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, + 0x02, 0xcd, 0xb0, 0x10, 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, + 0xc3, 0x40, 0x10, 0xc4, 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, + 0x48, 0x3e, 0xb7, 0x51, 0xc5, 0x4a, 0x4c, 0x7e, 0x71, 0xdb, 0x88, 0x18, + 0x86, 0x61, 0x28, 0xc4, 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, + 0x61, 0x0f, 0x21, 0xf9, 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, + 0x23, 0x82, 0x20, 0x08, 0xa2, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, + 0x04, 0xc5, 0x60, 0x88, 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, + 0x88, 0x61, 0x26, 0x39, 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, + 0x37, 0xa0, 0x85, 0x72, 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x07, + 0x39, 0x20, 0x85, 0x50, 0x90, 0x07, 0x79, 0x08, 0x87, 0x7c, 0xe0, 0x03, + 0x7b, 0x28, 0x87, 0x71, 0xa0, 0x87, 0x77, 0x90, 0x07, 0x3e, 0x30, 0x07, + 0x76, 0x78, 0x87, 0x70, 0xa0, 0x07, 0x36, 0x00, 0x03, 0x3a, 0xf0, 0x03, + 0x30, 0xf0, 0x03, 0x3d, 0xd0, 0x83, 0x76, 0x48, 0x07, 0x78, 0x98, 0x87, + 0x5f, 0xa0, 0x87, 0x7c, 0x80, 0x87, 0x72, 0x40, 0x01, 0x31, 0xd3, 0x19, + 0x8c, 0x03, 0x3b, 0x84, 0xc3, 0x3c, 0xcc, 0x83, 0x1b, 0xd0, 0x42, 0x39, + 0xe0, 0x03, 0x3d, 0xd4, 0x83, 0x3c, 0x94, 0x83, 0x1c, 0x90, 0x42, 0x28, + 0xc8, 0x83, 0x3c, 0x84, 0x43, 0x3e, 0xf0, 0x81, 0x3d, 0x94, 0xc3, 0x38, + 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, 0x03, 0x3b, 0xbc, 0x43, 0x38, + 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, 0x01, 0x18, 0xf8, 0x01, 0x12, + 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, 0x89, 0x75, 0xa8, 0x48, 0x20, + 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, 0x82, 0x88, 0x10, 0xd1, 0x75, + 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, 0xc2, 0xe4, 0xb3, 0x00, 0xf3, + 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, 0x80, 0x20, 0x30, 0x15, 0x08, + 0x00, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, 0x74, 0x60, 0x87, 0x36, + 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, 0x0d, 0xaf, 0x50, 0x0e, + 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, 0x0f, 0x7a, 0x30, 0x07, + 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0xa0, 0x07, + 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, 0x07, 0x73, 0x20, 0x07, + 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, + 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, + 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, 0x06, 0xe6, 0x10, 0x07, + 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, 0x0e, 0x73, 0x20, 0x07, + 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, 0x07, 0x74, 0xa0, 0x07, + 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, 0x07, 0x71, 0x60, 0x07, + 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x43, 0x9e, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x3c, + 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x10, 0x00, 0x00, 0x00, 0x32, + 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, 0x09, 0x26, 0x47, 0xc6, + 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, 0x8a, 0xa0, 0x1c, 0x4a, + 0xa2, 0x0c, 0x0a, 0xa6, 0x3c, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, 0x28, + 0x83, 0x42, 0x28, 0x10, 0xe2, 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, + 0x06, 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x1a, + 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, + 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, + 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, + 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, + 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, + 0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb2, 0x41, 0x18, 0x0c, 0x0a, 0x70, + 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x9c, 0x45, 0x60, 0x82, 0x40, + 0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36, + 0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20, + 0x7c, 0xd7, 0x04, 0x81, 0x68, 0x26, 0x08, 0x84, 0xb3, 0x01, 0x21, 0xa4, + 0x65, 0x22, 0x06, 0x0a, 0xd8, 0x10, 0x54, 0x13, 0x84, 0x30, 0xc0, 0x36, + 0x20, 0xc4, 0xb5, 0x30, 0xc4, 0x40, 0x00, 0x1b, 0x02, 0x6c, 0x03, 0x11, + 0x01, 0x56, 0x36, 0x41, 0x10, 0x83, 0x6c, 0x43, 0xb0, 0x4d, 0x10, 0x04, + 0x80, 0x8f, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, 0x5b, 0x9b, 0x0c, 0x51, + 0x90, 0x9c, 0x5c, 0x58, 0x1e, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, + 0x29, 0xa2, 0x09, 0x42, 0x01, 0x4d, 0x10, 0x8a, 0x68, 0x43, 0x40, 0x4c, + 0x10, 0x0a, 0x69, 0x83, 0x30, 0x4d, 0x1b, 0x16, 0xe2, 0x03, 0x83, 0x30, + 0x10, 0x83, 0x31, 0x18, 0xc6, 0x80, 0x08, 0x03, 0x32, 0xe0, 0x32, 0x65, + 0xf5, 0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x28, + 0xa6, 0x09, 0x42, 0x41, 0x6d, 0x58, 0x06, 0x33, 0x00, 0x83, 0x33, 0x10, + 0x03, 0x34, 0x18, 0xd0, 0x60, 0x08, 0x03, 0x60, 0x83, 0x50, 0x06, 0x69, + 0xc0, 0x64, 0xca, 0xea, 0x8b, 0x2a, 0x4c, 0xee, 0xac, 0x8c, 0x6e, 0x82, + 0x50, 0x54, 0x13, 0x04, 0xe2, 0xd9, 0x20, 0x4c, 0x6d, 0xb0, 0x61, 0x21, + 0xd6, 0x00, 0x0c, 0xd8, 0x40, 0x0c, 0xc2, 0x60, 0x40, 0x03, 0x22, 0x0c, + 0xdc, 0x60, 0x43, 0xf0, 0x06, 0x1b, 0x06, 0x35, 0x80, 0x03, 0x60, 0x43, + 0xd1, 0x79, 0x71, 0xa0, 0x01, 0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xd2, + 0xc8, 0xca, 0xdc, 0xe8, 0xa6, 0x04, 0x41, 0x15, 0x32, 0x3c, 0x17, 0xbb, + 0x32, 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c, 0xcf, + 0xc5, 0x2e, 0x8c, 0xcd, 0xae, 0x4c, 0x6e, 0x4a, 0x60, 0xd4, 0x21, 0xc3, + 0x73, 0x99, 0x43, 0x0b, 0x23, 0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b, 0x63, + 0x9b, 0x12, 0x20, 0x65, 0xc8, 0xf0, 0x5c, 0xe4, 0xca, 0xe6, 0xde, 0xea, + 0xe4, 0xc6, 0xca, 0xe6, 0xa6, 0x04, 0x59, 0x1d, 0x32, 0x3c, 0x17, 0xbb, + 0xb4, 0xb2, 0xbb, 0x24, 0xb2, 0x29, 0xba, 0x30, 0xba, 0xb2, 0x29, 0xc1, + 0x56, 0x87, 0x0c, 0xcf, 0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, + 0xcd, 0x8d, 0x6e, 0x6e, 0x4a, 0x10, 0x07, 0x00, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, + 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, + 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, + 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, + 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, + 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, + 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, + 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, + 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, + 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, + 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, + 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, + 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, + 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, + 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, + 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, + 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, + 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, + 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, + 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, + 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, + 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, + 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, + 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, + 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, + 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, + 0x20, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0xf0, 0x6c, 0x0b, 0x32, + 0x7d, 0x91, 0xc3, 0xd8, 0x9d, 0x16, 0x45, 0x00, 0x66, 0x04, 0xdb, 0x70, + 0xf9, 0xce, 0xe3, 0x0b, 0x01, 0x55, 0x14, 0x44, 0x54, 0x3a, 0xc0, 0x50, + 0x12, 0x06, 0x20, 0x60, 0x7e, 0x71, 0xdb, 0x56, 0xb0, 0x0d, 0x97, 0xef, + 0x3c, 0xbe, 0x10, 0x50, 0x45, 0x41, 0x44, 0xa5, 0x03, 0x0c, 0x25, 0x61, + 0x00, 0x02, 0xe6, 0x23, 0xb7, 0x6d, 0x06, 0xd2, 0x70, 0xf9, 0xce, 0xe3, + 0x0b, 0x11, 0x01, 0x4c, 0x44, 0x08, 0x34, 0xc3, 0x42, 0x58, 0xc0, 0x34, + 0x5c, 0xbe, 0xf3, 0xf8, 0x8b, 0x03, 0x0c, 0x62, 0xf3, 0x50, 0x93, 0x5f, + 0xdc, 0xb6, 0x0d, 0x54, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x01, 0xcc, 0xb3, + 0x10, 0x25, 0x51, 0x11, 0x8b, 0x5f, 0xdc, 0xb6, 0x09, 0x54, 0xc3, 0xe5, + 0x3b, 0x8f, 0x2f, 0x4d, 0x4e, 0x44, 0xa0, 0xd4, 0xf4, 0x50, 0x93, 0x5f, + 0xdc, 0x36, 0x00, 0x61, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x13, + 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x54, + 0x8d, 0x00, 0x10, 0x51, 0x0a, 0x25, 0x37, 0x03, 0x50, 0x76, 0x85, 0x50, + 0x7c, 0x54, 0x94, 0x00, 0x0d, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, + 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x75, 0x87, 0xb4, 0x6d, 0xc9, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x58, 0x1e, 0x12, 0x71, 0x9c, 0x32, 0x62, + 0x90, 0x00, 0x20, 0x08, 0x06, 0xd6, 0x97, 0x4c, 0x5d, 0xb7, 0x8c, 0x18, + 0x24, 0x00, 0x08, 0x82, 0x81, 0x51, 0x06, 0x87, 0xe7, 0x55, 0xc9, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x66, 0x80, 0x7c, 0x9f, 0xa1, 0x8c, + 0x18, 0x1c, 0x00, 0x08, 0x82, 0x01, 0x44, 0x06, 0xca, 0x00, 0x06, 0xa3, + 0x09, 0x01, 0x30, 0x9a, 0x20, 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, + 0x0c, 0x26, 0x1c, 0xf2, 0x31, 0xe1, 0x90, 0x8f, 0x09, 0x06, 0x7c, 0x4c, + 0x30, 0xe0, 0x33, 0x62, 0x70, 0x00, 0x20, 0x08, 0x06, 0x50, 0x1b, 0x4c, + 0x8c, 0x1a, 0x8c, 0x26, 0x04, 0xc1, 0x05, 0xc4, 0x5c, 0x30, 0xd4, 0x88, + 0xc1, 0x01, 0x80, 0x20, 0x18, 0x4c, 0x70, 0x70, 0x41, 0x6e, 0x30, 0x9a, + 0x10, 0x00, 0x17, 0x0c, 0x35, 0x62, 0xf0, 0x00, 0x20, 0x08, 0x06, 0x4d, + 0x1d, 0x60, 0x15, 0x95, 0x20, 0x84, 0x05, 0x07, 0x70, 0xb0, 0x05, 0xa3, + 0x09, 0x01, 0x30, 0x9a, 0x20, 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, + 0x0c, 0x23, 0x06, 0x09, 0x00, 0x82, 0x60, 0x80, 0xec, 0x81, 0x18, 0xd4, + 0x41, 0x1d, 0xb0, 0x01, 0x31, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0xc8, + 0x1e, 0x88, 0x41, 0x1d, 0xd4, 0x01, 0x37, 0x8c, 0x18, 0x24, 0x00, 0x08, + 0x82, 0x01, 0xb2, 0x07, 0x62, 0x50, 0x07, 0x75, 0xb0, 0x06, 0xc2, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x7b, 0x20, 0x06, 0x75, 0x50, 0x07, + 0x6a, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; TEXCOORD 0 xy 0 NONE float xy +; SV_Position 0 xyzw 1 POS float +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: 49c2f4be133400e07c3f23e9798b27f4 +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; TEXCOORD 0 linear +; SV_Position 0 noperspective +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; cbuffer SourceRegionBuffer +; { +; +; struct SourceRegionBuffer +; { +; +; float2 UVLeftTop; ; Offset: 0 +; float2 UVDimensions; ; Offset: 8 +; uint MipLevel; ; Offset: 16 +; float LayerOrDepth; ; Offset: 20 +; +; } SourceRegionBuffer; ; Offset: 0 Size: 24 +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; SourceRegionBuffer cbuffer NA NA CB0 cb0,space3 1 +; SourceSampler sampler NA NA S0 s0,space2 1 +; SourceTexture3D texture f32 3d T0 t0,space2 1 +; +; +; ViewId state: +; +; Number of inputs: 8, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0, 1 } +; output 1 depends on inputs: { 0, 1 } +; output 2 depends on inputs: { 0, 1 } +; output 3 depends on inputs: { 0, 1 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.CBufRet.f32 = type { float, float, float, float } +%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 } +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } +%"class.Texture3D >" = type { <4 x float>, %"class.Texture3D >::mips_type" } +%"class.Texture3D >::mips_type" = type { i32 } +%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float } +%struct.SamplerState = type { i32 } + +define void @BlitFrom3D() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0) ; CBufferLoadLegacy(handle,regIndex) + %7 = extractvalue %dx.types.CBufRet.f32 %6, 0 + %8 = extractvalue %dx.types.CBufRet.f32 %6, 1 + %9 = extractvalue %dx.types.CBufRet.f32 %6, 2 + %10 = extractvalue %dx.types.CBufRet.f32 %6, 3 + %11 = fmul fast float %9, %4 + %12 = fmul fast float %10, %5 + %13 = fadd fast float %11, %7 + %14 = fadd fast float %12, %8 + %15 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %16 = extractvalue %dx.types.CBufRet.f32 %15, 1 + %17 = call %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %18 = extractvalue %dx.types.CBufRet.i32 %17, 0 + %19 = uitofp i32 %18 to float + %20 = call %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32 62, %dx.types.Handle %1, %dx.types.Handle %2, float %13, float %14, float %16, float undef, i32 0, i32 0, i32 0, float %19) ; SampleLevel(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,LOD) + %21 = extractvalue %dx.types.ResRet.f32 %20, 0 + %22 = extractvalue %dx.types.ResRet.f32 %20, 1 + %23 = extractvalue %dx.types.ResRet.f32 %20, 2 + %24 = extractvalue %dx.types.ResRet.f32 %20, 3 + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %21) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %22) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %23) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %24) ; StoreOutput(outputSigId,rowIndex,colIndex,value) + ret void +} + +; Function Attrs: nounwind readnone +declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0 + +; Function Attrs: nounwind +declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 + +; Function Attrs: nounwind readonly +declare %dx.types.ResRet.f32 @dx.op.sampleLevel.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.CBufRet.i32 @dx.op.cbufferLoadLegacy.i32(i32, %dx.types.Handle, i32) #2 + +; Function Attrs: nounwind readonly +declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } +attributes #2 = { nounwind readonly } + +!llvm.ident = !{!0} +!dx.version = !{!1} +!dx.valver = !{!2} +!dx.shaderModel = !{!3} +!dx.resources = !{!4} +!dx.viewIdState = !{!12} +!dx.entryPoints = !{!13} + +!0 = !{!"clang version 3.7 (tags/RELEASE_370/final)"} +!1 = !{i32 1, i32 0} +!2 = !{i32 1, i32 6} +!3 = !{!"ps", i32 6, i32 0} +!4 = !{!5, null, !8, !10} +!5 = !{!6} +!6 = !{i32 0, %"class.Texture3D >"* undef, !"", i32 2, i32 0, i32 1, i32 4, i32 0, !7} +!7 = !{i32 0, i32 9} +!8 = !{!9} +!9 = !{i32 0, %SourceRegionBuffer* undef, !"", i32 3, i32 0, i32 1, i32 24, null} +!10 = !{!11} +!11 = !{i32 0, %struct.SamplerState* undef, !"", i32 2, i32 0, i32 1, i32 0, null} +!12 = !{[10 x i32] [i32 8, i32 4, i32 15, i32 15, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]} +!13 = !{void ()* @BlitFrom3D, !"BlitFrom3D", !14, !4, null} +!14 = !{!15, !20, null} +!15 = !{!16, !19} +!16 = !{i32 0, !"TEXCOORD", i8 9, i8 0, !17, i8 2, i32 1, i8 2, i32 0, i8 0, !18} +!17 = !{i32 0} +!18 = !{i32 3, i32 3} +!19 = !{i32 1, !"SV_Position", i8 9, i8 3, !17, i8 4, i32 1, i8 4, i32 1, i8 0, null} +!20 = !{!21} +!21 = !{i32 0, !"SV_Target", i8 9, i8 16, !17, i8 0, i32 1, i8 4, i32 0, i8 0, !22} +!22 = !{i32 3, i32 15} + +#endif + +const unsigned char g_BlitFrom3D[] = { + 0x44, 0x58, 0x42, 0x43, 0x02, 0xc7, 0x0f, 0x7e, 0xe3, 0x5a, 0xf4, 0x9b, + 0xc5, 0xb2, 0xf8, 0xed, 0xa6, 0x79, 0xed, 0xf4, 0x01, 0x00, 0x00, 0x00, + 0x3f, 0x12, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, + 0xe7, 0x01, 0x00, 0x00, 0x77, 0x02, 0x00, 0x00, 0x5f, 0x0a, 0x00, 0x00, + 0x7b, 0x0a, 0x00, 0x00, 0x53, 0x46, 0x49, 0x30, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x31, + 0x5d, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, + 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x00, 0x4f, 0x53, 0x47, 0x31, 0x32, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0x50, + 0x53, 0x56, 0x30, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, + 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x00, 0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x44, 0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x10, 0x03, 0x00, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x53, 0x30, 0x88, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x3c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x7c, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x41, 0x54, 0xe0, + 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x44, + 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc8, + 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xef, + 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, + 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, + 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, + 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, + 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, + 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, + 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, + 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, + 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, + 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, + 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, + 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, + 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, + 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, + 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, + 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, + 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, + 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, + 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, + 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, + 0xc5, 0x4a, 0x4c, 0x7e, 0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, + 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, + 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, + 0xa2, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, + 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, + 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, + 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x87, 0x39, 0x20, 0x05, 0x3e, + 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, + 0x60, 0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, + 0x00, 0x03, 0x3f, 0xd0, 0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, + 0xf8, 0x05, 0x7a, 0xc8, 0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, + 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, + 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xcc, 0x01, 0x29, 0xf0, + 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, + 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, + 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, + 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, + 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, + 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, + 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, + 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, + 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, + 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, + 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, + 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, + 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, + 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, + 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, + 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, + 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, + 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, + 0x07, 0x43, 0x9e, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x14, + 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x18, 0x19, 0x11, 0x4c, 0x90, 0x8c, + 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, + 0x8a, 0xa0, 0x10, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, 0x1c, 0x0a, 0xa2, 0x40, + 0x4a, 0xa1, 0x50, 0xca, 0xa3, 0x74, 0xa8, 0x28, 0x89, 0x11, 0x80, 0x22, + 0x28, 0x83, 0x42, 0x28, 0x10, 0xaa, 0x6a, 0x80, 0xb8, 0x19, 0x00, 0xf2, + 0x66, 0x00, 0xe8, 0x9b, 0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14, + 0x84, 0x78, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, + 0x02, 0x13, 0x44, 0x35, 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, + 0x93, 0x9b, 0x4b, 0x7b, 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, + 0x0b, 0x3b, 0x9b, 0x7b, 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, + 0x9a, 0xb9, 0x81, 0x79, 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, + 0x04, 0x13, 0x04, 0xe2, 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x36, + 0x08, 0x04, 0x41, 0x01, 0x6e, 0x6e, 0x82, 0x40, 0x24, 0x1b, 0x86, 0x03, + 0x21, 0x26, 0x08, 0x5c, 0xc7, 0x67, 0xea, 0xad, 0x4e, 0x6e, 0xac, 0x8c, + 0xaa, 0x0c, 0x8f, 0xae, 0x4e, 0xae, 0x6c, 0x86, 0x68, 0x82, 0x40, 0x28, + 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc, 0x06, 0x81, 0x70, 0x36, 0x24, + 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf, 0x86, 0x00, 0x9a, 0x20, 0x7c, + 0x1f, 0xa5, 0xa9, 0xb7, 0x3a, 0xb9, 0xb1, 0x32, 0xa9, 0xb2, 0xb3, 0xb4, + 0x37, 0x37, 0xa1, 0x3a, 0x33, 0xb3, 0x32, 0xb9, 0x09, 0x02, 0xd1, 0x4c, + 0x10, 0x08, 0x67, 0x03, 0x42, 0x48, 0x13, 0x45, 0x0c, 0x15, 0xb0, 0x21, + 0xb0, 0x26, 0x08, 0x61, 0x00, 0x06, 0x6c, 0xa6, 0xde, 0xea, 0xe4, 0xc6, + 0xca, 0xa6, 0xc2, 0xda, 0xe0, 0xd8, 0xca, 0xe4, 0x36, 0x20, 0x04, 0x96, + 0x31, 0xc4, 0x40, 0x00, 0x1b, 0x02, 0x6d, 0x03, 0x11, 0x01, 0xd7, 0x36, + 0x41, 0xf0, 0x3c, 0x26, 0x55, 0x56, 0x4c, 0x65, 0x66, 0x74, 0x54, 0x6f, + 0x70, 0x13, 0x04, 0xe2, 0x99, 0x20, 0x54, 0xdc, 0x06, 0x04, 0xf1, 0x28, + 0xe2, 0x73, 0x1c, 0x30, 0x20, 0x53, 0x65, 0x45, 0x94, 0xd6, 0x56, 0xe6, + 0x36, 0x97, 0xf6, 0xe6, 0x36, 0x37, 0x41, 0x20, 0xa0, 0x0d, 0x08, 0x22, + 0x06, 0xd4, 0x18, 0x7c, 0x8e, 0x03, 0x06, 0x44, 0x9a, 0xd2, 0xe0, 0x98, + 0xca, 0xec, 0xca, 0xd8, 0x26, 0x08, 0x44, 0x34, 0x41, 0x20, 0xa4, 0x0d, + 0x08, 0x52, 0x06, 0x94, 0x19, 0x7c, 0x67, 0xe0, 0x80, 0x01, 0x19, 0xa6, + 0xb0, 0xbc, 0x32, 0xb9, 0x27, 0x39, 0xa2, 0x32, 0x38, 0x3a, 0xb4, 0x09, + 0x02, 0x31, 0x6d, 0x40, 0x90, 0x34, 0xa0, 0xd4, 0xe0, 0x73, 0x1c, 0x30, + 0xd8, 0x50, 0x54, 0x61, 0x40, 0x06, 0x68, 0xb0, 0x06, 0x1b, 0x06, 0xa2, + 0x63, 0x83, 0x09, 0x82, 0x00, 0x6c, 0x00, 0x36, 0x0c, 0xc4, 0x1b, 0xbc, + 0xc1, 0x86, 0x00, 0x0e, 0x36, 0x0c, 0x83, 0x1b, 0xc4, 0xc1, 0x04, 0x41, + 0x0c, 0xc2, 0x60, 0x43, 0x30, 0x07, 0x54, 0x84, 0xd8, 0xd2, 0xe8, 0x8c, + 0xe4, 0xde, 0xda, 0x66, 0x88, 0x88, 0x50, 0x15, 0x61, 0x0d, 0x3d, 0x3d, + 0x49, 0x11, 0x4d, 0x10, 0x0a, 0x6b, 0x82, 0x50, 0x5c, 0x1b, 0x02, 0x62, + 0x82, 0x50, 0x60, 0x1b, 0x04, 0x8a, 0xda, 0xb0, 0x10, 0x76, 0x70, 0x07, + 0x78, 0x90, 0x07, 0x7a, 0x30, 0xe8, 0x01, 0x81, 0x07, 0x7b, 0xc0, 0x65, + 0xca, 0xea, 0x0b, 0xea, 0x6d, 0x2e, 0x8d, 0x2e, 0xed, 0xcd, 0x6d, 0x82, + 0x50, 0x64, 0x13, 0x84, 0x42, 0xdb, 0xb0, 0x0c, 0x7d, 0x70, 0x07, 0x7e, + 0x90, 0x07, 0x7f, 0x30, 0xfc, 0xc1, 0x80, 0x07, 0xc0, 0x06, 0x81, 0x0f, + 0x40, 0x81, 0xc9, 0x94, 0xd5, 0x17, 0x55, 0x98, 0xdc, 0x59, 0x19, 0xdd, + 0x04, 0xa1, 0xd8, 0x26, 0x08, 0x04, 0xb5, 0x41, 0xa0, 0x48, 0x61, 0xc3, + 0x42, 0x88, 0xc2, 0x1d, 0x8c, 0x42, 0x1e, 0xe0, 0xc1, 0xf0, 0x07, 0x04, + 0x1e, 0x94, 0xc2, 0x86, 0xc0, 0x14, 0x36, 0x0c, 0xa1, 0x70, 0x0a, 0xc0, + 0x86, 0xc2, 0x0d, 0xea, 0x00, 0x15, 0x38, 0x80, 0x86, 0x19, 0xdb, 0x5b, + 0x18, 0xdd, 0x1c, 0x8b, 0x34, 0xb7, 0x39, 0xba, 0xb9, 0x09, 0x02, 0x51, + 0xd1, 0x98, 0x4b, 0x3b, 0xfb, 0x62, 0x23, 0xa3, 0x31, 0x97, 0x76, 0xf6, + 0x35, 0x47, 0x47, 0x84, 0xae, 0x0c, 0xef, 0xcb, 0xed, 0x4d, 0xae, 0x6d, + 0x83, 0xa2, 0x0a, 0x67, 0xb0, 0x0a, 0xac, 0xd0, 0x0a, 0x8c, 0x2b, 0x34, + 0xaf, 0x30, 0x54, 0x61, 0x63, 0xb3, 0x6b, 0x73, 0x49, 0x23, 0x2b, 0x73, + 0xa3, 0x9b, 0x12, 0x04, 0x55, 0xc8, 0xf0, 0x5c, 0xec, 0xca, 0xe4, 0xe6, + 0xd2, 0xde, 0xdc, 0xa6, 0x04, 0x44, 0x13, 0x32, 0x3c, 0x17, 0xbb, 0x30, + 0x36, 0xbb, 0x32, 0xb9, 0x29, 0x41, 0x51, 0x87, 0x0c, 0xcf, 0x65, 0x0e, + 0x2d, 0x8c, 0xac, 0x4c, 0xae, 0xe9, 0x8d, 0xac, 0x8c, 0x6d, 0x4a, 0x80, + 0x94, 0x21, 0xc3, 0x73, 0x91, 0x2b, 0x9b, 0x7b, 0xab, 0x93, 0x1b, 0x2b, + 0x9b, 0x9b, 0x12, 0x6c, 0x95, 0xc8, 0xf0, 0x5c, 0xe8, 0xf2, 0xe0, 0xca, + 0x82, 0xdc, 0xdc, 0xde, 0xe8, 0xc2, 0xe8, 0xd2, 0xde, 0xdc, 0xe6, 0xa6, + 0x08, 0x6c, 0x10, 0x07, 0x75, 0xc8, 0xf0, 0x5c, 0xec, 0xd2, 0xca, 0xee, + 0x92, 0xc8, 0xa6, 0xe8, 0xc2, 0xe8, 0xca, 0xa6, 0x04, 0x73, 0x50, 0x87, + 0x0c, 0xcf, 0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, 0x8d, + 0x6e, 0x6e, 0x4a, 0x80, 0x0a, 0x5d, 0xc8, 0xf0, 0x5c, 0xc6, 0xde, 0xea, + 0xdc, 0xe8, 0xca, 0xe4, 0xe6, 0xa6, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x79, + 0x18, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, + 0xe1, 0x1c, 0x66, 0x14, 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, + 0x42, 0x80, 0x07, 0x79, 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, + 0x0f, 0xed, 0x10, 0x0e, 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, + 0xc1, 0x1d, 0xce, 0xa1, 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, + 0x84, 0x83, 0x1b, 0xcc, 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, + 0xcc, 0x78, 0x8c, 0x74, 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, + 0x70, 0x70, 0x07, 0x7a, 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, + 0x19, 0xcc, 0x11, 0x0e, 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, + 0x0f, 0xe3, 0xf0, 0x0e, 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, + 0x21, 0x1c, 0xd8, 0x21, 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, + 0xbc, 0x83, 0x3b, 0xd0, 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, + 0x84, 0x03, 0x3b, 0xcc, 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, + 0x37, 0x68, 0x87, 0x72, 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, + 0x70, 0x60, 0x07, 0x76, 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, + 0x77, 0x80, 0x87, 0x5f, 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, + 0x79, 0x98, 0x81, 0x2c, 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, + 0x0e, 0xec, 0x30, 0x03, 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, + 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, + 0x81, 0x1d, 0xca, 0x61, 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, + 0x98, 0x43, 0x39, 0xc8, 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, + 0x88, 0x03, 0x3b, 0x94, 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, + 0xd4, 0x03, 0x3b, 0xb0, 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, + 0x7a, 0x28, 0x87, 0x76, 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, + 0x06, 0xe4, 0x20, 0x0e, 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, + 0x0e, 0xe1, 0x90, 0x0f, 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, + 0x20, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, + 0x7d, 0x91, 0xc3, 0xdc, 0x9d, 0x11, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, + 0x04, 0x54, 0x51, 0x10, 0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, + 0xf9, 0xc5, 0x6d, 0x5b, 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, + 0x15, 0x05, 0x11, 0x95, 0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, + 0xdc, 0xb6, 0x19, 0x48, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, + 0x11, 0x21, 0xd0, 0x0c, 0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, + 0x2f, 0x0e, 0x30, 0x88, 0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, + 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, + 0x2c, 0x7e, 0x71, 0xdb, 0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, + 0x39, 0x11, 0x81, 0x52, 0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, 0x41, 0x53, 0x48, 0x14, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x49, 0xc2, 0xf4, 0xbe, 0x13, 0x34, 0x00, 0xe0, 0x7c, + 0x3f, 0x23, 0xe9, 0x79, 0x8b, 0x27, 0xf4, 0x44, 0x58, 0x49, 0x4c, 0xbc, + 0x07, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xef, 0x01, 0x00, 0x00, 0x44, + 0x58, 0x49, 0x4c, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xa4, + 0x07, 0x00, 0x00, 0x42, 0x43, 0xc0, 0xde, 0x21, 0x0c, 0x00, 0x00, 0xe6, + 0x01, 0x00, 0x00, 0x0b, 0x82, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x07, 0x81, 0x23, 0x91, 0x41, 0xc8, 0x04, 0x49, 0x06, + 0x10, 0x32, 0x39, 0x92, 0x01, 0x84, 0x0c, 0x25, 0x05, 0x08, 0x19, 0x1e, + 0x04, 0x8b, 0x62, 0x80, 0x18, 0x45, 0x02, 0x42, 0x92, 0x0b, 0x42, 0xc4, + 0x10, 0x32, 0x14, 0x38, 0x08, 0x18, 0x4b, 0x0a, 0x32, 0x62, 0x88, 0x48, + 0x90, 0x14, 0x20, 0x43, 0x46, 0x88, 0xa5, 0x00, 0x19, 0x32, 0x42, 0xe4, + 0x48, 0x0e, 0x90, 0x11, 0x23, 0xc4, 0x50, 0x41, 0x51, 0x81, 0x8c, 0xe1, + 0x83, 0xe5, 0x8a, 0x04, 0x31, 0x46, 0x06, 0x51, 0x18, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x1b, 0x8c, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x07, 0x40, + 0x02, 0xa8, 0x0d, 0x84, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x20, 0x6d, + 0x30, 0x86, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x09, 0xa8, 0x00, 0x49, + 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x13, 0x82, 0x60, 0x42, 0x20, + 0x4c, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x89, 0x20, 0x00, 0x00, 0x58, + 0x00, 0x00, 0x00, 0x32, 0x22, 0x88, 0x09, 0x20, 0x64, 0x85, 0x04, 0x13, + 0x23, 0xa4, 0x84, 0x04, 0x13, 0x23, 0xe3, 0x84, 0xa1, 0x90, 0x14, 0x12, + 0x4c, 0x8c, 0x8c, 0x0b, 0x84, 0xc4, 0x4c, 0x10, 0x8c, 0xc1, 0x08, 0x40, + 0x09, 0x00, 0x0a, 0x66, 0x00, 0xe6, 0x08, 0xc0, 0x60, 0x8e, 0x00, 0x29, + 0xc6, 0x40, 0x10, 0x44, 0x41, 0x90, 0x51, 0x0c, 0x80, 0x20, 0x88, 0x62, + 0x20, 0xe4, 0xa6, 0xe1, 0xf2, 0x27, 0xec, 0x21, 0x24, 0x7f, 0x25, 0xa4, + 0x95, 0x98, 0xfc, 0xe2, 0xb6, 0x51, 0x31, 0x0c, 0xc3, 0x40, 0x50, 0x71, + 0xcf, 0x70, 0xf9, 0x13, 0xf6, 0x10, 0x92, 0x1f, 0x02, 0xcd, 0xb0, 0x10, + 0x28, 0x58, 0x0a, 0xa3, 0x10, 0x0c, 0x33, 0x0c, 0xc3, 0x40, 0x10, 0xc4, + 0x40, 0xcd, 0x51, 0xc3, 0xe5, 0x4f, 0xd8, 0x43, 0x48, 0x3e, 0xb7, 0x51, + 0xc5, 0x4a, 0x4c, 0x7e, 0x71, 0xdb, 0x88, 0x18, 0x86, 0x61, 0x28, 0xc4, + 0x43, 0x30, 0x04, 0x41, 0x47, 0x0d, 0x97, 0x3f, 0x61, 0x0f, 0x21, 0xf9, + 0xdc, 0x46, 0x15, 0x2b, 0x31, 0xf9, 0xc8, 0x6d, 0x23, 0x82, 0x20, 0x08, + 0xa2, 0x10, 0x12, 0xc1, 0x10, 0x34, 0xcd, 0x11, 0x04, 0xc5, 0x60, 0x88, + 0x82, 0x20, 0x2a, 0xb2, 0x06, 0x02, 0x86, 0x11, 0x88, 0x61, 0xa6, 0x36, + 0x18, 0x07, 0x76, 0x08, 0x87, 0x79, 0x98, 0x07, 0x37, 0xa0, 0x85, 0x72, + 0xc0, 0x07, 0x7a, 0xa8, 0x07, 0x79, 0x28, 0x87, 0x39, 0x20, 0x05, 0x3e, + 0xb0, 0x87, 0x72, 0x18, 0x07, 0x7a, 0x78, 0x07, 0x79, 0xe0, 0x03, 0x73, + 0x60, 0x87, 0x77, 0x08, 0x07, 0x7a, 0x60, 0x03, 0x30, 0xa0, 0x03, 0x3f, + 0x00, 0x03, 0x3f, 0xd0, 0x03, 0x3d, 0x68, 0x87, 0x74, 0x80, 0x87, 0x79, + 0xf8, 0x05, 0x7a, 0xc8, 0x07, 0x78, 0x28, 0x07, 0x14, 0x10, 0x33, 0x89, + 0xc1, 0x38, 0xb0, 0x43, 0x38, 0xcc, 0xc3, 0x3c, 0xb8, 0x01, 0x2d, 0x94, + 0x03, 0x3e, 0xd0, 0x43, 0x3d, 0xc8, 0x43, 0x39, 0xcc, 0x01, 0x29, 0xf0, + 0x81, 0x3d, 0x94, 0xc3, 0x38, 0xd0, 0xc3, 0x3b, 0xc8, 0x03, 0x1f, 0x98, + 0x03, 0x3b, 0xbc, 0x43, 0x38, 0xd0, 0x03, 0x1b, 0x80, 0x01, 0x1d, 0xf8, + 0x01, 0x18, 0xf8, 0x01, 0x12, 0x32, 0x8d, 0xb6, 0x61, 0x04, 0x61, 0x38, + 0x89, 0x75, 0xa8, 0x48, 0x20, 0x56, 0xc2, 0x40, 0x9c, 0x66, 0xa3, 0x8a, + 0x82, 0x88, 0x10, 0xd1, 0x75, 0xc4, 0x40, 0xde, 0x4d, 0xd2, 0x14, 0x51, + 0xc2, 0xe4, 0xb3, 0x00, 0xf3, 0x2c, 0x44, 0xc4, 0x4e, 0xc0, 0x44, 0xa0, + 0x80, 0x20, 0x30, 0x15, 0x08, 0x00, 0x00, 0x13, 0x14, 0x72, 0xc0, 0x87, + 0x74, 0x60, 0x87, 0x36, 0x68, 0x87, 0x79, 0x68, 0x03, 0x72, 0xc0, 0x87, + 0x0d, 0xaf, 0x50, 0x0e, 0x6d, 0xd0, 0x0e, 0x7a, 0x50, 0x0e, 0x6d, 0x00, + 0x0f, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, + 0x0e, 0x71, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x78, 0xa0, + 0x07, 0x73, 0x20, 0x07, 0x6d, 0x90, 0x0e, 0x71, 0x60, 0x07, 0x7a, 0x30, + 0x07, 0x72, 0xd0, 0x06, 0xe9, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x73, 0x20, + 0x07, 0x6d, 0x90, 0x0e, 0x76, 0x40, 0x07, 0x7a, 0x60, 0x07, 0x74, 0xd0, + 0x06, 0xe6, 0x10, 0x07, 0x76, 0xa0, 0x07, 0x73, 0x20, 0x07, 0x6d, 0x60, + 0x0e, 0x73, 0x20, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xd0, 0x06, 0xe6, 0x60, + 0x07, 0x74, 0xa0, 0x07, 0x76, 0x40, 0x07, 0x6d, 0xe0, 0x0e, 0x78, 0xa0, + 0x07, 0x71, 0x60, 0x07, 0x7a, 0x30, 0x07, 0x72, 0xa0, 0x07, 0x76, 0x40, + 0x07, 0x43, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x86, 0x3c, 0x06, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0c, 0x79, 0x10, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x18, 0xf2, 0x34, 0x40, 0x00, 0x0c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe4, 0x81, 0x80, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xc8, 0x33, 0x01, 0x01, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x90, 0xc7, 0x02, 0x02, + 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2c, 0x10, 0x10, + 0x00, 0x00, 0x00, 0x32, 0x1e, 0x98, 0x14, 0x19, 0x11, 0x4c, 0x90, 0x8c, + 0x09, 0x26, 0x47, 0xc6, 0x04, 0x43, 0x22, 0x4a, 0x60, 0x04, 0xa0, 0x18, + 0x8a, 0xa0, 0x10, 0x4a, 0xa2, 0x0c, 0x0a, 0xa6, 0x3c, 0xa8, 0x28, 0x89, + 0x11, 0x80, 0x22, 0x28, 0x83, 0x42, 0x28, 0x10, 0xe2, 0x66, 0x00, 0xe8, + 0x9b, 0x01, 0xa0, 0x70, 0x06, 0x80, 0xc4, 0xb1, 0x14, 0x84, 0x78, 0x1e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x18, 0x00, 0x00, 0x67, + 0x00, 0x00, 0x00, 0x1a, 0x03, 0x4c, 0x90, 0x46, 0x02, 0x13, 0x44, 0x35, + 0x18, 0x63, 0x0b, 0x73, 0x3b, 0x03, 0xb1, 0x2b, 0x93, 0x9b, 0x4b, 0x7b, + 0x73, 0x03, 0x99, 0x71, 0xb9, 0x01, 0x41, 0xa1, 0x0b, 0x3b, 0x9b, 0x7b, + 0x91, 0x2a, 0x62, 0x2a, 0x0a, 0x9a, 0x2a, 0xfa, 0x9a, 0xb9, 0x81, 0x79, + 0x31, 0x4b, 0x73, 0x0b, 0x63, 0x4b, 0xd9, 0x10, 0x04, 0x13, 0x04, 0xe2, + 0x98, 0x20, 0x10, 0xc8, 0x06, 0x61, 0x20, 0x26, 0x08, 0x44, 0xb2, 0x41, + 0x18, 0x0c, 0x0a, 0x70, 0x73, 0x1b, 0x06, 0xc4, 0x20, 0x26, 0x08, 0x9c, + 0x45, 0x60, 0x82, 0x40, 0x28, 0x13, 0x04, 0x62, 0x99, 0x20, 0x10, 0xcc, + 0x06, 0x81, 0x70, 0x36, 0x24, 0x84, 0xb2, 0x30, 0xc4, 0xd0, 0x10, 0xcf, + 0x86, 0x00, 0x9a, 0x20, 0x7c, 0xd7, 0x04, 0x81, 0x68, 0x26, 0x08, 0x84, + 0xb3, 0x01, 0x21, 0xa4, 0x65, 0x22, 0x06, 0x0a, 0xd8, 0x10, 0x54, 0x13, + 0x84, 0x30, 0xc0, 0x36, 0x20, 0xc4, 0xb5, 0x30, 0xc4, 0x40, 0x00, 0x1b, + 0x02, 0x6c, 0x03, 0x11, 0x01, 0x56, 0x36, 0x41, 0x10, 0x83, 0x6c, 0x43, + 0xb0, 0x4d, 0x10, 0x04, 0x80, 0x8a, 0x10, 0x5b, 0x1a, 0x9d, 0x91, 0xdc, + 0x5b, 0xdb, 0x0c, 0x11, 0x11, 0xaa, 0x22, 0xac, 0xa1, 0xa7, 0x27, 0x29, + 0xa2, 0x09, 0x42, 0x01, 0x4d, 0x10, 0x8a, 0x68, 0x43, 0x40, 0x4c, 0x10, + 0x0a, 0x69, 0x83, 0x30, 0x4d, 0x1b, 0x16, 0xe2, 0x03, 0x83, 0x30, 0x10, + 0x83, 0x31, 0x18, 0xc6, 0x80, 0x08, 0x03, 0x32, 0xe0, 0x32, 0x65, 0xf5, + 0x05, 0xf5, 0x36, 0x97, 0x46, 0x97, 0xf6, 0xe6, 0x36, 0x41, 0x28, 0xa6, + 0x09, 0x42, 0x41, 0x6d, 0x58, 0x06, 0x33, 0x00, 0x83, 0x33, 0x10, 0x03, + 0x34, 0x18, 0xd0, 0x60, 0x08, 0x03, 0x60, 0x83, 0x50, 0x06, 0x69, 0xc0, + 0x64, 0xca, 0xea, 0x8b, 0x2a, 0x4c, 0xee, 0xac, 0x8c, 0x6e, 0x82, 0x50, + 0x54, 0x13, 0x04, 0xe2, 0xd9, 0x20, 0x4c, 0x6d, 0xb0, 0x61, 0x21, 0xd6, + 0x00, 0x0c, 0xd8, 0x40, 0x0c, 0xc2, 0x60, 0x40, 0x03, 0x22, 0x0c, 0xdc, + 0x60, 0x43, 0xf0, 0x06, 0x1b, 0x06, 0x35, 0x80, 0x03, 0x60, 0x43, 0xd1, + 0x79, 0x71, 0xa0, 0x01, 0x55, 0xd8, 0xd8, 0xec, 0xda, 0x5c, 0xd2, 0xc8, + 0xca, 0xdc, 0xe8, 0xa6, 0x04, 0x41, 0x15, 0x32, 0x3c, 0x17, 0xbb, 0x32, + 0xb9, 0xb9, 0xb4, 0x37, 0xb7, 0x29, 0x01, 0xd1, 0x84, 0x0c, 0xcf, 0xc5, + 0x2e, 0x8c, 0xcd, 0xae, 0x4c, 0x6e, 0x4a, 0x60, 0xd4, 0x21, 0xc3, 0x73, + 0x99, 0x43, 0x0b, 0x23, 0x2b, 0x93, 0x6b, 0x7a, 0x23, 0x2b, 0x63, 0x9b, + 0x12, 0x20, 0x65, 0xc8, 0xf0, 0x5c, 0xe4, 0xca, 0xe6, 0xde, 0xea, 0xe4, + 0xc6, 0xca, 0xe6, 0xa6, 0x04, 0x59, 0x1d, 0x32, 0x3c, 0x17, 0xbb, 0xb4, + 0xb2, 0xbb, 0x24, 0xb2, 0x29, 0xba, 0x30, 0xba, 0xb2, 0x29, 0xc1, 0x56, + 0x87, 0x0c, 0xcf, 0xa5, 0xcc, 0x8d, 0x4e, 0x2e, 0x0f, 0xea, 0x2d, 0xcd, + 0x8d, 0x6e, 0x6e, 0x4a, 0x10, 0x07, 0x00, 0x79, 0x18, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x33, 0x08, 0x80, 0x1c, 0xc4, 0xe1, 0x1c, 0x66, 0x14, + 0x01, 0x3d, 0x88, 0x43, 0x38, 0x84, 0xc3, 0x8c, 0x42, 0x80, 0x07, 0x79, + 0x78, 0x07, 0x73, 0x98, 0x71, 0x0c, 0xe6, 0x00, 0x0f, 0xed, 0x10, 0x0e, + 0xf4, 0x80, 0x0e, 0x33, 0x0c, 0x42, 0x1e, 0xc2, 0xc1, 0x1d, 0xce, 0xa1, + 0x1c, 0x66, 0x30, 0x05, 0x3d, 0x88, 0x43, 0x38, 0x84, 0x83, 0x1b, 0xcc, + 0x03, 0x3d, 0xc8, 0x43, 0x3d, 0x8c, 0x03, 0x3d, 0xcc, 0x78, 0x8c, 0x74, + 0x70, 0x07, 0x7b, 0x08, 0x07, 0x79, 0x48, 0x87, 0x70, 0x70, 0x07, 0x7a, + 0x70, 0x03, 0x76, 0x78, 0x87, 0x70, 0x20, 0x87, 0x19, 0xcc, 0x11, 0x0e, + 0xec, 0x90, 0x0e, 0xe1, 0x30, 0x0f, 0x6e, 0x30, 0x0f, 0xe3, 0xf0, 0x0e, + 0xf0, 0x50, 0x0e, 0x33, 0x10, 0xc4, 0x1d, 0xde, 0x21, 0x1c, 0xd8, 0x21, + 0x1d, 0xc2, 0x61, 0x1e, 0x66, 0x30, 0x89, 0x3b, 0xbc, 0x83, 0x3b, 0xd0, + 0x43, 0x39, 0xb4, 0x03, 0x3c, 0xbc, 0x83, 0x3c, 0x84, 0x03, 0x3b, 0xcc, + 0xf0, 0x14, 0x76, 0x60, 0x07, 0x7b, 0x68, 0x07, 0x37, 0x68, 0x87, 0x72, + 0x68, 0x07, 0x37, 0x80, 0x87, 0x70, 0x90, 0x87, 0x70, 0x60, 0x07, 0x76, + 0x28, 0x07, 0x76, 0xf8, 0x05, 0x76, 0x78, 0x87, 0x77, 0x80, 0x87, 0x5f, + 0x08, 0x87, 0x71, 0x18, 0x87, 0x72, 0x98, 0x87, 0x79, 0x98, 0x81, 0x2c, + 0xee, 0xf0, 0x0e, 0xee, 0xe0, 0x0e, 0xf5, 0xc0, 0x0e, 0xec, 0x30, 0x03, + 0x62, 0xc8, 0xa1, 0x1c, 0xe4, 0xa1, 0x1c, 0xcc, 0xa1, 0x1c, 0xe4, 0xa1, + 0x1c, 0xdc, 0x61, 0x1c, 0xca, 0x21, 0x1c, 0xc4, 0x81, 0x1d, 0xca, 0x61, + 0x06, 0xd6, 0x90, 0x43, 0x39, 0xc8, 0x43, 0x39, 0x98, 0x43, 0x39, 0xc8, + 0x43, 0x39, 0xb8, 0xc3, 0x38, 0x94, 0x43, 0x38, 0x88, 0x03, 0x3b, 0x94, + 0xc3, 0x2f, 0xbc, 0x83, 0x3c, 0xfc, 0x82, 0x3b, 0xd4, 0x03, 0x3b, 0xb0, + 0xc3, 0x0c, 0xc4, 0x21, 0x07, 0x7c, 0x70, 0x03, 0x7a, 0x28, 0x87, 0x76, + 0x80, 0x87, 0x19, 0xd1, 0x43, 0x0e, 0xf8, 0xe0, 0x06, 0xe4, 0x20, 0x0e, + 0xe7, 0xe0, 0x06, 0xf6, 0x10, 0x0e, 0xf2, 0xc0, 0x0e, 0xe1, 0x90, 0x0f, + 0xef, 0x50, 0x0f, 0xf4, 0x00, 0x00, 0x00, 0x71, 0x20, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0x06, 0xa0, 0x6c, 0x0b, 0x32, 0x7d, 0x91, 0xc3, 0xdc, + 0x9d, 0x11, 0x6c, 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x04, 0x54, 0x51, 0x10, + 0x51, 0xe9, 0x00, 0x43, 0x49, 0x18, 0x80, 0x80, 0xf9, 0xc5, 0x6d, 0x5b, + 0xc1, 0x36, 0x5c, 0xbe, 0xf3, 0xf8, 0x42, 0x40, 0x15, 0x05, 0x11, 0x95, + 0x0e, 0x30, 0x94, 0x84, 0x01, 0x08, 0x98, 0x8f, 0xdc, 0xb6, 0x19, 0x48, + 0xc3, 0xe5, 0x3b, 0x8f, 0x2f, 0x44, 0x04, 0x30, 0x11, 0x21, 0xd0, 0x0c, + 0x0b, 0x61, 0x01, 0xd3, 0x70, 0xf9, 0xce, 0xe3, 0x2f, 0x0e, 0x30, 0x88, + 0xcd, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x36, 0x50, 0x0d, 0x97, 0xef, 0x3c, + 0xbe, 0x04, 0x30, 0xcf, 0x42, 0x94, 0x44, 0x45, 0x2c, 0x7e, 0x71, 0xdb, + 0x26, 0x50, 0x0d, 0x97, 0xef, 0x3c, 0xbe, 0x34, 0x39, 0x11, 0x81, 0x52, + 0xd3, 0x43, 0x4d, 0x7e, 0x71, 0xdb, 0x00, 0x61, 0x20, 0x00, 0x00, 0x41, + 0x00, 0x00, 0x00, 0x13, 0x04, 0x41, 0x2c, 0x10, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x54, 0x8d, 0x00, 0x10, 0x51, 0x0a, 0x25, 0x57, 0x76, + 0x33, 0x00, 0xc5, 0x47, 0x45, 0x09, 0xd0, 0x30, 0x03, 0x00, 0x00, 0x23, + 0x06, 0x09, 0x00, 0x82, 0x60, 0x60, 0x71, 0x46, 0xa4, 0x69, 0xc8, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x58, 0xdd, 0x01, 0x6d, 0x5b, 0x32, 0x62, + 0x90, 0x00, 0x20, 0x08, 0x06, 0x96, 0x87, 0x48, 0x1c, 0xa7, 0x8c, 0x18, + 0x24, 0x00, 0x08, 0x82, 0x81, 0x41, 0x06, 0x5a, 0xd7, 0x51, 0xc7, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x18, 0x65, 0xb0, 0x79, 0x9e, 0x81, 0x8c, + 0x18, 0x1c, 0x00, 0x08, 0x82, 0x01, 0x34, 0x06, 0xca, 0xf0, 0x8d, 0x26, + 0x04, 0xc0, 0x68, 0x82, 0x10, 0x8c, 0x26, 0x0c, 0xc2, 0x68, 0x02, 0x31, + 0x98, 0x70, 0xc8, 0xc7, 0x84, 0x43, 0x3e, 0x26, 0x18, 0xf0, 0x31, 0xc1, + 0x80, 0xcf, 0x88, 0xc1, 0x01, 0x80, 0x20, 0x18, 0x40, 0x6c, 0x30, 0x31, + 0x69, 0x30, 0x9a, 0x10, 0x04, 0x23, 0x06, 0x07, 0x00, 0x82, 0x60, 0x30, + 0xb5, 0x41, 0xe5, 0xac, 0xc1, 0x68, 0x42, 0x00, 0x5c, 0x30, 0xd4, 0x88, + 0xc1, 0x03, 0x80, 0x20, 0x18, 0x34, 0x72, 0x60, 0x4d, 0xd2, 0x61, 0x10, + 0x54, 0x1b, 0xb4, 0x41, 0x1b, 0x04, 0xa3, 0x09, 0x01, 0x30, 0x9a, 0x20, + 0x04, 0xa3, 0x09, 0x83, 0x30, 0x9a, 0x40, 0x0c, 0x23, 0x06, 0x09, 0x00, + 0x82, 0x60, 0x80, 0xe0, 0xc1, 0x27, 0x07, 0x72, 0x90, 0x06, 0xc4, 0x88, + 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x78, 0xf0, 0xc9, 0x81, 0x1c, 0x68, + 0xc3, 0x88, 0x41, 0x02, 0x80, 0x20, 0x18, 0x20, 0x78, 0xf0, 0xc9, 0x81, + 0x1c, 0xa0, 0x81, 0x30, 0x62, 0x90, 0x00, 0x20, 0x08, 0x06, 0x08, 0x1e, + 0x7c, 0x72, 0x20, 0x07, 0x67, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; +#if 0 +; +; Input signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; TEXCOORD 0 xy 0 NONE float xy +; SV_Position 0 xyzw 1 POS float +; +; +; Output signature: +; +; Name Index Mask Register SysValue Format Used +; -------------------- ----- ------ -------- -------- ------- ------ +; SV_Target 0 xyzw 0 TARGET float xyzw +; +; shader hash: e88bd1fd8f6be3ae3e613ed8989b06d7 +; +; Pipeline Runtime Information: +; +; Pixel Shader +; DepthOutput=0 +; SampleFrequency=0 +; +; +; Input signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; TEXCOORD 0 linear +; SV_Position 0 noperspective +; +; Output signature: +; +; Name Index InterpMode DynIdx +; -------------------- ----- ---------------------- ------ +; SV_Target 0 +; +; Buffer Definitions: +; +; cbuffer SourceRegionBuffer +; { +; +; struct SourceRegionBuffer +; { +; +; float2 UVLeftTop; ; Offset: 0 +; float2 UVDimensions; ; Offset: 8 +; uint MipLevel; ; Offset: 16 +; float LayerOrDepth; ; Offset: 20 +; +; } SourceRegionBuffer; ; Offset: 0 Size: 24 +; +; } +; +; +; Resource Bindings: +; +; Name Type Format Dim ID HLSL Bind Count +; ------------------------------ ---------- ------- ----------- ------- -------------- ------ +; SourceRegionBuffer cbuffer NA NA CB0 cb0,space3 1 +; SourceSampler sampler NA NA S0 s0,space2 1 +; SourceTextureCube texture f32 cube T0 t0,space2 1 +; +; +; ViewId state: +; +; Number of inputs: 8, outputs: 4 +; Outputs dependent on ViewId: { } +; Inputs contributing to computation of Outputs: +; output 0 depends on inputs: { 0, 1 } +; output 1 depends on inputs: { 0, 1 } +; output 2 depends on inputs: { 0, 1 } +; output 3 depends on inputs: { 0, 1 } +; +target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +target triple = "dxil-ms-dx" + +%dx.types.Handle = type { i8* } +%dx.types.CBufRet.f32 = type { float, float, float, float } +%dx.types.CBufRet.i32 = type { i32, i32, i32, i32 } +%dx.types.ResRet.f32 = type { float, float, float, float, i32 } +%"class.TextureCube >" = type { <4 x float> } +%SourceRegionBuffer = type { <2 x float>, <2 x float>, i32, float } +%struct.SamplerState = type { i32 } + +define void @BlitFromCube() { + %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %3 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 2, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) + %4 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) + %6 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 0) ; CBufferLoadLegacy(handle,regIndex) + %7 = extractvalue %dx.types.CBufRet.f32 %6, 0 + %8 = extractvalue %dx.types.CBufRet.f32 %6, 1 + %9 = extractvalue %dx.types.CBufRet.f32 %6, 2 + %10 = extractvalue %dx.types.CBufRet.f32 %6, 3 + %11 = fmul fast float %9, %4 + %12 = fmul fast float %10, %5 + %13 = fadd fast float %11, %7 + %14 = fadd fast float %12, %8 + %15 = fmul fast float %13, 2.000000e+00 + %16 = fadd fast float %15, -1.000000e+00 + %17 = fmul fast float %14, 2.000000e+00 + %18 = fadd fast float %17, -1.000000e+00 + %19 = call %dx.types.CBufRet.f32 @dx.op.cbufferLoadLegacy.f32(i32 59, %dx.types.Handle %3, i32 1) ; CBufferLoadLegacy(handle,regIndex) + %20 = extractvalue %dx.types.CBufRet.f32 %19, 1 + %21 = fptoui float %20 to i32 + switch i32 %21, label %35 [ + i32 0, label %22 + i32 1, label %25 + i32 2, label %27 + i32 3, label %29 + i32 4, label %30 + i32 5, label %32 + ] + +;